Skip to content

Instantly share code, notes, and snippets.

@robsbots
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robsbots/9735778 to your computer and use it in GitHub Desktop.
Save robsbots/9735778 to your computer and use it in GitHub Desktop.
Game file as of week 5. Sounds, lives, ball speed up on score
package uk.ac.reading.sis05kol.mooc;
//Other parts of the android libraries that we use
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.media.AudioManager;
import android.media.SoundPool;
public class TheGame extends GameThread{
//Will store the image of a ball
private Bitmap mBall;
//The X and Y position of the ball on the screen
//The point is the top left corner, not middle, of the ball
//Initially at -100 to avoid them being drawn in 0,0 of the screen
private float mBallX = -100;
private float mBallY = -100;
//The speed (pixel/second) of the ball in direction X and Y
private float mBallSpeedX = 0;
private float mBallSpeedY = 0;
//Will store the image of the Paddle used to hit the ball
private Bitmap mPaddle;
//Paddle's x position. Y will always be the bottom of the screen
private float mPaddleX = 0;
//Will store the image of the smiley ball (score ball)
private Bitmap mSmileyBall;
//The X and Y position of the ball on the screen
//The point is the top left corner, not middle, of the ball
//Initially at -100 to avoid them being drawn in 0,0 of the screen
private float mSmileyBallX = -100;
private float mSmileyBallY = -100;
//Will store the image of the smiley ball (score ball)
private Bitmap mSadBall;
//The X and Y position of the SadBalls on the screen
//The point is the top left corner, not middle, of the balls
//Initially at -100 to avoid them being drawn in 0,0 of the screen
private float[] mSadBallX = {-100,-100,-100};
private float[] mSadBallY = new float[3];
//This will store the min distance allowed between a big ball and the small red ball
//This is used to check collisions
private float mMinDistanceBetweenRedBallAndBigBall = 0;
//Create a Soundpool object and load each sound for the game
private SoundPool mSoundPool;
private int mSoundBounce;
private int mSoundLose;
private int mSoundLoseLife;
private int mSoundScore;
private int mSoundPaddle;
private int mSoundNewgame;
//Create a variable to hold the count of lives
private byte mLives;
//This is run before anything else, so we can prepare things here
public TheGame(GameView gameView) {
//House keeping
super(gameView);
//Prepare the image so we can draw it on the screen (using a canvas)
mBall = BitmapFactory.decodeResource
(gameView.getContext().getResources(),
R.drawable.small_red_ball);
//Prepare the image of the paddle so we can draw it on the screen (using a canvas)
mPaddle = BitmapFactory.decodeResource
(gameView.getContext().getResources(),
R.drawable.yellow_ball);
//Prepare the image of the SmileyBall so we can draw it on the screen (using a canvas)
mSmileyBall = BitmapFactory.decodeResource
(gameView.getContext().getResources(),
R.drawable.smiley_ball);
//Prepare the image of the SadBall(s) so we can draw it on the screen (using a canvas)
mSadBall = BitmapFactory.decodeResource
(gameView.getContext().getResources(),
R.drawable.sad_ball);
// Load sound clip for each sound event
mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
//this.getApplicationContext()
mSoundBounce = mSoundPool.load(mContext, R.raw.click, 1);
mSoundLose = mSoundPool.load(mContext, R.raw.sadtrombone, 1);
mSoundScore = mSoundPool.load(mContext, R.raw.score, 1);
mSoundPaddle = mSoundPool.load(mContext, R.raw.bounce, 1);
mSoundNewgame = mSoundPool.load(mContext, R.raw.start, 1);
mSoundLoseLife = mSoundPool.load(mContext, R.raw.clang, 1);
}
//This is run before a new game (also after an old game)
@Override
public void setupBeginning() {
//Initialise speeds
//mCanvasWidth and mCanvasHeight are declared and managed elsewhere
mBallSpeedX = mCanvasWidth / 3;
mBallSpeedY = mCanvasHeight / 3;
//Place the ball in the middle of the screen.
//mBall.Width() and mBall.getHeigh() gives us the height and width of the image of the ball
mBallX = mCanvasWidth / 2;
mBallY = mCanvasHeight / 2;
//Place Paddle in the middle of the screen
mPaddleX = mCanvasWidth / 2;
//Place SmileyBall in the top middle of the screen
mSmileyBallX = mCanvasWidth / 2;
mSmileyBallY = mSmileyBall.getHeight()/2;
//Place all SadBalls forming a pyramid underneath the SmileyBall
mSadBallX[0] = mCanvasWidth / 3;
mSadBallY[0] = mCanvasHeight / 3;
mSadBallX[1] = mCanvasWidth - mCanvasWidth / 3;
mSadBallY[1] = mCanvasHeight / 3;
mSadBallX[2] = mCanvasWidth / 2;
mSadBallY[2] = mCanvasHeight / 5;
//Get the minimum distance between a small ball and a bigball
//We leave out the square root to limit the calculations of the program
//Remember to do that when testing the distance as well
mMinDistanceBetweenRedBallAndBigBall = (mPaddle.getWidth() / 2 + mBall.getWidth() / 2) * (mPaddle.getWidth() / 2 + mBall.getWidth() / 2);
// Play a sound when the game starts
mSoundPool.play(mSoundNewgame, 100, 100, 1, 0, 1.0f);
// Set number of lives to 3
mLives=3;
}
@Override
protected void doDraw(Canvas canvas) {
//If there isn't a canvas to do nothing
//It is ok not understanding what is happening here
if(canvas == null) return;
//House keeping
super.doDraw(canvas);
//canvas.drawBitmap(bitmap, x, y, paint) uses top/left corner of bitmap as 0,0
//we use 0,0 in the middle of the bitmap, so negate half of the width and height of the ball to draw the ball as expected
//A paint of null means that we will use the image without any extra features (called Paint)
//draw the image of the ball using the X and Y of the ball
canvas.drawBitmap(mBall, mBallX - mBall.getWidth() / 2, mBallY - mBall.getHeight() / 2, null);
//Draw Paddle using X of paddle and the bottom of the screen (top/left is 0,0)
canvas.drawBitmap(mPaddle, mPaddleX - mPaddle.getWidth() / 2, mCanvasHeight - mPaddle.getHeight() / 2, null);
//Draw SmileyBall
canvas.drawBitmap(mSmileyBall, mSmileyBallX - mSmileyBall.getWidth() / 2, mSmileyBallY - mSmileyBall.getHeight() / 2, null);
//Loop through all SadBall
for(int i = 0; i < mSadBallX.length; i++) {
//Draw SadBall in position i
canvas.drawBitmap(mSadBall, mSadBallX[i] - mSadBall.getWidth() / 2, mSadBallY[i] - mSadBall.getHeight() / 2, null);
}
// for each life we currently have draw a red ball in the top left of the screen
for(int i = 0; i < mLives; i++) {
canvas.drawBitmap(mBall, (i*30)+5, 20, null);
}
}
//This is run whenever the phone is touched by the user
@Override
protected void actionOnTouch(float x, float y) {
//Increase/decrease the speed of the ball making the ball move towards the touch
mPaddleX = x;
//mPaddleX = x - mPaddle.getWidth() / 2;
}
//This is run whenever the phone moves around its axises
@Override
protected void actionWhenPhoneMoved(float xDirection, float yDirection, float zDirection) {
//Ensure the paddle stays on the screen
if(mPaddleX >= 0 && mPaddleX <= mCanvasWidth) {
//Change the X value according to the x direction of the phone
mPaddleX = mPaddleX - xDirection;
//after movement ensure it is still on the screen
if(mPaddleX < 0) mPaddleX = 0;
if(mPaddleX > mCanvasWidth) mPaddleX = mCanvasWidth;
}
}
//This is run just before the game "scenario" is printed on the screen
@Override
protected void updateGame(float secondsElapsed) {
float distanceBetweenBallAndPaddle;
//If the ball moves down on the screen perform potential paddle collision
if(mBallSpeedY > 0) {
//Get actual distance (without square root - remember?) between the mBall and the ball being checked
distanceBetweenBallAndPaddle = (mPaddleX - mBallX) * (mPaddleX - mBallX) + (mCanvasHeight - mBallY) *(mCanvasHeight - mBallY);
//Check if the actual distance is lower than the allowed => collision
if(mMinDistanceBetweenRedBallAndBigBall >= distanceBetweenBallAndPaddle) {
//Get the present velocity (this should also be the velocity going away after the collision)
float velocityOfBall = (float) Math.sqrt(mBallSpeedX*mBallSpeedX + mBallSpeedY*mBallSpeedY);
//Change the direction of the ball
mBallSpeedX = mBallX - mPaddleX;
mBallSpeedY = mBallY - mCanvasHeight;
//Get the velocity after the collision
float newVelocity = (float) Math.sqrt(mBallSpeedX*mBallSpeedX + mBallSpeedY*mBallSpeedY);
//using the fraction between the original velocity and present velocity to calculate the needed
//speeds in X and Y to get the original velocity but with the new angle.
mBallSpeedX = mBallSpeedX * velocityOfBall / newVelocity;
mBallSpeedY = mBallSpeedY * velocityOfBall / newVelocity;
// Play sound when paddle hit
mSoundPool.play(mSoundPaddle, 100, 100, 1, 0, 1.0f);
}
}
//Move the ball's X and Y using the speed (pixel/sec)
mBallX = mBallX + secondsElapsed * mBallSpeedX;
mBallY = mBallY + secondsElapsed * mBallSpeedY;
//Check if the ball hits either the left side or the right side of the screen
//But only do something if the ball is moving towards that side of the screen
//If it does that => change the direction of the ball in the X direction
if((mBallX <= mBall.getWidth() / 2 && mBallSpeedX < 0) || (mBallX >= mCanvasWidth - mBall.getWidth() / 2 && mBallSpeedX > 0) ) {
mBallSpeedX = -mBallSpeedX;
// Play sound when ball hits left or right side of screen
mSoundPool.play(mSoundBounce, 100, 100, 1, 0, 1.0f);
}
distanceBetweenBallAndPaddle = (mSmileyBallX - mBallX) * (mSmileyBallX - mBallX) + (mSmileyBallY - mBallY) *(mSmileyBallY - mBallY);
//Check if the actual distance is lower than the allowed => collision
if(mMinDistanceBetweenRedBallAndBigBall >= distanceBetweenBallAndPaddle) {
//Get the present velocity (this should also be the velocity going away after the collision)
float velocityOfBall = (float) Math.sqrt(mBallSpeedX*mBallSpeedX + mBallSpeedY*mBallSpeedY);
//Change the direction of the ball
mBallSpeedX = mBallX - mSmileyBallX;
mBallSpeedY = mBallY - mSmileyBallY;
//Get the velocity after the collision
float newVelocity = (float) Math.sqrt(mBallSpeedX*mBallSpeedX + mBallSpeedY*mBallSpeedY);
//using the fraction between the original velocity and present velocity to calculate the needed
//speeds in X and Y to get the original velocity but with the new angle.
mBallSpeedX = mBallSpeedX * velocityOfBall / newVelocity;
mBallSpeedY = mBallSpeedY * velocityOfBall / newVelocity;
// Speed up ball by 5% on every score
mBallSpeedX = mBallSpeedX * 1.05f;
mBallSpeedY = mBallSpeedY * 1.05f;
// Play sound when ball hits target
mSoundPool.play(mSoundScore, 100, 100, 1, 0, 1.0f);
//Increase score
updateScore(1);
}
//Loop through all SadBalls
for(int i = 0; i < mSadBallX.length; i++) {
//Perform collisions (if necessary) between SadBall in position i and the red ball
//Get actual distance (without square root - remember?) between the mBall and the ball being checked
distanceBetweenBallAndPaddle = (mSadBallX[i] - mBallX) * (mSadBallX[i] - mBallX) + (mSadBallY[i] - mBallY) *(mSadBallY[i] - mBallY);
//Check if the actual distance is lower than the allowed => collision
if(mMinDistanceBetweenRedBallAndBigBall >= distanceBetweenBallAndPaddle) {
//Get the present velocity (this should also be the velocity going away after the collision)
float velocityOfBall = (float) Math.sqrt(mBallSpeedX*mBallSpeedX + mBallSpeedY*mBallSpeedY);
//Change the direction of the ball
mBallSpeedX = mBallX - mSadBallX[i];
mBallSpeedY = mBallY - mSadBallY[i];
//Get the velocity after the collision
float newVelocity = (float) Math.sqrt(mBallSpeedX*mBallSpeedX + mBallSpeedY*mBallSpeedY);
//using the fraction between the original velocity and present velocity to calculate the needed
//speeds in X and Y to get the original velocity but with the new angle.
mBallSpeedX = mBallSpeedX * velocityOfBall / newVelocity;
mBallSpeedY = mBallSpeedY * velocityOfBall / newVelocity;
mSoundPool.play(mSoundPaddle, 100, 100, 1, 0, 1.0f);
}
}
//If the ball goes out of the top of the screen and moves towards the top of the screen =>
//change the direction of the ball in the Y direction
if(mBallY <= mBall.getWidth() / 2 && mBallSpeedY < 0) {
mBallSpeedY = -mBallSpeedY;
// Play sound when ball hits top of screen
mSoundPool.play(mSoundBounce, 100, 100, 1, 0, 1.0f);
}
//If the ball goes out of the bottom of the screen => lose the game
if(mBallY >= mCanvasHeight) {
// Play sound when paddle misses ball
mSoundPool.play(mSoundLoseLife, 100, 100, 1, 0, 1.0f);
// Decrease count of lives by one
mLives--;
// Have we run out of lives
if(mLives==0) {
// We are out of lives. Play sad sound and end game
mSoundPool.play(mSoundLose, 100, 100, 1, 0, 1.0f);
setState(GameThread.STATE_LOSE);
}
else {
// We still have some lives left. Pause the game
setState(GameThread.STATE_PAUSE);
//Place the ball in the middle of the screen.
mBallX = mCanvasWidth / 2;
mBallY = mCanvasHeight / 2;
//Reset ball speed to starting speed
mBallSpeedX = mCanvasWidth / 3;
mBallSpeedY = mCanvasHeight / 3;
}
}
}
}
// 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