Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
GameThread as of week 5. Only one line needs chaning. This is for the soundpool setup
package uk.ac.reading.sis05kol.mooc;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
public abstract class GameThread extends Thread {
//Different mMode states
public static final int STATE_LOSE = 1;
public static final int STATE_PAUSE = 2;
public static final int STATE_READY = 3;
public static final int STATE_RUNNING = 4;
public static final int STATE_WIN = 5;
//Control variable for the mode of the game (e.g. STATE_WIN)
protected int mMode = 1;
//Control of the actual running inside run()
private boolean mRun = false;
//The surface this thread (and only this thread) writes upon
private SurfaceHolder mSurfaceHolder;
//the message handler to the View/Activity thread
private Handler mHandler;
//Android Context - this stores almost all we need to know
//private Context mContext;
// ####################################################################################
// # Changed to enable sound in the game. mContext needs to be available for SoundPool
protected Context mContext;
//The view
public GameView mGameView;
//We might want to extend this call - therefore protected
protected int mCanvasWidth = 1;
protected int mCanvasHeight = 1;
//Last time we updated the game physics
protected long mLastTime = 0;
protected Bitmap mBackgroundImage;
protected long score = 0;
private long now;
private float elapsed;
public GameThread(GameView gameView) {
mGameView = gameView;
mSurfaceHolder = gameView.getHolder();
mHandler = gameView.getmHandler();
mContext = gameView.getContext();
mBackgroundImage = BitmapFactory.decodeResource
(gameView.getContext().getResources(),
R.drawable.background);
}
/*
* Called when app is destroyed, so not really that important here
* But if (later) the game involves more thread, we might need to stop a thread, and then we would need this
* Dare I say memory leak...
*/
public void cleanup() {
this.mContext = null;
this.mGameView = null;
this.mHandler = null;
this.mSurfaceHolder = null;
}
//Pre-begin a game
abstract public void setupBeginning();
//Starting up the game
public void doStart() {
synchronized(mSurfaceHolder) {
setupBeginning();
mLastTime = System.currentTimeMillis() + 100;
setState(STATE_RUNNING);
setScore(0);
}
}
//The thread start
@Override
public void run() {
Canvas canvasRun;
while (mRun) {
canvasRun = null;
try {
canvasRun = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if (mMode == STATE_RUNNING) {
updatePhysics();
}
doDraw(canvasRun);
}
}
finally {
if (canvasRun != null) {
if(mSurfaceHolder != null)
mSurfaceHolder.unlockCanvasAndPost(canvasRun);
}
}
}
}
/*
* Surfaces and drawing
*/
public void setSurfaceSize(int width, int height) {
synchronized (mSurfaceHolder) {
mCanvasWidth = width;
mCanvasHeight = height;
// don't forget to resize the background image
mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true);
}
}
protected void doDraw(Canvas canvas) {
if(canvas == null) return;
if(mBackgroundImage != null) canvas.drawBitmap(mBackgroundImage, 0, 0, null);
}
private void updatePhysics() {
now = System.currentTimeMillis();
elapsed = (now - mLastTime) / 1000.0f;
updateGame(elapsed);
mLastTime = now;
}
abstract protected void updateGame(float secondsElapsed);
/*
* Control functions
*/
//Finger touches the screen
public boolean onTouch(MotionEvent e) {
if(e.getAction() != MotionEvent.ACTION_DOWN) return false;
if(mMode == STATE_READY || mMode == STATE_LOSE || mMode == STATE_WIN) {
doStart();
return true;
}
if(mMode == STATE_PAUSE) {
unpause();
return true;
}
synchronized (mSurfaceHolder) {
this.actionOnTouch(e.getRawX(), e.getRawY());
}
return false;
}
protected void actionOnTouch(float x, float y) {
//Override to do something
}
//The Accellerometer has changed
@SuppressWarnings("deprecation")
public void onSensorChanged(SensorEvent event) {
synchronized (mSurfaceHolder) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
actionWhenPhoneMoved(event.values[2],event.values[1], event.values[0]);
}
}
}
protected void actionWhenPhoneMoved(float xDirection, float yDirection, float zDirection) {
//Override to do something
}
/*
* Game states
*/
public void pause() {
synchronized (mSurfaceHolder) {
if (mMode == STATE_RUNNING) setState(STATE_PAUSE);
}
}
public void unpause() {
// Move the real time clock up to now
synchronized (mSurfaceHolder) {
mLastTime = System.currentTimeMillis();
}
setState(STATE_RUNNING);
}
//Send messages to View/Activity thread
public void setState(int mode) {
synchronized (mSurfaceHolder) {
setState(mode, null);
}
}
public void setState(int mode, CharSequence message) {
synchronized (mSurfaceHolder) {
mMode = mode;
if (mMode == STATE_RUNNING) {
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putString("text", "");
b.putInt("viz", View.INVISIBLE);
b.putBoolean("showAd", false);
msg.setData(b);
mHandler.sendMessage(msg);
}
else {
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
Resources res = mContext.getResources();
CharSequence str = "";
if (mMode == STATE_READY)
str = res.getText(R.string.mode_ready);
else
if (mMode == STATE_PAUSE)
str = res.getText(R.string.mode_pause);
else
if (mMode == STATE_LOSE)
str = res.getText(R.string.mode_lose);
else
if (mMode == STATE_WIN) {
str = res.getText(R.string.mode_win);
}
if (message != null) {
str = message + "\n" + str;
}
b.putString("text", str.toString());
b.putInt("viz", View.VISIBLE);
msg.setData(b);
mHandler.sendMessage(msg);
}
}
}
/*
* Getter and setter
*/
public void setSurfaceHolder(SurfaceHolder h) {
mSurfaceHolder = h;
}
public boolean isRunning() {
return mRun;
}
public void setRunning(boolean running) {
mRun = running;
}
public int getMode() {
return mMode;
}
public void setMode(int mMode) {
this.mMode = mMode;
}
/* ALL ABOUT SCORES */
//Send a score to the View to view
//Would it be better to do this inside this thread writing it manually on the screen?
public void setScore(long score) {
this.score = score;
synchronized (mSurfaceHolder) {
Message msg = mHandler.obtainMessage();
Bundle b = new Bundle();
b.putBoolean("score", true);
b.putString("text", getScoreString().toString());
msg.setData(b);
mHandler.sendMessage(msg);
}
}
public float getScore() {
return score;
}
public void updateScore(long score) {
this.setScore(this.score + score);
}
protected CharSequence getScoreString() {
return Long.toString(Math.round(this.score));
}
}
// This file is part of the course "Begin Programming: Build your first mobile game" from futurelearn.com
// Copyright: University of Reading and Karsten Lundqvist
// It is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// It is is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License
// along with it. If not, see <http://www.gnu.org/licenses/>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.