按键被按下时如何增加速度变量?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按键被按下时如何增加速度变量?相关的知识,希望对你有一定的参考价值。

我正在玩pygame游戏。我有一个角色的位置被改变了(L,R和D还有3个):

    if keys[pygame.K_UP]:
        y -= 10

这会使角色每60毫秒移动10个像素。我想写一个函数,按下按键的时间越长,然后在释放按键后重置速度。我试过这个:

def speed(velocity):
velocity *= 2
return velocity

if keys[pygame.K_UP]:
    y -= speed(10)

这只会使参数增加2,但按下按键的时间越长,它就不会增加,我无法弄清楚如何在释放按键后将变量重置为初始状态。我该如何实现?谢谢。

答案

这是一个实时下降精灵的小例子。按向上可降低速度,向下可增加速度。我可能过于复杂的例子,但如果一个人推高了足够的次数,花盆就会掉下来。

我已经将它实现为继承自PyGame sprite class的对象。使用对象带来的好处之一是能够在对象内保留项目的所有属性(如位置,位图,速度等)。这意味着您的程序不会出现这种情况的全局变量。 PyGame精灵还带来了许多有用和优雅的功能。当然,在开始时它是一些额外的工作,但稍后,编程进度将更加顺畅和容易。 (如果你不想使用对象,至少把所有内容都放入python字典或类似的东西,以便将它们全部保存在一起{"x":0, "y":0, "speed":3}等)

无论如何......代码的重要部分是FallingSprite.update()。这需要花费最后一次调用update()now之间的时间,使用它来计算对象应该移动多少像素,给定它的速度。该代码使用简单的恒定速度计算,而不是适当的重力下降计算,但公式可以只是交换。计算差异,然后应用于精灵的xyrect坐标(其中在屏幕上设置位置)。如果物体落在屏幕底部(或顶部),它会“缠绕”以重新开始。

import pygame
import time
import sys

# Window size
WINDOW_WIDTH  = 400
WINDOW_HEIGHT = 400
# background colour
SKY_BLUE      = (161, 255, 254)


class FallingSprite( pygame.sprite.Sprite ):
    """ A falling flower-pot sprite.  Falls at a given velocity in real-time """
    def __init__( self ):
        pygame.sprite.Sprite.__init__( self )
        self.image       = pygame.image.load("flower_pot.png").convert_alpha()
        self.rect        = self.image.get_rect()
        self.rect.center = ( WINDOW_WIDTH//2, -50 )
        self.fall_speed  = 150 # pixels / second
        self.image_height= self.image.get_rect().height
        self.last_update = int( time.time() * 1000.0 )

    def update( self ):
        # There should have been movement since the last update
        # calculate the new position
        time_now    = int( time.time() * 1000.0 )
        time_change = time_now - self.last_update             # How long since last update?
        # If we're moving, and time has passed
        if ( self.fall_speed != 0 and time_change > 0 ):
            distance_moved   = time_change * abs( self.fall_speed ) / 1000
            now_x, now_y     = self.rect.center               # Where am I, right now
            # Fall down (or up)
            if ( self.fall_speed > 0 ):
                updated_y = now_y + distance_moved
            else:
                updated_y = now_y - distance_moved
            # Did we fall off the bottom of the screen?
            if ( updated_y > WINDOW_HEIGHT + self.image_height ):
                updated_y = -self.image.get_rect().height     # move to just above top of screen
            # ... or off the top?
            elif ( updated_y < 0 - self.image_height ):
                updated_y = WINDOW_HEIGHT + self.image_height # move to just below screen
            # Reposition the sprite
            self.rect.center = ( now_x, updated_y )
        self.last_update = time_now

    def adjustSpeed( self, amount ):
        self.fall_speed += amount

    def stop( self ):
        self.fall_speed  = 0



### MAIN
pygame.init()
WINDOW    = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )
pygame.display.set_caption("Flowerpot")

# Add some sprites
FALLERS   = pygame.sprite.Group()   # a group, for a single sprite
flower_pot_sprite = FallingSprite()
FALLERS.add( flower_pot_sprite )


clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.VIDEORESIZE ):
            WINDOW_WIDTH  = event.w
            WINDOW_HEIGHT = event.h
            WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )

    # Movement keys
    keys = pygame.key.get_pressed()
    if ( keys[pygame.K_UP] ):
        flower_pot_sprite.adjustSpeed( -5 ) 
        print( "slower... ", end='' )
        sys.stdout.flush()

    elif ( keys[pygame.K_DOWN] ):
        flower_pot_sprite.adjustSpeed( 5 )  
        print( "faster! ", end='' )
        sys.stdout.flush()


    # Move the flower-pot, did it hit anything?
    FALLERS.update() # re-position the flower-pot

    # Re-draw the screen
    WINDOW.fill( SKY_BLUE )
    FALLERS.draw( WINDOW )    # draw the flower-pot
    pygame.display.flip()
    # Update the window, but not more than 60fps
    clock.tick_busy_loop( 60 )

pygame.quit()

flower_pot.png

我意识到这在技术上是一个仙人掌锅,请不要写。

另一答案

您已经开始使用正确的方法,但问题是您将速度存储在函数内的局部变量中。每次调用该函数时,该变量都将被重置。

相反,你应该在其他地方存储速度:

# Somewhere earlier in the program, eg. before your main loop
# Store the initial speed in a variable
base_speed = 10
# Initialise current speed to initial speed
speed = base_speed

然后在检查按键是否按下时,您可以执行以下操作:

if keys[pygame.K_UP]:
    y -= speed
    # Increase speed for the next round
    speed *= 2
else:
    # Did not press the key this time
    # Reset current speed to the initial speed (10, stored in the variable base_speed)
    speed = base_speed

这种解决方案的重要部分是

  1. speed在您正在进行检查的任何循环之前初始化,因此每次进入循环时它都不会被重置
  2. 它是在你正在使用它的同一个函数中初始化的,因此函数可以访问它

以上是关于按键被按下时如何增加速度变量?的主要内容,如果未能解决你的问题,请参考以下文章

FPGA培训专家 V3学院带你学习 按键消抖 和 边缘检测

如何使用 GetAsyncKeyState 查看按键被按下了 x 秒

按键消抖,矩阵键盘原理和矩阵键盘的仿真模型

按键消抖,矩阵键盘原理和矩阵键盘的仿真模型

jquery键盘事件及keycode大全

JavaScript键盘鼠标事件处理