[英]Pygame collision masks: sprite and ground
我正在 pygame 中开发游戏。 我有一个角色精灵和一个地面,它们都是图像。 我想使用掩码检测这些对象之间的碰撞。 这是我的代码:
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()
它仍然很乱,因为我刚刚开始,我留下了一些不必要的部分以使其更清晰。 当我尝试检测 redraw_game_window() function 中的碰撞时,我收到以下错误消息:
回溯(最后一次调用):文件“c:/Users/Pc/Desktop/Python/Games/Game Engine/First Game.py”,第 234 行,在 redraw_game_window() 文件“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): 文件 "C:\Data\Users\Pc \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
我试过的:
有谁知道我做错了什么?
更新的课程:
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()
该代码在不是 PyGame 精灵的对象上使用 PyGame 精灵库 spritecollide() function。 如果您想制作自己的精灵,您应该添加和维护Rect
对象以允许代码使用Rect.collide
函数集。
但是将现有的类似精灵的对象转换为正式的 PyGame 精灵会更容易和更快。 这意味着继承基础Sprite
class,并覆盖某些函数和成员变量。 使用 Sprite class 是(恕我直言)最简单和最好的前进方式。
class CharacterSprite( pygame.sprite.Sprite ):
def __init__(self, x, y, image_path ):
pygame.sprite.Sprite.__init__( self )
self.left_frames = []
self.left_masks = []
self.right_frames = []
self.right_masks = []
# Load the walking animation
for i in range( 4 ):
image_name = "left_%1.png" % (i)
image_path = os.path.join( image_path, image_name )
self.left_frames.append( pygame.image.load( image_path ).convert_alpha() )
self.left_masks.append( pygame.mask.from_surface( self.left_frames[-1] )
image_name = "right_%1.png" % (i)
image_path = os.path.join( image_path, image_name )
self.right_frames.append( pygame.image.load( image_path ).convert_alpha() )
self.right_masks.append( pygame.mask.from_surface( self.right_frames[-1] )
self.max_frames = len( self.left_frames )
self.frame_count = 0
self.image = self.left_frames[0]
self.mask = self.left_masks[0]
self.rect = self.image.get_rect() # position is always maintained in the sprite.rect
self.rect.center = ( x, y )
# Various Stats
self.is_left = True
self.is_jump = False
self.velocity = 5
def update( self ):
""" Choose the correct animation frame to show """
centre_point = self.rect.center
if ( self.is_left ):
self.image = self.left_frames[ self.frame_count ]
self.mask = self.left_masks[ self.frame_count ]
else:
self.image = self.right_frames[ self.frame_count ]
self.mask = self.right_masks[ self.frame_count ]
self.rect = self.image.get_rect()
self.rect.center = centre_point
def movement( self ):
""" handle changes of movement an the animation """
# handle the movement and animation
keys = pygame.key.get_pressed() #keyboard input
if ( keys[pygame.K_d] and self.rect.x < self.border ): # RIGHT
if ( self.is_left ):
# turned to the right
self.is_left = False
self.frame_count = 0
else:
# continue right
self.frame_count += 1
if ( frame_count >= self.max_frames ):
frame_count = 0
self.x += self.velocity
elif ( keys[pygame.K_a] and self.rect x > -20 ): # LEFT
if ( self.is_left ):
# continue left
self.frame_count += 1
if ( frame_count >= self.max_frames ):
frame_count = 0
else:
# turned to the left
self.is_left = True
self.frame_count = 0
self.x -= self.velocity
为简洁起见,我没有转换跳转功能。 您还需要对平台进行类似的更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.