Modifications, renaming
[rokon:rokon.git] / src / com / stickycoding / rokon / Scene.java
1 package com.stickycoding.rokon;\r
2 \r
3 import java.lang.reflect.InvocationTargetException;\r
4 import java.lang.reflect.Method;\r
5 import java.util.Arrays;\r
6 \r
7 import javax.microedition.khronos.opengles.GL10;\r
8 \r
9 import android.view.KeyEvent;\r
10 import android.view.MotionEvent;\r
11 \r
12 import com.badlogic.gdx.physics.box2d.Contact;\r
13 import com.badlogic.gdx.physics.box2d.ContactListener;\r
14 import com.badlogic.gdx.physics.box2d.World;\r
15 import com.stickycoding.rokon.background.Background;\r
16 import com.stickycoding.rokon.device.Graphics;\r
17 \r
18 /**\r
19  * Scene.java\r
20  * A Scene holds and prepares drawable objects or object groups\r
21  * \r
22  * @author Richard\r
23  */\r
24 public class Scene {\r
25         \r
26         public static final int SCENE_TEXTURE_COUNT = 32;\r
27         public static final int DEFAULT_LAYER_COUNT = 1;\r
28         public static final int DEFAULT_LAYER_OBJECT_COUNT = 32;\r
29 \r
30         protected Layer[] layer;\r
31         protected boolean loadedTextures;\r
32         protected int layerCount;\r
33         protected Window window = null;\r
34         protected Texture[] texturesToLoad;\r
35         protected Texture[] texturesOnHardware;\r
36         protected boolean useInvoke;\r
37         protected World world;\r
38         protected boolean usePhysics = false;\r
39         protected ContactListener contactListener;\r
40         protected boolean useContactListener;\r
41         protected Background background;\r
42 \r
43         public void onPreDraw(GL10 gl) { }\r
44         public void onPostDraw(GL10 gl) { }\r
45         \r
46         public void onPause() { }\r
47         public void onResume() { }\r
48         \r
49         public void onTouchDown(GameObject object, float x, float y, MotionEvent event) { }\r
50         public void onTouchUp(GameObject object, float x, float y, MotionEvent event) { }\r
51         public void onTouchMove(GameObject object, float x, float y, MotionEvent event) { }\r
52         public void onTouch(GameObject object, float x, float y, MotionEvent event) { }\r
53         public void onTouchDown(float x, float y, MotionEvent event) { }\r
54         public void onTouchMove(float x, float y, MotionEvent event) { }\r
55         public void onTouch(float x, float y, MotionEvent event) { }\r
56         public void onTouchUp(float x, float y, MotionEvent event) { }\r
57         \r
58         public void onTouchDownReal(float x, float y, MotionEvent event) { }\r
59         public void onTouchMoveReal(float x, float y, MotionEvent event) { }\r
60         public void onTouchUpReal(float x, float y, MotionEvent event) { }\r
61         public void onTouchReal(float x, float y, MotionEvent event) { }\r
62         \r
63         public void onKeyDown(int keyCode, KeyEvent event) { }\r
64         \r
65         /**\r
66          * Sets a World for the physics in this Scene\r
67          * Automatically flags usePhysics\r
68          * \r
69          * @param world valid World object\r
70          */\r
71         public void setWorld(World world) {\r
72                 this.world = world;\r
73                 Physics.world = world;\r
74                 usePhysics = true;\r
75         }\r
76         \r
77         /**\r
78          * Returns the World associated with this Scene\r
79          * \r
80          * @return NULL if no World set\r
81          */\r
82         public World getWorld() {\r
83                 return world;\r
84         }\r
85         \r
86         /**\r
87          * Flags to use physics in this Scene\r
88          */\r
89         public void usePhysics() {\r
90                 usePhysics = true;\r
91         }\r
92         \r
93         /**\r
94          * Flags to not use physics\r
95          */\r
96         public void noPhysics() {\r
97                 usePhysics = false;\r
98         }\r
99         \r
100         /**\r
101          * Removes the World from this Scene\r
102          */\r
103         public void removeWorld() {\r
104                 this.world = null;\r
105                 Physics.world = null;\r
106                 usePhysics = false;\r
107         }\r
108         \r
109         /**\r
110          * Triggers the Scene to begin invoking methods on certain events, this is not set by default.\r
111          * If the methods that are to be invoked don't exist, no exceptions will be raised.\r
112          */\r
113         public void useInvoke() {\r
114                 useInvoke = true;\r
115         }\r
116         \r
117         /**\r
118          * Stops the Scene from invoking methods on events, this is the default state\r
119          */\r
120         public void stopInvoke() {\r
121                 useInvoke = false;\r
122         }\r
123         \r
124         /**\r
125          * Invokes a method inside the Scene class, defined by given parameters.\r
126          * If no parameters exist, use the alternative invoke method\r
127          * \r
128          * @param methodName String\r
129          * @param params Class[]\r
130          * @param paramValues Object[]\r
131          * \r
132          * @return TRUE if successful, FALSE otherwise\r
133          */\r
134         public boolean invoke(String methodName, Class<?>[] params, Object[] paramValues) {\r
135                 for(Method m : this.getClass().getDeclaredMethods()) {\r
136                         if(m.getName().equals(methodName)) {\r
137                                 if(Arrays.equals(params, m.getParameterTypes())) {\r
138                                         try {\r
139                                                 m.invoke(this, paramValues);\r
140                                                 return true;\r
141                                         } catch (IllegalArgumentException e) {\r
142                                                 Debug.error("Invoking, IllegalArgument");\r
143                                                 e.printStackTrace();\r
144                                                 return false;\r
145                                         } catch (IllegalAccessException e) {\r
146                                                 Debug.error("Invoking, IllegalAccess");\r
147                                                 e.printStackTrace();\r
148                                                 return false;\r
149                                         } catch (InvocationTargetException e) {\r
150                                                 Debug.error("Invoking, IllegalTarget");\r
151                                                 e.printStackTrace();\r
152                                                 return false;\r
153                                         }\r
154                                 }\r
155                         }\r
156                 }\r
157                 return false;\r
158         }\r
159         \r
160         /**\r
161          * Invokes a method by parameters inside a Callback object\r
162          * \r
163          * @param callback valid Callback object\r
164          * @return TRUE if successful, FALSE otherwise\r
165          */\r
166         public boolean invoke(Callback callback) {\r
167                 if(callback.parameters == null) {\r
168                         return invoke(callback.methodName);\r
169                 } \r
170                 if(callback.parameterTypes == null) {\r
171                         return invoke(callback.methodName, callback.parameters);\r
172                 }\r
173                 return invoke(callback.methodName, callback.parameterTypes, callback.parameters);\r
174         }\r
175         \r
176         /**\r
177          * USE AT YOUR OWN RISK\r
178          * Invokes a method inside the Scene class, it selects the first matching method name and tries to pass on given parameters\r
179          * An error will be raised if this isn't the correct method. This routine is simply for those too lazy (or wanting to save\r
180          * on a little processing time) and are 100% sure there are no name conflicts.\r
181          * \r
182          * IllegalArgumentException may be passed to the Debug class, logcat will be notified - but there is no way to test at your end.\r
183          * \r
184          * @param methodName String\r
185          * @param paramValues Object[]\r
186          * \r
187          * @return TRUE if successful, FALSE otherwise\r
188          */\r
189         public boolean invoke(String methodName, Object[] paramValues) {\r
190                 for(Method m : this.getClass().getDeclaredMethods()) {\r
191                         if(m.getName().equals(methodName)) {\r
192                                 try {\r
193                                         m.invoke(this, paramValues);\r
194                                         return true;\r
195                                 } catch (IllegalArgumentException e) {\r
196                                         Debug.error("Invoking, IllegalArgument");\r
197                                         e.printStackTrace();\r
198                                         return false;\r
199                                 } catch (IllegalAccessException e) {\r
200                                         Debug.error("Invoking, IllegalAccess");\r
201                                         e.printStackTrace();\r
202                                         return false;\r
203                                 } catch (InvocationTargetException e) {\r
204                                         Debug.error("Invoking, IllegalTarget");\r
205                                         e.printStackTrace();\r
206                                         return false;\r
207                                 }\r
208                         }\r
209                 }\r
210                 return false;\r
211         }\r
212         \r
213         /**\r
214          * Invokes a method inside the Scene class, assuming there are no parameters to pass\r
215          * \r
216          * @param methodName String\r
217          * \r
218          * @return TRUE if successful, FALSE otherwise\r
219          */\r
220         public boolean invoke(String methodName) {\r
221                 for(Method m : this.getClass().getDeclaredMethods()) {\r
222                         if(m.getName().equals(methodName)) {\r
223                                 if(m.getParameterTypes().length == 0) {\r
224                                         try {\r
225                                                 m.invoke(this);\r
226                                                 return true;\r
227                                         } catch (IllegalArgumentException e) {\r
228                                                 Debug.error("Invoking, IllegalArgument");\r
229                                                 e.printStackTrace();\r
230                                                 return false;\r
231                                         } catch (IllegalAccessException e) {\r
232                                                 Debug.error("Invoking, IllegalAccess");\r
233                                                 e.printStackTrace();\r
234                                                 return false;\r
235                                         } catch (InvocationTargetException e) {\r
236                                                 Debug.error("Invoking, IllegalTarget");\r
237                                                 e.printStackTrace();\r
238                                                 return false;\r
239                                         }\r
240                                 }\r
241                         }\r
242                 }\r
243                 return false;\r
244         }\r
245         \r
246         protected void handleTouch(MotionEvent event) {\r
247                 float realX = event.getX() * (Graphics.getWidthPixels() / RokonActivity.gameWidth);\r
248                 float realY = event.getY() * (Graphics.getHeightPixels() / RokonActivity.gameHeight);\r
249                 if(window != null) {\r
250                         float xFraction = event.getX() / Graphics.getWidthPixels();\r
251                         float yFraction = event.getY() / Graphics.getHeightPixels();\r
252                         float gameX = window.x + (window.width * xFraction);\r
253                         float gameY = window.y + (window.height * yFraction);\r
254                         event.setLocation(gameX, gameY);\r
255                 } else {\r
256                         event.setLocation(event.getX() * (Graphics.getWidthPixels() / RokonActivity.gameWidth), event.getY() * (Graphics.getHeightPixels()  / RokonActivity.gameHeight));                       \r
257                 }\r
258                 onTouch(event.getX(), event.getY(), event);\r
259                 onTouchReal(realX, realY, event);\r
260                 switch(event.getAction()) {\r
261                         case MotionEvent.ACTION_DOWN:\r
262                                 onTouchDown(event.getX(), event.getY(), event);\r
263                                 onTouchDownReal(realX, realY, event);\r
264                                 break;\r
265                         case MotionEvent.ACTION_UP:\r
266                                 onTouchUp(event.getX(), event.getY(), event);\r
267                                 onTouchUpReal(realX, realY, event);\r
268                                 break;\r
269                         case MotionEvent.ACTION_MOVE:\r
270                                 onTouch(event.getX(), event.getY(), event);\r
271                                 onTouchUp(realX, realY, event);\r
272                                 break;\r
273                 }\r
274                 for(int i = 0; i < layerCount; i++) {\r
275                         for(int j = 0; j < layer[i].maximumDrawableObjects; j++) {\r
276                                 float checkX, checkY;\r
277                                 checkX = event.getX();\r
278                                 checkY = event.getY();\r
279                                 if(layer[i].ignoreWindow) {\r
280                                         checkX = realX;\r
281                                         checkY = realY;\r
282                                 }\r
283                                 GameObject object = layer[i].gameObjects.get(j);\r
284                                 if(object != null && object.isTouchable) {\r
285                                         if(MathHelper.pointInRect(checkX, checkY, object.x, object.y, object.width, object.height)) {\r
286                                                 onTouch(object, checkX, checkY, event);\r
287                                                 if(object.getName() != null) {\r
288                                                         invoke(object.getName() + "_onTouch", new Class[] { float.class, float.class, MotionEvent.class }, new Object[] { event.getX(), event.getY(), event });\r
289                                                 }\r
290                                                 switch(event.getAction()) {\r
291                                                         case MotionEvent.ACTION_DOWN:\r
292                                                                 onTouchDown(object, checkX, checkY, event);\r
293                                                                 if(object.getName() != null) {\r
294                                                                         invoke(object.getName() + "_onTouchDown", new Class[] { float.class, float.class, MotionEvent.class }, new Object[] { event.getX(), event.getY(), event });\r
295                                                                 }\r
296                                                                 break;\r
297                                                         case MotionEvent.ACTION_UP:\r
298                                                                 onTouchUp(object, checkX, checkY, event);\r
299                                                                 if(object.getName() != null) {\r
300                                                                         invoke(object.getName() + "_onTouchUp", new Class[] { float.class, float.class, MotionEvent.class }, new Object[] { event.getX(), event.getY(), event });\r
301                                                                 }\r
302                                                                 break;\r
303                                                         case MotionEvent.ACTION_MOVE:\r
304                                                                 onTouch(object, checkX, checkY, event);\r
305                                                                 if(object.getName() != null) {\r
306                                                                         invoke(object.getName() + "_onTouchMove", new Class[] { float.class, float.class, MotionEvent.class }, new Object[] { event.getX(), event.getY(), event });\r
307                                                                 }\r
308                                                                 break;\r
309                                                 }\r
310                                         }\r
311                                 }\r
312                         }\r
313                 }\r
314         }\r
315         \r
316         /**\r
317          * Creates a new Scene with given layer count, and a corresponding maximum DrawableObject count \r
318          * \r
319          * @param layerCount maximum number of layers\r
320          * @param layerObjectCount maximum number of DrawableObjects per layer, the array length must match layerCount\r
321          */\r
322         public Scene(int layerCount, int[] layerObjectCount) {\r
323                 this.layerCount = layerCount;\r
324                 layer = new Layer[layerCount];\r
325                 for(int i = 0; i < layerCount; i++) {\r
326                         layer[i] = new Layer(this, layerObjectCount[i]);\r
327                 }\r
328                 prepareNewScene();\r
329         }\r
330         \r
331         /**\r
332          * Creates a new Scene with given layer count, all layers will have the same maximum number of DrawableObjects\r
333          * \r
334          * @param layerCount maximum number of layers\r
335          * @param layerObjectCount maximum number of DrawableObjects per layer\r
336          */\r
337         public Scene(int layerCount, int layerObjectCount) {\r
338                 this.layerCount = layerCount;\r
339                 layer = new Layer[layerCount];\r
340                 for(int i = 0; i < layerCount; i++) {\r
341                         layer[i] = new Layer(this, layerObjectCount);\r
342                 }\r
343                 prepareNewScene();\r
344         }\r
345         \r
346         /**\r
347          * Creates a new Scene with given layer count, and a default maximum DrawableObject count of DEFAULT_LAYER_OBJECT_COUNT\r
348          * \r
349          * @param layerCount maximum number of layers\r
350          */\r
351         public Scene(int layerCount) {\r
352                 this(layerCount, DEFAULT_LAYER_OBJECT_COUNT);\r
353         }\r
354         \r
355         /**\r
356          * Creates a new Scene with defaults, DEFAULT_LAYER_COUNT and DEFAULT_LAYER_OBJECT_COUNT\r
357          */\r
358         public Scene() {\r
359                 this(DEFAULT_LAYER_COUNT, DEFAULT_LAYER_OBJECT_COUNT);\r
360                 \r
361         }\r
362         \r
363         private void prepareNewScene() {\r
364                 texturesToLoad = new Texture[SCENE_TEXTURE_COUNT];\r
365                 texturesOnHardware = new Texture[SCENE_TEXTURE_COUNT];\r
366         }\r
367         \r
368         /**\r
369          * Flags a Texture to be loaded into this Scene\r
370          * This must be called before RokonActivity.setScene\r
371          * \r
372          * @param texture valid Texture object\r
373          */\r
374         public void useTexture(Texture texture) {\r
375                 for(int i = 0; i < texturesToLoad.length; i++) {\r
376                         if(texturesToLoad[i] == texture) return;\r
377                         if(texturesToLoad[i] == null) {\r
378                                 texturesToLoad[i] = texture;\r
379                                 return;\r
380                         }\r
381                 }\r
382                 Debug.warning("Scene.useTexture", "Tried loading too many Textures onto the Scene, max is " + texturesToLoad.length);\r
383         }\r
384         \r
385         /**\r
386          * Defines the active Window for this Scene\r
387          * If no Window is given, a default static view will be rendered \r
388          * \r
389          * @param window\r
390          */\r
391         public void setWindow(Window window) {\r
392                 if(window == null) {\r
393                         Debug.warning("Scene.setWindow", "Tried setting a NULL Window");\r
394                         return;\r
395                 }\r
396                 this.window = window;\r
397         }\r
398         \r
399         /**\r
400          * Removes the current active Window, returning it to NULL\r
401          */\r
402         public void removeWindow() {\r
403                 window = null;\r
404         }\r
405         \r
406         /**\r
407          * @return NULL if there is no Window associated with this Scene\r
408          */\r
409         public Window getWindow() {\r
410                 if(window == null)\r
411                         return null;\r
412                 return window;\r
413         }\r
414         \r
415         /**\r
416          * Fetches the Layer object associated with the given index\r
417          * \r
418          * @param index the index of the Layer\r
419          * @return NULL if invalid index is given\r
420          */\r
421         public Layer getLayer(int index) {\r
422                 if(index < 0 || index > layerCount) {\r
423                         Debug.warning("Scene.getLayer", "Tried fetching invalid layer (" + index + "), maximum is " + layerCount);\r
424                         return null;\r
425                 }\r
426                 return layer[index];\r
427         }\r
428         \r
429         /**\r
430          * Clears the DrawableObjects from all Layers\r
431          */\r
432         public void clear() {\r
433                 for(int i = 0; i < layerCount; i++) {\r
434                         layer[i].clear();\r
435                 }\r
436         }\r
437         \r
438         /**\r
439          * Clears all the DrawableObjects from a specified Layer\r
440          * \r
441          * @param index the index of the Layer\r
442          */\r
443         public void clearLayer(int index) {\r
444                 if(index <= 0 || index > layerCount) {\r
445                         Debug.warning("Scene.clearLayer", "Tried clearing invalid layer (" + index + "), maximum is " + layerCount);\r
446                         return;\r
447                 }\r
448                 layer[index].clear();\r
449         }\r
450         \r
451         /**\r
452          * Moves a Layer from one index to another, and shuffles the others up or down to accomodate\r
453          * \r
454          * @param startIndex the current index of the Layer\r
455          * @param endIndex the desired final index of the Layer\r
456          */\r
457         public void moveLayer(int startIndex, int endIndex) {\r
458                 if(startIndex == endIndex) {\r
459                         Debug.warning("Scene.moveLayer", "Tried moving a Layer to its own position, stupid");\r
460                         return;\r
461                 }\r
462                 if(startIndex <= 0 || startIndex > layerCount) {\r
463                         Debug.warning("Scene.moveLayer", "Tried moving an invalid Layer, startIndex=" + startIndex + ", maximum is " + layerCount);\r
464                         return;\r
465                 }\r
466                 if(endIndex <= 0 || endIndex > layerCount) {\r
467                         Debug.warning("Scene.moveLayer", "Tried moving an invalid Layer, endIndex=" + endIndex + ", maximum is " + layerCount);\r
468                         return;\r
469                 }\r
470                 Layer temporaryLayer = layer[startIndex];\r
471                 if(endIndex < startIndex) {\r
472                         for(int i = endIndex; i < startIndex; i++) {\r
473                                 layer[i + 1] = layer[i];\r
474                         }\r
475                         layer[endIndex] = temporaryLayer;\r
476                 }\r
477                 if(endIndex > startIndex) { \r
478                         for(int i = startIndex; i < endIndex; i++) {\r
479                                 layer[i] = layer[i + 1];\r
480                         }\r
481                         layer[endIndex] = temporaryLayer;\r
482                 }\r
483         }\r
484         \r
485         /**\r
486          * Switches the position of one Layer with another\r
487          * \r
488          * @param layer1 the index of the first Layer\r
489          * @param layer2 the index of the second Layer\r
490          */\r
491         public void switchLayers(int layer1, int layer2) {\r
492                 if(layer1 == layer2) {\r
493                         Debug.warning("Scene.switchLayers", "Tried switching the same Layer");\r
494                         return;\r
495                 }\r
496                 if(layer1 < 0 || layer1 > layerCount) {\r
497                         Debug.warning("Scene.switchLayers", "Tried switch an invalid Layer, layer1=" + layer1 + ", maximum is " + layerCount);\r
498                         return;\r
499                 }\r
500                 if(layer2 < 0 || layer2 > layerCount) {\r
501                         Debug.warning("Scene.switchLayers", "Tried switch an invalid Layer, layer2=" + layer2 + ", maximum is " + layerCount);\r
502                         return;\r
503                 }\r
504                 Layer temporaryLayer = layer[layer1];\r
505                 layer[layer1] = layer[layer2];\r
506                 layer[layer2] = temporaryLayer;\r
507         }\r
508         \r
509         /**\r
510          * Replaces a Layer object in this Scene\r
511          * \r
512          * @param index a valid index for a Layer, less than getLayerCount\r
513          * @param layer a valid Layer object to replace the existing Layer\r
514          */\r
515         public void setLayer(int index, Layer layer) {\r
516                 if(layer == null) {\r
517                         Debug.warning("Scene.setLayer", "Tried setting to a null Layer");\r
518                         return;\r
519                 }\r
520                 if(index < 0 || index > layerCount) {\r
521                         Debug.warning("Scene.setLayer", "Tried setting an invalid Layer, index=" + index + ", maximum is " + layerCount);\r
522                         return;\r
523                 }\r
524                 this.layer[index] = layer;\r
525         }\r
526         \r
527         /**\r
528          * Adds a DrawableObject to the first (0th) Layer\r
529          * \r
530          * @param drawableObject a valid DrawableObject\r
531          */\r
532         public void add(GameObject drawableObject) {\r
533                 layer[0].add(drawableObject);\r
534         }\r
535         \r
536         /**\r
537          * Adds a DrawableObject to a given Layer\r
538          * \r
539          * @param layerIndex a valid index of a Layer\r
540          * @param drawableObject a valid DrawableObject\r
541          */\r
542         public void add(int layerIndex, GameObject drawableObject) {\r
543                 if(layerIndex < 0 || layerIndex > layerCount) {\r
544                         Debug.warning("Scene.add", "Tried adding to an invalid Layer, layerIndex=" + layerIndex + ", maximum is " + layerCount);\r
545                         return;\r
546                 }\r
547                 if(drawableObject == null) {\r
548                         Debug.warning("Scene.add", "Tried adding a NULL DrawableObject");\r
549                         return;\r
550                 }\r
551                 layer[layerIndex].add(drawableObject);\r
552         }\r
553         \r
554         /**\r
555          * Removes a DrawableObject from the Scene\r
556          * \r
557          * @param drawableObject a valid DrawableObject\r
558          */\r
559         public void remove(DrawableObject drawableObject) {\r
560                 drawableObject.remove();\r
561         }\r
562         \r
563         protected void onUpdate() {\r
564                 \r
565         }\r
566         \r
567         protected void onGameLoop() {\r
568                 \r
569         }\r
570         \r
571         protected void onSetScene() {\r
572                 loadedTextures = false;\r
573         }\r
574         \r
575         protected void onEndScene() {\r
576                 \r
577         }\r
578         \r
579         protected void onLoadTextures(GL10 gl) {\r
580                 Debug.print("Loading textures onto the Scene");\r
581                 for(int i = 0; i < texturesToLoad.length; i++) {\r
582                         if(texturesToLoad[i] != null) {\r
583                                 texturesToLoad[i].onLoadTexture(gl);\r
584                                 boolean foundSpace = false;\r
585                                 for(int j = 0; j < texturesOnHardware.length; j++) {\r
586                                         if(texturesOnHardware[j] == null) {\r
587                                                 Debug.print("found room...");\r
588                                                 texturesOnHardware[j] = texturesToLoad[i];\r
589                                                 foundSpace = true;\r
590                                                 break;\r
591                                         }\r
592                                 }\r
593                                 if(!foundSpace) {\r
594                                         Debug.warning("Loading more textures than we can remember - will not be there if we onPause, may not be destroyed on Scene death");\r
595                                 }\r
596                                 texturesToLoad[i] = null;\r
597                         }\r
598                 }\r
599                 loadedTextures = true;\r
600         }\r
601         \r
602         protected void onReloadTextures(GL10 gl) {\r
603                 texturesToLoad = texturesOnHardware;\r
604                 for(int i = 0; i < texturesOnHardware.length; i++) {\r
605                         texturesOnHardware[i] = null;\r
606                 }\r
607                 onLoadTextures(gl);\r
608         }\r
609         \r
610         protected void onDraw(GL10 gl) {\r
611                 onPreDraw(gl);\r
612                 if(background != null) {\r
613                         background.onDraw(gl);\r
614                 }\r
615                 if(window != null) {\r
616                         window.onUpdate(gl);\r
617                 }\r
618                 if(usePhysics && !pausePhysics) {\r
619                         world.step(Time.getTicksFraction(), 10, 10);\r
620                 }\r
621                 gl.glClear(GL10.GL_COLOR_BUFFER_BIT);\r
622                 gl.glMatrixMode(GL10.GL_MODELVIEW);\r
623         gl.glLoadIdentity();\r
624                 for(int i = 0; i < layerCount; i++) {\r
625                         layer[i].onDraw(gl);\r
626                 }\r
627                 onPostDraw(gl);\r
628         }\r
629         \r
630         protected boolean pausePhysics = false;\r
631         \r
632         public void pausePhysics() {\r
633                 pausePhysics = true;\r
634         }\r
635         \r
636         public void resumePhysics() {\r
637                 pausePhysics = false;\r
638         }\r
639         \r
640         public void setBackground(Background background) {\r
641                 this.background = background;\r
642                 background.parentScene = this;\r
643         }\r
644         \r
645         public Background getBackground() {\r
646                 return this.background;\r
647         }\r
648         \r
649         \r
650         \r
651         \r
652         \r
653         \r
654         \r
655         \r
656         protected class SceneContactListener implements ContactListener {\r
657 \r
658                 public void beginContact(Contact contact) {\r
659                         // TODO Auto-generated method stub\r
660                         \r
661                 }\r
662 \r
663                 public void endContact(Contact contact) {\r
664                         // TODO Auto-generated method stub\r
665                         \r
666                 }\r
667                 \r
668         }\r
669         \r
670         public void useContactListener() {\r
671                 if(contactListener == null) {\r
672                         contactListener = new SceneContactListener();\r
673                 }\r
674                 useContactListener = true;\r
675         }\r
676         \r
677         public void stopContactListener() {\r
678                 useContactListener = false;\r
679         }\r
680         \r
681         public void setContactListener(ContactListener contactListener) {\r
682                 this.contactListener = contactListener;\r
683         }\r
684         \r
685         \r
686         \r
687 }\r