0

I am trying to make a "space invaders" game in pygame...I have much of the game already running, but I ran into an annoying problem I cannot solve myself (it is the first programming course I have taken). Here is the code in question:

for enemy in enemies:
   if hero.sprite.rect.colliderect(enemy.sprite.rect) or enemy.posy>400:
      hero.health-=1
      initgame()
      break
   else:
      enemy.moveBy(enemyPos, ENEMYVERT)
      enemy.draw()

So what this should supposedly do is:

  1. check for every item in a list named "enemies" (where I have appended all my enemy instances)
  2. if it collides with the hero sprite or if they have reached the bottom of the screen
  3. then remove one life from the player, initialise the game (remake the enemy list, reset positions)
  4. and break the "for" loop.
  5. Else, move the enemies and blit them as usual.

However, what this does is actually remove ALL lives from the player on touch. Shouldn't it stop calculating since I used break? I think it keeps calculating if any in enemies has reached 400px thus keeps removing lives from my player.

This is my initgame function

def initgame():
    enemies=[]
    createEnemies("1.png", 50, 250)
    createEnemies("2.png", 50, 190)
    createEnemies("3.png", 50, 130)
    createEnemies("4.png", 50, 70)
    createEnemies("5.png", 50, 10)
    enemyPos=0
    enemyDir=-1
    hero.score=0
    restartFlag=False
    for enemy in enemies:
        enemy.draw()
2
  • Are you sure you are resetting the enemy positions correctly in initgame()? I suspect you error lies there. Commented Apr 11, 2012 at 14:54
  • Please check the original question for my initgame. Commented Apr 11, 2012 at 14:57

3 Answers 3

1

It looks like you aren't emptying enemies, so the old ones plus the new ones are there after initgame(). The problem is that the line enemies=[] is creating and setting a local variable. In order to do what you want, try:

def initgame():
    global enemies
    enemies=[]
Sign up to request clarification or add additional context in comments.

3 Comments

This sounds good, and I would use it, but the last time I used "global", the professor told me that it is a no-go for programming...and lowered my assignment grade by 3! Maybe I could put "enemies" in the inputs of the initgame, then do a "return enemies"?
Well, since the functions don't take enemies as an argument, you're already using a global variable. Its just that in most cases you don't have to declare the global. If global variables are not allowed, you will have to make sure you pass enemies to every function that needs to know about it (and return it if it is being changed).
I used global, I think I can stand a few points missed. I'm quite fed up with it right now.
1

Try putting

global enemies

at the row before enemies=[] in initgame()

You are not clearing your global enemies variable otherwise. In general it is better to put everything in a class and use self.enemies to share data between functions, than to rely on global variables.

You put your functions in a class, like this:

class SpaceInvaders:
  def __init__(self):
    self.initgame()

  def initgame(self):
    self.enemies = []
    ...#createEnemies
    self.enemyPos = 0
    self.enemyDir = -1
    #etc

  def run(self):
    #your while loop here

All variables that should be shared between functions will now be referred to as self.. This distinguish them from local variables (like "enemy" in your for loop) that are only used inside the function.

You use this class by making an object an calling run.

game = SpaceInvaders()
game.run()

2 Comments

It did work with the "global" but I am afraid this will once more make me lose points...plus I've heard it is not good programming if you use "global". Could you elaborate on the classes method? I already have a class for enemies.
Your enemies list is already global. All you are doing with "global enemies" is admitting that fact :). I'll make a quick edit to explain how you can avoid this.
0

Your break statement should work as anticipated. There must be another reason for health dropping all the way back (other than looping too much). Probably this reason can be found in initgame().

5 Comments

Please check the original question for my initgame.
What is hero.health before running the loop? And what exactly is hero.health after the loop (presumably 0).
hero.health starts of as 3 ("Hero" class variable) and the loop should make it 2. I added a print statement in the "if...collide" statement and the output is 3 2 1.
and you are sure it is not the loop itself that is called repeatedly?
I'm very sorry, I did not understand what you mean. The "for enemy in enemies" loop is under my main "while" loop so it shouldn't continue until the next "while" restart since I broke it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.