Pygame - Дрейф движения - PullRequest
1 голос
/ 16 мая 2019

В настоящее время у меня есть объект, у которого есть код, который вращает его вокруг своего центра и перемещает его (изменяя значения pos).

Однако я хочу сделать так, чтобы при нажатии стрелки вверх онбудет ускоряться в направлении, обращенном к нему, и когда он отпущен, он снова будет замедляться обратно до 0. В коде я использую значение dt для изменения во времени.

Я пытался синхронизировать время, когда кнопканажмите и отпустите и используйте это значение dt; при использовании этого метода значение dT может быть отрицательным.Я также думаю, что это не сработает, потому что тогда ракета получит, скажем, значение dT, равное 1 секунде, и обновит свою скорость, чтобы двигаться очень быстро, вместо плавного ускорения / замедления.

class Rocket:
    def __init__(self, image, pos, angle):
        self.image = pygame.image.load(image)
        self.imageDimensions = self.image.get_rect()
        self.angle = angle
        self.pos = pos
        self.center = (self.pos[0], self.pos[1])

        self.velocity = [0, 0]

        self.acceleration = [0, 0]
        self.angularVelocity = 0
        self.angularAcceleration = 0

        self.isAccelerating = False
        self.thrust = 50

    def draw(self, surface):
        rotatedImg = pygame.transform.rotate(self.image, self.angle)
        rotatedImgDimensions = rotatedImg.get_rect()

        #display image
        surface.blit(rotatedImg, (self.pos[0] - rotatedImgDimensions.center[0], self.pos[1] - rotatedImgDimensions.center[1]))

    def update(self, dt):
        #update angle
        self.angularVelocity += self.angularAcceleration * dt
        self.angle += self.angularVelocity * dt

        #if accelerating update the acceleration
        if self.isAccelerating:
            self.acceleration[0] -= self.thrust * math.sin(math.radians(self.angle))
            self.acceleration[1] -= self.thrust * math.sin(math.radians(self.angle))

        #update velocity
        self.velocity[0] += self.acceleration[0] * dt
        self.velocity[1] += self.acceleration[1] * dt

        #update position
        self.pos[0] += self.velocity[0] * dt
        self.pos[1] += self.velocity[1] * dt

Короче говоря, я ожидаю, что ракета ускорится вперед, когда я нажимаю стрелку вверх, уменьшаю скорость до 0, когда я нажимаю стрелку вниз, и поворачиваюсь влево и вправо, когда нажимаю стрелку влево и вправо.

Обратите внимание, что вышеуказанный класснаходится в другом файле с именем Objects.py

Спасибо !!

Вот остаток кода:

import pygame
from pygame.locals import *
import math
import Objects

#colors
WHITE = (255,255,255)
BLACK = (0,0,0)
TRANSPARENT = (0,0,0,0)

#size window
Width, Height = (1280,720)

#Main menu
def game_intro():
    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    intro = False
        screen.fill(BLACK)


FPS = 30

#initialise pygame
pygame.init()
fpsClock = pygame.time.Clock()

screen = pygame.display.set_mode((Width, Height))
pygame.display.set_caption("Rockets and Missiles")

#Add players
Rocket1 = Objects.Rocket("rocket.png", [100, 100], 0)    #start at pos 50,50

#run main menu first
game_intro()
run = True
while run:

    screen.fill(BLACK)

    Rocket1.draw(screen)

    #event handler

    pressed = pygame.key.get_pressed() #list with all pressed keys
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            Time0 = pygame.time.get_ticks()
        if event.type == pygame.KEYUP:
            Time1 = pygame.time.get_ticks()

    if pressed[pygame.K_UP]:
        dT = Time1 - Time0
        print(dT)
        Rocket1.update(dT)

    pygame.display.update()
    fpsClock.tick(FPS)

pygame.quit()
quit()

Ответы [ 3 ]

1 голос
/ 16 мая 2019

Не думаю, что у вас есть очень полезное определение dT. Насколько я могу вам сказать, звоните Rocket.update() только при нажатии клавиши, ракеты должны обновлять каждый кадр маленьким dT, если вы хотите плавного движения. Без более последовательного вызова update() в вашем ракетном классе вы не получите желаемого движения.

Я предлагаю что-то подобное для вашего основного цикла:

dT = 1/FPS
while run:

    screen.fill(BLACK)

    Rocket1.draw(screen)

    #event handler

    pressed = pygame.key.get_pressed() #list with all pressed keys
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    if pressed[pygame.K_UP]:
        Rocket1.ChangeCurrentAcceleration()
    Rocket1.update()
    pygame.display.update()
    fpsClock.tick(FPS)

Для некоторой новой функции ChangeCurrentAcceleration(), которая добавляет ускорение в вашей ракете, вы можете затем изменить update(), предполагая, что она уже имеет правильное ускорение от тяги и вычисляет новую скорость и положение оттуда (возможно, добавьте 0,95 * множитель ускорения, поэтому он естественно замедляется).

0 голосов
/ 16 мая 2019

Спасибо, ребята, за помощь, я не понял эту часть: D Однако я хочу ответить на свой вопрос для людей, посещающих эту страницу позже.

Возможно, лучший способ сделать это - получить время, необходимое программному обеспечению для прохождения каждой итерации, и использовать его как dT. это будет выглядеть следующим образом: BB перед основным циклом: fpsClock = pygame.time.Clock()

Основной цикл:

while run:

    screen.fill(BLACK)

    Rocket1.draw(screen)

    #draw missiles
    for missile in Missiles:
        missile.draw(screen)

    #event handler

    pressed = pygame.key.get_pressed() #list with all pressed keys
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    if pressed[K_UP]:
        Rocket1.acceleration = [0, -100]
    if pressed[K_DOWN]:
        Rocket1.acceleration = [0, 100]
    if pressed[K_RCTRL]:
        Missiles.append(Objects.Missile("missile.png", Rocket1.pos, Rocket1.angle))

    dT = fpsClock.get_time()

    Rocket1.update(dT/1000)

    pygame.display.update()
    fpsClock.tick(FPS)
0 голосов
/ 16 мая 2019

Я не думаю, что измерение времени нажатия кнопки является правильным подходом.Каждая итерация основного цикла соответствует фиксированному количеству времени, и для создания анимации вы хотите перемещать ракету на это фиксированное количество времени на каждую итерацию.Поэтому не нужно рассчитывать dt, как вы делаете.Он у вас уже есть, и он равен 1/FPS.

. Обычно вы хотите установить скорость / ускорение для вашей ракеты.Теперь все они равны 0, но вы должны установить фиксированное значение, отличное от нуля: насколько вы хотите, чтобы оно было быстрее, или насколько быстрее вы хотите, чтобы оно ускорялось, когда нажата клавиша.
И когданажмите соответствующую кнопку, вызовите метод update, чтобы рассчитать новую позицию / угол на основе этой скорости / ускорения, а затем перерисовать ракету, учитывая, что пройденное время равно 1/FPS.

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

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