TiltBall.java – 2
There was a problem in the threading system of the previous copy of this code. The application worked perfectly with the standard lock screen, but when you locked the screen with something like WidgetLocker while running it, the app froze and had to be killed before it would work correctly again. This is the updated code.
TiltBallActivity.java
package com.tornquist.nathan;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class TiltBallActivity extends Activity{
/** Called when the activity is first created. */
MainGamePanel viewPanel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Window state functions.
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//This works without declaring a viewPanel instance here.
//The instance declaration is needed to pass the
//onPause and onResume commands though.
viewPanel = new MainGamePanel(this);
setContentView(viewPanel);
}
//Restarts the accelerometer after onPause
protected void onResume() {
super.onResume();
viewPanel.resume(this);
}
//Standard Method run when the Application loses focus.
//This runs the pause() function in the viewPanel so that
//the accelerometer can be paused.
protected void onPause() {
super.onPause();
viewPanel.pause();
}
protected void onDestroy() {
super.onDestroy();
viewPanel.destroy();
}
}
MainGamePanel.java
package com.tornquist.nathan;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainGamePanel extends SurfaceView implements SensorEventListener, SurfaceHolder.Callback
{
//Variable Declarations.
private MainThread thread;
public int xColor;
public int yColor;
public int zColor;
public float xPos;
public float yPos;
public float oldXPos;
public float oldYPos;
public int screenWidth;
public int screenHeight;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
Paint paint;
public MainGamePanel(Context context)
{
//Standard Initialization
super(context);
//This line adds a callback for the touch screen.
//This allows you to actually capture touch input.
getHolder().addCallback(this);
thread = new MainThread(getHolder(),this);
xColor = 100;
yColor = 100;
zColor = 100;
paint = new Paint();
paint.setAntiAlias(true);
Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();
yPos = screenHeight/2;
xPos = screenWidth/2;
oldYPos = yPos;
oldXPos = xPos;
//This registers the accelerometer. Without registering it, the onSensorChanged
//event will never be called, and you cannot get the accelerometer values.
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
//Also required for touch input.
setFocusable(true);
//start thread
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//continue the thread
synchronized (thread) {
thread.pleaseWait = false;
thread.notifyAll();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//pause the thread
synchronized (thread) {
thread.pleaseWait = true;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// check if in the lower part of the screen we exit
if (event.getY() > getHeight() - 50) {
thread.setRunning(false);
((Activity)getContext()).finish();
}
if (xColor < 235)
xColor = xColor + 20;
else
xColor = 0;
if (yColor < 235)
yColor = yColor + 20;
else
yColor = 0;
if (zColor < 235)
zColor = zColor + 20;
else
zColor = 0;
yPos = event.getY();
xPos = event.getX();
}
return true;
}
@Override
protected void onDraw(Canvas canvas)
{
//canvas.drawColor(Color.CYAN);
canvas.drawColor(Color.rgb(xColor, yColor, zColor));
int xInvert = (int) (255 - xColor);
int yInvert = (int) (255 - yColor);
int zInvert = (int) (255 - zColor);
paint.setColor(Color.rgb(xInvert, yInvert, zInvert));
paint.setStyle(Style.FILL);
canvas.drawCircle(xPos, yPos, 50, paint);
}
public void update() {
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
oldYPos = yPos;
oldXPos = xPos;
xColor = (int) (255 + (event.values[0])*11);
if (xColor > 255)
xColor = 255;
if (xColor < 0)
xColor = 0;
yColor = (int) (255 + (event.values[1])*11);
if (yColor > 255)
yColor = 255;
if (yColor < 0)
yColor = 0;
zColor = (int) (255 + (event.values[2])*11);
if (zColor > 255)
zColor = 255;
if (zColor < 0)
zColor = 0;
xPos = xPos + -1*(event.values[0])*5;
yPos = yPos + event.values[1]*5;
if (xPos < 50)
xPos = 50;
if (xPos > screenWidth - 50)
xPos = screenWidth - 50;
if (yPos < 50)
yPos = 50;
if (yPos > screenHeight - 50)
yPos = screenHeight - 50;
if ((oldYPos == yPos) && (oldXPos == xPos))
{
invalidate();
}
}
public void pause() {
mSensorManager.unregisterListener(this);
//thread.setRunning(false);
//((Activity)getContext()).finish();
}
public void resume(Context context) {
//mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
//mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
}
public void destroy() {
thread.setRunning(false);
if (thread != null)
{
Thread killThread = thread;
thread = null;
killThread.interrupt();
}
}
}
MainThread.java
package com.tornquist.nathan;
import com.tornquist.nathan.MainGamePanel;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MainThread extends Thread {
private SurfaceHolder surfaceHolder;
private MainGamePanel gamePanel;
private boolean running;
public boolean pleaseWait = true;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
@Override
public void run()
{
Canvas canvas;
while (running) {
if(!pleaseWait) {
canvas = null;
// try locking the canvas for exclusive pixel editing on the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
// update game state
this.gamePanel.update();
// draws the canvas on the panel
this.gamePanel.onDraw(canvas);
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
else {
synchronized (this) {
try {
wait();
} catch (Exception e) { }
}
}
}
}
}
No comments yet.