我是Python,Pygame和一般编程的新手。我正在尝试创建一个Asteroids克隆,但我无法弄清楚如何让我的播放器精灵同时移动和旋转。我使用了来自this answer的Vector2D类(尝试用键盘而不是鼠标修改它)所以我的精灵有点旋转(它不会旋转成一个完整的圆圈),但现在它不会移动。我正在尝试使用向上和向下键加速/减速并使用向左和向右箭头转动。我希望船能够面向它移动的方向。
这是迄今为止的代码:
# an asteroids clone
try:
import sys
import random
import math
import os
import getopt
import pygame
from socket import *
from pygame.locals import *
from pygame.mixer import Sound
except ImportError, err:
print "couldn't load module. %s" % (err)
sys.exit(2)
# these are warnings if font or sound modules are not available.
if not pygame.font: print 'Warning, fonts disabled'
if not pygame.mixer: print 'Warning, sound disabled'
# VECTOR CLASS
class Vector2D(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector2D(self.x - other.x, self.y - other.y)
def __mul__(self, other):
if isinstance(other, Vector2D):
# Vector multiplication
return self.x * other.x + self.y * other.y
else:
# Scalar multiplication
return Vector2D(self.x * other, self.y * other)
__radd__ = __add__
__rsub__ = __sub__
__rmul__ = __mul__
def get_length(self):
return (self.x ** 2 + self.y ** 2) ** (1/2)
def get_angle(self, other, radians=False):
"""Will return the angle between this vector and the other vector."""
if self.get_length() == 0 or other.get_length() == 0:
return 0
if not radians:
return (360 / (2 * math.pi)) * (math.atan2(other.y, other.x) - math.atan2(self.y, self.x))
else:
return math.atan2(other.y, other.x) - math.atan2(self.y, self.x)
def normalize(self):
if self.get_length() == 0:
return Vector2D(0, 0)
return Vector2D(self.x / self.get_length(), self.y / self.get_length())
class Player(pygame.sprite.Sprite):
"""moves ship on screen"""
def __init__(self, image_file, pos=(0, 0)):
super(Player, self).__init__() # call Sprite initializer
self.original_image = pygame.image.load(image_file).convert() # RemEMBER TO CONVERT
self.image = self.original_image # this will reference our rotated copy
self.rect = self.image.get_rect()
self.position = Vector2D(*pos)
self.moving = 0 # won't move at start of game
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.speed = 10
self.state = "still"
degree = 0
self.reinit()
def reinit(self):
self.state = "still"
self.movepos = [0,0]
def update(self):
newpos = self.rect.move(self.movepos)
if self.area.contains(newpos):
self.rect = newpos
# Create a vector pointing at the key position
key_pos = self.rect.move(self.movepos)
# Create a vector pointing from the image towards the key direction
rel_key_pos = key_pos - self.position
# Calculate the angle between the y_axis and the vector pointing from the
# image towards the mouse position
y_axis = Vector2D(0, -1)
angle = -y_axis.get_angle(rel_key_pos) # Negating bc pygame rotates counter-clockwise
# Create the rotated copy
self.image = pygame.transform.rotate(self.original_image, angle).convert() # Angle is absolute value!!
# Make sure your rect represent the actual Surface
self.rect = self.image.get_rect()
# Since the dimension probably changed you should move its center back to where it was.
self.rect.center = self.position.x, self.position.y
pygame.event.pump()
def accelerate(self):
self.speed += 1
self.state = "accelerate"
def decelerate(self):
self.speed -= 1
self.state = "decelerate"
def moveleft(self):
self.movepos[0]-=(self.speed)
self.state="moveleft"
def moveright(self):
self.movepos[0]+=(self.speed)
self.state="moveright"
class Bullet():
pass
class Asteroid():
pass
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self) #call Sprite initializer
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
# main event loop
def main():
# initialize screen
pygame.init()
pygame.mixer.init()
pygame.key.set_repeat(500,30)
screen = pygame.display.set_mode((1280, 1024))
pygame.display.set_caption('Asteroids')
pygame.mouse.set_visible(0)
# make background
background = Background('data\stars1.jpg', [0,0])
# prepare background music
pygame.mixer.music.load('data\patakasmusic.wav')
pygame.mixer.music.play(-1)
# load player sprite
global player
player = Player('data\ship.png', [0,0])
# initialize player sprite
playersprite = pygame.sprite.RenderPlain((player))
# initialize clock
clock = pygame.time.Clock()
# event loop
while 1:
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN:
if event.key == K_UP:
player.accelerate()
if event.key == K_DOWN:
player.decelerate()
if event.key == K_LEFT:
player.moveleft()
if event.key == K_RIGHT:
player.moveright()
elif event.type == KEYUP:
if event.key == K_UP or event.key == K_DOWN:
player.movepos = [0,0]
screen.fill([255, 255, 255])
screen.blit(background.image, background.rect)
screen.blit(player.image, (500,500))
playersprite.draw(screen)
playersprite.update()
pygame.display.update()
playersprite.update()
pygame.display.flip()
if __name__ == '__main__': main()
答案 0 :(得分:0)
我会使用另一个向量来存储精灵的direction
,并添加angle_speed
属性。当用户想要转动船只时,将angle_speed
设置为所需的度数值,并在update
方法中将方向向量旋转角速度。要移动精灵,请将direction
乘以self.speed
以获得速度并将其添加到self.position
,然后更新矩形。
我建议使用pygame.math.Vector2
类,因为它具有更多功能并且速度非常快,因为它是用C语言实现的。
import math
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos=(420, 420)):
super(Player, self).__init__()
self.image = pg.Surface((70, 50), pg.SRCALPHA)
pg.draw.polygon(self.image, (50, 120, 180), ((0, 0), (0, 50), (70, 25)))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.position = Vector2(pos)
self.direction = Vector2(1, 0) # A unit vector pointing rightward.
self.speed = 2
self.angle_speed = 0
self.angle = 0
def update(self):
if self.angle_speed != 0:
# Rotate the direction vector and then the image.
self.direction.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
self.image = pg.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
# Update the position vector and the rect.
self.position += self.direction * self.speed
self.rect.center = self.position
def main():
pg.init()
screen = pg.display.set_mode((1280, 720))
player = Player((420, 420))
playersprite = pg.sprite.RenderPlain((player))
clock = pg.time.Clock()
done = False
while not done:
clock.tick(60)
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
player.speed += 1
elif event.key == pg.K_DOWN:
player.speed -= 1
elif event.key == pg.K_LEFT:
player.angle_speed = -4
elif event.key == pg.K_RIGHT:
player.angle_speed = 4
elif event.type == pg.KEYUP:
if event.key == pg.K_LEFT:
player.angle_speed = 0
elif event.key == pg.K_RIGHT:
player.angle_speed = 0
playersprite.update()
screen.fill((30, 30, 30))
playersprite.draw(screen)
pg.display.flip()
if __name__ == '__main__':
main()
pg.quit()