Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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,-100,-100};
- private float[] mSadBallY = new float[5];
- // this will hold values for removing sad balls and finally the Smiley Ball from the screen
- private int[] mBallRemove={5,7,10,12,15,20};
- // this will be passed to the ball remove function as a parameter
- private int mBallchk = 0;
- private int mWinStreak = 0;
- //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
- private SoundPool mSoundPool;
- // Create 1 int variable for each sound clip you wish to play in the game
- private int mSoundLose;
- private int mSoundMove;
- private int mSoundExplode;
- private int mSoundEnd;
- // used for logic removing sad balls
- private int mExplodeCount = 0;
- //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 a sound clip for each sound event you want
- // Setup the new sound pool object
- // I have chosen 3 streams. This means you can play 3 sounds
- // at any one time
- mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
- // Load the sounds into soundpool and assign each to an int defined above
- mSoundLose = mSoundPool.load(mContext, R.raw.woe, 1);
- mSoundMove = mSoundPool.load(mContext, R.raw.duh, 2);
- mSoundExplode = mSoundPool.load(mContext, R.raw.explose, 3);
- mSoundEnd = mSoundPool.load(mContext, R.raw.htgot, 4);
- }
- //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;
- if (mWinStreak == 1){
- mSadBallX[3] = mCanvasWidth / 2 -20;
- mSadBallY[3] = mCanvasHeight / 5;
- }
- if (mWinStreak > 1){
- mSadBallX[4] = mCanvasWidth / 2 +20;
- mSadBallY[4] = 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);
- // playEnd();
- }
- @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);
- }
- }
- //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 - 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) {
- //If the ball moves down on the screen
- if(mBallSpeedY > 0) {
- //Check for a paddle collision
- updateBallCollusion(mPaddleX, mCanvasHeight);
- }
- //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;
- }
- // playEnd();
- //Check for SmileyBall collision
- if(updateBallCollusion(mSmileyBallX, mSmileyBallY)) {
- //Increase score
- // Play sounds & bring balls down
- // increment the explode count
- mExplodeCount = mExplodeCount +1;
- // play sound
- mSoundPool.play(mSoundExplode, 100, 100, 1, 0, 1.0f);
- for(int i = 0; i <2; i++) {
- mSoundPool.play(mSoundMove, 100, 100, 1, 0, 1.0f);
- }
- // move the sad balls after each hit on SmileyBall
- moveballs();
- updateScore(1);
- if (mExplodeCount > 15){
- randomSmile();}
- //Place Paddle in the middle of the screen
- setPaddle();
- // check if explode count matches magic numbers & remove sad balls accordingly
- for(int i = 0; i < mBallRemove.length; i++) {
- // check if an entry in the magic numbers matches the explode count
- if (mBallRemove[i] == mExplodeCount) {
- // if it does set the parameter to pass to the remove ball function
- mBallchk = mBallRemove[i];
- }
- }
- // if the remove parameter is set
- if(mBallchk >0);{
- // call the remove function passing the magic value
- removeballs(mBallchk);
- // reset parameter once it is passed otherwise you would get errors
- mBallchk = 0;
- }
- // if last Sad ball randomise position of smile
- if (mExplodeCount > 10){
- randomSmile();}
- }
- //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
- updateBallCollusion(mSadBallX[i], mSadBallY[i]);
- }
- //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;
- }
- //If the ball goes out of the bottom of the screen => lose the game
- if(mBallY >= mCanvasHeight) {
- // Play a sound
- mSoundPool.play(mSoundLose, 100, 100, 1, 0, 1.0f);
- // reset variables and balls
- loseReset();
- // display loose message
- setState(GameThread.STATE_LOSE);
- }
- }
- //Collusion control between mBall and another big ball
- private boolean updateBallCollusion(float x, float y) {
- //Get actual distance (without square root - remember?) between the mBall and the ball being checked
- float distanceBetweenBallAndPaddle = (x - mBallX) * (x - mBallX) + (y - mBallY) *(y - 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 - x;
- mBallSpeedY = mBallY - y;
- //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;
- return true;
- }
- return false;
- }
- public void moveballs(){
- /* this should move sad balls
- from SadBalls pyramid underneath the SmileyBall
- down the screen
- Note I also move Balls 4 & 5 even if they are not present as this save if statements
- */
- mSadBallY[0] = mSadBallY[0] +5;
- mSadBallY[1] = mSadBallY[1] +5;
- mSadBallY[2] = mSadBallY[2] +5;
- mSadBallY[2] = mSadBallY[3] +5;
- mSadBallY[2] = mSadBallY[4] +5;
- }
- public void removeballs(int mBallchk){
- /* this should remove sad balls
- from SadBalls pyramid underneath the SmileyBall
- magic numbers are checked and depending on the value passed in
- the correct sad ball is removed
- Last check is to remove the s
- Smiley ball which is end game
- It also changes position of remaining sad balls
- */
- if (mBallchk == 5 ){
- mSadBallX[0] = -100;
- mSadBallY[0] = -100;
- mSadBallY[1] = mSadBallY[1] +10;
- mSadBallY[2] = mSadBallY[2] +10;
- mSadBallY[3] = mSadBallY[2] +10;
- mSadBallY[4] = mSadBallY[2] +10;
- }
- if (mBallchk == 7 ){
- mSadBallX[0] = -100;
- mSadBallY[0] = -100;
- mSadBallX[3] = -100;
- mSadBallY[3] = -100;
- mSadBallY[1] = mSadBallY[1] +10;
- mSadBallY[2] = mSadBallY[2] +10;
- mSadBallY[4] = mSadBallY[2] +10;
- }
- if (mBallchk == 10){
- mSadBallX[1] = -100;
- mSadBallY[1] = -100;
- mSadBallY[2] = mSadBallY[2] +10;
- mSadBallY[4] = mSadBallY[2] +10;
- }
- if (mBallchk == 15){
- mSadBallX[2] = -100;
- mSadBallY[2] = -100;
- mSadBallX[4] = -100;
- mSadBallY[4] = -100;
- }
- if (mBallchk == 20){
- mSmileyBallX = -100;
- mSmileyBallY = -100;
- playEnd();
- setState(GameThread.STATE_WIN);
- // increment Win Streak
- mWinStreak = mWinStreak + 1;
- }
- }
- public void setPaddle(){
- //Place Paddle in the middle of the screen
- mPaddleX = mCanvasWidth / 2;
- }
- public void randomSmile(){
- int rn = (int) (Math.random() * 20) +1;
- mSmileyBallX = mSmileyBallX + rn;
- mSmileyBallY = mSmileyBallY + rn;
- if (mSmileyBallX > mCanvasWidth){
- mSmileyBallX = (mCanvasWidth / rn);
- }
- if (mSmileyBallY > mCanvasHeight){
- mSmileyBallY = (mCanvasHeight / rn);
- }
- }
- public void loseReset(){
- //called by lose game
- // removes extra balls that will only reappear when win streak > 0
- // reset explode count
- mExplodeCount = 0;
- // reset WinStreak
- mWinStreak = 0;
- // lose extra balls
- mSadBallX[3] = -100;
- mSadBallY[3] = -100;
- mSadBallX[4] = -100;
- mSadBallY[4] = -100;
- }
- public void playEnd(){
- mSoundPool.play(mSoundEnd, 1, 1, 0, 0, 1.0f);
- }
- }
- // 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/>.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement