| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.replica.replicaisland; |
| |
| import android.os.SystemClock; |
| import android.view.KeyEvent; |
| |
| |
| /** |
| * The GameThread contains the main loop for the game engine logic. It invokes the game graph, |
| * manages synchronization of input events, and handles the draw queue swap with the rendering |
| * thread. |
| */ |
| public class GameThread implements Runnable { |
| private long mLastTime; |
| |
| private ObjectManager mGameRoot; |
| private GameRenderer mRenderer; |
| private Object mPauseLock; |
| private boolean mFinished; |
| private boolean mPaused = false; |
| private int mProfileFrames; |
| private long mProfileTime; |
| |
| private static final float PROFILE_REPORT_DELAY = 3.0f; |
| |
| public GameThread(GameRenderer renderer) { |
| mLastTime = SystemClock.uptimeMillis(); |
| mRenderer = renderer; |
| mPauseLock = new Object(); |
| mFinished = false; |
| mPaused = false; |
| } |
| |
| public void run() { |
| mLastTime = SystemClock.uptimeMillis(); |
| mFinished = false; |
| while (!mFinished) { |
| if (mGameRoot != null) { |
| mRenderer.waitDrawingComplete(); |
| |
| final long time = SystemClock.uptimeMillis(); |
| final long timeDelta = time - mLastTime; |
| long finalDelta = timeDelta; |
| if (timeDelta > 12) { |
| float secondsDelta = (time - mLastTime) * 0.001f; |
| if (secondsDelta > 0.1f) { |
| secondsDelta = 0.1f; |
| } |
| mLastTime = time; |
| |
| mGameRoot.update(secondsDelta, null); |
| |
| CameraSystem camera = mGameRoot.sSystemRegistry.cameraSystem; |
| float x = 0.0f; |
| float y = 0.0f; |
| if (camera != null) { |
| x = camera.getFocusPositionX(); |
| y = camera.getFocusPositionY(); |
| } |
| BaseObject.sSystemRegistry.renderSystem.swap(mRenderer, x, y); |
| |
| final long endTime = SystemClock.uptimeMillis(); |
| |
| finalDelta = endTime - time; |
| |
| mProfileTime += finalDelta; |
| mProfileFrames++; |
| if (mProfileTime > PROFILE_REPORT_DELAY * 1000) { |
| final long averageFrameTime = mProfileTime / mProfileFrames; |
| DebugLog.d("Game Profile", "Average: " + averageFrameTime); |
| mProfileTime = 0; |
| mProfileFrames = 0; |
| mGameRoot.sSystemRegistry.hudSystem.setFPS(1000 / (int)averageFrameTime); |
| } |
| } |
| // If the game logic completed in less than 16ms, that means it's running |
| // faster than 60fps, which is our target frame rate. In that case we should |
| // yield to the rendering thread, at least for the remaining frame. |
| |
| if (finalDelta < 16) { |
| try { |
| Thread.sleep(16 - finalDelta); |
| } catch (InterruptedException e) { |
| // Interruptions here are no big deal. |
| } |
| } |
| |
| synchronized(mPauseLock) { |
| if (mPaused) { |
| SoundSystem sound = BaseObject.sSystemRegistry.soundSystem; |
| if (sound != null) { |
| sound.pauseAll(); |
| BaseObject.sSystemRegistry.inputSystem.releaseAllKeys(); |
| } |
| while (mPaused) { |
| try { |
| mPauseLock.wait(); |
| } catch (InterruptedException e) { |
| // No big deal if this wait is interrupted. |
| } |
| } |
| } |
| } |
| } |
| } |
| // Make sure our dependence on the render system is cleaned up. |
| BaseObject.sSystemRegistry.renderSystem.emptyQueues(mRenderer); |
| } |
| |
| public void stopGame() { |
| synchronized (mPauseLock) { |
| mPaused = false; |
| mFinished = true; |
| mPauseLock.notifyAll(); |
| } |
| } |
| |
| public void pauseGame() { |
| synchronized (mPauseLock) { |
| mPaused = true; |
| } |
| } |
| |
| public void resumeGame() { |
| synchronized (mPauseLock) { |
| mPaused = false; |
| mPauseLock.notifyAll(); |
| } |
| } |
| |
| public boolean getPaused() { |
| return mPaused; |
| } |
| |
| public void setGameRoot(ObjectManager gameRoot) { |
| mGameRoot = gameRoot; |
| } |
| |
| } |