用Python和Pygame写游戏-从入门到精通(9)学习笔记

引入向量

向量可以通过两个点来计算出来,如下图,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)]



猜你喜欢

转载自blog.csdn.net/qq_41805514/article/details/80658799
今日推荐