Pygame,当玩家的头撞到方块(瓷砖)时如何进行碰撞

Pygame, how to make collision when the player hits its head into a block (tile)

当玩家的头撞到方块时,我不知道如何进行碰撞。 当它用头从底部撞到方块时,它就会向上“传送”。 当玩家水平击中方块时也会发生同样的事情,所以如果 self.xself.player_rect.x 击中方块,它会将玩家向上传送。

所以基本上,如果玩家的头撞到方块上,那么玩家就需要倒下。 如果它水平击中它,那么玩家 X,那么玩家需要停止移动。

我试过这样做:

#COLLISION WITH BLOCKS
for tile in self.tile_list:
    if tile[1].colliderect(self.player_rect):
        if self.player_rect.y > 0:
            self.player_rect.bottom = tile[1].top
            self.y = self.player_rect.y
        elif self.player_rect.y < 0:
            self.player_rect.top = tile[1].bottom
            self.y = self.player_rect.y

但没有帮助。 tile_list 是实际保存瓦片的列表。我循环遍历该列表以检查所有瓦片(块)并进行碰撞。但是我的玩家可以站在方块(方块)上,但我想让它变得更好,所以我只希望我的玩家在碰到方块时不要传送's.y 或 x.

main.py:

import pygame as pg
import sys
import os

from pygame import key
from mapdata import game_map_data

#ASSETS
GRASS_IMAGE = pg.image.load(r'C:\Users\user\Desktop\pygame-tilemap.11.2022\assets\platform.jpg')
sky = pg.image.load(r'C:\Users\user\Desktop\pygame-tilemap.11.2022\assets\sky.png')
CONTINUE = True

#CONSTANT VARIABLES
#WIDTH;HEIGHT
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 598
PLAYER_WIDTH = 20
PLAYER_HEIGHT = 20
#COLORS
COLOR_DARKBLUE = 'darkblue'
COLOR_RED = 'red'
#WINDOW
WINDOW = pg.display.set_mode((WINDOW_WIDTH,WINDOW_HEIGHT))

sky = pg.transform.scale(sky,(800,599))

class Player(object):
    def __init__(self,x,y,width,height,jumpRange):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.isJump = False
        self.jumpRange = jumpRange

    def Draw(self):
        self.player = pg.image.load(r'C:\Users\user\Desktop\pygame-tilemap.11.2022\assets\player.png')
        self.player = pg.transform.scale(self.player,(PLAYER_WIDTH,PLAYER_HEIGHT))
        self.player_rect = self.player.get_rect()
        WINDOW.blit(self.player,dest=(self.x,self.y))
        self.player_rect.x = self.x
        self.player_rect.y = self.y

    #COLLISION WITH BLOCKS
    for tile in self.tile_list:
        if tile[1].colliderect(self.player_rect):
            if self.player_rect.y > 0:
                self.player_rect.bottom = tile[1].top
                self.y = self.player_rect.y
            elif self.player_rect.y < 0:
                self.player_rect.top = tile[1].bottom
                self.y = self.player_rect.y
                
    def handle_keys(self,speed,vel_y):
        keys = pg.key.get_pressed()
        self.speed = speed
        self.vel_y = vel_y
        if keys[pg.K_RIGHT]:
            if CONTINUE == True:
                self.x += speed
        if keys[pg.K_LEFT]:
            if CONTINUE == True:
                self.x -= speed


    def jump(self,jumpRange):
        if self.isJump == True:
            if self.jumpRange >= -11:
                neg = 1
                if self.jumpRange < 0:
                    neg = -1
                self.y -= self.jumpRange**2 * 0.1 * neg
                self.jumpRange -= 1
            else:
                self.isJump = False
                self.jumpRange = jumpRange

    ###########
    ##TILEMAP##
    ###########

    def tile(self,data,tile_size,img_size):
        self.tile_list = []

        #SAVING TILES IN A LIST

        row_count = 0
        self.tile_size = tile_size
        self.img_size = img_size

        for row in data:
            col_count = 0
            for tile in row:
                if tile == 1:
                    self.rect_img = img.get_rect()
                    self.rect_img.x = col_count * tile_size
                    self.rect_img.y = row_count * tile_size
                    tile = (img,self.rect_img)
                    self.tile_list.append(tile)
                col_count += 1
            row_count += 1

    #DRAWING TILES FROM THE LIST
    def draw_tile(self):
        for tile in self.tile_list:
            WINDOW.blit(tile[0], tile[1])



#FPS
clock = pg.time.Clock()


game_map_data = game_map_data


#PLAYER
player = Player(x=30,y=500,width=PLAYER_WIDTH,height=PLAYER_HEIGHT,jumpRange=11)


img_size = 17
img = pg.transform.scale(GRASS_IMAGE,(img_size,img_size))
gamemap = player.tile(game_map_data,tile_size=17,img_size=20)



while True:
    FPS = 60
    pg.display.update()
    clock.tick(FPS)

    
    for event in pg.event.get():
        if event.type == pg.QUIT:
            sys.exit()
        elif event.type == pg.KEYDOWN:
            if event.key == pg.K_SPACE:
                # Start to jump by setting isJump to True.
                player.isJump = True

    SKY_POSITION = (0,0)

    WINDOW.blit(sky,SKY_POSITION)
    player.draw_tile()
    player.jump(jumpRange=11)
    player.Draw()
    player.handle_keys(speed=3,vel_y=3)
    pg.display.update()
    pg.display.flip()

如果您想测试代码,请创建 2 个文件,mapdata.py 和 main.py,并更改照片(纹理)

mapdata.py:

game_map_data = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
]

我认为在使用 pygame 时,如果使用 pygame sprite class :

会容易得多

您可能需要此功能进行碰撞。

# this function is used when there is one object collides with many objects
if pygame.sprite.spritecollide(player,power_pellets,false):
    # do something 

您可以使用的另一个函数是:groupcollide(...

#this function is used when a group of objects collide with other group of objects.
collide_with_wall = pygame.sprite.groupcollide(smart_ghost, walls, False, False)
if collide_with_wall:
    # do something

要使用pygame精灵,你需要从pygam精灵继承它class

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image_origin = pacman_img  # use this technique when rotate many times
        self.image_origin.set_colorkey(BLACK)
        self.image = self.image_origin.copy()
        self.rect = self.image.get_rect()  # second mandatory
def update(self): # 
# do something here

转到此 youtube 以了解有关与 pygame 精灵碰撞的更多信息:https://youtu.be/Eltz-XJMxuU

相信我,这个频道非常适合设计游戏;导师还建议您可以从哪里获得免费资源(游戏图像、图标、音效等...)