1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.replica.replicaisland; 18 19 import android.os.SystemClock; 20 import android.view.KeyEvent; 21 22 23 /** 24 * The GameThread contains the main loop for the game engine logic. It invokes the game graph, 25 * manages synchronization of input events, and handles the draw queue swap with the rendering 26 * thread. 27 */ 28 public class GameThread implements Runnable { 29 private long mLastTime; 30 31 private ObjectManager mGameRoot; 32 private GameRenderer mRenderer; 33 private Object mPauseLock; 34 private boolean mFinished; 35 private boolean mPaused = false; 36 private int mProfileFrames; 37 private long mProfileTime; 38 39 private static final float PROFILE_REPORT_DELAY = 3.0f; 40 GameThread(GameRenderer renderer)41 public GameThread(GameRenderer renderer) { 42 mLastTime = SystemClock.uptimeMillis(); 43 mRenderer = renderer; 44 mPauseLock = new Object(); 45 mFinished = false; 46 mPaused = false; 47 } 48 run()49 public void run() { 50 mLastTime = SystemClock.uptimeMillis(); 51 mFinished = false; 52 while (!mFinished) { 53 if (mGameRoot != null) { 54 mRenderer.waitDrawingComplete(); 55 56 final long time = SystemClock.uptimeMillis(); 57 final long timeDelta = time - mLastTime; 58 long finalDelta = timeDelta; 59 if (timeDelta > 12) { 60 float secondsDelta = (time - mLastTime) * 0.001f; 61 if (secondsDelta > 0.1f) { 62 secondsDelta = 0.1f; 63 } 64 mLastTime = time; 65 66 mGameRoot.update(secondsDelta, null); 67 68 CameraSystem camera = mGameRoot.sSystemRegistry.cameraSystem; 69 float x = 0.0f; 70 float y = 0.0f; 71 if (camera != null) { 72 x = camera.getFocusPositionX(); 73 y = camera.getFocusPositionY(); 74 } 75 BaseObject.sSystemRegistry.renderSystem.swap(mRenderer, x, y); 76 77 final long endTime = SystemClock.uptimeMillis(); 78 79 finalDelta = endTime - time; 80 81 mProfileTime += finalDelta; 82 mProfileFrames++; 83 if (mProfileTime > PROFILE_REPORT_DELAY * 1000) { 84 final long averageFrameTime = mProfileTime / mProfileFrames; 85 DebugLog.d("Game Profile", "Average: " + averageFrameTime); 86 mGameRoot.sSystemRegistry.hudSystem.setFPS((int)(1000 * mProfileFrames / mProfileTime)); 87 mProfileTime = 0; 88 mProfileFrames = 0; 89 } 90 } 91 // If the game logic completed in less than 16ms, that means it's running 92 // faster than 60fps, which is our target frame rate. In that case we should 93 // yield to the rendering thread, at least for the remaining frame. 94 95 if (finalDelta < 16) { 96 try { 97 Thread.sleep(16 - finalDelta); 98 } catch (InterruptedException e) { 99 // Interruptions here are no big deal. 100 } 101 } 102 103 synchronized(mPauseLock) { 104 if (mPaused) { 105 SoundSystem sound = BaseObject.sSystemRegistry.soundSystem; 106 if (sound != null) { 107 sound.pauseAll(); 108 BaseObject.sSystemRegistry.inputSystem.releaseAllKeys(); 109 } 110 while (mPaused) { 111 try { 112 mPauseLock.wait(); 113 } catch (InterruptedException e) { 114 // No big deal if this wait is interrupted. 115 } 116 } 117 } 118 } 119 } 120 } 121 // Make sure our dependence on the render system is cleaned up. 122 BaseObject.sSystemRegistry.renderSystem.emptyQueues(mRenderer); 123 } 124 stopGame()125 public void stopGame() { 126 synchronized (mPauseLock) { 127 mPaused = false; 128 mFinished = true; 129 mPauseLock.notifyAll(); 130 } 131 } 132 pauseGame()133 public void pauseGame() { 134 synchronized (mPauseLock) { 135 mPaused = true; 136 } 137 } 138 resumeGame()139 public void resumeGame() { 140 synchronized (mPauseLock) { 141 mPaused = false; 142 mPauseLock.notifyAll(); 143 } 144 } 145 getPaused()146 public boolean getPaused() { 147 return mPaused; 148 } 149 setGameRoot(ObjectManager gameRoot)150 public void setGameRoot(ObjectManager gameRoot) { 151 mGameRoot = gameRoot; 152 } 153 154 } 155