Python、Pygame - 如何使我的宇宙飞船在给予推力的方向上保持动量,而不管旋转如何?

问题描述 投票:0回答:1

我正在尝试使飞船控制功能如下:

按 W 会增加飞船面向方向的动量。 当飞船有动量时旋转飞船不应影响动量的方向。 旋转后向宇宙飞船添加推力,同时在不同方向上具有动量,应该在新方向上添加动量,而不消除之前的动量(除非您朝相反方向推力,否则它应该慢慢抵消并最终增加动量反方向)。

我设法让它发挥作用,但目前动力在船所面向的方向上不断增加。基本上,在有动量的情况下转弯会使船像汽车一样转弯。

def blit_rotate_center(win, image, top_left, angle):
    rotated_image = pygame.transform.rotate(image, angle)
    new_rect = rotated_image.get_rect(center = image.get_rect(topleft = top_left).center)
    win.blit(rotated_image, new_rect.topleft)

class PlayerShip:
    def __init__(self):
        self.img = assets.SPACE_SHIP_1
        self.max_vel = 12
        self.vel = 0
        self.acceleration = 0.02
        self.rotation_vel = 0.8
        self.angle = 0
        self.x = 400
        self.y = 400
        self.drag = 0.015
        self.acc_angle = 0
        self.vertical = 0
        self.horizontal = 0
        
    
    def rotate(self, left = False, right = False):
        if left:
            self.angle += self.rotation_vel
        elif right:
            self.angle -= self.rotation_vel
    
    def draw(self, win):
        blit_rotate_center(win, self.img, (self.x, self.y), self.angle)
        # Moving the player according to angle
        radians = math.radians(self.angle)
        self.vertical = math.cos(radians) * self.vel
        self.horizontal = math.sin(radians) * self.vel
        self.y -= self.vertical
        self.x -= self.horizontal
        self.reduce_speed()
    
    def key_input(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_a]:
            self.rotate(left = True)
        if keys[pygame.K_d]:
            self.rotate(right = True)
        if keys[pygame.K_w]:
            self.move_forward()
        if keys[pygame.K_s]:
            self.move_backward()
    
    def move_forward(self):
        self.vel = min(self.vel + self.acceleration, self.max_vel)

    def move_backward(self):
        self.vel = min(self.vel - self.acceleration, self.max_vel)
        if self.vel < self.max_vel - self.max_vel * 2:
            self.vel = self.max_vel - self.max_vel * 2
    
    def reduce_speed(self):
        if self.vel < 0:
            self.vel += self.drag
        elif self.vel > 0:
            self.vel -= self.drag

我认为这与 self.angle 不断更新有关,但我已经没有关于如何让它发挥作用的想法了。

我尝试将速度存储在多个变量中,将它们应用到不同的函数中,等等。

python pygame game-physics
1个回答
0
投票

您可以通过以下方法来实现此目的:

您可以存储代表船舶当前动量的方向和大小的动量向量。当您施加推力时,您会将船舶当前旋转方向的矢量添加到该动量矢量中。

以下是如何执行此操作的简化实现:

class PlayerShip:
def __init__(self):
    ...
    self.momentum = pygame.Vector2(0, 0)
    ...

def draw(self, win):
    ...
    # Use momentum for movement, instead of the ship's rotation
    self.x += self.momentum.x
    self.y += self.momentum.y
    ...

def move_forward(self):
    # Calculate a vector in the direction the ship is currently facing
    radians = math.radians(self.angle)
    forward = pygame.Vector2(math.cos(radians), math.sin(radians))
    # Scale this vector by the acceleration amount, and add it to the ship's momentum
    self.momentum += forward * self.acceleration
    # Limit the magnitude of the momentum vector to max_vel
    if self.momentum.length() > self.max_vel:
        self.momentum.scale_to_length(self.max_vel)

def move_backward(self):
    radians = math.radians(self.angle)
    backward = pygame.Vector2(math.cos(radians), math.sin(radians))
    # Subtract the backward vector from momentum to simulate moving backward
    self.momentum -= backward * self.acceleration
    # If the length of the momentum vector is greater than max_vel, scale it back down
    if self.momentum.length() > self.max_vel:
        self.momentum.scale_to_length(self.max_vel)

这里的主要区别在于,我们不是在每次绘制船舶时根据船舶的旋转来改变船舶的速度,而是在施加推力时添加动量向量,并且该向量在帧之间持续存在。当船舶旋转时,动量矢量的方向不会改变,因此即使船舶旋转,船舶也会继续沿上次推进的方向移动。

记得导入pygame向量:import pygame.math.Vector2。

这可能不太适合您的游戏(因为它是一个简化的示例),但希望它能让您了解如何修改现有代码以实现您想要的行为!

© www.soinside.com 2019 - 2024. All rights reserved.