简体   繁体   中英

How to make enemy sprites collide and not mesh together when moving

EDIT: Please stop referring me to the bird colliding with a rock game, my problem is no where near his. I have the player able to collide with and not go through the walls in my game, but the code does not transfer to the zombies. The zombies do not collide and rub against each other, they just slide into each other and become one block. Read my explanation below please <3

So I'm working on a game in pygame where zombies move toward the player as the player shoots them down (I know, original, right?) But the code I have to detect the zombies collision with each other does not work in any practical way and without it the zombies simply move toward the player and mesh together into one zombie block. What can I change in the zombie's code to make them not move into each other as they close in to eat my brains?

class Enemy(pygame.sprite.Sprite):
    def __init__(self, color):
        super().__init__()
        self.image = pygame.Surface([20, 20])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.pos_x = self.rect.x = random.randrange(35, screen_width - 35)
        self.pos_y = self.rect.y = random.randrange(35, screen_height - 135)

        # How Zombies move towards player

    def update(self):
        zombie_vec_x = self.rect.x - player.rect.x
        zombie_vec_y = self.rect.y - player.rect.y
        vec_length = math.sqrt(zombie_vec_x ** 2 + zombie_vec_y ** 2)
        zombie_vec_x = (zombie_vec_x / vec_length) * 1 # These numbers determine
        zombie_vec_y = (zombie_vec_y / vec_length) * 1 # zombie movement speed

        self.pos_x -= zombie_vec_x
        self.pos_y -= zombie_vec_y

        self.rect.x = self.pos_x
        self.rect.y = self.pos_y


        block_hit_list = pygame.sprite.spritecollide(self, sprites_list, False)
        for block in block_hit_list:
            if self.rect.x > 0:
                self.rect.right = block.rect.left
            elif self.rect.x < 0:
                self.rect.left = block.rect.right
            elif self.rect.y > 0:
                self.rect.bottom = block.rect.top
            else:
                self.rect.top = block.rect.bottom

This is the entire zombie code, the current collision code is at the bottom, starting at block_hit_list = . Any insight on how to correct this or explain how collision coding works would be greatly appreciated!

I'm not 100% certain of the code details, since you haven't described your coordinate system in detail. However, the main point is that you have to find a safe place for the current zombie to move, a place without other zombies in it. This really requires you to work from the most restricted area to the least. Can you sort the zombies into some spatial order? Perhaps iterate through your zombie list from lower-left to upper right?

Given that, each zombie has to check for a spot with respect to all of the others, not merely getting out of the way of each other zombie in turn. You have to consider the x and y directions more holistically. I think this could well work, depending on the movement speed (can a zombie take a step more than half a zombie width?).

    block_hit_list = pygame.sprite.spritecollide(self, sprites_list, False)
    if self.rect.x > 0:
        self.rect.right = min(block.rect.left for block in block_hit_list)
    else:
        self.rect.left = max(block.rect.right for block in block_hit_list)

    if self.rect.y > 0:
        self.rect.bottom = min(block.rect.top for block in block_hit_list)
    else:
        self.rect.top = max(block.rect.bottom for block in block_hit_list)

Note that I'm handling both coordinates, not just one -- I'm assuming that a zombie can move diagonally. I'm not sure I have the directions matched up properly in your coordinate system: if self.rect.x > 0, do I want the most positive zombie's left edge? I don't know whether left > right or top > bottom in your coordinate system. Please test and adjust as necessary.

Also, please temporarily insert a tracing print statement in each branch: display at least the x/y coordinates before and after.

Does this get you moving toward a solution?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM