I’m trying to detect collision between two classes I’ve created in PyGame, and on collision, delete the objects from their respective lists. However, I cannot get the collision detection to work. Any help would be greatly appreciated.
import pygame
import sys
WIDTH = 800
HEIGHT = 600
GROUND = 500
pygame.init()
# set the screen, caption, clock, font, basic surfaces
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Snail Jumper')
clock = pygame.time.Clock()
test_font = pygame.font.Font('Pixeltype.ttf', 50)
sky = pygame.Surface((800, GROUND))
sky.fill('Light Blue')
groundImage = pygame.image.load('ground.png')
# Timer
currentTime = 0
timeSurface = test_font.render(f'{currentTime}', False, (64,64,64))
# Snail Essentials
snailImage = pygame.image.load('snail1.png')
snailX = GROUND
snailY = 665
snail = snailImage.get_rect(bottomleft=(snailY, snailX))
snailXSpeed = -4
snailYSpeed = 0
# Jump/Gravity Variables
playerVelocity = 0
jumpVelocity = -16
gravity = 1
snailStatus = 0
jump = 1
offsetCooldown = 100
# Obstacle variables
obstacles = []
nextOffset = 0
obstacleDimen = 20
obstacleCooldown = 0
bullets = []
xVel = -8
yVel = 0
bulletX = 0
bulletY = 30
bulletCount = 1
# Collisions
hits = 0
hitSurface = test_font.render(f'Collisions: {hits}', False, 'Black')
collideSound = pygame.mixer.Sound("punch.wav")
# Obstacle Class
class Obstacle(object):
def __init__(self,x,y,width,height):
self.x = x
self.y = y
self.width = width
self.height = height
self.xSpeed = 2.5
self.ySpeed = 0
self.color = (23,23,23)
self.rect = pygame.Rect(x,y,width,height)
def draw(self,scrn):
pygame.draw.rect(scrn, self.color, (self.x, self.y, self.width,self.height))
def getRect(self):
return self.rect.copy()
class projectile(object):
def __init__(self,x,y,radius,color,xVel,yVel):
self.x = x
self.y = y
self.radius = radius
self.color = color
self.xVel = xVel
self.yVel = yVel
self.rect = pygame.Rect(x,y,radius,radius)
def draw(self,scrn):
pygame.draw.circle(scrn, self.color, (self.x,self.y), self.radius)
def getRect(self):
return self.rect.copy()
def collidesWith(self, otherRect):
result = self.rect.colliderect(otherRect)
if result:
print("true")
return result
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] and jump > 0:
playerVelocity = jumpVelocity
jump -= 1
# Projectiles
bulletXOffset = snail.x + bulletX
bulletYOffset = snail.y + bulletY
if keys[pygame.K_f]:
if bulletCount > 0:
bullets.append(projectile(bulletXOffset, bulletYOffset, 6, (173,255,47),xVel,yVel))
#bulletCount -= 1
# Gravity logic
if snailStatus == 0:
playerVelocity += gravity
snail.y += playerVelocity
if snail.bottom >= GROUND:
snail.bottom = GROUND
playerVelocity = 0
jump = 1
elif snailStatus == 1:
playerVelocity += gravity
snail.x += playerVelocity
if snail.left <= 0:
snail.left = 0
playerVelocity = 0
jump = 1
elif snailStatus == 2:
playerVelocity += gravity
snail.y += playerVelocity
if snail.top <= 0:
snail.top = 0
playerVelocity = 0
jump = 1
else:
playerVelocity += gravity
snail.x += playerVelocity
if snail.right >= WIDTH+36:
snail.right = WIDTH+36
playerVelocity = 0
jump = 1
if offsetCooldown > 0:
offsetCooldown -= 1
# Snail Rotation
if snail.left < 0:
snailXSpeed = 0
snailYSpeed = -4
snailImage = pygame.transform.rotate(snailImage,-90)
snailStatus = 1
jumpVelocity = 16
gravity = -1
snail.width = 36
bulletY = 0
bulletX = 6
xVel = 0
yVel = -8
if snail.top < 0:
snailXSpeed = 4
snailYSpeed = 0
snailImage = pygame.transform.rotate(snailImage,-90)
snailStatus = 2
snail.width = 72
bulletX = 72
bulletY = 6
xVel = 8
yVel = 0
# Final two need offsets to account for image rect size
if snail.right > WIDTH-10 and offsetCooldown <= 0 and snail.top < 200:
offsetCooldown = 80
snail.right = WIDTH+36
snailXSpeed = 0
snailYSpeed = 4
snailImage = pygame.transform.rotate(snailImage,-90)
snailStatus = 3
jumpVelocity = -16
gravity = 1
bulletX = 30
bulletY = 72
xVel = 0
yVel = 8
if snail.bottom > GROUND-20 and offsetCooldown <= 0 and snail.right > 650:
offsetCooldown = 80
snail.bottom = GROUND
snailXSpeed = -4
snailYSpeed = 0
snailImage = pygame.transform.rotate(snailImage,-90)
snailStatus = 0
bulletX = 0
bulletY = 30
xVel = -8
yVel = 0
# Obstacle Creation
obstacleCooldown -= 1
if obstacleCooldown <= 0 and (snail.bottom < 380 or snail.left > 200):
obstacles.append(Obstacle(10+nextOffset, GROUND-obstacleDimen-nextOffset, obstacleDimen, obstacleDimen))
if nextOffset == 0:
nextOffset = 40
else:
nextOffset = 0
obstacleCooldown = 350
# Obstacle Movement
for obst in obstacles:
if (obst.y == GROUND-obstacleDimen and obst.x >= WIDTH-obstacleDimen) or (obst.y == GROUND-obstacleDimen-40 and obst.x >= WIDTH-40-obstacleDimen):
obst.xSpeed = 0
obst.ySpeed = -2.5
if (obst.y == 0 and obst.x >= WIDTH-obstacleDimen) or (obst.y == 40 and obst.x == WIDTH-40-obstacleDimen):
obst.xSpeed = -2.5
obst.ySpeed = 0
if (obst.y == 0 and obst.x <= 0) or (obst.y == 40 and obst.x <= 40):
obst.xSpeed = 0
obst.ySpeed = 2.5
if (obst.y == GROUND-obstacleDimen and obst.x <= 0) or (obst.y == GROUND-obstacleDimen-40 and obst.x == 40):
obst.xSpeed = 2.5
obst.ySpeed = 0
# Obstacle Collision
for obst in obstacles:
if snail.colliderect(obst.x,obst.y,obst.width,obst.height):
obstacles.remove(obst)
collideSound.play()
hits += 1
hitSurface = test_font.render(f'Collisions: {hits}', False, 'Black')
for bullet in bullets:
if bullet.collidesWith(obstacle.rect):
obstacles.remove(obst)
bullets.remove(bullet)
# if hits == 10:
# gameActive = False
for obst in obstacles:
obst.x += obst.xSpeed
obst.y += obst.ySpeed
for bullet in bullets:
bullet.x += bullet.xVel
bullet.y += bullet.yVel
snail.x += snailXSpeed
snail.y += snailYSpeed
#blits
screen.blit(sky, (0, 0))
screen.blit(groundImage, (0, GROUND))
screen.blit(snailImage, snail)
screen.blit(timeSurface, (375, 300))
for obst in obstacles:
obst.draw(screen)
for bullet in bullets:
bullet.draw(screen)
currentTime = pygame.time.get_ticks()
currentTime = int(currentTime/1000)
timeSurface = test_font.render(f'{currentTime}', False, (64,64,64))
pygame.display.update()
clock.tick(60) # sets a frame rate
The collision detection in the class functions are not performing as intended – it never prints the test string.
In the #Obstacle Collision section at the bottom of the code, I tried multiple solutions – the current code there now is just the latest attempt. I tried putting it within the “for obst” loop, and tried using rect.copy and many other methods, but nothing I’ve tried has worked and it never detects the collision between the obstacle and projectile.
Havok is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
0