user2817437
user2817437

Reputation: 79

Pygame - Keep Sprites from overlapping

I'm making a space invaders type game using python and pygame. I currently have where I can move my user ship back and forth along the bottom with my arrow keys, and my enemies spawn and move back and forth across the top. My problem is with the enemies. I have it set so if they hit 100 pixels from the edge of the game screen, they start going back the other direction. This results in an overlap while the ones that have hit the limit are already heading back and the ones that haven't hit the limit are still going the original direction. I want it so that when the enemies on the edge hit the limit, all the enemies immediately go back in the other direction, just like in space invaders. My code is below. I have KeepFormation under enemies to try to do what I wanted, but it isn't working. Thank you!

from pygame import *

size_x = 900
size_y = 650

class Object:
    def disp(self, screen):
        screen.blit(self.sprite, self.rect)

class User_Ship(Object):
    def __init__(self):
        self.sprite = image.load("mouse.bmp")
        self.rect = self.sprite.get_rect()
        self.rect.centerx = size_x/2
        self.rect.centery = size_y - 40
        self.count = 0
        self.move_x = 0
        self.move_y = 0

    def checkwith(self, otherrect):
        if self.rect.colliderect(otherrect):
            exit()

    def cycle(self):
        self.rect.centerx += self.move_x
        if self.rect.centerx < 100:
            self.rect.centerx = 100
        if self.rect.centerx > size_x - 100:
            self.rect.centerx = size_x - 100

        self.rect.centery += self.move_y
        if self.rect.centery < 0:
            self.rect.centery = 800

    def right(self):
        self.move_x += 10

    def left(self):
        self.move_x -= 10

    def stop_x(self):
        self.move_x = 0

    def stop_y(self):
        self.move_y = 0

    def shoot(self):
        if keys[pygame.K_SPACE]:
            self.Bullet.x = self.rect.centerx
            self.Bullet.y = self.rect.centery
            self.Bullet.speed = 10

class Enemys(Object):
    def __init__(self):
        self.sprite = image.load("ball.bmp")
        self.rect = self.sprite.get_rect()
        self.rect.centerx = size_x/3
        self.rect.centery = 200
        self.mval = -2

    def KeepFormation(self, otherrect):
        if self.rect.colliderect(otherrect):
            self.rect.centerx += 5

    def cycle(self):
        self.rect.centerx += self.mval
        if self.rect.centerx < 100:
            self.mval = 2
        elif self.rect.centerx > (size_x - 100):
            self.mval = -2

class Bullet(Object):
    def __init__(self):
        self.sprite = image.load("missile.png")
        self.rect = self.sprite.get_rect()
        self.rect.centerx = -100
        self.rect.centery = 100
        self.speed = 0

EnemyList = []
for i in range(14):
    EnemyList.append(Enemys())
    EnemyList[i].rect.centerx = (i) * 50
#   EnemyList[i].count = i * 20 

init()
screen = display.set_mode((size_x, size_y))
m = User_Ship()
en = Enemys()
b = Bullet()
clock = time.Clock()

while True:
    for e in event.get():
        if e.type == QUIT:
            quit()
        if e.type == KEYDOWN:
            if e.key == K_RIGHT:
                m.right()
            elif e.key == K_LEFT:
                m.left()
        if e.type == KEYUP:
            if e.key == K_RIGHT or e.key == K_LEFT:
                m.stop_x()

    m.cycle()
    screen.fill((255,255,255))
    for enemy in EnemyList:
        enemy.cycle()
        enemy.disp(screen)
        enemy.KeepFormation(enemy.rect)
    m.disp(screen)
    b.disp(screen)
    display.flip()
    clock.tick(60)  

Upvotes: 2

Views: 1057

Answers (1)

shad0w_wa1k3r
shad0w_wa1k3r

Reputation: 13372

Add a flag in

def cycle(self):
    self.rect.centerx += self.mval
    if self.rect.centerx < 100:
        self.mval = 2
        return True # Direction change!
    elif self.rect.centerx > (size_x - 100):
        self.mval = -2
        return True
    return False # no change

But then you need to make this change happen only once. Thus...

done_once = False
for enemy in EnemyList:
    if not done_once:
        change = enemy.cycle()
    if change and not done_once:
        # call the new enemy function that changes every enemy's direction
        done_once = True
    enemy.disp(screen)
    enemy.KeepFormation(enemy.rect)

Process this flag such that everyone should change direction now. You may need another function & direction_tracking variable in your Enemy class. Good luck & good job!

Upvotes: 2

Related Questions