2015-04-07 3 views
0

Je travaille sur un jeu de tir à défilement latéral en Python et Pygame. Au début du jeu, je crée un tas de listes telles que les ennemis [] et les tirs []. Quand le jeu redémarre, j'ai essayé tout ce que je peux penser, mais toutes les instances sont toujours à l'écran depuis le dernier playthrough!Python/Pygame: toutes les instances toujours à l'écran après le redémarrage

Dans mon code de redémarrage Je cette ...

for item in enemies: 
    enemies.remove(item) 
    del item 
for item in shots: 
    shots.remove(item) 
    del item 

Je le code ai même ajouté après pour réinitialiser la liste,:

enemies=[] 
shots=[] 

Mais sur le nouveau tout playthrough est toujours là. Aidez-moi!

+0

duplication possible de [Comment vider une liste en Python?] (Http://stackoverflow.com/questions/1400608/how-to-empty-a-list-in-python) –

+1

Lorsque vous faites des ennemis = [] 'et' shots = [] ', vous comptez sur le garbage collector pour supprimer toutes les anciennes instances pour vous. (c'est-à-dire que vous comptez sur les objets pour n'avoir aucune liaison, ce qui n'est pas nécessairement vrai!) La meilleure façon d'effacer une liste sans en créer une nouvelle est d'utiliser une affectation d'épissure: 'l [:] = []'. Alternativement: 'del l [:]'. – Shashank

+0

@shashank: alors que votre solution proposée fonctionnerait, votre explication est incorrecte. Cela n'a rien à voir avec "le garbage collector n'avait pas encore atteint cet objet". – jsbueno

Répondre

2

Votre principal problème est que vos listes existent dans plus d'un contexte (une autre méthode ou une autre fonction)

Lorsque vous enemies = [] vous désactivez la variable locale appelée « ennemis » - mais il cesse de pointer vers la objet précédent, qui est utilisé dans une autre méthode/méthode funtc (bien que vous n'ayez pas listé le code ici).

Votre autre approche, en utilisant for essaie d'itérer sur une liste en la modifiant - elle devrait (et elle) se casse de façon inattendue.

Il suffit de faire:

enemies[:] = [] 
shots[:] = [] 

place: ceux-ci changeront l'objet actuellement référencé par ces noms, ne pas créer de nouveaux objets et de les utiliser localement. De cette façon, le contenu de n'importe quelle autre fonction qui utilise ces listes sera également vidé (ce n'est pas magique: la syntaxe tranche [:] adresse tous les éléments de la liste - du premier au dernier, et l'attribution fait que ces éléments soient remplacé par le contenu de la liste vide: rien)

Bien que cela fonctionne pour l'instant, si vous utilisez des ennemis, des tirs et d'autres structures de données à travers plusieurs fonctions/méthodes, peut-être que vous auriez un design plus propre en utilisant un class , en conservant toutes vos structures de données en tant qu'attributs de cette classe, et en faisant la promotion de vos fonctions sur les méthodes (même si, dans le cas contraire, vous ne faites pas actuellement d'autres utilisations d'un design orienté objet). De cette façon, il serait explicite que vous essayez de modifier les mêmes objets qui sont utilisés dans d'autres parties du code. Un autre conseil: lisez les docs, et familiarisez-vous avec les groupes (et Sprites) de pygame - ils sont très pratiques pour un design propre, et peuvent certainement faire mieux que tout ce que vous faites avec vos objets de liste au-dessus de (par exemple, si enemies étaient un groupe, vous souhaitez simplement appeler enemies.empty() dans ce cas)

+0

Cela a fonctionné parfaitement après avoir déplacé les variables des globales vers leur propre classe avec leurs propres méthodes. Merci beaucoup, cependant, est-ce que vous (ou quelqu'un d'autre) vous expliquez pourquoi cela échouait quand je les ai listés comme des variables globales, mais ça a bien fonctionné dans une classe?Qu'est-ce que je ne comprends pas sur le fonctionnement des variables globales? –

+0

@calsouza: Si vous avez une liste (ou un dictionnaire, ou objet mutable) et l'utiliser dans une fonction sans déclarer son nom comme « global » dans la fonction - Python modifiera l'objet global de toute façon - à moins d'une cession à l'intérieur la même fonction (même si plus tard dans le code) pour ces noms. Dans ce cas, le compilateur suppose ces noms pour désigner des objets locaux (et vous avez probablement fait obtenir un « NameError » exception lorsque vous a présenté les ennemis = ligne [], dans une partie du code qui n'a pas eu erros avant. – jsbueno

+0

http://www.python-course.eu/python3_global_vs_local_variables.php <- plus des explications sur la façon dont fonctionnent gLOBALS – jsbueno

0

utilisez-vous des objets tels que Pygame Sprites et Groups?

Pygame a un objet pour le stockage Sprite appelé Group. Il dispose d'un certain nombre de méthodes pratiques pour la détection des occurrences, le dessin et l'ajout/la suppression de Sprites de sorte que vous ne devriez jamais avoir à supprimer quoi que ce soit. En outre, les sprites ont une méthode self.kill() qui les supprime de tous les groupes auxquels ils appartiennent. De cette façon, peu importe si un Sprite appartient à 1 Groupe ou 703 Groupes; ça va être retiré de tous.Enfin, aucun des codes que vous avez postés ne semble couvrir le dessin réel de quoi que ce soit à l'écran. Est-il possible que vous manquiez une instance de vos objets qui sont dans une sorte de séquence "dessinez-les-à-l'écran"? Si c'est le cas, alors essayer de les supprimer comme vous le faites ici ne les supprimera pas nécessairement de toutes les listes, ou de toutes les portées pertinentes. Exemple:

>>> foo = {} 
>>> bar = [] 
>>> bar.append(foo) 
>>> del foo 
>>> foo 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'foo' is not defined 
>>> bar 
[{}] # the object lives! 

En fin de compte, vous aurez probablement envie d'utiliser des objets pygame.sprite.Sprite et pygame.sprite.Group pour rendre la vie un peu plus simple - encore une fois, ils ont des méthodes pratiques pour gérer tout ce genre de choses que vous ne devez pas chercher et détruisez chaque instance d'un objet lorsque vous n'en avez plus besoin.

+0

Je ne suis pas ... le jeu est un test de mes capacités et je voulais le faire « à la dure, "c'est-à-dire utiliser uniquement les capacités graphiques de pygame et programmer tout le reste à partir de rien. –

0

Je suis désolé mais ma réponse dépend de votre code complet.

Cela dépend surtout de comment vous appelez ennemis et tirs mise à jour.
Donc, si vous itérer liste et met à jour tous les objets que cela devrait fonctionner:

enemies = [] 
shots = [] 

Mais vous avez dit qu'il ne fonctionne pas.
Il y a deux choses les plus vraisemblables que vous avez eu tort: ​​

  1. enemies et shots ne sont pas de vraies listes d'itération si vous les mettez à jour par une autre liste. Si vous utilisez des bibliothèques supplémentaires, elles peuvent avoir leur liste de mise à jour.
  2. Vous ne mettez pas à jour le vieux enemies ni le shots, mais vous n'avez pas rempli votre écran ou quelque chose de familier.

Notez que cette réponse serait probablement mieux si vous avez ajouté plus de votre code et il n'est pas encore en retard.