Reputation: 810
I have two moving sprites, one is called wall and it just moves up and down; the other is called Player and it bounces around the screen and changes direction whenever it hit an obstacles.
I got this to work to a degree: The player ball does bounce around but sometimes there is a bug where the ball seems to be confused about the movement and just wobbles back and forth when colliding with the wall. The faster I set the speed of the player ball or the movement of the wall, the more frequent the bug becomes.
Here is the code for the project:
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)
many thanks in advance :)
Upvotes: 2
Views: 1280
Reputation: 6056
You can realize that your code works perfectly if the the wall is moving away from the player when they collide. The problem occurs when they are moving towards each other. This is because your player is actually goes inside the wall, you detect a collision, reverse the speed of the player and at the next iteration your player is still inside the wall (because wall is moving towards your player, the player couldn't find enough time to escape it) and you detect a collision again, reverse the speed of the player...
You can modify your code like this to solve the problem:
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
Upvotes: 2