引入向量
向量可以通过两个点来计算出来,如下图,A经过向量AB到达了B,则向量AB就是(30, 35) – (10, 20) = (20, 15)。我们也能猜到向量BA会是(-20, -15),注意向量AB和向量BA,虽然长度一样,但是方向不同。
这里写了一个极简版的Vector2:
#-*- coding:utf-8 -*- import math class Vector2(object): def __init__(self, x=0.0, y=0.0): self.x = x self.y = y #字符串方法 def __str__(self): return "(%s, %s)" % (self.x, self.y) #加法 def __add__(self, other): return Vector2(self.x + other.x, self.y + other.y) #减法 def __sub__(self, other): return Vector2(self.x - other.x, self.y - other.y) #乘法 def __mul__(self, scalar): return Vector2(self.x * scalar, self.y * scalar) #除法 def __div__(self, scalar): return Vector2(self.x / scalar, self.y / scalar) #用修饰器继承类的方法 @classmethod #计算向量 def from_points(cls, p1, p2): return cls(p2[0] - p1[0], p2[1] - p1[1]) #计算向量的模 def sq(self): return math.sqrt(self.x**2 + self.y**2) #将向量除以它的模后,所得的向量就是它的单位向量 def normalize(self): magnitude = self.sq() self.x /= magnitude self.y /= magnitude A = (10.0, 20.0) B = (30.0, 50.0) AB = Vector2.from_points(A, B) print(AB)
作者后来提供了一个”更帅的库“,http://eyehere.net/wp-content/uploads/2011/06/gameobjects-0.0.3.zip
这里是该库源码的地址,我只是将该库里的gameobjects包添加到了我的文件夹中。import就能用了
使用向量的游戏动画
#-*- coding:utf-8 -*- background_image_filename = './images/sushiplate.jpg' sprite_image_filename = './images/fugu.png' import pygame from pygame.locals import * from sys import exit from gameobjects.vector2 import Vector2 pygame.init() screen = pygame.display.set_mode((640, 480), 0, 32) background = pygame.image.load(background_image_filename).convert() sprite = pygame.image.load(sprite_image_filename) #记录经过的时间 clock = pygame.time.Clock() #传入x,y的坐标 position = Vector2(100.0, 100.0) #heading为Vector2的一个实例对象(self) heading = Vector2() while True: for event in pygame.event.get(): if event.type == QUIT: exit() screen.blit(background, (0, 0)) screen.blit(sprite, position) #帧数 time_passed = clock.tick() time_passed_seconds = time_passed/1000.0 #参数前面加*意味着把列表或元组展开,get_pos和get_size都是一个向量的元组 destination = Vector2(*pygame.mouse.get_pos()) - Vector2(*sprite.get_size()) / 2 #计算鱼儿当前位置到鼠标位置的向量 vector_to_mouse = Vector2.from_points(position, destination) #向量规格化(求单位向量) vector_to_mouse.normalise() # 这个heading可以看做是鱼的速度,但是由于这样的运算,鱼的速度就不断改变了 # 在没有到达鼠标时,加速运动,超过以后则减速。因而鱼会在鼠标附近晃动。 heading = heading + (vector_to_mouse * .6) #位置随鼠标每帧变换(始终在鼠标周围移动) position += heading * time_passed_seconds pygame.display.update()
效果图:大致是一直跟着鼠标移动,愈远愈慢
贴一些Vector2的源码:
@classmethod def from_points(cls, p1, p2): """Creates a Vector2 object between two points. @param p1: First point @param p2: Second point """ v = cls.__new__(cls, object) x, y = p1 xx, yy = p2 v._v = [float(xx-x), float(yy-y)] return v
def normalise(self): """Normalises this vector.""" v = self._v x, y = v l = sqrt(x*x +y*y) try: v[0] /= l v[1] /= l except ZeroDivisionError: v[0] = 0. v[1] = 0. return self normalize = normalise
class Vector2(object): __slots__ = ('_v',) _gameobjects_vector = 2 def __init__(self, x=0., y=0.): """Initialise a vector @type x: number @param x: The x value (defaults to 0.), or a container of 2 values @type x: number @param y: The y value (defaults to 0.) """ if hasattr(x, "__getitem__"): x, y = x self._v = [float(x), float(y)] else: self._v = [float(x), float(y)]