-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprimitives.py
153 lines (118 loc) · 4.18 KB
/
primitives.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
##!/usr/bin/env python3
import math
class GameObject:
def __init__(self, game):
self.game = game
def update(self, dt, events):
raise NotImplementedError()
def draw(self, surf, offset=(0, 0)):
raise NotImplementedError()
class Pose:
def __init__(self, position, angle=0):
""" Initialize the Pose.
position: two-length tuple (x, y)
angle: angle, in degrees counterclockwise from right ->
"""
self.set_position(position)
self.angle = angle
def set_x(self, new_x):
self.x = new_x
def set_y(self, new_y):
self.y = new_y
def set_position(self, position):
self.x, self.y = position
def set_angle(self, angle):
self.angle = angle
def get_position(self):
return self.x, self.y
def get_angle_of_position(self):
return math.atan2(-self.y, self.x)
def get_angle_radians(self):
return self.angle*math.pi/180
def get_unit_vector(self):
""" Return the unit vector equivalent of the Pose's angle """
# Note: y component is inverted because of indexing on displays;
# negative y points up, while positive y points down.
unit_x = math.cos(self.get_angle_radians())
unit_y = -math.sin(self.get_angle_radians())
return unit_x, unit_y
def get_weighted_position(self, weight):
return self.x*weight, self.y*weight
def add_position(self, position):
add_x, add_y = position
self.set_x(self.x + add_x)
self.set_y(self.y + add_y)
def add_angle(self, angle):
self.set_angle(self.angle + angle)
def rotate_position(self, angle):
x = self.x*math.cos(angle*math.pi/180) \
+ self.y*math.sin(angle*math.pi/180)
y = -self.x*math.sin(angle*math.pi/180) \
+ self.y*math.cos(angle*math.pi/180)
self.set_position((x, y))
def add_pose(self, other, weight=1, frame=None):
if frame:
other = other.copy()
other.rotate_position(frame.angle)
self.add_position(other.get_weighted_position(weight))
self.add_angle(other.angle*weight)
def distance_to(self, other):
return (self - other).magnitude()
def magnitude(self):
distance = math.sqrt(self.x*self.x + self.y*self.y)
return distance
def clear(self):
self.x = 0
self.y = 0
self.angle = 0
def copy(self):
return Pose(self.get_position(), self.angle)
def scale_to(self, magnitude):
""" Scale the X and Y components of the Pose to have a particular
magnitude. Angle is unchanged.
"""
my_magnitude = self.magnitude()
if my_magnitude == 0:
self.x = magnitude
self.y = 0
return
self.x *= magnitude / my_magnitude
self.y *= magnitude / my_magnitude
def __add__(self, other):
copy = self.copy()
copy.add_pose(other)
return copy
def __sub__(self, other):
return Pose((self.x - other.x, self.y - other.y), self.angle - other.angle)
def __mul__(self, other):
copy = self.copy()
copy.x *= other
copy.y *= other
copy.angle *= other
return copy
def __pow__(self, other):
copy = self.copy()
if(copy.x>=0):
copy.x = copy.x ** other
else:
copy.x = (abs(copy.x) ** other) * -1
if (copy.y >= 0):
copy.y = copy.y ** other
else:
copy.y = (abs(copy.y) ** other) * -1
return copy
def __str__(self):
return f"<Pose x:{self.x} y:{self.y} angle:{self.angle}>"
def __repr__(self):
return self.__str__()
def dot(self, other):
return self.x * other.x + self.y * other.y
class PhysicsObject(GameObject):
def __init__(self, game, position, angle):
super().__init__(game)
self.pose = Pose(position, angle)
self.velocity = Pose(position=(0, 0), angle=0)
self.acceleration = Pose(position=(0, 0), angle=0)
def update(self, dt, events):
self.velocity.add_pose(self.acceleration, weight=dt)
self.pose.add_pose(self.velocity, weight=dt)