@Override protected void onStart() { super.onStart(); em = new EntityManager(); MetaEntity.defaultEntityManager = em; Game game = new Game(em); /** create the surface + thread */ SurfaceViewThePit surfaceView = new SurfaceViewThePit(this, game); RenderSystemSimpleDrawable renderSystem = new RenderSystemSimpleDrawable(em, surfaceView, game); MainRunThread runGameThread = new MainRunThread(this, em, surfaceView, renderSystem); runGameThread.loadAllCoreSubSystems(); // runGameThread.setGameResult( gameToStart ); SubsystemTouchHandler systemTh = new SubsystemTouchHandler(em); runGameThread.orderedSubSystems.addLast(systemTh); // MUST be before the Collision Subsystem TouchListenerPlayerMovement thv = new TouchListenerPlayerMovement(systemTh); SubsystemGhosts systemGhosts = new SubsystemGhosts(em, game); runGameThread.orderedSubSystems.addLast(systemGhosts); SubsystemMovementAndCollision systemCollision = new SubsystemMovementAndCollision(em, renderSystem); runGameThread.orderedSubSystems.addLast(systemCollision); SubsystemLighting systemLighting = new SubsystemLighting(em, game); runGameThread.orderedSubSystems.addLast(systemLighting); SubsystemTriggers systemTriggers = new SubsystemTriggers(this, em, game); runGameThread.orderedSubSystems.addLast(systemTriggers); surfaceView.setOnTouchListener(thv); surfaceView.thread = runGameThread; Log.i(getClass().getSimpleName(), "initialized thread and surface"); /** * Finally ... tell the game that the ES is now valid, it's ship reference is OK, and it can do * game-setup */ game.preSetupGame(); renderSystem.shiftCanvasToKeepPositionOnScreen( new CPosition( game.initialPlayerLocation.x, game.initialPlayerLocation.y, game.mazeCellWidth, game.mazeCellHeight)); // turn off the window's title bar requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow() .setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(surfaceView); }
public void run() { Log.i(getClass().getSimpleName(), "Starting thread (run method started)"); boolean gameOverTriggered = false; long currentFrameIndex = 0; long currentFrameTimesAccumulated = 0; long lastLoopStartTime = System.currentTimeMillis(); // Debug.startMethodTracing( "escapePitTrace" ); // gameResult.status = GameResultStatus.RUNNING; loadFirstLevel(); if (orderedSubSystems == null) throw new IllegalStateException( "Cannot start a MainRunThread until you've loaded all SubSystems; try calling loadAllCoreSubSystems() first"); /** * ********************************************************************* START OF MAIN BODY OF * RUN LOOP ********************************************************************** */ while (myThread != null) { long loopStartTime = System.currentTimeMillis(); long lastFrameTime = loopStartTime - lastLoopStartTime; currentFrameTimesAccumulated += lastFrameTime; Canvas c = surfaceView.getHolder().lockCanvas(null); try { /** * Critical: lots of things in rendering depend on the size / shape of the Canvas; => we * must make sure the renderingSystem has the latest, current, correct Canvas before we do * anything else */ renderingSystem.canvas = c; for (SubSystem system : orderedSubSystems) { system.processOneGameTick(lastFrameTime); } synchronized (surfaceView.getHolder()) { renderingSystem.drawBackground(); renderingSystem.processOneGameTick(lastFrameTime); } Thread.sleep(5); } catch (GameOverError goe) { Log.i(getClass().getSimpleName(), "GameOver; killing thread"); myThread = null; Log.i(getClass().getSimpleName(), "GameOver; locking Entity System"); es.freeze(); gameOverTriggered = true; } catch (Throwable t) { Log.e( getClass().getSimpleName(), "Inside main draw loop, a major exception, killing draw thread:" + t); t.printStackTrace(); myThread = null; } finally { // ANDROID EXAMPLE CODE COMMENT: // do this in a finally so that if an exception is thrown // during the above, we don't leave the Surface in an // inconsistent state if (c != null) { surfaceView.getHolder().unlockCanvasAndPost(c); } currentFrameIndex++; lastLoopStartTime = loopStartTime; int frameTimesPerSample = 25; if (currentFrameIndex % frameTimesPerSample == 0) { // DEBUG: Log.i( getClass().getSimpleName(), "Averaged frame rate = " + // frameTimesPerSample * 1000 / currentFrameTimesAccumulated + " fps" ); currentFrameTimesAccumulated = 0; } } } // Debug.stopMethodTracing(); if (gameOverTriggered) { /** * Another bad design decision from the Android authors? This is not a great way to manage * inter-Activity communication (is there a better way?) */ Intent i = parentActivity.getIntent(); parentActivity.setResult(Activity.RESULT_OK, i); parentActivity.finish(); } Log.i( getClass().getSimpleName(), "Thread-stop COMPLETE: (run method expired; mythread was set to null)"); }