package com.andlabs.gd.base;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import com.andlabs.gd.R;
public abstract class GameActivity extends Activity implements OnTouchListener, SensorEventListener, SurfaceHolder.Callback {
/**
* the game's (surface)view
*/
private SurfaceView mGameView;
/**
* determines whether the main game loop is running or not
*/
private boolean mMainLoopRunning;
/**
* the surface holder of the game view
*/
private SurfaceHolder mSurfaceHolder;
/**
* the main game rendering thread
*/
private Thread mRenderingThread;
/**
* the main game simulation thread
*/
private Thread mSimulationThread;
/**
* listener for the game's simulation
*/
private SimulationListener mSimulationListener;
/**
* listener for the game's rendering
*/
private RenderingListener mRenderingListener;
/**
* the delta time between the last simulation iteration and now
*/
private float mDeltaTime = 0;
/**
* the timestamp of the last simulation iteration
*/
private long mLastSimulationIteration = 0;
/**
* touch coordinates
**/
private int mTouchX, mTouchY;
/**
* touched state
*/
private boolean mIsTouched;
/**
* acceleration on the 3 axis
**/
private float[] mAcceleration = new float[3];
/**
* all these are for calculating the fps
*/
private int mFPS = 0;
private int mFPSCount = 0;
private float mTimeElapsed = 0;
private long mLastRenderingIteration = 0;
public boolean mIsMoving;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGameView = new SurfaceView(this);
mSurfaceHolder = mGameView.getHolder();
mSurfaceHolder.addCallback(this);
mGameView.setOnTouchListener(this);
setContentView(mGameView);
mMainLoopRunning = true;
mRenderingThread = new Thread(new Runnable(){
public void run() {
render();
}
}, "Rendering Thread");
mSimulationThread = new Thread(new Runnable(){
public void run() {
simulate();
}
}, "Simulation Thread");
SensorManager manager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
if(manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() > 0){
final Sensor accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME );
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE){
mTouchX = (int)event.getX();
mTouchY = (int)event.getY();
mIsTouched = true;
if(event.getAction() == MotionEvent.ACTION_MOVE){
mIsMoving = true;
}
}
if( event.getAction() == MotionEvent.ACTION_UP ){
mIsTouched = false;
mIsMoving = false;
}
try{
Thread.sleep( 30 );
}catch(Exception ex){
//zonk!
}
return true;
}
private void render(){
if(mRenderingListener != null){
mRenderingListener.initializeSplash();
}
new Thread(new Runnable(){
@Override
public void run() {
if(mRenderingListener != null){
mRenderingListener.initializeRendering();
}
}
}).start();
Canvas c;
while(mMainLoopRunning){
c = null;
try {
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder) {
if(mRenderingListener != null){
if(mRenderingListener.isInitializingRendering() || mSimulationListener == null || mSimulationListener.isInitializingSimulation()){
mRenderingListener.renderSplash(c);
} else{
mRenderingListener.render(c);
}
}
}
} finally {
// 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) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
//the fps calculation
mFPSCount++;
mTimeElapsed += (System.nanoTime() - mLastRenderingIteration) / 1000000000.0;
if(mTimeElapsed >= 1){
mFPS = mFPSCount;
Log.d("GameActivity", "FPS: " + mFPS);
mFPSCount = 0;
mTimeElapsed = 0;
}
mLastRenderingIteration = System.nanoTime();
}
}
private void simulate(){
if(mSimulationListener != null){
mSimulationListener.initializeSimulation();
}
while(mMainLoopRunning){
if(mSimulationListener != null && !mSimulationListener.isInitializingSimulation() && mRenderingListener != null && !mRenderingListener.isInitializingRendering()){
mDeltaTime = (System.nanoTime() - mLastSimulationIteration) / 1000000000.0f;
mLastSimulationIteration = System.nanoTime();
mSimulationListener.simulationIteration(mDeltaTime);
}
}
}
public void startIterations(){
mMainLoopRunning = true;
mRenderingThread.start();
mSimulationThread.start();
}
public void stopIterations(){
mMainLoopRunning = false;
boolean retry = true;
//stop the rendering thread
while (retry) {
try {
mRenderingThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
//stop the simulation thread
retry = true;
while (retry) {
try {
mSimulationThread.join();
retry = false;
} catch (InterruptedException e) {
// ...
}
}
}
public void setSimulationListener(SimulationListener simulationListener) {
mSimulationListener = simulationListener;
}
public void setRenderingListener(RenderingListener renderingListener) {
mRenderingListener = renderingListener;
}
/**
* @return the frames per second
*/
public int getFPS(){
return mFPS;
}
/**
* Called when the accuracy of the Sensor has changed.
* @param sensor
* @param accuracy
*/
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy){
// we ignore this
}
/**
* Called when the sensor has new input
* @param event The SensorEvent
*/
@Override
public void onSensorChanged(SensorEvent event){
System.arraycopy( event.values, 0, mAcceleration, 0, 3 );
}
/**
* @return the delta time in seconds
*/
public float getDeltaTime( ){
return mDeltaTime;
}
/**
* @return the last known touch coordinate on the x axis
*/
public int getTouchX( ){
return mTouchX;
}
/**
* @return the last known touch coordinate on the x axis
*/
public int getTouchY( ) {
return mTouchY;
}
/**
* @return whether the touch screen is touched or not
*/
public boolean isTouched( ) {
return mIsTouched;
}
/**
* @return the acceleration on the x-Axis of the device
*/
public float getAccelerationOnXAxis( ){
return mAcceleration[0];
}
/**
* @return the acceleration on the x-Axis of the device
*/
public float getAccelerationOnYAxis( ){
return mAcceleration[1];
}
/**
* @return the acceleration on the x-Axis of the device
*/
public float getAccelerationOnZAxis( ){
return mAcceleration[2];
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
//implement something, if this can happen in your game
}
/**
* called when the surface created
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
//start the two main threads
startIterations();
}
/**
* called when the surface is destroyed
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//stop the two main threads
stopIterations();
}
}
|