python - Pygame 碰撞检测

标签 python pygame collision-detection collision

我的问题:

在我的游戏中,我想添加一些功能,例如双跳、墙跳等。
然而,我的碰撞检测遇到了问题,而且我似乎无法解决它。
问题是,当我的角色与地面碰撞时,它会记录碰撞。
然而,即使我在地面上,下一个刻度也不再记录碰撞。
这会在检测我是否与墙壁碰撞或者当前是否与地面碰撞等方面产生问题。
这会产生更多问题,因为当它没有检测到碰撞时,我的 y 速度会不断降低。
因此,我的玩家在地面上时的 y 速度不断增加,而不仅仅是 0。

示例:

正如您在左下角看到的,我的 y 速度在数字之间跳跃,如下所示:

0  
0  
0.3  
0.6  
0.9

然后一切重新开始。
我真正需要的是,当我在地面上时,这个值始终为 0,并且代码能够识别出我在地面上。
但事实并非如此,我不明白为什么,有人可以帮忙吗?

代码:

import pygame
from pygame import *

WIN_WIDTH = 800
WIN_HEIGHT = 640
HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30

def main():
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)
    #pygame.display.set_caption("Use arrows to move!")
    timer = pygame.time.Clock()

    up = down = left = right = space = False
    bg = Surface((32,32))
    bg.convert()
    bg.fill(Color("#0094FF"))
    entities = pygame.sprite.Group()
    player = Player(32, 32)
    platforms = []
    plants = []

    space_num = 0

    x = 0
    y = 0
    level = [
        "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                                          P",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                           PPPP     PPPPPPP",
        "P                                       PPPP",
        "P                                       PPPP",
        "P                                       PPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",
        "PPPPPPPPPPPPPPP           PPPPPPPPPPPPPPPPPP",]
    # build the level
    for row in level:
        for col in row:
            if col == "P":
                p = Platform(x, y)
                platforms.append(p)
                entities.add(p)
            if col == "E":
                e = ExitBlock(x, y)
                platforms.append(e)
                entities.add(e)
            if col == "p":
                p = Plant(x, y)
                plants.append(p)
                entities.add(p)
            x += 32
        y += 32
        x = 0

    total_level_width = len(level[0]) * 32
    total_level_height = len(level) * 32
    camera = Camera(complex_camera, total_level_width, total_level_height)
    entities.add(player)

    while 1:
        timer.tick(60)

        for e in pygame.event.get():
            if e.type == QUIT: raise SystemExit, "QUIT"
            if e.type == KEYDOWN and e.key == K_ESCAPE:
                raise SystemExit, "ESCAPE"
            if e.type == KEYDOWN and e.key == K_UP:
                up = True
            if e.type == KEYDOWN and e.key == K_DOWN:
                down = True
            if e.type == KEYDOWN and e.key == K_LEFT:
                left = True
            if e.type == KEYDOWN and e.key == K_RIGHT:
                right = True
            if e.type == KEYDOWN and e.key == K_SPACE:
                if space_num < 6:
                    space = True
                    space_num += 1

            if e.type == KEYUP and e.key == K_UP:
                up = False
            if e.type == KEYUP and e.key == K_DOWN:
                down = False
            if e.type == KEYUP and e.key == K_LEFT:
                left = False
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False
            if e.type == KEYUP and e.key == K_SPACE:
                space = False

        # draw background
        for y in range(20):
            for x in range(25):
                screen.blit(bg, (x * 32, y * 32))

        camera.update(player)

        # update player, draw everything else
        player.update(up, down, left, right, platforms, space)
        for e in entities:
            screen.blit(e.image, camera.apply(e))
        pygame.display.update()

class Camera(object):
    def __init__(self, camera_func, width, height):
        self.camera_func = camera_func
        self.state = Rect(0, 0, width, height)

    def apply(self, target):
        return target.rect.move(self.state.topleft)

    def update(self, target):
        self.state = self.camera_func(self.state, target.rect)

#def simple_camera(camera, target_rect):
#    l, t, _, _ = target_rect
#    _, _, w, h = camera
#    return Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)

def complex_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    l, t, _, _ = -l + HALF_WIDTH, -t+HALF_HEIGHT, w, h

    l = min(0, l)                           # stop scrolling left
    l = max(-(camera.width-WIN_WIDTH), l)   # stop scrolling right
    t = max(-(camera.height-WIN_HEIGHT), t) # stop scrolling bottom

    return Rect(l, t, w, h)

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class Player(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.xvel = 0
        self.yvel = 0
        self.onGround = False
        self.image = Surface((32,32))
        self.image.fill(Color("#0000FF"))
        self.image.convert()
        self.rect = Rect(400, 400, 32, 32)

    def update(self, up, down, left, right, platforms, space):
        if space:
            if not self.onGround:
                self.yvel = -12
            if self.onGround:
                self.yvel = 0
        else:
            if up:
                if self.onGround: self.yvel -= 10 # only jump if on the ground
            if down:
                pass
            if left:
                self.xvel = -8
            if right:
                self.xvel = 8
            if not self.onGround:
                self.yvel += 0.3 # only accelerate with gravity if in the air
                if self.yvel > 40: self.yvel = 40 # max falling speed
            if not(left or right):
                self.xvel = 0

            self.rect.left += self.xvel # increment in x direction
            self.collide(self.xvel, 0, platforms) # do x-axis collisions
            self.rect.top += self.yvel # increment in y direction
            self.onGround = False; # assuming we're in the air
            self.collide(0, self.yvel, platforms) # do y-axis collisions

    def collide(self, xvel, yvel, platforms):
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, ExitBlock):
                    pygame.event.post(pygame.event.Event(QUIT))
                if xvel > 0: self.rect.right = p.rect.left
                if xvel < 0: self.rect.left = p.rect.right
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.yvel = 0
                if yvel < 0: self.rect.top = p.rect.bottom


class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = Surface((32, 32))
        self.image.convert()
        self.image.fill(Color("#DDDDDD"))
        self.rect = Rect(x, y, 32, 32)

    def update(self):
        pass

class ExitBlock(Platform):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image = pygame.image.load("bush.png")

class Decoration(Entity):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class Plant(Decoration):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = Surface((64, 64))
        self.image.convert()
        #self.image = pygame.image.load("bush.png")
        self.rect = Rect(x, y, 64, 64)




if __name__ == "__main__":
    main()

最佳答案

看起来只要不按住空格,更新代码就会将你设置为在空中:

def update(self, up, down, left, right, platforms, space):
    if space:
    else:
        self.onGround = False; # assuming we're in the air
        self.collide(0, self.yvel, platforms) # do y-axis collisions

如果角色没有移动单个像素来重叠平台,而是恰好在平台上,那么 pygame 的碰撞代码也许不会检测到碰撞?在这种情况下,你会经历一个着陆循环,将 yvel 设置为 0。好吧,我们正在下降,0.3,下降,0.6,下降,0.9,下降...好吧,我们移动了 1 个像素,然后重叠,我们着陆了,将 yvel 设置为 0。然后从头开始重复。

关于python - Pygame 碰撞检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14449651/

相关文章:

Python 配置解析器 : how to work out options set in a specific section (rather than defaults)

Python游戏总是崩溃或卡住| pygame

python - pygame中的旋转命中框矩形

java - 给定 75 : android 时条件不会触发

python - Pandas:按行扩展数据帧,类似于 R 的 SurvSplit()

python - 如何访问 kivy 中不同类的小部件

python - 多处理策略-共享嵌套对象

python - 我无法让碰撞在 pygame 中工作

python - Pygame 在表面上绘图与直接在显示器上绘图

java - 当与 Android 中的图 block 碰撞时停止玩家