I am working on a game in pygame. I have a character sprite and a ground which are both images. I want to detect collision between those objects using masks. Here is my code:
import pygame
import os
import sys
import time
import gradients
pygame.init()
#window size
screen_width = 1080
screen_height = 720
monitor_size = [pygame.display.Info().current_w, pygame.display.Info().current_h]
win = pygame.display.set_mode((screen_width, screen_height), pygame.RESIZABLE)
fullscreen = False
in_options = False
pygame.display.set_caption("Pokemon Firered")
#time for FPS management
clock = pygame.time.Clock()
class character(object):
def __init__(self,x,y):
self.left = [pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_1.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_2.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_3.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_4.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_5.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_6.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_7.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_8.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_9.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_10.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_11.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_12.png")).convert_alpha()]
self.right = [pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_1.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_2.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_3.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_4.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_5.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_6.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_7.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_8.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_9.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_10.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_11.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_12.png")).convert_alpha()]
self.x = x
self.y = y
self.is_right = False
self.is_left = True
self.is_jump = False
self.velocity = 5
self.walk_count = 0
self.jump_count= 10
self.latest_direction = "left"
self.border = 1000
if self.latest_direction == "left":
self.mask = pygame.mask.from_surface(self.left[self.walk_count])
if self.latest_direction == "right":
self.mask = pygame.mask.from_surface(self.right[self.walk_count])
def jump(self, win):
neg = 1
if self.jump_count >= -10:
if self.jump_count < 0:
neg = -1
self.y -= (self.jump_count**2)//2.5 * neg
self.jump_count -= 1
else:
self.is_jump = False
self.jump_count = 10
def movement(self, win):
keys = pygame.key.get_pressed() #keyboard input
if keys[pygame.K_a] and self.x > -20:
self.is_left = True
self.is_right = False
self.latest_direction = "left"
self.x -= self.velocity
elif keys[pygame.K_d] and self.x < self.border:
self.is_left = False
self.is_right = True
self.latest_direction = "right"
self.x += self.velocity
else:
self.is_left = False
self.is_right = False
if keys[pygame.K_SPACE] and self.x > 5:
self.is_jump = True
if self.is_jump:
self.jump(win)
def draw(self, win):
if self.walk_count + 1 >= 36:
self.walk_count = 0
if self.is_left:
win.blit(self.left[self.walk_count//3], (self.x, self.y))
self.walk_count += 1
elif self.is_right:
win.blit(self.right[self.walk_count//3], (self.x, self.y))
self.walk_count += 1
elif self.is_jump:
if self.latest_direction == "left":
win.blit(self.left[self.walk_count//3], (self.x, self.y))
if self.latest_direction == "right":
win.blit(self.right[self.walk_count//3], (self.x, self.y))
else:
if self.latest_direction == "left":
win.blit(self.left[3], (self.x, self.y))
if self.latest_direction == "right":
win.blit(self.right[3], (self.x, self.y))
avatar = character(500, 350)
class controls_panel(object):
#controls panel
class ground(object):
def __init__(self):
self.ground = pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Background", "ground.png")).convert_alpha()
self.mask = pygame.mask.from_surface(self.ground)
def draw(self, win):
#ground
ground_height = 502
ground_width = 590
repeat = screen_width//590+1
for i in range(repeat):
win.blit(self.ground, (0+590*i,ground_height))
ground_width = 590*(i+1)
ground = ground()
def event_handling(win):
global fullscreen
global run
global screen_width
global in_options
for event in pygame.event.get():
if event.type == pygame.KEYUP:
if event.key == pygame.K_ESCAPE:
run = False
if event.type == pygame.VIDEORESIZE:
if not fullscreen:
screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
avatar.border = event.w-75
screen_width = event.w
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_f:
fullscreen = not fullscreen
if fullscreen:
screen = pygame.display.set_mode(monitor_size, pygame.FULLSCREEN)
else:
screen = pygame.display.set_mode((screen.get_width(), screen.get_height()), pygame.RESIZABLE)
if event.key == pygame.K_e:
in_options = not in_options
#texts
font = pygame.font.SysFont(None, 25)
def print_text(msg, colour, cords):
text = font.render(msg, True, colour)
win.blit(text, cords)
def options(win):
#options menu
def redraw_game_window():
event_handling(win)
#display background
#win.fill(0)
#win.fill(0)
background_gradient = gradients.vertical([screen_width, screen_height], (209, 77, 135, 255), (249, 175, 88, 255))
win.blit(background_gradient, (0,0))
#ground
ground.draw(win)
if pygame.sprite.spritecollide(avatar, ground, False, pygame.sprite.collide_mask):
print(True)
#options
if in_options:
options(win)
#ingame controls
controls_panel.input(win)
#character
avatar.movement(win)
avatar.draw(win)
pygame.display.update()
run = True
while run:
clock.tick(36) #FPS rate
redraw_game_window()
#Mainloop End
pygame.quit()
It is still very messy because I've just started and I left a few unnecessary bits out to keep it a bit more legible. When I try to detect the collision in the redraw_game_window() function, I get the following error message:
Traceback (most recent call last): File "c:/Users/Pc/Desktop/Python/Games/Game Engine/First Game.py", line 234, in redraw_game_window() File "c:/Users/Pc/Desktop/Python/Games/Game Engine/First Game.py", line 215, in redraw_game_window if pygame.sprite.spritecollide(avatar, ground, False, pygame.sprite.collide_mask): File "C:\Users\Pc\AppData\Roaming\Python\Python37\site-packages\pygame\sprite.py", line 1532, in spritecollide return [s for s in group if collided(sprite, s)] TypeError: 'ground' object is not iterable
What I've tried:
- using rectangles as masks (produces the same error)
Does anyone know what I am doing wrong?
------
Updated classes:
class character(pygame.sprite.Sprite):
def __init__(self,x,y):
pygame.sprite.Sprite.__init__(self)
self.left = [pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_1.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_2.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_3.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_4.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_5.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_6.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_7.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_8.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_9.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_10.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_11.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Left", "left_12.png")).convert_alpha()]
self.left_masks = []
for i in range(len(self.left)):
self.left_masks.append(pygame.mask.from_surface(self.left[i]))
self.right = [pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_1.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_2.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_3.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_4.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_5.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_6.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_7.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_8.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_9.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_10.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_11.png")).convert_alpha(), pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Character\Right", "right_12.png")).convert_alpha()]
self.right_masks = []
for i in range(len(self.right)):
self.right_masks.append(pygame.mask.from_surface(self.right[i]))
self.max_frames = len(self.left)
self.image = self.left[0]
self.mask = self.left_masks[0]
self.rect = self.image.get_rect()
self.rect_center = (x, y)
self.x = x
self.y = y
self.is_right = False
self.is_left = True
self.is_jump = False
self.velocity = 5
self.walk_count = 0
self.jump_count= 10
self.latest_direction = "left"
self.border = 1000
def jump(self, win):
neg = 1
if self.jump_count >= -10:
if self.jump_count < 0:
neg = -1
self.y -= (self.jump_count*self.jump_count//1.5)//2.5 * neg
self.jump_count -= 1
else:
self.is_jump = False
self.jump_count = 10
def movement(self, win):
keys = pygame.key.get_pressed() #keyboard input
if keys[pygame.K_a] and self.x > -20:
self.is_left = True
self.is_right = False
self.latest_direction = "left"
self.x -= self.velocity
elif keys[pygame.K_d] and self.x < self.border:
self.is_left = False
self.is_right = True
self.latest_direction = "right"
self.x += self.velocity
else:
self.is_left = False
self.is_right = False
if keys[pygame.K_SPACE] and self.x > 5:
self.is_jump = True
if self.is_jump:
self.jump(win)
def draw(self, win):
self.hand_left = [(self.x+43, self.y+82), (self.x+41, self.y+82), (self.x+40, self.y+82), (self.x+35, self.y+77), (self.x+33, self.y+74), (self.x+30, self.y+74)]
self.hand_right = [(self.x+45, self.y+73)]
center_point = self.rect_center
if self.walk_count + 1 >= 36:
self.walk_count = 0
if self.is_left:
win.blit(self.left[self.walk_count//3], (self.x, self.y))
self.rect = self.left[self.walk_count//3]
self.walk_count += 1
#item
win.blit(item_flask.image, (self.hand_left[self.walk_count//6]))
elif self.is_right:
win.blit(self.right[self.walk_count//3], (self.x, self.y))
self.rect = self.left[self.walk_count//3]
self.walk_count += 1
elif self.is_jump:
if self.latest_direction == "left":
win.blit(self.left[self.walk_count//3], (self.x, self.y))
self.rect = self.left[self.walk_count//3]
if self.latest_direction == "right":
win.blit(self.right[self.walk_count//3], (self.x, self.y))
self.rect = self.left[self.walk_count//3]
else:
if self.latest_direction == "left":
win.blit(self.left[3], (self.x, self.y))
self.rect = self.left[self.walk_count//3]
if self.latest_direction == "right":
win.blit(self.right[3], (self.x, self.y))
self.rect = self.left[self.walk_count//3]
self.rect_center = center_point
#pygame.draw.rect(win, (25, 25, 25), pygame.Rect(self.x+30, self.y+74, 10, 10))
avatar = character(500, 350)
class ground(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.ground = pygame.image.load(os.path.join("Desktop\Python\Games\Game Engine\Background", "ground.png")).convert_alpha()
self.mask = pygame.mask.from_surface(self.ground)
def draw(self, win):
#ground
ground_height = 502
ground_width = 590
win.blit(self.ground, (590/2, ground_height))
def redraw_game_window():
event_handling(win)
#display background
background_gradient = gradients.vertical([screen_width, screen_height], (209, 77, 135, 255), (249, 175, 88, 255))
win.blit(background_gradient, (0,0))
#COLLISION TESTING
if pygame.sprite.spritecollide(avatar, ground, False, pygame.sprite.collide_mask):
print(True)
#ground
ground.draw(win)
#options
if in_options:
options(win)
#character
avatar.movement(win)
avatar.draw(win)
pygame.display.update()
run = True
while run:
clock.tick(36) #FPS rate
redraw_game_window()
#Mainloop End
pygame.quit()
spritecollide()
but not sprites. Is this intentional? - Kingsley