forked from kayleema/Physformer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
elements.py
178 lines (155 loc) · 5.41 KB
/
elements.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
from Graphics import Graphics
"""This file has element class which contains everything you can see
"""
class Element(object):
exist = True
def __init__(self, x_co, y_co, w_co, h_co, vx_co, vy_co, mass, level_co, c_co):
"""
initialize everything
x_co, y_co: the center coordinates.
w_co, h_co: the width and height.
vx_co, vy_co: speed to 2 coordinates.
c_co: coefficient of restitution
"""
self.w = w_co
self.h = h_co
self.vx = vx_co
self.vy = vy_co
self.mylevel = level_co
self.graphics = Graphics(self)
self.m = mass
self.c = c_co
self.update(x_co, y_co)
self.af = 0.9
def set_exist(self, x):
self.exist = x
def update(self, x1, y1):
"""
update the position of element
"""
self.x = x1
self.y = y1
self.left = self.x - self.w/2.0
self.right = self.x + self.w/2.0
self.top = self.y - self.h/2.0
self.bottom = self.y + self.h/2.0
def in_inter(self, x, a, b):
"""
return true when x is inside the interval [a, b]
"""
assert a <= b, 'Invalid interval'
if x >= a and x <= b:
return True
return False
def touch(self, elem):
"""
return true if the two elements are overlapped by the other
"""
gapright = self.right - elem.left
gapleft = elem.right - self.left
gaptop = -self.top + elem.bottom
gapbottom = -elem.top + self.bottom
if gapleft > 0 and gapright > 0 and gaptop > 0 and gapbottom > 0:
if min(gapleft, gapright) < min(gaptop, gapbottom):
#collision horizontal
if gapleft < gapright:
return 3
else:
return 1
else:
#collision vertical
if gaptop < gapbottom:
return 2
else:
return 4
else:
return 0
def touch_ammount(self, elem):
gapright = self.right - elem.left
gapleft = elem.right - self.left
gaptop = -self.top + elem.bottom
gapbottom = -elem.top + self.bottom
direction = self.touch(elem)
if direction == 0:
return 0
elif direction == 1:
return gapright
elif direction == 2:
return gaptop
elif direction == 3:
return gapleft
elif direction == 4:
return gapbottom
else:
assert False, "invalid direction"
def move(self, elem):
"""
move something out of another element under the presumption that those two elements are overlapped
return nothing
"""
direction = self.touch(elem)
ammount = self.touch_ammount(elem)
if direction == 0:
return
elif direction == 1:
elem.x += ammount
elif direction == 2:
elem.y -= ammount
elif direction == 3:
elem.x -= ammount
elif direction == 4:
elem.y += ammount
else:
assert False, "invalid direction"
elem.update(elem.x, elem.y)
def phy_for(self, va, vb, ma, mb, coef):
"""
take in objects a and b's speed and mass and return the speed for object b
coef is the coefficient of restitution which is the average of the c of two elements
"""
v = (coef * ma * (va - vb) + ma * va + mb * vb) / (ma + mb)
return v
def collide(self, elem):
"""
modify the other element's speed; return nothing
"""
direction = self.touch(elem)
coef = (self.c + elem.c)/2
if direction == 1 or direction == 3:
if elem.vy > 0:
elem.vy = max(0, elem.vy - self.af * abs(elem.vx))
else:
elem.vy = min(0, elem.vy + self.af * abs(elem.vx))
elem.vx = self.phy_for(self.vx, elem.vx, self.m, elem.m, coef)
elif direction == 2 or direction == 4:
if elem.vx > 0:
elem.vx = max(0, elem.vx - self.af * abs(elem.vy))
else:
elem.vx = min(0, elem.vx + self.af * abs(elem.vy))
elem.vy = self.phy_for(self.vy, elem.vy, self.m, elem.m, coef)
else:
return
"""
elem.vx = elem.vy = 0"""
def sim(self, time):
"""
simulate the element move in the certain direction for certain time.
REMEMBER TO CHECK!
"""
self.vy += self.mylevel.g * time
x1 = self.x + time * self.vx
y1 = self.y + time * self.vy
self.update(x1, y1)
def within_screen(self, scr_left, scr_right, scr_top, scr_bot):
"""
return True if the element is in screen; False otherwise.
scr_left: the left bound of the screen
scr_right: the right bound of the screen
"""
#TODO: Fixme
return True
def draw(self, screen, x, y, w, h):
"""
convey the arguments x and y to graphics function to draw things.
"""
self.graphics.draw(screen, x, y, w, h)