comparison demos/shooter/scripts/scene.py @ 477:6b33d80b468b

Projectiles are now part of the scene. Cleaned up the scene update() function. Moved garbage collection to the beginning of the frame. Introduced global object types. Projectiles now only check for collisions in a limited number of scene nodes rather than the entire screen.
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Thu, 22 Apr 2010 19:52:34 +0000
parents 78a1eb57c074
children 41f7754f2a4b
comparison
equal deleted inserted replaced
476:78a1eb57c074 477:6b33d80b468b
20 # Free Software Foundation, Inc., 20 # Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 # #################################################################### 22 # ####################################################################
23 23
24 from fife import fife 24 from fife import fife
25 from scripts.ships.shipbase import Ship 25 from scripts.ships.shipbase import *
26 from scripts.ships.player import Player 26 from scripts.ships.player import Player
27 from scripts.ships.enemies import * 27 from scripts.ships.enemies import *
28 from scripts.common.helpers import Rect 28 from scripts.common.helpers import Rect
29 29
30 class SceneNode(object): 30 class SceneNode(object):
66 66
67 self._paused = False 67 self._paused = False
68 self._timemod = 0 68 self._timemod = 0
69 69
70 self._gameover = False 70 self._gameover = False
71
72 self._boss = None
73 71
74 def destroyScene(self): 72 def destroyScene(self):
75 nodestodelete = list() 73 nodestodelete = list()
76 objtodelete = list() 74 objtodelete = list()
77 75
94 92
95 def initScene(self, mapobj): 93 def initScene(self, mapobj):
96 #initialize our scene array to some arbitrary size 94 #initialize our scene array to some arbitrary size
97 for i in range(0,self._maxnodes): 95 for i in range(0,self._maxnodes):
98 self._nodes.append(SceneNode()) 96 self._nodes.append(SceneNode())
99
100 self._boss = None
101 97
102 self._player = Player(self, 'player') 98 self._player = Player(self, 'player')
103 self._player.init() 99 self._player.init()
104 self._player.start() 100 self._player.start()
105 101
137 enemy = DiagSaucer(self, 'enemy', 1, instance, False) 133 enemy = DiagSaucer(self, 'enemy', 1, instance, False)
138 elif objectName == "streaker": 134 elif objectName == "streaker":
139 enemy = Streaker(self, 'enemy', instance, False) 135 enemy = Streaker(self, 'enemy', instance, False)
140 elif objectName == "boss": 136 elif objectName == "boss":
141 enemy = Boss(self, 'enemy', instance, False) 137 enemy = Boss(self, 'enemy', instance, False)
142 self._boss = enemy
143 else: 138 else:
144 enemy = Ship(self, 'enemy', instance, False) 139 enemy = Ship(self, 'enemy', instance, False)
145 140
146 enemy.start() 141 enemy.start()
147 142
200 def addObjectToScene(self, obj): 195 def addObjectToScene(self, obj):
201 #TODO: search to ensure the object isn't already part of the scene 196 #TODO: search to ensure the object isn't already part of the scene
202 loc = obj.instance.getLocation().getExactLayerCoordinates() 197 loc = obj.instance.getLocation().getExactLayerCoordinates()
203 nodeindex = int(loc.x * self._xscale) 198 nodeindex = int(loc.x * self._xscale)
204 199
205 obj.scenenodeid = nodeindex 200 if nodeindex >= 0:
206 self._nodes[nodeindex].spaceobjects.append(obj) 201 obj.scenenodeid = nodeindex
207 202 self._nodes[nodeindex].spaceobjects.append(obj)
208 def addProjectileToScene(self, projectile): 203 else:
209 self._projectiles.append(projectile) 204 self.queueObjectForRemoval(obj)
210 205
211 def moveObjectInScene(self, obj): 206 def moveObjectInScene(self, obj):
212 loc = obj.instance.getLocation().getExactLayerCoordinates() 207 loc = obj.instance.getLocation().getExactLayerCoordinates()
213 nodeindex = int(loc.x * self._xscale) 208 nodeindex = int(loc.x * self._xscale)
214 209
215 if nodeindex != obj.scenenodeid: 210 if nodeindex >= 0:
216 if obj in self._nodes[obj.scenenodeid].spaceobjects: 211 if nodeindex != obj.scenenodeid:
217 self._nodes[obj.scenenodeid].spaceobjects.remove(obj) 212 if obj in self._nodes[obj.scenenodeid].spaceobjects:
218 213 self._nodes[obj.scenenodeid].spaceobjects.remove(obj)
219 obj.scenenodeid = nodeindex 214
220 self._nodes[nodeindex].spaceobjects.append(obj) 215 self._nodes[nodeindex].spaceobjects.append(obj)
216
217 obj.scenenodeid = nodeindex
218 else:
219 self.queueObjectForRemoval(obj)
221 220
222 def removeObjectFromScene(self, obj): 221 def removeObjectFromScene(self, obj):
223 for node in self._nodes: 222 for node in self._nodes:
224 if obj in node.spaceobjects: 223 if obj in node.spaceobjects:
224 if obj.instance:
225 self._layer.deleteInstance(obj.instance)
226 obj.instance = None
225 node.spaceobjects.remove(obj) 227 node.spaceobjects.remove(obj)
226 self._layer.deleteInstance(obj.instance) 228 break
227 obj.instance = None
228 return
229 229
230 def attachCamera(self, cam): 230 def attachCamera(self, cam):
231 self._camera = cam 231 self._camera = cam
232 self._camera.setLocation(self._player.location) 232 self._camera.setLocation(self._player.location)
233 233
241 timedelta = (time - self._timemod) - self._time 241 timedelta = (time - self._timemod) - self._time
242 self._timedelta = timedelta 242 self._timedelta = timedelta
243 self._time = time - self._timemod 243 self._time = time - self._timemod
244 244
245 self._keystate = keystate 245 self._keystate = keystate
246
247
248 #some garbage cleanup
249 for obj in self._objectstodelete:
250 self.removeObjectFromScene(obj)
251
252 self._objectstodelete = list()
246 253
247 #update camera location 254 #update camera location
248 loc = self._camera.getLocation() 255 loc = self._camera.getLocation()
249 exactloc = self._camera.getLocation().getExactLayerCoordinates() 256 exactloc = self._camera.getLocation().getExactLayerCoordinates()
250 #slowly move to the right 257 #slowly move to the right
266 rightnode = self._maxnodes 273 rightnode = self._maxnodes
267 screenlist = self.getObjectsInRange(leftnode, rightnode) 274 screenlist = self.getObjectsInRange(leftnode, rightnode)
268 275
269 #update objects on the screen 276 #update objects on the screen
270 for obj in screenlist: 277 for obj in screenlist:
271 if obj == self._boss: 278 if obj.type == SHTR_LASTBOSS:
272 if bottomright.x > ((self._boss.location.getExactLayerCoordinates().x * self._xscale) + 0.5): 279 if bottomright.x > ((obj.location.getExactLayerCoordinates().x * self._xscale) + 0.5):
273 self.stopCamera() 280 self.stopCamera()
274 281
275 if not (obj == self._player and self._gameover): 282 if not (obj.type == SHTR_PLAYER and self._gameover):
276 obj.update() 283 obj.update()
277 284
278 if obj.changedposition: 285 if obj.changedposition:
279 self.moveObjectInScene(obj) 286 self.moveObjectInScene(obj)
280 287
281 if obj != self._player: 288 if obj.type != SHTR_PLAYER and obj.type != SHTR_PROJECTILE:
282 if obj.running and obj.boundingbox.intersects(self._player.boundingbox): 289 if obj.running and obj.boundingbox.intersects(self._player.boundingbox):
283 #player touched an enemy. Destroy player and 290 #player touched an enemy. Destroy player and
284 #re-initialize scene 291 #re-initialize scene
285 if not self._player.invulnerable: 292 if not self._player.invulnerable:
286 #collision damage of 1 293 #collision damage of 1
287 self.playerHit(1) 294 self.playerHit(1)
288 obj.applyHit(1) 295 obj.applyHit(1)
289 296
290 # self._world.renderBoundingBox(obj) 297 elif obj.type == SHTR_PROJECTILE:
291 298 #could probably just get the nodes in the projectiles scenenode.
292 299 #use a range to be sure.
293 300 pcollide = self.getObjectsInRange(obj.scenenodeid - 1, obj.scenenodeid + 1)
294 #update the list of projectiles 301
295 projtodelete = list() 302 for o in pcollide:
296 for p in self._projectiles: 303 #cant get hit by your own bullet
297 p.update() 304 if obj.owner != o and o.type != SHTR_PROJECTILE:
298 #check to see if the projectile hit any object on the screen 305 if o.running and obj.boundingbox.intersects(o.boundingbox):
299 for o in screenlist: 306 if o != self._player and obj.owner.type == SHTR_PLAYER:
300 #cant get hit by your own bullet 307 o.applyHit(obj.damage)
301 if p.owner != o: 308 #check if enemy ship was destroyed
302 if o.running and p.boundingbox.intersects(o.boundingbox): 309 if not o.running:
303 if o != self._player and p.owner.isplayer: 310 self._player.applyScore(o.scorevalue)
304 o.applyHit(p.damage) 311 obj.destroy()
305 #check if enemy ship was destroyed 312 elif o == self._player:
306 if not o.running: 313 #player got hit by a projectile
307 self._player.applyScore(o.scorevalue) 314 if not self._player.invulnerable:
308 p.destroy() 315 self.playerHit(obj.damage)
309 elif o == self._player: 316 obj.destroy()
310 #player got hit by a projectile 317
311 if not self._player.invulnerable: 318 #queue list of projectiles to remove (ttl expired or has been destroyed)
312 self.playerHit(p.damage) 319 if not obj.running:
313 p.destroy() 320 self.queueObjectForRemoval(obj)
314 321
315 # self._world.renderBoundingBox(p) 322 # self._world.renderBoundingBox(obj)
316 323
317
318 #build a list of projectiles to remove (ttl expired)
319 if not p.running:
320 projtodelete.append(p)
321
322 #remove any expired projectiles
323 for p in projtodelete:
324 if p in self._projectiles:
325 p.destroy()
326 self._projectiles.remove(p)
327
328 for obj in self._objectstodelete:
329 self.removeObjectFromScene(obj)
330 self._layer.deleteInstance(obj.instance)
331 obj.instance = None
332
333 self._objectstodelete = list()
334 324
335 325
336 def _getPlayer(self): 326 def _getPlayer(self):
337 return self._player 327 return self._player
338 328