Pygame碰撞蒙版:精灵和地面

问题描述 投票:2回答:1

我正在开发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()函数中检测到冲突时,出现以下错误消息:

追踪(最近通话): 文件“ 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”,行215,在redraw_game_window中 如果pygame.sprite.spritecollide(头像,地面,False,pygame.sprite.collide_mask): spritecollide中的文件“ C:\ Users \ Pc \ AppData \ Roaming \ Python \ Python37 \ site-packages \ pygame \ sprite.py”,第1532行 返回[如果碰撞,则表示组中s的s(sprite,s)]TypeError:“地面”对象不可迭代

我尝试过的:

  • 使用矩形作为遮罩(产生相同的错误)

有人知道我在做什么错吗?

python pygame collision-detection
1个回答
1
投票

代码在非PyGame精灵上的对象上使用PyGame精灵库spritecollide()函数。如果要创建自己的精灵,应该添加并维护Rect对象,以使代码使用Rect.collide组函数。

但是将现有的类似Sprite的对象转换为正式的PyGame Sprite会更加容易和快捷。这意味着继承基Sprite类,并重写某些函数和成员变量。 使用Sprite类是(IMHO)最简单,最好的方法

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

为了简洁起见,我没有转换跳转功能。您还需要对Platform进行类似的更改。

© www.soinside.com 2019 - 2024. All rights reserved.