用Python和Pygame写游戏-从入门到精通(9) Vector2d

来源:互联网 发布:诸葛武侯巧连神数 算法 编辑:程序博客网 时间:2024/06/07 00:19

1、Vector2d

import mathclass 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)        @classmethod    def from_points(cls, P1, P2):        return cls(P2[0] - P1[0], P2[1] - P1[1])        def get_magnitude(self):        return math.sqrt( self.x**2 + self.y**2 )        def get_normalize(self):        magnitude = self.get_magnitude()        self.x /= magnitude        self.y /= magnitude        return "(%s, %s)" % (self.x, self.y)        def __add__(self, rhs):        return Vector2(self.x + rhs.x, self.y + rhs.y)        def __sub__(self, rhs):        return Vector2(self.x - rhs.x, self.y - rhs.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)    A = (10.0, 20.0)B = (30.0, 35.0)C = (-10.0, 0.0)D = (0.0, -5.0)AB = Vector2.from_points(A, B)CD = Vector2.from_points(D, C)print("Vector AB is", AB)print("Vector CD is", CD)print("AB * 2 is", AB*2)print("AB / 2 is", AB*(1/2))print("AB + (–10, 5) is", AB+CD)print("Magnitude of AB is", AB.get_magnitude())print("AB normalized is", AB.get_normalize())

2、2DVectorClass

################## http://www.pygame.org/wiki/2DVectorClass ##################import operatorimport mathclass Vec2d(object):    """2d vector class, supports vector and scalar operators,       and also provides a bunch of high level functions       """    __slots__ = ['x', 'y']    def __init__(self, x_or_pair, y = None):        if y == None:            self.x = x_or_pair[0]            self.y = x_or_pair[1]        else:            self.x = x_or_pair            self.y = y    def __len__(self):        return 2    def __getitem__(self, key):        if key == 0:            return self.x        elif key == 1:            return self.y        else:            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")    def __setitem__(self, key, value):        if key == 0:            self.x = value        elif key == 1:            self.y = value        else:            raise IndexError("Invalid subscript "+str(key)+" to Vec2d")    # String representaion (for debugging)    def __repr__(self):        return 'Vec2d(%s, %s)' % (self.x, self.y)    # Comparison    def __eq__(self, other):        if hasattr(other, "__getitem__") and len(other) == 2:            return self.x == other[0] and self.y == other[1]        else:            return False    def __ne__(self, other):        if hasattr(other, "__getitem__") and len(other) == 2:            return self.x != other[0] or self.y != other[1]        else:            return True    def __nonzero__(self):        return bool(self.x or self.y)    # Generic operator handlers    def _o2(self, other, f):        "Any two-operator operation where the left operand is a Vec2d"        if isinstance(other, Vec2d):            return Vec2d(f(self.x, other.x),                         f(self.y, other.y))        elif (hasattr(other, "__getitem__")):            return Vec2d(f(self.x, other[0]),                         f(self.y, other[1]))        else:            return Vec2d(f(self.x, other),                         f(self.y, other))    def _r_o2(self, other, f):        "Any two-operator operation where the right operand is a Vec2d"        if (hasattr(other, "__getitem__")):            return Vec2d(f(other[0], self.x),                         f(other[1], self.y))        else:            return Vec2d(f(other, self.x),                         f(other, self.y))    def _io(self, other, f):        "inplace operator"        if (hasattr(other, "__getitem__")):            self.x = f(self.x, other[0])            self.y = f(self.y, other[1])        else:            self.x = f(self.x, other)            self.y = f(self.y, other)        return self    # Addition    def __add__(self, other):        if isinstance(other, Vec2d):            return Vec2d(self.x + other.x, self.y + other.y)        elif hasattr(other, "__getitem__"):            return Vec2d(self.x + other[0], self.y + other[1])        else:            return Vec2d(self.x + other, self.y + other)    __radd__ = __add__    def __iadd__(self, other):        if isinstance(other, Vec2d):            self.x += other.x            self.y += other.y        elif hasattr(other, "__getitem__"):            self.x += other[0]            self.y += other[1]        else:            self.x += other            self.y += other        return self    # Subtraction    def __sub__(self, other):        if isinstance(other, Vec2d):            return Vec2d(self.x - other.x, self.y - other.y)        elif (hasattr(other, "__getitem__")):            return Vec2d(self.x - other[0], self.y - other[1])        else:            return Vec2d(self.x - other, self.y - other)    def __rsub__(self, other):        if isinstance(other, Vec2d):            return Vec2d(other.x - self.x, other.y - self.y)        if (hasattr(other, "__getitem__")):            return Vec2d(other[0] - self.x, other[1] - self.y)        else:            return Vec2d(other - self.x, other - self.y)    def __isub__(self, other):        if isinstance(other, Vec2d):            self.x -= other.x            self.y -= other.y        elif (hasattr(other, "__getitem__")):            self.x -= other[0]            self.y -= other[1]        else:            self.x -= other            self.y -= other        return self    # Multiplication    def __mul__(self, other):        if isinstance(other, Vec2d):            return Vec2d(self.x*other.x, self.y*other.y)        if (hasattr(other, "__getitem__")):            return Vec2d(self.x*other[0], self.y*other[1])        else:            return Vec2d(self.x*other, self.y*other)    __rmul__ = __mul__    def __imul__(self, other):        if isinstance(other, Vec2d):            self.x *= other.x            self.y *= other.y        elif (hasattr(other, "__getitem__")):            self.x *= other[0]            self.y *= other[1]        else:            self.x *= other            self.y *= other        return self    # Division    def __div__(self, other):        return self._o2(other, operator.div)    def __rdiv__(self, other):        return self._r_o2(other, operator.div)    def __idiv__(self, other):        return self._io(other, operator.div)    def __floordiv__(self, other):        return self._o2(other, operator.floordiv)    def __rfloordiv__(self, other):        return self._r_o2(other, operator.floordiv)    def __ifloordiv__(self, other):        return self._io(other, operator.floordiv)    def __truediv__(self, other):        return self._o2(other, operator.truediv)    def __rtruediv__(self, other):        return self._r_o2(other, operator.truediv)    def __itruediv__(self, other):        return self._io(other, operator.floordiv)    # Modulo    def __mod__(self, other):        return self._o2(other, operator.mod)    def __rmod__(self, other):        return self._r_o2(other, operator.mod)    def __divmod__(self, other):        return self._o2(other, operator.divmod)    def __rdivmod__(self, other):        return self._r_o2(other, operator.divmod)    # Exponentation    def __pow__(self, other):        return self._o2(other, operator.pow)    def __rpow__(self, other):        return self._r_o2(other, operator.pow)    # Bitwise operators    def __lshift__(self, other):        return self._o2(other, operator.lshift)    def __rlshift__(self, other):        return self._r_o2(other, operator.lshift)    def __rshift__(self, other):        return self._o2(other, operator.rshift)    def __rrshift__(self, other):        return self._r_o2(other, operator.rshift)    def __and__(self, other):        return self._o2(other, operator.and_)    __rand__ = __and__    def __or__(self, other):        return self._o2(other, operator.or_)    __ror__ = __or__    def __xor__(self, other):        return self._o2(other, operator.xor)    __rxor__ = __xor__    # Unary operations    def __neg__(self):        return Vec2d(operator.neg(self.x), operator.neg(self.y))    def __pos__(self):        return Vec2d(operator.pos(self.x), operator.pos(self.y))    def __abs__(self):        return Vec2d(abs(self.x), abs(self.y))    def __invert__(self):        return Vec2d(-self.x, -self.y)    # vectory functions    def get_length_sqrd(self):        return self.x**2 + self.y**2    def get_length(self):        return math.sqrt(self.x**2 + self.y**2)    def __setlength(self, value):        length = self.get_length()        self.x *= value/length        self.y *= value/length    length = property(get_length, __setlength, None, "gets or sets the magnitude of the vector")    def rotate(self, angle_degrees):        radians = math.radians(angle_degrees)        cos = math.cos(radians)        sin = math.sin(radians)        x = self.x*cos - self.y*sin        y = self.x*sin + self.y*cos        self.x = x        self.y = y    def rotated(self, angle_degrees):        radians = math.radians(angle_degrees)        cos = math.cos(radians)        sin = math.sin(radians)        x = self.x*cos - self.y*sin        y = self.x*sin + self.y*cos        return Vec2d(x, y)    def get_angle(self):        if (self.get_length_sqrd() == 0):            return 0        return math.degrees(math.atan2(self.y, self.x))    def __setangle(self, angle_degrees):        self.x = self.length        self.y = 0        self.rotate(angle_degrees)    angle = property(get_angle, __setangle, None, "gets or sets the angle of a vector")    def get_angle_between(self, other):        cross = self.x*other[1] - self.y*other[0]        dot = self.x*other[0] + self.y*other[1]        return math.degrees(math.atan2(cross, dot))    def normalized(self):        length = self.length        if length != 0:            return self/length        return Vec2d(self)    def normalize_return_length(self):        length = self.length        if length != 0:            self.x /= length            self.y /= length        return length    def perpendicular(self):        return Vec2d(-self.y, self.x)    def perpendicular_normal(self):        length = self.length        if length != 0:            return Vec2d(-self.y/length, self.x/length)        return Vec2d(self)    def dot(self, other):        return float(self.x*other[0] + self.y*other[1])    def get_distance(self, other):        return math.sqrt((self.x - other[0])**2 + (self.y - other[1])**2)    def get_dist_sqrd(self, other):        return (self.x - other[0])**2 + (self.y - other[1])**2    def projection(self, other):        other_length_sqrd = other[0]*other[0] + other[1]*other[1]        projected_length_times_other_length = self.dot(other)        return other*(projected_length_times_other_length/other_length_sqrd)    def cross(self, other):        return self.x*other[1] - self.y*other[0]    def interpolate_to(self, other, range):        return Vec2d(self.x + (other[0] - self.x)*range, self.y + (other[1] - self.y)*range)    def convert_to_basis(self, x_vector, y_vector):        return Vec2d(self.dot(x_vector)/x_vector.get_length_sqrd(), self.dot(y_vector)/y_vector.get_length_sqrd())    def __getstate__(self):        return [self.x, self.y]    def __setstate__(self, dict):        self.x, self.y = dict########################################################################## Unit Testing                                                       ##########################################################################if __name__ == "__main__":    import unittest    import pickle    ####################################################################    class UnitTestVec2D(unittest.TestCase):        def setUp(self):            pass        def testCreationAndAccess(self):            v = Vec2d(111,222)            self.assert_(v.x == 111 and v.y == 222)            v.x = 333            v[1] = 444            self.assert_(v[0] == 333 and v[1] == 444)        def testMath(self):            v = Vec2d(111,222)            self.assertEqual(v + 1, Vec2d(112,223))            self.assert_(v - 2 == [109,220])            self.assert_(v * 3 == (333,666))            self.assert_(v / 2.0 == Vec2d(55.5, 111))            self.assert_(v / 2 == (55.5, 111))            self.assert_(v ** Vec2d(2,3) == [12321, 10941048])            self.assert_(v + [-11, 78] == Vec2d(100, 300))            self.assert_(v / [10,2] == [11.1,111])        def testReverseMath(self):            v = Vec2d(111,222)            self.assert_(1 + v == Vec2d(112,223))            self.assert_(2 - v == [-109,-220])            self.assert_(3 * v == (333,666))            self.assert_([222,888] / v == [2,4])            self.assert_([111,222] ** Vec2d(2,3) == [12321, 10941048])            self.assert_([-11, 78] + v == Vec2d(100, 300))        def testUnary(self):            v = Vec2d(111,222)            v = -v            self.assert_(v == [-111,-222])            v = abs(v)            self.assert_(v == [111,222])        def testLength(self):            v = Vec2d(3,4)            self.assert_(v.length == 5)            self.assert_(v.get_length_sqrd() == 25)            self.assert_(v.normalize_return_length() == 5)            self.assert_(v.length == 1)            v.length = 5            self.assert_(v == Vec2d(3,4))            v2 = Vec2d(10, -2)            self.assert_(v.get_distance(v2) == (v - v2).get_length())        def testAngles(self):            v = Vec2d(0, 3)            self.assertEquals(v.angle, 90)            v2 = Vec2d(v)            v.rotate(-90)            self.assertEqual(v.get_angle_between(v2), 90)            v2.angle -= 90            self.assertEqual(v.length, v2.length)            self.assertEquals(v2.angle, 0)            self.assertEqual(v2, [3, 0])            self.assert_((v - v2).length < .00001)            self.assertEqual(v.length, v2.length)            v2.rotate(300)            self.assertAlmostEquals(v.get_angle_between(v2), -60)            v2.rotate(v2.get_angle_between(v))            angle = v.get_angle_between(v2)            self.assertAlmostEquals(v.get_angle_between(v2), 0)        def testHighLevel(self):            basis0 = Vec2d(5.0, 0)            basis1 = Vec2d(0, .5)            v = Vec2d(10, 1)            self.assert_(v.convert_to_basis(basis0, basis1) == [2, 2])            self.assert_(v.projection(basis0) == (10, 0))            self.assert_(basis0.dot(basis1) == 0)        def testCross(self):            lhs = Vec2d(1, .5)            rhs = Vec2d(4,6)            self.assert_(lhs.cross(rhs) == 4)        def testComparison(self):            int_vec = Vec2d(3, -2)            flt_vec = Vec2d(3.0, -2.0)            zero_vec = Vec2d(0, 0)            self.assert_(int_vec == flt_vec)            self.assert_(int_vec != zero_vec)            self.assert_((flt_vec == zero_vec) == False)            self.assert_((flt_vec != int_vec) == False)            self.assert_(int_vec == (3, -2))            self.assert_(int_vec != [0, 0])            self.assert_(int_vec != 5)            self.assert_(int_vec != [3, -2, -5])        def testInplace(self):            inplace_vec = Vec2d(5, 13)            inplace_ref = inplace_vec            inplace_src = Vec2d(inplace_vec)            inplace_vec *= .5            inplace_vec += .5            inplace_vec /= (3, 6)            inplace_vec += Vec2d(-1, -1)            self.assertEquals(inplace_vec, inplace_ref)        def testPickle(self):            testvec = Vec2d(5, .3)            testvec_str = pickle.dumps(testvec)            loaded_vec = pickle.loads(testvec_str)            self.assertEquals(testvec, loaded_vec)    ####################################################################    unittest.main()    ########################################################################


阅读全文
0 0
原创粉丝点击