0

我对这个网站真的很陌生,所以请多多包涵。我目前正在为一个学校项目开发类似涂鸦跳跃的游戏,但我无法让玩家始终如一地上下跳跃。问题是如果跳跃的命令执行超过几秒钟,它就会开始变得不一致(没有降落在正确的高度,跳跃距离减小......)。我能想到的唯一可能导致这种不一致的是clock.tick()函数。请注意,您必须按空格键才能启动该过程。任何关于改进游戏的建议以及关于单位碰撞和让屏幕随着玩家的进步而“向上移动”的提示也是受欢迎的。再次道歉,因为我是 pygame 和这个网站的绝对新手。

bif = "Background.jpg"
mif = "Ball.png"
import pygame, sys
import random
import os
from pygame.locals import*
import time

class Ball(object):

    def __init__(self):
        x = 320
        y = 460
        self.dx = 0
        self.dy = 0
        self.g = 0
        self.rect = pygame.Rect(x,y,16,16)

    def update(self):
        self.rect.x += self.dx
        self.rect.y += self.dy
        self.dx = 0
        self.dy = 0

    def aground(self):
        if self.g <= 500:
            return True
        elif self.g > 500:
            return False

    def moveleft(self):
        if self.rect.x > 640:
            self.rect.x = 0
        elif self.rect.x < 0:
            self.rect.x = 640
            self.dx = (-(speed*seconds))
            self.update()

    def moveright(self):
        if self.rect.x > 640:
            self.rect.x = 0
        elif self.rect.x < 0:
            self.rect.x = 640
        self.dx = (speed*seconds)
        self.update()

    def jump(self):
        if self.g == 1000:
            self.g = 0
        if self.aground() == True:
            self.dy = -(speed*seconds)
            self.g += 1
            self.update()
        elif self.aground() == False:
            self.dy = (speed*seconds)
            self.g += 1
            self.update()


pygame.init()

screen = pygame.display.set_mode((640,480),0,32)
background = pygame.image.load(bif).convert()
ball = pygame.image.load(mif).convert_alpha()
x = 0
a = 0
y = 480
player = Ball()
clock = pygame.time.Clock()
speed = 1000
j = 0
start = 0
init = 0

while True:

    screen.blit(background,(0,0))

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    key = pygame.key.get_pressed()
    if key[pygame.K_LEFT]:
        player.moveleft()
    if key[pygame.K_RIGHT]:
        player.moveright()
    if key[pygame.K_SPACE]:
        init = 1

    if init == 1:
        player.jump()

    milli = clock.tick()
    seconds = milli/1000.

    if a%10 == 0:
        pygame.draw.rect(background,(140,240,130), Rect((x,y),(70,30)))

    a +=12
    x = random.randint(0,640)
    y -= 15

    pygame.draw.rect(screen,(255, 200, 0),player.rect)
    pygame.display.update()
4

1 回答 1

1

正如 Patashu 所说,使用重力系统来处理跳跃会更有意义。以下是我自己的一个 pygame 项目中的一些片段,让您了解它是如何工作的:

 def update(self):

        self.find_state()
        self.find_move()
        self.do_move()

        if not(self.onGround):      # player is in the air
            self.playerForces.append(Player.gravity)
            if self.primary_state == PlayerState.JUMPFORWARD:
                self.playerVel[0] = self.walkingSpeed * (-1 if self.facing_left else 1)
            elif self.primary_state == PlayerState.JUMPBACKWARD:
                self.playerVel[0] = self.backSpeed * (1 if self.facing_left else -1)
        else:                       # player is on the ground
            if self.secondary_state == PlayerState.WALKING:
                self.playerVel[0] = self.walkingSpeed * (-1 if self.facing_left else 1)
            elif self.secondary_state == PlayerState.BACKING:
                self.playerVel[0] = self.backSpeed * (1 if self.facing_left else -1)
            else:
                self.playerVel[0] = 0

            # first frame of jumping
            if self.primary_state == PlayerState.JUMPING:
                self.playerForces.append([0, -self.jumpHeight])
                self.onGround = False

        self.apply_forces()

        self.playerForces = list() # after applying forces for this frame, clear the list

您可以看到我的Player班级有一个名为onGround. 这被设置为False玩家跳跃时,用于确定是否对Player物体施加重力。通过这样做,该Player.jumpHeight值可能从 10 开始(这意味着每帧向上移动 10 个像素),并且在空中的每一帧,该Player值都会减少一定的量(重力值)。最终,重力将克服跳跃的力,Player并将开始返回地面。

在我的代码的另一部分中,我有一个pygame.Rect对象用于Player对象和“地面”。我检查它们是否发生了碰撞,如果发生了碰撞,我将Player'onGround标志改回,True以便停止对其施加重力:

 if playerRect.colliderect(ground):
        collisionShift = gameUtils.getMinTransVect(playerRect, ground)
        player1.playerForces.append([0, collisionShift[1]])
        player1.onGround = True
        player1.playerVel[1] = 0

你可能从中可以看出,我还Player对碰撞后物体的位置做了一个小的“修正”。这确保了每次Player“落地”在地面上,它根本不会“沉没”。如果在一帧中一个对象在一个方向上移动的像素多于两个可碰撞对象之间的像素,则可能会发生这种情况(因此,如果Player对象与地面之间有 4 个像素的间隙,并且Player在一帧中向下移动了 8 个像素。在那情况下,如果您Player在检测到碰撞后简单地停止移动,它将有点沉入地下)。

于 2013-05-02T14:19:21.307 回答