PYGAME:碰撞无法正常工作。玩家和平台表现不佳。救命,这里是python新手

PYGAME:碰撞无法正常工作。玩家和平台表现不佳。救命,这里是python新手,python,oop,pygame,sprite,game-physics,Python,Oop,Pygame,Sprite,Game Physics,这是我在stackoverflow中的第一个问题。我3个月前开始学习python,我正在用精灵构建一个平台游戏。我必须隔离问题,所以我只发布问题所在的部分 每当正方形降落在任何平台上时,都会检测到碰撞,但正方形实际上向下穿过平台约10像素(在碰撞期间),然后又向上移动,并在平台顶部稳定下来 如果将FPS调整为2,可以更好地看到效果。 我怎样才能解决这个问题?我记得以前做过一个游戏,但是没有在“x”轴(摩擦力)和“y”轴(重力)上使用加速度,只是快速停止方块运动(左/右/上/下)检测碰撞,方块从未

这是我在stackoverflow中的第一个问题。我3个月前开始学习python,我正在用精灵构建一个平台游戏。我必须隔离问题,所以我只发布问题所在的部分

每当正方形降落在任何平台上时,都会检测到碰撞,但正方形实际上向下穿过平台约10像素(在碰撞期间),然后又向上移动,并在平台顶部稳定下来

如果将FPS调整为2,可以更好地看到效果。 我怎样才能解决这个问题?我记得以前做过一个游戏,但是没有在“x”轴(摩擦力)和“y”轴(重力)上使用加速度,只是快速停止方块运动(左/右/上/下)检测碰撞,方块从未穿过平台

这是一个孤立的问题:

import pygame as pg
import random

WIDTH = 900
HEIGHT = 600
NAME = "square"
FPS = 60

green = (0, 150, 0)
white = (255, 255, 255)
black = (0, 0, 0)

class Platform(pg.sprite.Sprite):
    def __init__(self, x, y, width, height, color):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((width, height))
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

class Player(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((40, 40))
        self.image.fill(black)
        self.rect = self.image.get_rect()
        self.rect.center = (WIDTH / 2, HEIGHT / 2)
        self.posx = WIDTH / 2
        self.posy = HEIGHT * 0.10
        self.velx = 0
        self.vely = 0
        self.accx = 0
        self.accy = 0
        self.jumping = False
        self.jump_go = False

    def jump(self):
        if self.jumping == False:
            self.jumping = True
            self.vely = -25

    def update(self):

        self.accx = 0    #FRICTION
        self.accy = 1    #GRAVITY

        keys = pg.key.get_pressed()

        if keys[pg.K_RIGHT]:
            self.accx = 1
        if keys[pg.K_LEFT]:
            self.accx = -1

        if self.vely != 0:
            self.jump_go = False

        #MOVEMENT IN X:

        self.accx = self.accx + (self.velx * (-0.10))
        self.velx = self.velx + self.accx
        self.posx = self.posx + self.velx
        self.rect.x = self.posx

        if abs(self.velx) < 0.5:
            self.velx = 0

        #MOVEMENT IN Y:

        self.accy = self.accy + (self.vely * (-0.05))
        self.vely = self.vely + self.accy
        self.posy = self.posy + self.vely
        self.rect.y = self.posy

        #IF PLAYER FALLS TO EDGE OF SCREEN:

        if self.posy > HEIGHT:
            self.posy = 0
        if self.posx < 0:
            self.posx = WIDTH
        if self.posx > WIDTH:
            self.posx = 0


class Game:
    def __init__(self):
        pg.init()
        pg.mixer.init()
        pg.font.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        self.clock = pg.time.Clock()
        self.running = True

    def new(self):
        self.all_sprites = pg.sprite.Group()
        self.all_platforms = pg.sprite.Group()

        for i in range(3):
            self.platform = Platform(random.randint(0, WIDTH), random.randint(HEIGHT * .15,
                                     HEIGHT - 25), random.randint(100, 300), 50, green)
            self.all_platforms.add(self.platform)
            self.all_sprites.add(self.platform)

        self.player = Player()
        self.all_sprites.add(self.player)
        self.run()

    def run(self):
        self.playing = True
        while self.playing:
            self.clock.tick(FPS)
            self.eventos()
            self.update()
            self.draw()

    def eventos(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                if self.playing:
                    self.playing = False
                self.running = False
            if event.type == pg.KEYDOWN:
                if self.player.jump_go:
                    if event.key == pg.K_a:
                        self.player.jump()

    def update(self):
        self.all_sprites.update()

        # Check if player hit platfom:
        if self.player.vely > 0:
            hits = pg.sprite.spritecollide(self.player, self.all_platforms, False)
            if hits:
                for hit in hits:
                    if self.player.rect.top < hit.rect.top:
                        self.player.posy = hit.rect.top - self.player.rect.height
                        self.player.vely = 0
                        self.player.jumping = False
                        self.player.jump_go = True

    def draw(self):
        self.screen.fill(white)
        self.all_sprites.draw(self.screen)
        pg.display.flip()

g = Game()
while g.running:
    g.new()

pg.quit()
将pygame导入为pg
随机输入
宽度=900
高度=600
NAME=“square”
FPS=60
绿色=(0,150,0)
白色=(255,255,255)
黑色=(0,0,0)
课堂讲台(第三页:雪碧、雪碧):
定义初始值(自、x、y、宽度、高度、颜色):
精灵精灵。精灵。精灵初始(自我)
self.image=pg.Surface((宽度、高度))
self.image.fill(颜色)
self.rect=self.image.get_rect()
self.rect.x=x
自校正y=y
职业玩家(第三页精灵):
定义初始化(自):
精灵精灵。精灵。精灵初始(自我)
self.image=pg.Surface((40,40))
self.image.fill(黑色)
self.rect=self.image.get_rect()
self.rect.center=(宽度/2,高度/2)
self.posx=宽度/2
self.posy=高度*0.10
self.velx=0
self.vely=0
self.accx=0
self.accy=0
自我跳跃=错误
self.jump\u go=False
def跳转(自):
如果self.jumping==False:
self.jumping=True
self.vely=-25
def更新(自我):
self.accx=0#摩擦力
self.accy=1#重力
keys=pg.key.get_pressed()
如果键[pg.K_RIGHT]:
self.accx=1
如果键[pg.K_左]:
self.accx=-1
如果自作主张!=0:
self.jump\u go=False
#X中的运动:
self.accx=self.accx+(self.velx*(-0.10))
self.velx=self.velx+self.accx
self.posx=self.posx+self.velx
self.rect.x=self.posx
如果abs(自粘性)小于0.5:
self.velx=0
#Y方向的运动:
self.accy=self.accy+(self.vely*(-0.05))
self.vely=self.vely+self.accy
self.posy=self.posy+self.voly
self.rect.y=self.posy
#如果玩家跌落到屏幕边缘:
如果self.posy>高度:
self.posy=0
如果self.posx<0:
self.posx=宽度
如果self.posx>宽度:
self.posx=0
班级游戏:
定义初始化(自):
第init页()
pg.mixer.init()
pg.font.init()
self.screen=pg.display.set_模式((宽度、高度))
self.clock=pg.time.clock()
self.running=True
def新(自我):
self.all_sprite=pg.sprite.Group()
self.all_platforms=pg.sprite.Group()
对于范围(3)中的i:
self.platform=平台(random.randint(0,宽度),random.randint(高度*.15,
高度-25),随机。随机数(100300),50,绿色)
self.all_platforms.add(self.platform)
self.all_sprites.add(self.platform)
self.player=player()
self.all_精灵添加(self.player)
self.run()
def运行(自):
自弹=真
自娱自乐时:
自我时钟滴答声(FPS)
self.eventos()
self.update()
self.draw()
def事件(自):
对于pg.event.get()中的事件:
如果event.type==pg.QUIT:
如果自己玩:
自我表现=错误
self.running=False
如果event.type==pg.KEYDOWN:
如果self.player.jump_go:
如果event.key==pg.K_a:
self.player.jump()
def更新(自我):
self.all_sprites.update()
#检查玩家是否击中平台:
如果self.player.vely>0:
hits=pg.sprite.spritecollide(self.player,self.all_platforms,False)
如果点击:
点击率:
如果self.player.rect.top
在碰撞检查中,您会得到所有的
命中次数
,然后检查每个
命中次数

if self.player.rect.top < hit.rect.top:
导致您看到的所描述的“通过和跳起”效果

您可以通过更改

if self.player.rect.top < hit.rect.top:

减少“通过”效应。

我认为您应该将碰撞检测移动到
Player.update()
Player.jump()
函数

这背后的原因是碰撞检测的复杂性。每次
update()
您的播放器都会在二维空间中移动一定数量的像素。但是让我们只考虑一个维度,让它更简单…… 假设你的播放器向右移动了5个像素(
+x
),而障碍物距离你3个像素远。显然,它将与2个像素的重叠发生碰撞。那么在这种情况下会发生什么呢?这取决于你的游戏逻辑,但在大多数情况下,玩家应该停止一个只有+3像素,休息的障碍物旁边。这是一个知道运动方向和尺寸的简单计算
if self.player.rect.top < hit.rect.top:
    if (self.player.rect.top - self.player.rect.height) < hit.rect.top:
 self.bottom_quart = self.rect.y + (self.rect.height/2)
 def update(self):
     self.all_sprites.update()

     #Check if player hit platfom:
     if self.player.vely > 0:
         hits = pg.sprite.spritecollide(self.player, self.all_platforms, False)
         if hits:
             for hit in hits:

                 if self.player.rect.bottom > hit.rect.top > self.player.rect.top 
                    and self.player.bottom_quart < hit.rect.top:

                         self.player.rect.bottom = hit.rect.top
                         self.player.posy = hit.rect.top - self.player.rect.height
                         self.player.vely = 0
                         self.player.jumping = False
                         self.player.jump_go = True
  self.player.rect.bottom = hit.rect.top
  self.player.posy = hit.rect.top - self.player.rect.height
   self.bottom_quart = self.rect.y + (self.rect.height/2)