pygame - 如何使精灵沿着向量面向的方向移动?

cas*_*sol 4 python pygame

我正在用小行星之类的控件制作游戏,向上箭头用于加速,向右箭头顺时针旋转,向左箭头逆时针旋转,例如,如果我想减速,我需要将船旋转 180\xc2\xb0 并加速。\我能够旋转,为此我画了两个向量(速度和航向)。\n我正在尝试用向量实现这种类型的运动,但也许我不应该这样做?\n所以这就是我的想法。

\n\n
import pygame\nimport sys\nfrom pygame.locals import *  # pygame.locals.QUIT --> QUIT\n# Vector2\nvec = pygame.math.Vector2\n\n# initialize pygame\npygame.init()\nFPS = 60  # frames per second\nfps_clock = pygame.time.Clock()\n# set up the window\nWIDTH = 800\nHEIGHT = 800\nDISPLAY = pygame.display.set_mode((WIDTH, HEIGHT))\npygame.display.set_caption(\'VECTOR_2\')\nFONT = pygame.font.Font(None, 24)\n# RGB colors\nRED = (255, 0, 0)\nGREEN = (0, 255, 0)\nBLUE = (0, 0, 255)\nWHITE = (255, 255, 255)\nBLACK = (0, 0, 0)\n\nMAX_SPEED = 9\n\n\nclass Player(pygame.sprite.Sprite):\n    def __init__(self):\n        pygame.sprite.Sprite.__init__(self)\n        # set ship image\n        self.image = pygame.Surface((70, 50), pygame.SRCALPHA)\n        pygame.draw.polygon(self.image, (50, 120, 180), ((35, 0), (0, 35), (70, 35)))\n        self.original_image = self.image\n        self.rect = self.image.get_rect()\n        self.rect.center = (WIDTH / 2, HEIGHT / 2)\n        self.position = vec(WIDTH / 2, HEIGHT / 2)\n        self.vel = vec(0, 0)\n        self.acceleration = vec(0, 0)\n        # heading vector\n        self.heading = vec(0, -1)  # upwards\n        self.rect.center = self.position\n        self.angle_speed = 0\n        self.angle = 0\n\n    def update(self):\n        self.acceleration = vec(0, 0)\n        keys = pygame.key.get_pressed()\n        if keys[K_LEFT]:\n            self.acceleration.x = -0.2\n        if keys[K_RIGHT]:\n            self.acceleration.x = 0.2\n\n        if keys[K_UP]:\n            self.acceleration.y = -0.2\n\n        if keys[K_DOWN]:\n            self.acceleration.y = 0.2\n\n        if keys[K_a]:\n            self.angle_speed = -1\n            player.rotate()\n        if keys[K_d]:\n            self.angle_speed = 1\n            player.rotate()\n        # max speed\n        if self.vel.length() > MAX_SPEED:\n            self.vel.scale_to_length(MAX_SPEED)\n\n        self.vel += self.acceleration\n        self.position += self.vel\n\n        self.rect.center = self.position\n\n    def rotate(self):\n        # rotate the heading vector\n        self.heading.rotate_ip(self.angle_speed)\n        self.angle += self.angle_speed\n        if self.angle > 360:\n            self.angle -= 360\n        elif self.angle < 0:\n            self.angle += 360\n        self.image = pygame.transform.rotate(self.original_image, -self.angle)\n        self.rect = self.image.get_rect(center=self.rect.center)\n\n    def draw_vectors(self, screen):\n        scale = 20\n        # vel\n        pygame.draw.line(screen, GREEN, self.position, (self.position + self.vel * scale), 5)\n        # desired\n        pygame.draw.line(screen, RED, self.position, (self.position + self.heading * scale), 5)\n\n    def wrap_around_screen(self):\n        """Wrap around screen."""\n        if self.position.x > WIDTH:\n            self.position.x = 0\n        if self.position.x < 0:\n            self.position.x = WIDTH\n        if self.position.y <= 0:\n            self.position.y = HEIGHT\n        if self.position.y > HEIGHT:\n            self.position.y = 0\n\nall_sprites = pygame.sprite.Group()\nplayer = Player()\nall_sprites.add(player)\n\nwhile True:  # game loop\n    for event in pygame.event.get():\n        if event.type == QUIT:\n            pygame.quit()\n            sys.exit()\n\n    DISPLAY.fill(BLACK)\n    player.wrap_around_screen()\n    all_sprites.update()\n    all_sprites.draw(DISPLAY)\n    player.draw_vectors(DISPLAY)\n    txt = FONT.render(\'angle {:.1f}\'.format(player.angle), True, (150, 150, 170))\n    DISPLAY.blit(txt, (10, 10))\n    pygame.display.update()\n    fps_clock.tick(FPS)\n
Run Code Online (Sandbox Code Playgroud)\n\n

任何帮助,将不胜感激

\n

skr*_*krx 5

您可以给self.acceleration向量一个初始长度(在本例中为 0.2),如果玩家按下 ← 或 → 则旋转它,并且只有按下self.vel↑ 或 ↓ 时才加速(将其添加到向量中)。

import sys
import pygame
from pygame.locals import *


vec = pygame.math.Vector2

pygame.init()
FPS = 60
fps_clock = pygame.time.Clock()
WIDTH = 800
HEIGHT = 800
DISPLAY = pygame.display.set_mode((WIDTH, HEIGHT))
BLACK = (0, 0, 0)

MAX_SPEED = 9


class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((70, 50), pygame.SRCALPHA)
        pygame.draw.polygon(self.image, (50, 120, 180), ((35, 0), (0, 35), (70, 35)))
        self.original_image = self.image
        self.position = vec(WIDTH / 2, HEIGHT / 2)
        self.rect = self.image.get_rect(center=self.position)
        self.vel = vec(0, 0)
        self.acceleration = vec(0, -0.2)  # The acceleration vec points upwards.
        self.angle_speed = 0
        self.angle = 0

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[K_LEFT]:
            self.angle_speed = -1
            player.rotate()
        if keys[K_RIGHT]:
            self.angle_speed = 1
            player.rotate()
        # If up or down is pressed, accelerate the ship by
        # adding the acceleration to the velocity vector.
        if keys[K_UP]:
            self.vel += self.acceleration
        if keys[K_DOWN]:
            self.vel -= self.acceleration

        # max speed
        if self.vel.length() > MAX_SPEED:
            self.vel.scale_to_length(MAX_SPEED)

        self.position += self.vel
        self.rect.center = self.position

    def rotate(self):
        # Rotate the acceleration vector.
        self.acceleration.rotate_ip(self.angle_speed)
        self.angle += self.angle_speed
        if self.angle > 360:
            self.angle -= 360
        elif self.angle < 0:
            self.angle += 360
        self.image = pygame.transform.rotate(self.original_image, -self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)

    def wrap_around_screen(self):
        """Wrap around screen."""
        if self.position.x > WIDTH:
            self.position.x = 0
        if self.position.x < 0:
            self.position.x = WIDTH
        if self.position.y <= 0:
            self.position.y = HEIGHT
        if self.position.y > HEIGHT:
            self.position.y = 0


all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    player.wrap_around_screen()
    all_sprites.update()

    DISPLAY.fill(BLACK)
    all_sprites.draw(DISPLAY)
    pygame.display.set_caption('angle {:.1f} accel {} accel angle {:.1f}'.format(
        player.angle, player.acceleration, player.acceleration.as_polar()[1]))
    pygame.display.update()
    fps_clock.tick(FPS)
Run Code Online (Sandbox Code Playgroud)