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