4 from pyworlds
.utils
import *
8 # none - No simulation at all.
9 # (The body gets paused)
12 # Simulation done on each frame render
13 # (Good for fast-action games, live is good for games with low cpu use)
16 # Simulation done in each round, and the render is interpolated
17 # (Good for simulation games than need to execute thins more often than once per frame)
18 # (Interpolation has a penalty: the object is rendered with a lag of one round)
22 # Simulation done in both, on rounds and on each frame.
23 # (Increases CPU cost to create a simulation that doesn't need to interpolate)
29 class Body(soya
.Body
):
30 def __init__(self
, parent
= None, model
= None):
31 soya
.Body
.__init
__(self
,parent
,model
)
32 self
.set_timefactor(1)
33 self
.elapsed_render_time
= 0
34 self
.elapsed_round_time
= 0
35 self
.elapsed_real_time
= 0
36 self
.set_timesimulation(SIM_TYPE
['live'])
38 self
.min_elapse_time
= 1 / 80.0
39 self
.max_elapse_time
= 1 / 20.0
40 self
.state1
= soya
.CoordSystState(self
)
41 self
.state2
= soya
.CoordSystState(self
)
44 self
.round_duration
= 0.04
45 self
.list_elapsecalls
=[self
.elapsed_time
]
47 def set_timesimulation(self
,sim_type
):
48 self
.sim_type
=sim_type
50 def set_timefactor(self
,factor
):
51 self
.time_factor
= factor
53 def elapse_to_time(self
,new_time
):
54 seconds
= new_time
- self
.elapsed_real_time
56 while seconds
> self
.min_elapse_time
:
57 if seconds
> self
.max_elapse_time
:
58 seconds
= self
.max_elapse_time
60 for elapsedcall
in self
.list_elapsecalls
:
62 # if elapsed_seconds : seconds = elapsed_seconds
63 assert seconds
> self
.min_elapse_time
/ 2.0
65 self
.elapsed_real_time
+= seconds
66 total_elapsed
+= seconds
67 seconds
= new_time
- self
.elapsed_real_time
70 def addloopcall(self
, funccall
):
72 print "Testing funccall..."
74 print "return value: %s , expected 0" % s
77 self
.list_elapsecalls
.append(funccall
)
81 def elapsed_time(self
,seconds
):
84 def get_absoluteangleXZ(self
,vector
=None):
85 parent
= self
.get_root()
87 vector
= soya
.Vector(self
,0,0,-1)
91 return xy_toangle(q
.x
,q
.z
)
93 def begin_round(self
):
94 soya
.Body
.begin_round(self
)
98 self
.round_duration
= self
.parent
.round_duration
* self
.time_factor
100 seconds
= 1 * self
.round_duration
101 self
.elapsed_round_time
+= seconds
103 if (self
.sim_type
== SIM_TYPE
['round'] or
104 self
.sim_type
== SIM_TYPE
['both']):
105 elapsed
= self
.elapse_to_time(self
.elapsed_round_time
)
108 self
.state1
= soya
.CoordSystState(self
.state2
)
109 self
.state2
= soya
.CoordSystState(self
)
110 self
.state1_time
= self
.state2_time
111 self
.state2_time
= self
.elapsed_round_time
114 def advance_time(self
, proportion
):
115 soya
.Body
.advance_time(self
, proportion
)
116 seconds
= proportion
* self
.round_duration
117 self
.elapsed_render_time
+= seconds
119 if (self
.sim_type
== SIM_TYPE
['live'] or
120 self
.sim_type
== SIM_TYPE
['both']):
121 self
.elapse_to_time(self
.elapsed_render_time
)
123 time1
= self
.state2_time
- self
.state1_time
124 time2
= self
.elapsed_render_time
- self
.state1_time
126 factor
= time2
/ time1
127 self
.interpolate(self
.state1
, self
.state2
, factor
)
130 if (self
.sim_type
== SIM_TYPE
['live'] or
131 self
.sim_type
== SIM_TYPE
['both']):
134 self
.interpolate(self
.state1
, self
.state2
, 1)
138 class PhysicsBody(Body
):
139 def __init__(self
, parent
= 'scene', mesh
= None, mesh_file
= None, animatedmesh_file
= None):
140 if parent
== 'scene':
142 parent
= pyworlds
.worlds
.scene
145 mesh
= soya
.Model
.get(mesh_file
)
147 if animatedmesh_file
:
148 mesh
= soya
.AnimatedModel
.get(animatedmesh_file
)
152 Body
.__init
__(self
,parent
,mesh
)
153 self
.initialize_vars()
155 def initialize_vars(self
):
156 self
.speed
= soya
.Vector(self
,0,0,0)
157 self
.rotation
= [0,0,0]
159 def elapsed_time(self
,seconds
):
160 self
.add_mul_vector(seconds
, self
.speed
)
161 #self.rotate_x(seconds * self.rotation[0])
162 #self.rotate_y(seconds * self.rotation[1])
163 #self.rotate_z(seconds * self.rotation[2])
165 self
.turn_x(seconds
* self
.rotation
[0])
166 self
.turn_y(seconds
* self
.rotation
[1])
167 self
.turn_z(seconds
* self
.rotation
[2])
171 class CharacterBody(PhysicsBody
):
172 def initialize_vars(self
):
173 PhysicsBody
.initialize_vars(self
)
175 "stop" : ["garde","attente"],
179 self
.statecycle
= None
180 self
.character_setstate("stop")
181 self
.desiredangle
= 0
182 self
.look_at_speed
= 500
185 def elapsed_time(self
, seconds
):
186 PhysicsBody
.elapsed_time(self
, seconds
)
188 self
.angle
= self
.get_absoluteangleXZ()
189 if self
.desiredangle
>= 360: self
.desiredangle
-=360
190 if self
.desiredangle
< 0: self
.desiredangle
+=360
192 anglediff
= self
.desiredangle
- self
.angle
193 if anglediff
> 180: anglediff
-=360
194 if anglediff
< -180: anglediff
+=360
195 factor
= self
.look_at_speed
* seconds
196 # -> we can't handle computing limit in this way:
197 #if factor > 1/elapsed : factor = 1/elapsed
198 if factor
> 1/seconds
:
201 anglemov
= anglediff
* factor
203 if abs(self
.rotation
[1])>abs(anglemov
):
204 self
.rotation
[1]=(self
.rotation
[1]-anglemov
)/2.0
206 self
.rotation
[1]=(self
.rotation
[1]*5-anglemov
)/6.0
208 self
.rotation
[1]=-anglediff
212 def character_setstate(self
,newstate
):
213 if newstate
==self
.state
: return False
214 if not hasattr(self
.mesh
,"animations"): return False
215 if len(self
.states
[newstate
])<1: raise
218 for statecycle
in self
.states
[newstate
]:
219 if statecycle
in self
.mesh
.animations
:
220 newstatecycle
=statecycle
224 if not newstatecycle
:
225 print "Not found any animation for %s: " % newstate
, self
.states
[newstate
]
226 print "Available animations:", self
.mesh
.animations
.keys()
230 self
.animate_clear_cycle(self
.statecycle
)
231 self
.statecycle
= None
232 self
.animate_blend_cycle(newstatecycle
)
233 self
.statecycle
= newstatecycle
241 class Label3DFlat(soya
.label3d
.Label3D
):
242 def __init__(self
, size
= 0.01, compensation
= 0.02, follows
= None, offset
= (0.0,1.0,1.0), *args
, **kwargs
):
243 if 'parent' not in kwargs
:
244 kwargs
['parent']=pyworlds
.worlds
.scene
245 soya
.label3d
.Label3D
.__init
__(self
, *args
, **kwargs
)
246 self
.flat_follows
= follows
247 self
.flat_offset
= offset
248 self
.flat_size
= size
249 self
.flat_compensation
= compensation
253 def advance_time(self
,proportion
):
254 if self
.flat_follows
:
255 self
.move(self
.flat_follows
)
256 self
.size
= self
.flat_size
+ self
.flat_compensation
* self
.flat_size
* self
.distance_to(pyworlds
.worlds
.camera
)
258 matrix
= list(self
.matrix
)
261 matrix
[x
+y
*4] = pyworlds
.worlds
.camera
.matrix
[x
+y
*4]
262 self
.matrix
= tuple(matrix
)
263 self
.add_vector(soya
.Vector(self
,self
.flat_offset
[0],self
.flat_offset
[1],self
.flat_offset
[2]))