pygame在KEYUP时减速物体?

0 投票
3 回答
2415 浏览
提问于 2025-04-17 19:23

我正在用pygame制作一个简单的游戏。我已经导入了一个角色的图片,并且可以自由移动他。我想知道如何让角色在

event.type == KEYUP:

时慢慢停下来。也就是说,当我松开按键时,角色会在松开按键后慢慢移动,比如说移动50个像素,然后再慢慢停下来。

我试过几种不同的方法,但似乎都没有效果。下面是我的代码。任何帮助都非常感谢 =]

bg="bg.jpg"
staticCharacter="toon.png"

import pygame, sys, time
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((640,360),0,32)

background=pygame.image.load(bg).convert()

staticToon = pygame.image.load(characterMid).convert_alpha()

x = 0
y = 0
movex = 0
movey = 0

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

        if event.type == KEYDOWN:
            if event.key == K_LEFT:
                movex = -0.20 
            elif event.key == K_RIGHT:
                movex = +0.20        
            elif event.key == K_UP:
                movey = -0.20       
            elif event.key == K_DOWN:
                movey = +0.20

        if event.type == KEYUP:
            if event.key == K_LEFT:
                movex = 0           
            elif event.key == K_RIGHT:
                movex = 0                    
            elif event.key == K_UP:
                movey = 0         
            elif event.key == K_DOWN:
                movey = 0


    x += movex
    y += movey

    if x > 560:
        x = 560
    if y > 280:
        y = 280
    if x < 0:
        x = 0
    if y < 0:
        y = 0

screen.blit(background,(0,0))
screen.blit(staticToon,(x,y))
pygame.display.update()

3 个回答

0

通常,角色的移动是和机器的速度无关的。在你的例子中,你不知道While循环每秒执行多少次,这取决于电脑的速度。所以首先,你应该使用pygame的时钟来计算每次调用move()之间的时间差。

myclock = pygame.Clock()
delta = myclock.tick()

当你有了时间差后,可以用一个距离公式来计算,比如这样:

position += speed * direction * delta

delta是以毫秒为单位的,所以你需要根据这个来设置你的speeddirection的值会是-1或+1,这取决于当前按下的键。如果松开键,direction就会变成0。

现在回到问题上。你需要稍微调整一下上面的内容。松开键时,direction会减去一个小值。

然后检查一下direction是否不是1或-1,如果是,就从direction中再减去一个值。你每次循环都要这样做。这样的话,direction会越来越小,看起来就像你的角色在减速一样。最好还要把你减去的值乘以delta,这样在每台电脑上减速的效果都是一致的。

0

我的建议是:
去这个网站看看:http://karpathy.ca/phyces/tutorial1.php
下载pygamehelper和startercode(我保证这会让你的生活简单很多)。
FPS(每秒帧数)是内置的,所以你不需要在你的移动逻辑中进行调整。
如果你想要更详细的解释,可以看看其他一些教程,另外如果你想要更酷的效果,可以使用向量库。

1

距离 = 速度 × 时间

与其通过 movexmovey 来改变位置,不如直接改变速度:

delta = {
    pygame.K_LEFT: (-20, 0),
    pygame.K_RIGHT: (+20, 0),
    pygame.K_UP: (0, -20),
    pygame.K_DOWN: (0, +20),  
    }
...

elif event.type == pygame.KEYDOWN:
    deltax, deltay = delta.get(event.key, (0, 0))
    ball.speed[0] += deltax
    ball.speed[1] += deltay

现在,为了让物体(在我下面的例子中是一个球)减速,可以添加一些摩擦力:

    ball.speed[0] *= 0.95
    ball.speed[1] *= 0.95  

这会在每次循环中稍微减少速度。

让物体移动的距离等于 速度 × 时间。为了简单起见,我们就把时间的变化设为1。

self.rect = self.rect.move(self.speed)

下面是一个可以运行的例子:(只需为 staticCharacter 添加正确的路径。)

import sys
import pygame
import os

'''
Based on http://www.pygame.org/docs/tut/intro/intro.html
Draws a red ball bouncing around in the window.
Pressing the arrow keys moves the ball
'''

staticCharacter = "toon.png"

delta = {
    pygame.K_LEFT: (-20, 0),
    pygame.K_RIGHT: (+20, 0),
    pygame.K_UP: (0, -20),
    pygame.K_DOWN: (0, +20),  
    }

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) 
        self.image = pygame.image.load(staticCharacter)
        self.rect = self.image.get_rect()
        self.speed = [2, 2]
        self.area = pygame.display.get_surface().get_rect()
    def update(self):
        self.rect = self.rect.move(self.speed)
        if self.rect.left < 0 or self.rect.right > self.area.width:
            self.speed[0] = -self.speed[0]
        if self.rect.top < 0 or self.rect.bottom > self.area.height:
            self.speed[1] = -self.speed[1]

class Main(object):
    def __init__(self):
        self.setup()
    def setup(self):
        pygame.init()
        size = (self.width, self.height) = (640,360)
        self.black = (0, 0, 0)
        self.screen = pygame.display.set_mode(size, 0, 32)
        self.ball = Ball()
        self.setup_background()
    def setup_background(self):
        self.background = pygame.Surface(self.screen.get_size())
        self.background = self.background.convert()
        self.background.fill(self.black)
        self.screen.blit(self.background, (0, 0))
        pygame.display.flip()
    def draw(self):
        self.screen.blit(self.background, (0, 0))
        self.screen.blit(self.ball.image, self.ball.rect)
        pygame.display.flip()
    def event_loop(self):
        ball = self.ball
        while True:
            for event in pygame.event.get():
                if ((event.type == pygame.QUIT) or 
                    (event.type == pygame.KEYDOWN and 
                     event.key == pygame.K_ESCAPE)):
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    deltax, deltay = delta.get(event.key, (0, 0))
                    ball.speed[0] += deltax
                    ball.speed[1] += deltay
            ball.speed = [0.99*s for s in ball.speed]
            ball.update()
            self.draw()
            pygame.time.delay(10)

if __name__ == '__main__':
    app = Main()
    app.event_loop()

撰写回答