PageRenderTime 93ms CodeModel.GetById 54ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 1ms

/examples/advanced/physics/scenes/AirHockeyScene.java

http://mt4j.googlecode.com/
Java | 587 lines | 418 code | 75 blank | 94 comment | 57 complexity | a4c6b45d0c977b1c66ae38279d713d55 MD5 | raw file
  1package advanced.physics.scenes;
  2
  3import java.awt.event.KeyEvent;
  4
  5import org.jbox2d.collision.AABB;
  6import org.jbox2d.collision.shapes.CircleDef;
  7import org.jbox2d.collision.shapes.PolygonDef;
  8import org.jbox2d.collision.shapes.Shape;
  9import org.jbox2d.common.Vec2;
 10import org.jbox2d.dynamics.Body;
 11import org.jbox2d.dynamics.BodyDef;
 12import org.jbox2d.dynamics.ContactListener;
 13import org.jbox2d.dynamics.World;
 14import org.jbox2d.dynamics.contacts.ContactPoint;
 15import org.jbox2d.dynamics.contacts.ContactResult;
 16import org.jbox2d.dynamics.joints.Joint;
 17import org.jbox2d.dynamics.joints.JointType;
 18import org.jbox2d.dynamics.joints.MouseJoint;
 19import org.mt4j.MTApplication;
 20import org.mt4j.components.MTComponent;
 21import org.mt4j.components.visibleComponents.font.FontManager;
 22import org.mt4j.components.visibleComponents.font.IFont;
 23import org.mt4j.components.visibleComponents.shapes.MTEllipse;
 24import org.mt4j.components.visibleComponents.shapes.MTLine;
 25import org.mt4j.components.visibleComponents.shapes.MTRectangle;
 26import org.mt4j.components.visibleComponents.widgets.MTTextArea;
 27import org.mt4j.input.inputProcessors.IGestureEventListener;
 28import org.mt4j.input.inputProcessors.MTGestureEvent;
 29import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragEvent;
 30import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
 31import org.mt4j.input.inputProcessors.globalProcessors.CursorTracer;
 32import org.mt4j.sceneManagement.AbstractScene;
 33import org.mt4j.util.MTColor;
 34import org.mt4j.util.camera.MTCamera;
 35import org.mt4j.util.math.ToolsMath;
 36import org.mt4j.util.math.Vector3D;
 37
 38import processing.core.PApplet;
 39import processing.core.PImage;
 40import advanced.physics.physicsShapes.IPhysicsComponent;
 41import advanced.physics.physicsShapes.PhysicsCircle;
 42import advanced.physics.physicsShapes.PhysicsRectangle;
 43import advanced.physics.util.PhysicsHelper;
 44import advanced.physics.util.UpdatePhysicsAction;
 45
 46public class AirHockeyScene extends AbstractScene {
 47	private float timeStep = 1.0f / 60.0f;
 48	private int constraintIterations = 10;
 49	
 50	/** THE CANVAS SCALE **/
 51	private float scale = 20;
 52	private MTApplication app;
 53	private World world;
 54	
 55	private MTComponent physicsContainer;
 56	private MTTextArea t1;
 57	private MTTextArea t2;
 58	
 59	private int scorePlayer1;
 60	private int scorePlayer2;
 61	private HockeyBall ball;
 62	/*
 63	private Minim minim;
 64	private AudioSnippet wallHit;
 65	private AudioSample paddleBallClash;
 66	private AudioSnippet goalHit;
 67	private AudioSnippet paddleHit;
 68	*/
 69	private Paddle redCircle;
 70	private Paddle blueCircle;
 71	
 72	private boolean enableSound = true;
 73	
 74	
 75	//TODO sometimes goal not recognized when shot at fast
 76	//TODO after goal reset puck and make 3 second countdown -> dont use physics until countdown up!
 77	//TODO get graphics, sounds, effects
 78	
 79//	private String imagesPath = System.getProperty("user.dir") + File.separator + "examples" + File.separator +"advanced"+ File.separator +  "physics"  + File.separator + "data" +  File.separator  + "images" +  File.separator;
 80	private String imagesPath =  "advanced" + MTApplication.separator +  "physics"  + MTApplication.separator + "data" +  MTApplication.separator  + "images" +  MTApplication.separator;
 81	
 82	
 83	public AirHockeyScene(MTApplication mtApplication, String name) {
 84		super(mtApplication, name);
 85		this.app = mtApplication;
 86//		this.setClearColor(new MTColor(120,150,150));
 87//		this.setClearColor(new MTColor(190, 190, 170, 255));
 88		this.setClearColor(new MTColor(0, 0, 0, 255));
 89//		this.setClearColor(new MTColor(40, 40, 40, 255));
 90		this.registerGlobalInputProcessor(new CursorTracer(app, this));
 91		
 92		this.scorePlayer1 = 0;
 93		this.scorePlayer2 = 0;
 94		
 95		float worldOffset = 10; //Make Physics world slightly bigger than screen borders
 96		//Physics world dimensions
 97		AABB worldAABB = new AABB(new Vec2(-worldOffset, -worldOffset), new Vec2((app.width)/scale + worldOffset, (app.height)/scale + worldOffset));
 98		Vec2 gravity = new Vec2(0, 0);
 99		boolean sleep = true;
100		//Create the pyhsics world
101		this.world = new World(worldAABB, gravity, sleep);
102		
103		//Update the positions of the components according the the physics simulation each frame
104		this.registerPreDrawAction(new UpdatePhysicsAction(world, timeStep, constraintIterations, scale));
105		
106		physicsContainer = new MTComponent(app);
107		//Scale the physics container. Physics calculations work best when the dimensions are small (about 0.1 - 10 units)
108		//So we make the display of the container bigger and add in turn make our physics object smaller
109		physicsContainer.scale(scale, scale, 1, Vector3D.ZERO_VECTOR);
110		this.getCanvas().addChild(physicsContainer);
111		
112		//Create borders around the screen
113		this.createScreenBorders(physicsContainer);
114		
115		//Create gamefield marks
116		MTLine line = new MTLine(mtApplication, mtApplication.width/2f/scale, 0, mtApplication.width/2f/scale, mtApplication.height/scale);
117		line.setPickable(false);
118//		line.setStrokeColor(new MTColor(0,0,0));
119		line.setStrokeColor(new MTColor(150,150,150));
120		line.setStrokeWeight(0.5f);
121		physicsContainer.addChild(line);
122		
123		MTEllipse centerCircle = new MTEllipse(mtApplication, new Vector3D(mtApplication.width/2f/scale, mtApplication.height/2f/scale), 80/scale, 80/scale);
124		centerCircle.setPickable(false);
125		centerCircle.setNoFill(true);
126//		centerCircle.setStrokeColor(new MTColor(0,0,0));
127		centerCircle.setStrokeColor(new MTColor(150,150,150));
128		centerCircle.setStrokeWeight(0.5f);
129		physicsContainer.addChild(centerCircle);
130		
131		MTEllipse centerCircleInner = new MTEllipse(mtApplication, new Vector3D(mtApplication.width/2f/scale, mtApplication.height/2f/scale), 10/scale, 10/scale);
132		centerCircleInner.setPickable(false);
133		centerCircleInner.setFillColor(new MTColor(160,160,160));
134//		centerCircleInner.setStrokeColor(new MTColor(150,150,150));
135//		centerCircleInner.setStrokeColor(new MTColor(0,0,0));
136		centerCircleInner.setStrokeColor(new MTColor(150,150,150));
137		centerCircleInner.setStrokeWeight(0.5f);
138		physicsContainer.addChild(centerCircleInner);
139		
140		//Create the paddles
141		PImage paddleTex = mtApplication.loadImage(imagesPath + "paddle.png");
142		redCircle = new Paddle(app, new Vector3D(mtApplication.width - 60, mtApplication.height/2f), 50, world, 1.0f, 0.3f, 0.4f, scale);
143		redCircle.setTexture(paddleTex);
144		redCircle.setFillColor(new MTColor(255,50,50));
145		redCircle.setNoStroke(true);
146		redCircle.setName("red");
147		redCircle.setPickable(false);
148		physicsContainer.addChild(redCircle);
149		
150		blueCircle = new Paddle(app, new Vector3D(80, mtApplication.height/2f), 50, world, 1.0f, 0.3f, 0.4f, scale);
151		blueCircle.setTexture(paddleTex);
152		blueCircle.setFillColor(new MTColor(50,50,255));
153		blueCircle.setNoStroke(true);
154		blueCircle.setName("blue");
155		blueCircle.setPickable(false);
156		physicsContainer.addChild(blueCircle);
157		
158		//Create the ball
159		ball = new HockeyBall(app, new Vector3D(mtApplication.width/2f, mtApplication.height/2f), 38, world, 0.5f, 0.005f, 0.70f, scale);
160//		MTColor ballCol = new MTColor(0,255,0);
161//		ball.setFillColor(ballCol);
162		PImage ballTex = mtApplication.loadImage(imagesPath + "puk.png");
163		ball.setTexture(ballTex);
164//		ball.setFillColor(new MTColor(160,160,160,255));
165		ball.setFillColor(new MTColor(255,255,255,255));
166		ball.setNoStroke(true);
167		ball.setName("ball");
168		physicsContainer.addChild(ball);
169		ball.getBody().applyImpulse(new Vec2(ToolsMath.getRandom(-8f, 8),ToolsMath.getRandom(-8, 8)), ball.getBody().getWorldCenter());
170		
171		//Create the GOALS
172		HockeyGoal goal1 = new HockeyGoal(new Vector3D(0, mtApplication.height/2f), 50, mtApplication.height/4f, mtApplication, world, 0.0f, 0.1f, 0.0f, scale);
173		goal1.setName("goal1");
174		goal1.setFillColor(new MTColor(0,0,255));
175		goal1.setStrokeColor(new MTColor(0,0,255));
176		physicsContainer.addChild(goal1);
177		
178		HockeyGoal goal2 = new HockeyGoal(new Vector3D(mtApplication.width, mtApplication.height/2f), 50, mtApplication.height/4f, mtApplication, world, 0.0f, 0.1f, 0.0f, scale);
179		goal2.setName("goal2");
180		goal2.setFillColor(new MTColor(255,0,0));
181		goal2.setStrokeColor(new MTColor(255,0,0));
182		physicsContainer.addChild(goal2);
183		
184		//Make two components for both game field sides to drag the puks upon
185		MTRectangle leftSide = new MTRectangle(
186				app, PhysicsHelper.scaleDown(0, scale), 
187				PhysicsHelper.scaleDown(0, scale), PhysicsHelper.scaleDown(app.width/2f, scale)
188				, PhysicsHelper.scaleDown(app.height, scale));
189		leftSide.setName("left side");
190		leftSide.setNoFill(true); //Make it invisible -> only used for dragging
191		leftSide.setNoStroke(true);
192		leftSide.unregisterAllInputProcessors();
193		leftSide.removeAllGestureEventListeners(DragProcessor.class);
194		leftSide.registerInputProcessor(new DragProcessor(app));
195		leftSide.addGestureListener(DragProcessor.class, new GameFieldHalfDragListener(blueCircle));
196		physicsContainer.addChild(0, leftSide);
197		MTRectangle rightSide = new MTRectangle(
198				app, PhysicsHelper.scaleDown(app.width/2f, scale), 
199				PhysicsHelper.scaleDown(0, scale), PhysicsHelper.scaleDown(app.width, scale)
200				, PhysicsHelper.scaleDown(app.height, scale));
201		rightSide.setName("right Side");
202		rightSide.setNoFill(true); //Make it invisible -> only used for dragging
203		rightSide.setNoStroke(true);
204		rightSide.unregisterAllInputProcessors();
205		rightSide.removeAllGestureEventListeners(DragProcessor.class);
206		rightSide.registerInputProcessor(new DragProcessor(app));
207		rightSide.addGestureListener(DragProcessor.class, new GameFieldHalfDragListener(redCircle));
208		physicsContainer.addChild(0, rightSide);
209		
210		//Display Score UI
211		MTComponent uiLayer = new MTComponent(mtApplication, new MTCamera(mtApplication));
212		uiLayer.setDepthBufferDisabled(true);
213		getCanvas().addChild(uiLayer);
214		IFont font = FontManager.getInstance().createFont(mtApplication, "arial", 50, MTColor.WHITE);
215		
216		t1 = new MTTextArea(mtApplication, font);
217		t1.setPickable(false);
218		t1.setNoFill(true);
219		t1.setNoStroke(true);
220		t1.setPositionGlobal(new Vector3D(5,30,0));
221		uiLayer.addChild(t1);
222		
223		t2 = new MTTextArea(mtApplication, font);
224		t2.setPickable(false);
225		t2.setNoFill(true);
226		t2.setNoStroke(true);
227		t2.setPositionGlobal(new Vector3D(mtApplication.width - 65 , 30,0));
228		uiLayer.addChild(t2);
229		this.updateScores();
230		
231		//Set up check for collisions between objects
232		this.addWorldContactListener(world);
233
234		/*
235		//Sound
236		if (enableSound){
237			minim = new Minim(mtApplication);
238			wallHit = minim.loadSnippet(MT4jSettings.getInstance().getDataFolderPath() + "sound" + File.separator + "paddleBallHit.wav");
239//			paddleBallClash = minim.loadSample(MT4jSettings.getInstance().getDataFolderPath() + "sound" + File.separator + "paddleBallHit.wav", 2048);
240//			goalHit = minim.loadSnippet(MT4jSettings.getInstance().getDataFolderPath() + "sound" + File.separator + "goal.wav");
241//			goalHit.play();
242			paddleHit = minim.loadSnippet(MT4jSettings.getInstance().getDataFolderPath() + "sound" + File.separator + "wallHit.wav");
243		}
244		*/
245	}
246	
247	
248	
249	private class GameFieldHalfDragListener implements IGestureEventListener{
250		private MTComponent comp;
251		
252		public GameFieldHalfDragListener(MTComponent dragComp){
253			this.comp = dragComp;
254			if (comp.getUserData("box2d") == null){
255				throw new RuntimeException("GameFieldHalfDragListener has to be given a physics object!");
256			}
257		}
258		
259		public boolean processGestureEvent(MTGestureEvent ge) {
260			DragEvent de = (DragEvent)ge;
261			try{
262				Body body = (Body)comp.getUserData("box2d");
263				MouseJoint mouseJoint;
264				Vector3D to = new Vector3D(de.getTo());
265				//Un-scale position from mt4j to box2d
266				PhysicsHelper.scaleDown(to, scale);
267				switch (de.getId()) {
268				case DragEvent.GESTURE_STARTED:
269					comp.sendToFront();
270					body.wakeUp();
271					body.setXForm(new Vec2(to.x,  to.y), body.getAngle());
272					mouseJoint = PhysicsHelper.createDragJoint(world, body, to.x, to.y);
273					comp.setUserData(comp.getID(), mouseJoint);
274					break;
275				case DragEvent.GESTURE_UPDATED:
276					mouseJoint = (MouseJoint) comp.getUserData(comp.getID());
277					if (mouseJoint != null){
278						boolean onCorrectGameSide = ((MTComponent)de.getTarget()).containsPointGlobal(de.getTo());
279						//System.out.println(((MTComponent)de.getTargetComponent()).getName()  + " Contains  " + to + " -> " + contains);
280						if (onCorrectGameSide){
281							mouseJoint.setTarget(new Vec2(to.x, to.y));	
282						}
283					}
284					break;
285				case DragEvent.GESTURE_ENDED:
286					mouseJoint = (MouseJoint) comp.getUserData(comp.getID());
287					if (mouseJoint != null){
288						comp.setUserData(comp.getID(), null);
289						//Only destroy the joint if it isnt already (go through joint list and check)
290						for (Joint joint = world.getJointList(); joint != null; joint = joint.getNext()) {
291							JointType type = joint.getType();
292							switch (type) {
293							case MOUSE_JOINT:
294								MouseJoint mj = (MouseJoint)joint;
295								if (body.equals(mj.getBody1()) || body.equals(mj.getBody2())){
296									if (mj.equals(mouseJoint)) {
297										world.destroyJoint(mj);
298									}
299								}
300								break;
301							default:
302								break;
303							}
304						}
305					}
306					mouseJoint = null;
307					break;
308				default:
309					break;
310				}
311			}catch (Exception e) {
312				System.err.println(e.getMessage());
313			}
314			return false;
315		}
316	}
317	
318	
319	private class Paddle extends PhysicsCircle{
320		public Paddle(PApplet applet, Vector3D centerPoint, float radius,
321				World world, float density, float friction, float restitution, float worldScale) {
322			super(applet, centerPoint, radius, world, density, friction, restitution, worldScale);
323		} 
324		@Override
325		protected void bodyDefB4CreationCallback(BodyDef def) {
326			super.bodyDefB4CreationCallback(def);
327			def.fixedRotation = true;
328			def.linearDamping = 0.5f;
329		}
330	}
331	
332	private class HockeyBall extends PhysicsCircle{
333		public HockeyBall(PApplet applet, Vector3D centerPoint, float radius,
334				World world, float density, float friction, float restitution, float worldScale) {
335			super(applet, centerPoint, radius, world, density, friction, restitution, worldScale);
336		} 
337		
338		@Override
339		protected void circleDefB4CreationCallback(CircleDef def) {
340			super.circleDefB4CreationCallback(def);
341			def.radius = def.radius -5/scale;
342		}
343		@Override
344		protected void bodyDefB4CreationCallback(BodyDef def) {
345			super.bodyDefB4CreationCallback(def);
346//			def.linearDamping = 0.15f;
347			def.linearDamping = 0.25f;
348			def.isBullet = true;
349			def.angularDamping = 0.9f;
350			
351//			def.fixedRotation = true;
352		}
353	}
354	
355	
356	private class HockeyGoal extends PhysicsRectangle {
357		public HockeyGoal(Vector3D centerPosition, float width, float height,
358				PApplet applet, World world, float density, float friction,float restitution, float scale) {
359			super(centerPosition, width, height, applet, world, density, friction,restitution, scale);
360		}
361		
362		@Override
363		protected void bodyDefB4CreationCallback(BodyDef def) {
364			def.isBullet = true;
365			super.bodyDefB4CreationCallback(def);
366		}
367
368		@Override
369		protected void polyDefB4CreationCallback(PolygonDef def) {
370			super.polyDefB4CreationCallback(def);
371			def.isSensor = true; //THIS AS SENSOR!
372		}
373	}
374	
375	
376	
377	
378	private void addWorldContactListener(World world){
379		world.setContactListener(new ContactListener() {
380			public void result(ContactResult point) {
381//				System.out.println("Result contact");
382			}
383			//@Override
384			public void remove(ContactPoint point) {
385//				System.out.println("remove contact");
386			}
387			//@Override
388			public void persist(ContactPoint point) {
389//				System.out.println("persist contact");
390			}
391			//@Override
392			public void add(ContactPoint point) {
393//				/*
394				Shape shape1 = point.shape1;
395				Shape shape2 = point.shape2;
396				final Body body1 = shape1.getBody();
397				final Body body2 = shape2.getBody();
398				Object userData1 = body1.getUserData();
399				Object userData2 = body2.getUserData();
400				
401				if (userData1 instanceof IPhysicsComponent  && userData2 instanceof IPhysicsComponent) { //Check for ball/star collision
402					IPhysicsComponent physObj1 = (IPhysicsComponent) userData1;
403					IPhysicsComponent physObj2 = (IPhysicsComponent) userData2;
404//					System.out.println("Collided: " + mt4jObj1 + " with " + mt4jObj2);
405					if (physObj1 instanceof MTComponent && physObj2 instanceof MTComponent) {
406						MTComponent comp1 = (MTComponent) physObj1;
407						MTComponent comp2 = (MTComponent) physObj2;
408
409						//Check if one of the components is the BALL
410						MTComponent ball = isHit("ball", comp1, comp2);
411						final MTComponent theBall = ball;
412						
413						//Check if one of the components is the GOAL
414						MTComponent goal1 = isHit("goal1", comp1, comp2);
415						MTComponent goal2 = isHit("goal2", comp1, comp2);
416						
417						//Check if a puck was involved
418						MTComponent bluePuck = isHit("blue", comp1, comp2);
419						MTComponent redPuck = isHit("red", comp1, comp2);
420						
421						//Check if a border was hit
422						MTComponent border = null;
423						if (comp1.getName() != null && comp1.getName().startsWith("border")){
424							border = comp1;
425						}else if (comp2.getName() != null && comp2.getName().startsWith("border")){
426							border = comp2;
427						}
428						
429						if (ball != null){
430							//CHECK IF BALL HIT A PADDLE
431							if (enableSound && (bluePuck != null || redPuck != null)){
432//								System.out.println("PUCK HIT BALL!");
433								/*
434								triggerSound(paddleHit);
435								*/
436							}
437							
438							
439							//Check if BALL HIT A GOAL 
440							if (goal1 != null || goal2 != null){
441								//BALL HIT A GOAL
442								if (goal1 != null){
443									System.out.println("GOAL FOR PLAYER 2!");
444									scorePlayer2++;
445								}else if (goal2 != null){
446									System.out.println("GOAL FOR PLAYER 1!");
447									scorePlayer1++;
448								}
449								
450								//Update scores
451								updateScores();
452								//Play goal sound
453//								triggerSound(goalHit);
454								
455								if (scorePlayer1 >= 15 || scorePlayer2 >= 15){
456									reset();
457								}else{
458								
459								//Reset ball
460								if (theBall.getUserData("resetted") == null){ //To make sure that we call destroy only once
461									theBall.setUserData("resetted", true); 
462									app.invokeLater(new Runnable() {
463										public void run() {
464											IPhysicsComponent a = (IPhysicsComponent)theBall;
465											a.getBody().setXForm(new Vec2(getMTApplication().width/2f/scale, getMTApplication().height/2f/scale), a.getBody().getAngle());
466//											a.getBody().setLinearVelocity(new Vec2(0,0));
467											a.getBody().setLinearVelocity(new Vec2(ToolsMath.getRandom(-8, 8),ToolsMath.getRandom(-8, 8)));
468											a.getBody().setAngularVelocity(0);
469											theBall.setUserData("resetted", null); 
470										}
471									});
472								}
473								}
474								
475							}
476							
477							//If ball hit border Play sound
478							if (enableSound && border != null){
479								/*
480								triggerSound(wallHit);
481								*/
482							}
483						}
484					}
485				}else{ //if at lest one if the colliding bodies' userdata is not a physics shape
486					
487				}
488//				*/
489			}
490		});
491	}
492	
493	/*
494	private void triggerSound(AudioSnippet snippet){
495		if (!snippet.isPlaying()){
496			snippet.pause();
497			snippet.rewind();
498			snippet.play();
499		}
500	}
501	*/
502	
503	private MTComponent isHit(String componentName, MTComponent comp1, MTComponent comp2){
504		MTComponent hitComp = null;
505		if (comp1.getName() != null && comp1.getName().equalsIgnoreCase(componentName)){
506			hitComp = comp1;
507		}else if (comp2.getName() != null && comp2.getName().equalsIgnoreCase(componentName)){
508			hitComp = comp2;
509		}
510		return hitComp;
511	}
512	
513	private void updateScores(){
514		t1.setText(Integer.toString(scorePlayer1));
515		t2.setText(Integer.toString(scorePlayer2));
516	}
517	
518	private void reset(){
519		if (ball.getUserData("resetted") == null){ //To make sure that we call destroy only once
520			ball.setUserData("resetted", true); 
521			app.invokeLater(new Runnable() {
522				public void run() {
523					IPhysicsComponent a = (IPhysicsComponent)ball;
524					a.getBody().setXForm(new Vec2(getMTApplication().width/2f/scale, getMTApplication().height/2f/scale), a.getBody().getAngle());
525//					a.getBody().setLinearVelocity(new Vec2(0,0));
526					a.getBody().setLinearVelocity(new Vec2(ToolsMath.getRandom(-8, 8),ToolsMath.getRandom(-8, 8)));
527					a.getBody().setAngularVelocity(0);
528					ball.setUserData("resetted", null); 
529				}
530			});
531		}
532		this.scorePlayer1 = 0;
533		this.scorePlayer2 = 0;
534		this.updateScores();
535	}
536	
537	
538	private void createScreenBorders(MTComponent parent){
539		//Left border 
540		float borderWidth = 50f;
541		float borderHeight = app.height;
542		Vector3D pos = new Vector3D(-(borderWidth/2f) , app.height/2f);
543		PhysicsRectangle borderLeft = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
544		borderLeft.setName("borderLeft");
545		parent.addChild(borderLeft);
546		//Right border
547		pos = new Vector3D(app.width + (borderWidth/2), app.height/2);
548		PhysicsRectangle borderRight = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
549		borderRight.setName("borderRight");
550		parent.addChild(borderRight);
551		//Top border
552		borderWidth = app.width;
553		borderHeight = 50f;
554		pos = new Vector3D(app.width/2, -(borderHeight/2));
555		PhysicsRectangle borderTop = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
556		borderTop.setName("borderTop");
557		parent.addChild(borderTop);
558		//Bottom border
559		pos = new Vector3D(app.width/2 , app.height + (borderHeight/2));
560		PhysicsRectangle borderBottom = new PhysicsRectangle(pos, borderWidth, borderHeight, app, world, 0,0,0, scale);
561		borderBottom.setName("borderBottom");
562		parent.addChild(borderBottom);
563	}
564	
565
566	public void onEnter() {
567		getMTApplication().registerKeyEvent(this);
568	}
569	
570	public void onLeave() {	
571		getMTApplication().unregisterKeyEvent(this);
572	}
573	
574	public void keyEvent(KeyEvent e){
575		int evtID = e.getID();
576		if (evtID != KeyEvent.KEY_PRESSED)
577			return;
578		switch (e.getKeyCode()){
579		case KeyEvent.VK_SPACE:
580			this.reset();
581			break;
582			default:
583				break;
584		}
585	}
586
587}