pygame - 子弹精灵错误偏离船角(Vectors2)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pygame - 子弹精灵错误偏离船角(Vectors2)相关的知识,希望对你有一定的参考价值。
当船在移动时以某些角度从船上射出子弹时,似乎有一种奇怪的偏移。此外,如果船舶向同一方向射击,那么子弹速度就会降低。我尝试使用一些SO答案,这就是我想出的:
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)
BLUE = (0, 0, 255)
MAX_SPEED = 7
class Player(pygame.sprite.Sprite):
"""This class represents the Player."""
def __init__(self):
"""Set up the player on creation."""
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):
"""Update the player's position."""
keys = pygame.key.get_pressed()
if keys[K_LEFT]:
self.angle_speed = -2
player.rotate()
if keys[K_RIGHT]:
self.angle_speed = 2
player.rotate()
# If up is pressed, accelerate the ship by
# adding the acceleration to the velocity vector.
if keys[K_UP]:
self.vel += self.acceleration
if keys[K_SPACE]:
player.shoot()
# 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
def shoot(self):
# create and add missile object to the group
missile = Missile(self.rect.center, self.acceleration, player.acceleration.as_polar()[1])
all_sprites.add(missile)
missiles.add(missile)
class Missile(pygame.sprite.Sprite):
"""This class represents the bullet.
A missile launched by the player's ship.
"""
def __init__(self, position, direction, angle):
"""Initialize missile sprite.
Take the position, direction and angle of the player.
"""
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([4, 10], pygame.SRCALPHA)
self.image.fill(BLUE)
# Rotate the image by the player.angle
self.image = pygame.transform.rotozoom(self.image, angle, 1)
# Pass the center of the player as the center of the bullet.rect.
self.rect = self.image.get_rect(center=position)
self.position = vec(position) # The position vector.
self.velocity = direction * 50 # Multiply by desired speed.
def update(self):
"""Move the bullet."""
self.position += self.velocity # Update the position vector.
self.rect.center = self.position # And the rect.
if self.rect.x < 0 or self.rect.x > WIDTH or self.rect.y < 0 or self.rect.y > HEIGHT:
self.kill()
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
missiles = pygame.sprite.Group()
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)**
任何帮助,将不胜感激
答案
你几乎肯定希望你的导弹从发射船的速度开始(除了船的方向有一定的速度)。
您可以使用direction
参数将Missile.__init__
参数替换为velocity
,该参数可以直接保存为self.velocity
(没有乘法)。然后可以修改Player.shoot
方法以传递适当的值,该值同时考虑船舶的方向和速度:
def shoot(self):
# create and add missile object to the group
missile = Missile(self.rect.center,
self.velocity + 50 * self.acceleration, # new value here!
player.acceleration.as_polar()[1])
all_sprites.add(missile)
missiles.add(missile)
您可能希望使用较小倍数的船舶加速度矢量,而不是我从当前代码中复制的50
,因为它不再是导弹速度的唯一组成部分。
另一答案
唯一的问题是.rotozoom
使用逆时针方向的角度,而.as_polar
矢量方法返回顺时针方向的角度(考虑到在过去的数学课程中学到的东西,人们可能期望.as_polar
产生逆时针角度,但是Surfaces上的Y轴指向下方,而数学类通常Y指向上方)。
TL; DR:你只需要反转在rotozoom调用中传递的角度:
self.image = pygame.transform.rotozoom(self.image, -angle, 1)
您可能还想交换导弹的宽度X高度:
self.image = pygame.Surface([10, 4], pygame.SRCALPHA)
以上是关于pygame - 子弹精灵错误偏离船角(Vectors2)的主要内容,如果未能解决你的问题,请参考以下文章