|
Android example source code file (AirHockey.java)
The AirHockey.java Android example source code
package net.clc.bt;
import net.clc.bt.Connection.OnConnectionLostListener;
import net.clc.bt.Connection.OnConnectionServiceReadyListener;
import net.clc.bt.Connection.OnIncomingConnectionListener;
import net.clc.bt.Connection.OnMaxConnectionsReachedListener;
import net.clc.bt.Connection.OnMessageReceivedListener;
import net.clc.bt.Demo_Ball.BOUNCE_TYPE;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.view.WindowManager.BadTokenException;
import android.widget.Toast;
import java.util.ArrayList;
public class AirHockey extends Activity implements Callback {
public static final String TAG = "AirHockey";
private static final int SERVER_LIST_RESULT_CODE = 42;
public static final int UP = 3;
public static final int DOWN = 4;
public static final int FLIPTOP = 5;
private AirHockey self;
private int mType; // 0 = server, 1 = client
private SurfaceView mSurface;
private SurfaceHolder mHolder;
private Paint bgPaint;
private Paint goalPaint;
private Paint ballPaint;
private Paint paddlePaint;
private PhysicsLoop pLoop;
private ArrayList<Point> mPaddlePoints;
private ArrayList<Long> mPaddleTimes;
private int mPaddlePointWindowSize = 5;
private int mPaddleRadius = 55;
private Bitmap mPaddleBmp;
private Demo_Ball mBall;
private int mBallRadius = 40;
private Connection mConnection;
private String rivalDevice = "";
private SoundPool mSoundPool;
private int tockSound = 0;
private MediaPlayer mPlayer;
private int hostScore = 0;
private int clientScore = 0;
private OnMessageReceivedListener dataReceivedListener = new OnMessageReceivedListener() {
public void OnMessageReceived(String device, String message) {
if (message.indexOf("SCORE") == 0) {
String[] scoreMessageSplit = message.split(":");
hostScore = Integer.parseInt(scoreMessageSplit[1]);
clientScore = Integer.parseInt(scoreMessageSplit[2]);
showScore();
} else {
mBall.restoreState(message);
}
}
};
private OnMaxConnectionsReachedListener maxConnectionsListener = new OnMaxConnectionsReachedListener() {
public void OnMaxConnectionsReached() {
}
};
private OnIncomingConnectionListener connectedListener = new OnIncomingConnectionListener() {
public void OnIncomingConnection(String device) {
rivalDevice = device;
WindowManager w = getWindowManager();
Display d = w.getDefaultDisplay();
int width = d.getWidth();
int height = d.getHeight();
mBall = new Demo_Ball(true, width, height - 60);
mBall.putOnScreen(width / 2, (height / 2 + (int) (height * .05)), 0, 0, 0, 0, 0);
}
};
private OnConnectionLostListener disconnectedListener = new OnConnectionLostListener() {
public void OnConnectionLost(String device) {
class displayConnectionLostAlert implements Runnable {
public void run() {
Builder connectionLostAlert = new Builder(self);
connectionLostAlert.setTitle("Connection lost");
connectionLostAlert
.setMessage("Your connection with the other player has been lost.");
connectionLostAlert.setPositiveButton("Ok", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
connectionLostAlert.setCancelable(false);
try {
connectionLostAlert.show();
} catch (BadTokenException e){
// Something really bad happened here;
// seems like the Activity itself went away before
// the runnable finished.
// Bail out gracefully here and do nothing.
}
}
}
self.runOnUiThread(new displayConnectionLostAlert());
}
};
private OnConnectionServiceReadyListener serviceReadyListener = new OnConnectionServiceReadyListener() {
public void OnConnectionServiceReady() {
if (mType == 0) {
mConnection.startServer(1, connectedListener, maxConnectionsListener,
dataReceivedListener, disconnectedListener);
self.setTitle("Air Hockey: " + mConnection.getName() + "-" + mConnection.getAddress());
} else {
WindowManager w = getWindowManager();
Display d = w.getDefaultDisplay();
int width = d.getWidth();
int height = d.getHeight();
mBall = new Demo_Ball(false, width, height - 60);
Intent serverListIntent = new Intent(self, ServerListActivity.class);
startActivityForResult(serverListIntent, SERVER_LIST_RESULT_CODE);
}
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
self = this;
mPaddleBmp = BitmapFactory.decodeResource(getResources(), R.drawable.paddlelarge);
mPaddlePoints = new ArrayList<Point>();
mPaddleTimes = new ArrayList<Long>();
Intent startingIntent = getIntent();
mType = startingIntent.getIntExtra("TYPE", 0);
setContentView(R.layout.main);
mSurface = (SurfaceView) findViewById(R.id.surface);
mHolder = mSurface.getHolder();
bgPaint = new Paint();
bgPaint.setColor(Color.BLACK);
goalPaint = new Paint();
goalPaint.setColor(Color.RED);
ballPaint = new Paint();
ballPaint.setColor(Color.GREEN);
ballPaint.setAntiAlias(true);
paddlePaint = new Paint();
paddlePaint.setColor(Color.BLUE);
paddlePaint.setAntiAlias(true);
mPlayer = MediaPlayer.create(this, R.raw.collision);
mConnection = new Connection(this, serviceReadyListener);
mHolder.addCallback(self);
}
@Override
protected void onDestroy() {
if (mConnection != null) {
mConnection.shutdown();
}
if (mPlayer != null) {
mPlayer.release();
}
super.onDestroy();
}
public void surfaceCreated(SurfaceHolder holder) {
pLoop = new PhysicsLoop();
pLoop.start();
}
private void draw() {
Canvas canvas = null;
try {
canvas = mHolder.lockCanvas();
if (canvas != null) {
doDraw(canvas);
}
} finally {
if (canvas != null) {
mHolder.unlockCanvasAndPost(canvas);
}
}
}
private void doDraw(Canvas c) {
c.drawRect(0, 0, c.getWidth(), c.getHeight(), bgPaint);
c.drawRect(0, c.getHeight() - (int) (c.getHeight() * 0.02), c.getWidth(), c.getHeight(),
goalPaint);
if (mPaddleTimes.size() > 0) {
Point p = mPaddlePoints.get(mPaddlePoints.size() - 1);
// Debug circle
// Point debugPaddleCircle = getPaddleCenter();
// c.drawCircle(debugPaddleCircle.x, debugPaddleCircle.y,
// mPaddleRadius, ballPaint);
if (p != null) {
c.drawBitmap(mPaddleBmp, p.x - 60, p.y - 200, new Paint());
}
}
if ((mBall == null) || !mBall.isOnScreen()) {
return;
}
float x = mBall.getX();
float y = mBall.getY();
if ((x != -1) && (y != -1)) {
float xv = mBall.getXVelocity();
Bitmap bmp = BitmapFactory
.decodeResource(this.getResources(), R.drawable.android_right);
if (xv < 0) {
bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.android_left);
}
// Debug circle
Point debugBallCircle = getBallCenter();
// c.drawCircle(debugBallCircle.x, debugBallCircle.y, mBallRadius,
// ballPaint);
c.drawBitmap(bmp, x - 17, y - 23, new Paint());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
try {
pLoop.safeStop();
} finally {
pLoop = null;
}
}
private class PhysicsLoop extends Thread {
private volatile boolean running = true;
@Override
public void run() {
while (running) {
try {
Thread.sleep(5);
draw();
if (mBall != null) {
handleCollision();
int position = mBall.update();
mBall.setAcceleration(0, 0);
if (position != 0) {
if ((position == UP) && (rivalDevice.length() > 1)) {
mConnection.sendMessage(rivalDevice, mBall.getState() + "|"
+ FLIPTOP);
} else if (position == DOWN) {
if (mType == 0) {
clientScore = clientScore + 1;
} else {
hostScore = hostScore + 1;
}
mConnection.sendMessage(rivalDevice, "SCORE:" + hostScore + ":"
+ clientScore);
showScore();
WindowManager w = getWindowManager();
Display d = w.getDefaultDisplay();
int width = d.getWidth();
int height = d.getHeight();
mBall.putOnScreen(width / 2, (height / 2 + (int) (height * .05)),
0, 0, 0, 0, 0);
} else {
mBall.doRebound();
}
}
}
} catch (InterruptedException ie) {
running = false;
}
}
}
public void safeStop() {
running = false;
interrupt();
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((resultCode == Activity.RESULT_OK) && (requestCode == SERVER_LIST_RESULT_CODE)) {
String device = data.getStringExtra(ServerListActivity.EXTRA_SELECTED_ADDRESS);
int connectionStatus = mConnection.connect(device, dataReceivedListener,
disconnectedListener);
if (connectionStatus != Connection.SUCCESS) {
Toast.makeText(self, "Unable to connect; please try again.", 1).show();
} else {
rivalDevice = device;
}
return;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Point p = new Point((int) event.getX(), (int) event.getY());
mPaddlePoints.add(p);
mPaddleTimes.add(System.currentTimeMillis());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
Point p = new Point((int) event.getX(), (int) event.getY());
mPaddlePoints.add(p);
mPaddleTimes.add(System.currentTimeMillis());
if (mPaddleTimes.size() > mPaddlePointWindowSize) {
mPaddleTimes.remove(0);
mPaddlePoints.remove(0);
}
} else {
mPaddleTimes = new ArrayList<Long>();
mPaddlePoints = new ArrayList<Point>();
}
return false;
}
// TODO: Scale this for G1 sized screens
public Point getBallCenter() {
if (mBall == null) {
return new Point(-1, -1);
}
int x = (int) mBall.getX();
int y = (int) mBall.getY();
return new Point(x + 10, y + 12);
}
// TODO: Scale this for G1 sized screens
public Point getPaddleCenter() {
if (mPaddleTimes.size() > 0) {
Point p = mPaddlePoints.get(mPaddlePoints.size() - 1);
int x = p.x + 10;
int y = p.y - 130;
return new Point(x, y);
} else {
return new Point(-1, -1);
}
}
private void showScore() {
class showScoreRunnable implements Runnable {
public void run() {
String scoreString = "";
if (mType == 0) {
scoreString = hostScore + " - " + clientScore;
} else {
scoreString = clientScore + " - " + hostScore;
}
Toast.makeText(self, scoreString, 0).show();
}
}
self.runOnUiThread(new showScoreRunnable());
}
private void handleCollision() {
// TODO: Handle multiball case
if (mBall == null) {
return;
}
if (mPaddleTimes.size() < 1) {
return;
}
Point ballCenter = getBallCenter();
Point paddleCenter = getPaddleCenter();
final int dy = ballCenter.y - paddleCenter.y;
final int dx = ballCenter.x - paddleCenter.x;
final float distance = dy * dy + dx * dx;
if (distance < ((2 * mBallRadius) * (2 * mPaddleRadius))) {
// Get paddle velocity
float vX = 0;
float vY = 0;
Point endPoint = new Point(-1, -1);
Point startPoint = new Point(-1, -1);
long timeDiff = 0;
try {
endPoint = mPaddlePoints.get(mPaddlePoints.size() - 1);
startPoint = mPaddlePoints.get(0);
timeDiff = mPaddleTimes.get(mPaddleTimes.size() - 1) - mPaddleTimes.get(0);
} catch (IndexOutOfBoundsException e) {
// Paddle points were removed at the last moment
return;
}
if (timeDiff > 0) {
vX = ((float) (endPoint.x - startPoint.x)) / timeDiff;
vY = ((float) (endPoint.y - startPoint.y)) / timeDiff;
}
// Determine the bounce type
BOUNCE_TYPE bounceType = BOUNCE_TYPE.TOP;
if ((ballCenter.x < (paddleCenter.x - mPaddleRadius / 2))
&& (ballCenter.y < (paddleCenter.y - mPaddleRadius / 2))) {
bounceType = BOUNCE_TYPE.TOPLEFT;
} else if ((ballCenter.x > (paddleCenter.x + mPaddleRadius / 2))
&& (ballCenter.y < (paddleCenter.y - mPaddleRadius / 2))) {
bounceType = BOUNCE_TYPE.TOPRIGHT;
} else if ((ballCenter.x < (paddleCenter.x - mPaddleRadius / 2))
&& (ballCenter.y > (paddleCenter.y + mPaddleRadius / 2))) {
bounceType = BOUNCE_TYPE.BOTTOMLEFT;
} else if ((ballCenter.x > (paddleCenter.x + mPaddleRadius / 2))
&& (ballCenter.y > (paddleCenter.y + mPaddleRadius / 2))) {
bounceType = BOUNCE_TYPE.BOTTOMRIGHT;
} else if ((ballCenter.x < paddleCenter.x)
&& (ballCenter.y > (paddleCenter.y - mPaddleRadius / 2))
&& (ballCenter.y < (paddleCenter.y + mPaddleRadius / 2))) {
bounceType = BOUNCE_TYPE.LEFT;
} else if ((ballCenter.x > paddleCenter.x)
&& (ballCenter.y > (paddleCenter.y - mPaddleRadius / 2))
&& (ballCenter.y < (paddleCenter.y + mPaddleRadius / 2))) {
bounceType = BOUNCE_TYPE.RIGHT;
} else if ((ballCenter.x > (paddleCenter.x - mPaddleRadius / 2))
&& (ballCenter.x < (paddleCenter.x + mPaddleRadius / 2))
&& (ballCenter.y > paddleCenter.y)) {
bounceType = BOUNCE_TYPE.RIGHT;
}
mBall.doBounce(bounceType, vX, vY);
if (!mPlayer.isPlaying()) {
mPlayer.release();
mPlayer = MediaPlayer.create(this, R.raw.collision);
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mPlayer.start();
}
}
}
}
Other Android examples (source code examples)Here is a short list of links related to this Android AirHockey.java source code file: |
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.