1

This game is a space shooter and I'm having a weird problem where my lasers only sometimes hit the enemy, and other times pass right through.

for lasers in amtLasers:
    if lasers.y < invaders.y:
        if lasers.x > invaders.x-56 and lasers.x < invaders.x+28:
            amtLasers.pop(amtLasers.index(lasers))
            amtInvaders.pop(amtInvaders.index(invaders))
            score += 20

I have classes for the lasers and invaders and amtLasers is a list that stores the onscreen lasers until they get deleted. I don't have it set to destroy the enemy on contact, so I was able to notice that if I continue shooting an enemy, the same enemy will get hit sometimes and not get hit other times. Why does this happen and how can I fix it?

Here's an edit: The lasers only hit the most recently spawned enemy, and I think I know why

class invader(object):
    def __init__(self):
        self.x = randint(30, 1020)
        self.y = 0
        color = randint(1, 3)
        if color == 1:
            self.col = (225,0,0)
        elif color == 2:
            self.col = (0,225,0)
        elif color == 3:
            self.col = (0,115,255)
        self.vel = randint(1, 2)

When a new enemy is spawned, invaders.x and invaders.y track that specific enemy and none of the other ones because this class has multiple enemies onscreen at once. How would I track each enemy separately?

Cheesy
  • 23
  • 5
  • Not really enough information to respond. try adding more info. you might print your lasers.x and linvaders.x in your loop to see if the values make sense. – LhasaDad Mar 14 '21 at 01:18
  • 1
    Could it be that your lasers move fast enough to move all the way through an enemy in between updates? – Samwise Mar 14 '21 at 01:20
  • ok I found out something important. It passes through any enemy that isn't the highest up onscreen. This means that when a new enemy spawns at the top, the lasers will pass through every enemy except that one. – Cheesy Mar 14 '21 at 01:25

1 Answers1

1

You will need to test to see if any of the lasers hit any of the enemies. Use 2 nested loops to iterate the enemies and the lasers:

for lasers in amtLasers[:]:
    for invaders in amtInvaders[:]:

        if lasers.y < invaders.y:
            if lasers.x > invaders.x-56 and lasers.x < invaders.x+28:
                amtLasers.pop(amtLasers.index(lasers))
                amtInvaders.pop(amtInvaders.index(invaders))
                score += 20

Note that you need to iterate over shallow copies of the list. See How to remove items from a list while iterating?.

I recommend to use pygame.Rect objects and colliderect for the collision test:

laser_rect = pygame.Rect(laser.x, laser.y, laser_width, laser_height)
invader_rect = pygame.Rect(invaders.x, invaders.y, invaders_width, invaders_height)

if laser_rect .colliderect(invader_rect):
    amtLasers.pop(amtLasers.index(lasers))
    amtInvaders.pop(amtInvaders.index(invaders))
    score += 20

See How do I detect collision in pygame? and How to detect collisions between two rectangular objects or images in pygame.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174