目标:用pygame自带的pygame.math.Vector2 悠闲的向着夕阳奔跑
Vector2 里提供了二维坐标的常用功能,列如计算距离,角度,长度等,尝试下用这个函数来算距离和偏角。
import pygame
import math
from pygame import Vector2
vect = pygame.math.Vector2
pos0 =vect (0,0)
pos1 = vect(1,1)
pos2 = vect (2,2)
dist12 = pos2 - pos1
dist01 = pos1 -pos0
angle01 = pos0.angle_to(dist01)
angle12 = pos1.angle_to(dist12)
print(angle01,angle12)
测试如上代码,原意是输出pos1的角度,pos2-pos1这条线的角度,以为结果会是 45,45,但结果是 45.0 ,0.00。
理解了一下,pos2的角度是45,pos1的角度是45,两者的差值当然是0度了。
改行代码就实现了想要的效果,输出两点间的角度。
#angle12 = pos1.angle_to(dist12)
angle12 = pos0.angle_to(dist12)
print(angle01,angle12)
因为角度都是相对于原点的,也就是(0,0),一个差值包含了坐标和角度的信息,其实就是个向量,所以从原点到该点的角度就是在笛卡尔坐标里的真实角度。由于函数自带了异常处理方法,所以不用进行上篇中分母为零的判断。也不用进行象限的判定,不用进行数学直角坐标和笛卡尔坐标的转换。
再测试一组数据来验证。对应四个象限。
import pygame
import math
from pygame import Vector2
vect = pygame.math.Vector2
pos0 = vect (0,0)
pos1 = vect(1,1.732)
pos2 = vect (-1,1.732)
pos3 = vect (-1, - 1.732)
pos4 = vect (1,-1.732)
angle01 = pos0.angle_to(pos1)
angle02 = pos0.angle_to(pos2)
angle03 = pos0.angle_to(pos3)
angle04 = pos0.angle_to(pos4)
print(pos1,pos2,pos3,pos4)
print(angle01,angle02,angle03,angle04)
输出结果:[1, 1.732] [-1, 1.732] [-1, -1.732] [1, -1.732]
59.99927221917263 120.00072778082739 -120.00072778082739 -59.99927221917263
符合预期效果。
回到游戏中来。子弹从中间发射,向着四个目标奔跑。修改main.py就行了。
完整代码如下:main.py
import pygame
from bullet import *
from sys import exit
import random
from pygame import Vector2
vect = pygame.math.Vector2
pygame.init()
#定义屏幕类
class MainScene(object):
#初始化
def __init__(self):
self.size = (480,860)
self.scene = pygame.display.set_mode(self.size)
pygame.display.set_caption("自学飞机大战--V0.98")
self.image = pygame.image.load('images/bg.png')
self.bullet_sprite = pygame.sprite.Group()
#子弹1方向向下
bullet1 = Bullet()
bullet1.set_pos(50,0)
bullet1.set_speed(5,90)
#子弹2 方向向上
bullet2 = Bullet()
bullet2.set_pos(400,680)
bullet2.set_speed(4,270)
#子弹3,随机,夕阳方向(0,0)(480,0)(0,860)(480,860)
pos0 = vect (0,0)
pos1 = vect(0,0)
pos2 = vect (480,0)
pos3 = vect (0, 860)
pos4 = vect (480,860)
pos_bullet = vect(random.randint(0,580), 300)
angle1 = pos0.angle_to(pos1 - pos_bullet)
angle2 = pos0.angle_to(pos2 - pos_bullet)
angle3 = pos0.angle_to(pos3 - pos_bullet)
angle4 = pos0.angle_to(pos4 - pos_bullet)
bullet31 = Bullet()
bullet31.set_pos(pos_bullet.x,pos_bullet.y)
bullet31.set_speed(10,angle1)
bullet32 = Bullet()
bullet32.set_pos(pos_bullet.x,pos_bullet.y)
bullet32.set_speed(100,angle2)
bullet33 = Bullet()
bullet33.set_pos(pos_bullet.x,pos_bullet.y)
bullet33.set_speed(100,angle3)
bullet34 = Bullet()
bullet34.set_pos(pos_bullet.x,pos_bullet.y)
bullet34.set_speed(100,angle4)
self.bullet_sprite.add(bullet1)
self.bullet_sprite.add(bullet2)
# self.bullet_sprite.add(bullet3)
self.bullet_sprite.add(bullet31)
self.bullet_sprite.add(bullet32)
self.bullet_sprite.add(bullet33)
self.bullet_sprite.add(bullet34)
#绘制各个元素
def drawElements(self):
self.scene.blit(self.image,(0,0))
self.bullet_sprite.draw(self.scene)
#处理键盘相应
def handleEvent(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
#运行主程序
def runScene(self):
while True:
self.drawElements()
self.handleEvent()
self.bullet_sprite.update()
pygame.display.update()
pygame.time.delay(100)
if __name__ == '__main__':
mainScene = MainScene()
mainScene.runScene()
程序中未考虑子弹本身的尺寸,未考虑float和int之间换算存在的偏差,所以看起来目标不是很准。设置了两个速度,速度快的,准确性高,设置了延迟,方便观察。
bullet.py
import pygame
import math
import random
class Bullet(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('images/enemybullet5.png')
self.rect = self.image.get_rect()
# self.speed = 2
self.x_speed = 0.00
self.y_speed = 2.00
self.angle = 0
def update(self):
self.rect.x += self.x_speed
self.rect.y += self.y_speed
def set_pos(self,x, y):
self.rect.x = x
self.rect.y = y
def set_speed(self,speed, angle = 0):
# self.speed = speed
self.angle = math.pi * angle/180
self.x_speed = speed * math.cos(self.angle)
self.y_speed = speed * math.sin(self.angle)