Disabled actor rotation for speed
[flail.git] / actor.py
blob35ba0b70690eca7d2a9043c2e909a37b484bd32f
1 from __future__ import division
2 from geom import vector, line, ellipse
6 EPSILON = 0.00001
7 TOLERANCE = 0.01
8 JUMP_RANGE = 0.5
9 MIN_BOUNCE = 20
10 MAX_AIRTIME = 0.10
14 class actor (object):
16 def __init__ (self, owner):
17 self.owner = owner
18 self.oval = ellipse ()
19 self.vel = vector ()
20 self.spin = 0
21 self.surf = None
22 self.__jump = False
23 self.__airtime = None
25 def drop (self, dv):
26 self.vel.y -= dv
28 def jump (self, v, dt, key):
29 if self.surf:
30 seg1 = self.surf.seg
32 if key:
33 # key is pressed
34 if self.__airtime is None:
35 if not self.__jump:
36 seg2 = seg1.transform (self.oval)
38 if abs (seg2.dist () - 1) < JUMP_RANGE:
39 self.vel += seg1.perp ().normed (v * dt)
40 self.__airtime = dt
41 elif self.__airtime < MAX_AIRTIME:
42 self.vel += seg1.perp ().normed (v * dt)
43 self.__airtime += dt
44 elif self.__airtime is not None:
45 # key is released
46 seg2 = seg1.perp ()
47 self.vel += seg2.normed (v * (self.__airtime - MAX_AIRTIME) / 2)
48 self.__airtime = None
50 self.__jump = key
52 def left (self, dv):
53 self.vel.x -= dv
55 def right (self, dv):
56 self.vel.x += dv
58 def update (self, dt):
59 from copy import deepcopy
60 from wall import wall
62 surf, contact, frac = None, None, 1
64 oval = deepcopy (self.oval)
65 oval.pos += dt * self.vel
66 oval.angle += dt * self.spin
68 for w in self.owner.walls:
69 line1 = w.seg.transform (self.oval)
70 line2 = w.seg.transform (oval)
72 dist1 = line1.dist ()
73 dist2 = line2.dist ()
75 if dist2 > 1 + TOLERANCE or dist2 > dist1:
76 # actor is above wall or moving up
77 continue
79 # trajectories of the endpoints
80 line3 = line (line1.p1, line2.p1)
81 line4 = line (line1.p2, line2.p2)
83 try:
84 dist3 = line3.dist ()
86 if dist3 > 1:
87 # actor is beyond the left edge
88 continue
89 elif dist1 > 0 and dist3 > -1:
90 # actor might touch the left edge
91 units = [t for t in line3.units () if 0 <= t < frac]
93 for t in units:
94 if t < frac:
95 surf, contact, frac = w, line3 (t), t
96 except ZeroDivisionError:
97 pass
99 try:
100 dist4 = line4.dist ()
102 if dist4 < -1:
103 # actor is beyond the right edge
104 continue
105 elif dist1 > 0 and dist4 < 1:
106 # actor might touch the right edge
107 units = [t for t in line4.units () if 0 <= t < frac]
109 for t in units:
110 if t < frac:
111 surf, contact, frac = w, line4 (t), t
112 except ZeroDivisionError:
113 pass
115 if dist1 < 1 - TOLERANCE:
116 continue
118 try:
119 # actor is in the middle
120 t = (1 + TOLERANCE - dist1) / (dist2 - dist1)
122 if t < frac:
123 tline = line (line3 (t), line4 (t))
124 tpoint = tline.p1.proj (tline.perp ())
126 if (tpoint.cross (tline.p1).z < 0 and
127 tpoint.cross (tline.p2).z > 0):
128 # actor is definitely touching wall
129 surf, contact, frac = w, tpoint, t
130 except ZeroDivisionError:
131 pass
133 self.oval.pos += frac * dt * self.vel
134 self.oval.angle += frac * dt * self.spin
136 if isinstance (surf, wall):
137 try:
138 dir = self.vel.proj (surf.seg.dir ())
140 perp = surf.seg.perp ()
141 self.oval.pos += perp.normed (EPSILON)
142 perp = self.vel.proj (perp)
143 norm = abs (perp)
144 perp = -surf.bounce * perp
146 if perp.normsq () < MIN_BOUNCE * MIN_BOUNCE:
147 speed = abs (dir)
149 if speed < surf.stiction * norm:
150 speed = 0
151 else:
152 speed -= surf.friction * norm
154 try:
155 dir = dir.normed (speed)
156 except ZeroDivisionError:
157 pass
159 perp.x, perp.y = 0, 0
161 self.surf = surf
162 self.vel = perp + dir
163 actor.update (self, dt * (1 - TOLERANCE - frac))
164 except ZeroDivisionError:
165 pass
167 def render (self):
168 raise NotImplementedError ('actor.render')