Как увеличить скорость с течением времени, пока нажата клавиша? - PullRequest
1 голос
/ 07 марта 2019

Я делаю игру в пигам.У меня есть персонаж, положение которого изменяется следующим образом (есть еще 3 для L, R и D):

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

Это перемещает персонажа на 10 пикселей каждые 60 мс.Я хотел бы написать функцию, которая увеличивает скорость при более длительном нажатии клавиши, а затем сбрасывает скорость после отпускания клавиши.Я пробовал это:

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

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

Это только увеличивает параметр на 2, но не увеличивает его при более длительном нажатии клавиши, и я не мог понять, как сбросить переменную в ее начальное состояние после отпусканияключ.Как бы я это реализовал?Спасибо.

Ответы [ 2 ]

1 голос
/ 08 марта 2019

Вот небольшой пример падающего спрайта в реальном времени.Нажатие Вверх уменьшает скорость, а Вниз увеличивает ее.Я, вероятно, слишком усложнил пример, но если один раз нажать Up , цветочный горшок упадет.

Я реализовал это как объект, который наследуется от PyGame класс спрайтов .Одной из приятных вещей, которые приносит использование объекта, является возможность сохранять все атрибуты элемента (например, местоположение, растровое изображение, скорость и т. Д.) внутри объекта.Это означает, что ваша программа не замусорена глобальными переменными для , и , .Спрайт PyGame также содержит множество полезных и элегантных функций.Конечно, в начале это будет немного дополнительной работой, но позже процесс программирования будет намного более плавным и более легким .(Если вы не хотите использовать объекты, по крайней мере, поместите все в словарь Python или что-то подобное, чтобы сохранить все вместе {"x":0, "y":0, "speed":3} и т. Д.)

В любом случае ... важной частью кода является FallingSprite.update().Это занимает время между последним вызовом update() и now, используя его для вычисления количества пикселей, которое объект должен переместить, учитывая его скорость.В коде используется простое вычисление с постоянной скоростью, а не правильное вычисление падения под действием силы тяжести, но формула может быть просто заменена. Разница рассчитывается, а затем применяется к x & y координатамспрайта rect (который устанавливает позицию на экране).Если объект падает внизу экрана (или сверху), он «оборачивается», чтобы начать снова.

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

Я понимаю,технически это кактусовый горшок , пожалуйста, не пишите.

1 голос
/ 07 марта 2019

Вы начали с правильного подхода, но проблема в том, что вы сохраняете скорость в локальной переменной внутри функции.Эта переменная будет сбрасываться каждый раз, когда вы вызываете функцию.

Вместо этого вы должны сохранить скорость где-то еще:

# 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. , что он инициализируется в той же функции, в которой вы его используете, поэтому он доступен для функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...