pygame在KEYUP时减速物体?
我正在用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 个回答
通常,角色的移动是和机器的速度无关的。在你的例子中,你不知道While循环每秒执行多少次,这取决于电脑的速度。所以首先,你应该使用pygame的时钟来计算每次调用move()之间的时间差。
myclock = pygame.Clock()
delta = myclock.tick()
当你有了时间差后,可以用一个距离公式来计算,比如这样:
position += speed * direction * delta
delta
是以毫秒为单位的,所以你需要根据这个来设置你的speed
。direction
的值会是-1或+1,这取决于当前按下的键。如果松开键,direction
就会变成0。
现在回到问题上。你需要稍微调整一下上面的内容。松开键时,direction
会减去一个小值。
然后检查一下direction
是否不是1或-1,如果是,就从direction
中再减去一个值。你每次循环都要这样做。这样的话,direction
会越来越小,看起来就像你的角色在减速一样。最好还要把你减去的值乘以delta
,这样在每台电脑上减速的效果都是一致的。
我的建议是:
去这个网站看看:http://karpathy.ca/phyces/tutorial1.php。
下载pygamehelper和startercode(我保证这会让你的生活简单很多)。
FPS(每秒帧数)是内置的,所以你不需要在你的移动逻辑中进行调整。
如果你想要更详细的解释,可以看看其他一些教程,另外如果你想要更酷的效果,可以使用向量库。
距离 = 速度 × 时间
与其通过 movex
或 movey
来改变位置,不如直接改变速度:
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()