I am trying to have a pixel perfect collision with my pong object and my rotated paddle object. However, I realized that the pong ball is still hitting the rectangle of the rotated paddle object. As you can see, the ball is hitting the rect of the paddle, instead of the actual paddle
Here is my pong class with defined collision detection. Please check the checkCollision() function because I use the pygame.sprite.colliderect() function.
class Pong(pygame.sprite.Sprite):
def __init__(self, screensize):
pygame.sprite.Sprite.__init__(self)
self.screensize = screensize
self.centerx = screensize[0] // 2
self.centery = screensize[1] // 2
self.radius = 25
self.rect = pygame.Rect(self.centerx-self.radius,
self.centery-self.radius,
self.radius*2, self.radius*2)
self.image = pygame.image.load("pokeball.png").convert()
self.colorkey = self.image.get_at((0,0))
self.image = pygame.transform.scale(self.image, (self.radius, self.radius))
#Create the mask
self.mask = pygame.mask.from_surface(self.image)
self.color = (100,100,255)
self.direction = [-2,1]
self.speedx = 2
self.speedy = 3
self.hit_edge_left = False
self.hit_edge_right = False
def checkCollision(self, player_paddle, ai_paddle):
col = pygame.sprite.collide_rect(self, player_paddle)
return col
def collisionFormula(self, player_paddle, ai_paddle):
if self.checkCollision(self, player_paddle):
relative_IntersectionY = player_paddle.centery - self.rect.centery
normal_IntersectionY = relative_IntersectionY / (player_paddle.height /2)
bounce_angle = normal_IntersectionY * (5*math.pi/ 12 )
self.direction[0] = math.cos(bounce_angle)
self.direction[1] = -1 * math.sin(bounce_angle)
def update_ball_position(self):
#update the position of the ball
self.centerx += self.direction[0]*self.speedx
self.centery += self.direction[1]*self.speedy
self.rect.center = (self.centerx, self.centery)
def reset_ball(self):
if self.rect.right >= self.screensize[0]-1:
self.hit_edge_right = True
self.__init__(self.screensize)
elif self.rect.left <= 0:
self.hit_edge_left = True
self.__init__(self.screensize)
def collision_checks(self, player_paddle, ai_paddle):
#if the ball hits the top or bottom of the screen, change the y direction
if self.rect.top <= 0 or self.rect.bottom >= self.screensize[1] - 1:
self.direction[1] *= -1
#if the pong hits the paddles, change how the pong ball moves
if self.rect.colliderect(player_paddle.rect) or self.rect.colliderect(ai_paddle.rect):
self.collisionFormula(player_paddle, ai_paddle)
def update(self, player_paddle, ai_paddle):
self.update_ball_position()
self.reset_ball()
self.collision_checks(player_paddle, ai_paddle)
def render(self, screen):
screen.blit(self.image, (self.centerx, self.centery))<!-- Paste the part of the code that shows the problem.
Here is my PlayerPaddle class with defined rotate functions.
class PlayerPaddle(pygame.sprite.Sprite):
def __init__(self, screensize):
pygame.sprite.Sprite.__init__(self)
self.screensize = screensize
self.centerx = 50
self.centery = screensize[1]//2
self.height = 100
self.width = 20
self.imageMaster = pygame.image.load("naruto.png").convert()
self.colorkey = self.imageMaster.get_at((0,0))
self.imageMaster = pygame.transform.scale(self.imageMaster, (100, 200))
self.image = self.imageMaster
#mask
#self.maskMaster = pygame.mask.from_surface(self.image)
#self.mask = self.maskMaster
self.rect = self.image.get_rect()
self.rect.center = (screensize[0]//2, screensize[1]//2)
self.dir = 0
self.color = (100,255,100)
self.speed = 3
self.direction = 0
self.update()
def update(self):
#Rotate functions
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imageMaster, self.dir).convert()
self.image.set_colorkey(self.colorkey)
self.rect = self.image.get_rect()
#self.rect.center = oldCenter
self.mask = pygame.mask.from_surface(self.image)
self.centery += self.direction*self.speed
self.rect.center = (self.centerx, self.centery)
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > self.screensize[1]-1:
self.rect.bottom = self.screensize[1]-1
def render(self, screen):
screen.blit(self.image, (self.rect.x, self.rect.y))
def turnLeft(self):
self.dir += 45
if self.dir > 360:
self.dir = 45
def turnRight(self):
self.dir -= 45
if self.dir < 0:
self.dir = 315
And I write this within the while loop of my main().
if pygame.sprite.spritecollide(pong_sprite, paddleGroup, False, pygame.sprite.collide_mask):
print("Collided")
I'm not sure why this is occurring but I'd like to know how to get a pixel perfect collision so I can avoid the issue from the image.
EDIT: I changed the update function of my PlayerPaddle class.
def update(self):
#Rotate functions
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imageMaster, self.dir)
self.rect = self.image.get_rect()
self.rect.center = oldCenter
self.mask = pygame.mask.from_surface(self.image)
self.centery += self.direction*self.speed
self.rect.center = (self.centerx, self.centery)
if self.rect.top < 0:
self.rect.top = 0
if self.rect.bottom > self.screensize[1]-1:
self.rect.bottom = self.screensize[1]-1
And here is my main():
def main():
pygame.init()
screensize = (640,700)
screen = pygame.display.set_mode(screensize)
background = pygame.Surface(screen.get_size())
background.fill((0, 255, 0))
clock = pygame.time.Clock()
pong_sprite = Pong(screensize)
player_paddle = PlayerPaddle(screensize)
ai_paddle = AIPaddle(screensize)
paddleGroup = pygame.sprite.Group()
paddleGroup.add(player_paddle)
pongGroup = pygame.sprite.Group()
pongGroup.add(pong_sprite)
running = True
keymap = {pygame.K_u: False}
while running:
#fps limiting/reporting phase
clock.tick(64)
screen.fill((100,100,100))
#event handling phase
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if event.key in keymap:
keymap[event.key] = True
if event.key == K_UP:
player_paddle.direction = -1
elif event.key == K_DOWN:
player_paddle.direction = 1
elif event.key == K_LEFT:
player_paddle.turnLeft()
elif event.key == K_RIGHT:
player_paddle.turnRight()
if event.type == KEYUP:
if event.key in keymap:
keymap[event.key] = False
if event.key == K_UP and player_paddle.direction == -1:
player_paddle.direction = 0
elif event.key == K_DOWN and player_paddle.direction == 1:
player_paddle.direction = 0
#object updating phase
ai_paddle.update(pong_sprite, player_paddle)
#player_paddle.update()
#pong.update(player_paddle, ai_paddle)
if pygame.sprite.spritecollide(pong_sprite, paddleGroup, False, pygame.sprite.collide_mask):
print("Collided")
if pong_sprite.hit_edge_left:
print("You won")
#running = False
elif pong_sprite.hit_edge_right:
print("You Lose")
#running = False
#rendering phase
ai_paddle.render(screen)
player_paddle.render(screen)
#pong.render(screen)
paddleGroup.clear(screen, background)
paddleGroup.update()
paddleGroup.draw(screen)
pongGroup.clear(screen,background)
pongGroup.update(player_paddle, ai_paddle)
pongGroup.draw(screen)
pygame.display.flip()
pygame.quit()
Here is my imageenter image description here: This is the naruto.jpg image
And here is the pokeball.jpg enter image description here