столкновение между движущимися спрайтами в pygame - PullRequest
2 голосов
/ 09 мая 2020

У меня есть два движущихся спрайта, один называется стеной, и он просто движется вверх и вниз; другой называется Player, он прыгает по экрану и меняет направление всякий раз, когда сталкивается с препятствием.

У меня это в какой-то степени работает: мяч игрока отскакивает, но иногда возникает ошибка, когда кажется, что мяч не понимает движения и просто раскачивается назад и вперед при столкновении со стеной. Чем быстрее я устанавливаю скорость мяча игрока или движения стены, тем чаще появляется ошибка.

Вот код проекта:

import pygame, sys

# The class that creates the player ball; it does not take user input but just bounces around
class Player(pygame.sprite.Sprite):
    def __init__(self, color, width, height,speed_x,speed_y):
        super().__init__()
        self.image = pygame.Surface([width, height])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.speed_x = speed_x
        self.speed_y = speed_y

    def update(self,collision_group):
        self.rect.x += self.speed_x
        self.rect.y += self.speed_y

        # code to get a bounce when the ball hits the edge of the screen
        if self.rect.right >= screen_width or self.rect.left <= 0:
            self.speed_x *= -1
        if self.rect.bottom >= screen_height or self.rect.top <= 0:
            self.speed_y *= -1

        # Code to get a bounce when the player collides with the wall
        collide_object = pygame.sprite.spritecollide(self,collision_group,False)
        if collide_object:
            if collide_object[0].rect.collidepoint(self.rect.midbottom) or collide_object[0].rect.collidepoint(self.rect.midtop):
                self.speed_y *= -1
        if collide_object[0].rect.collidepoint(self.rect.midright) or collide_object[0].rect.collidepoint(self.rect.midleft):
                self.speed_x *= -1          

# Code for the wall, it just moves up and down
class Wall(pygame.sprite.Sprite):
    def __init__(self,width,height,pos_x,pos_y,color):
        super().__init__()
        self.image = pygame.Surface([width,height])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = pos_x
        self.rect.y = pos_y
        self.speed = 5

    def update(self):
        self.rect.y += self.speed

        if self.rect.bottom >= screen_height:
            self.speed *= -1 
        if self.rect.top <= 0:
            self.speed *= -1

# General setup
pygame.init()
clock = pygame.time.Clock()

# Game Screen
screen_width = 800
screen_height = 800
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("Side by side collision")

# Creating the sprites and groups
moving_sprites = pygame.sprite.Group()
player = Player((255,0,0),20,20,8,8)
moving_sprites.add(player)

wall_sprites = pygame.sprite.Group()
center_wall = Wall(500,200,300,300,(255,255,0))
wall_sprites.add(center_wall)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    # Drawing
    screen.fill((0,0,0))
    wall_sprites.draw(screen)
    wall_sprites.update()
    moving_sprites.draw(screen)
    moving_sprites.update(wall_sprites)

    pygame.display.flip()
    clock.tick(60)

заранее большое спасибо :)

1 Ответ

2 голосов
/ 09 мая 2020

Вы можете понять, что ваш код отлично работает, если стена удаляется от игрока, когда он сталкивается. Проблема возникает, когда они движутся навстречу друг другу. Это потому, что ваш игрок фактически входит в стену, вы обнаруживаете столкновение, меняете скорость игрока, и на следующей итерации ваш игрок все еще находится внутри стены (поскольку стена движется к вашему игроку, игрок не может найти достаточно времени, чтобы избежать этого), и вы снова обнаружите столкновение, измените скорость игрока ...

Чтобы решить проблему, вы можете изменить свой код следующим образом:

if collide_object:
    rect = collide_object[0].rect
    if rect.collidepoint(self.rect.midbottom): # if we hit from bottom
        if self.speed_y > 0: # and the player was moving down
            self.speed_y *= -1 # go up
    elif rect.collidepoint(self.rect.midtop): # if we hit from top
        if self.speed_y < 0: # and the player was moving up
            self.speed_y *= -1 # go down
...