In this project, we will build a really simple but fun version of the classic Breakout game for Android. Often known as the “Brick breaker game” the history of the game is interesting and if you like nostalgia I urge you to read this history of Breakout. Breakout sometimes called Arkanoid was developed by Atari in the early 1970s and was a kind of spiritual successor to Pong. What made it exciting at the time was that it had all the proven game mechanics of Pong, and some extras but was playable by a single player. Let’s build a Breakout/Arkanoid game.
So what we are left with is a BreakoutView who’s run method constantly calls update and draw whilst keeping track of the frame rate. There is a slight change in the run method as I have wrapped the call to update with an if(!paused) statement so the player can start the game with a touch of the screen. We will build classes to represent the player’s paddle, a single brick, and of course a ball. We will then see how we can use the objects of these classes to make our game.
Create a new project in Android Studio, call it Breakout Game, and name the Activity BreakoutGame then enter the slightly modified simple game engine code below that we have just discussed. You could run this code but all you will get is a blank screen.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; public class BreakoutGame extends Activity { // gameView will be the view of the game // It will also hold the logic of the game // and respond to screen touches as well BreakoutView breakoutView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize gameView and set it as the view breakoutView = new BreakoutView(this); setContentView(breakoutView); } // Here is our implementation of GameView // It is an inner class. // Note how the final closing curly brace } // is inside SimpleGameEngine // Notice we implement runnable so we have // A thread and can override the run method. class BreakoutView extends SurfaceView implements Runnable { // This is our thread Thread gameThread = null; // This is new. We need a SurfaceHolder // When we use Paint and Canvas in a thread // We will see it in action in the draw method soon. SurfaceHolder ourHolder; // A boolean which we will set and unset // when the game is running- or not. volatile boolean playing; // Game is paused at the start boolean paused = true; // A Canvas and a Paint object Canvas canvas; Paint paint; // This variable tracks the game frame rate long fps; // This is used to help calculate the fps private long timeThisFrame; // When the we initialize (call new()) on gameView // This special constructor method runs public BreakoutView(Context context) { // The next line of code asks the // SurfaceView class to set up our object. // How kind. super(context); // Initialize ourHolder and paint objects ourHolder = getHolder(); paint = new Paint(); } @Override public void run() { while (playing) { // Capture the current time in milliseconds in startFrameTime long startFrameTime = System.currentTimeMillis(); // Update the frame // Update the frame if(!paused){ update(); } // Draw the frame draw(); // Calculate the fps this frame // We can then use the result to // time animations and more. timeThisFrame = System.currentTimeMillis() - startFrameTime; if (timeThisFrame >= 1) { fps = 1000 / timeThisFrame; } } } // Everything that needs to be updated goes in here // Movement, collision detection etc. public void update() { } // Draw the newly updated scene public void draw() { // Make sure our drawing surface is valid or we crash if (ourHolder.getSurface().isValid()) { // Lock the canvas ready to draw canvas = ourHolder.lockCanvas(); // Draw the background color canvas.drawColor(Color.argb(255, 26, 128, 182)); // Choose the brush color for drawing paint.setColor(Color.argb(255, 255, 255, 255)); // Draw the paddle // Draw the ball // Draw the bricks // Draw the HUD // Draw everything to the screen ourHolder.unlockCanvasAndPost(canvas); } } // If SimpleGameEngine Activity is paused/stopped // shutdown our thread. public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { Log.e("Error:", "joining thread"); } } // If SimpleGameEngine Activity is started theb // start our thread. public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } // The SurfaceView class implements onTouchListener // So we can override this method and detect screen touches. @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { // Player has touched the screen case MotionEvent.ACTION_DOWN: break; // Player has removed finger from screen case MotionEvent.ACTION_UP: break; } return true; } } // This is the end of our BreakoutView inner class // This method executes when the player starts the game @Override protected void onResume() { super.onResume(); // Tell the gameView resume method to execute breakoutView.resume(); } // This method executes when the player quits the game @Override protected void onPause() { super.onPause(); // Tell the gameView pause method to execute breakoutView.pause(); } } // This is the end of the BreakoutGame class |
Now we will do something else new.
Making the game a full-screen landscape
We want to use every pixel that the device has to offer so we will make changes to the app’s AndroidManifest.xml configuration file.
- In the project explorer pane in Android Studio double click on the manifests folder, this will open up the AndroidManifest.xml file in the code editor.
- In the AndroidManifest.xml file find the following line of code, android:name=".BreakoutGame"
- Immediately below type or copy and paste these two lines to make the game run full screen and lock it in the landscape orientation.
1 2 |
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:screenOrientation="landscape" |
That’s it. If you run the game it will be full-screen and landscape. Note however that some tablets don’t allow true full-screen.
Getting the screen resolution
In this project, we are going to make a much fuller system than in our simple game engine. Having said that we will still not be making a fully featured engine; we will progress steadily in complexity with each game project. One improvement this game will have is that we will detect and respond to the individual device resolutions that our Breakout game might run on. Add two variables to hold the horizontal and vertical resolution of the device just after the declaration of timeThisFrame. For more context, you can see the entire listing of BreakoutGame.java at the end of this page.
1 2 3 |
// The size of the screen in pixels int screenX; int screenY; |
Now we can initialize those variables via an object of the type Point using a Display object in the next block of code. Add this code into the BreakoutView constructor just after we initialize the paint object.
1 2 3 4 5 6 7 8 |
// Get a Display object to access screen details Display display = getWindowManager().getDefaultDisplay(); // Load the resolution into a Point object Point size = new Point(); display.getSize(size); screenX = size.x; screenY = size.y; |
Creating the player paddle
Right-click the java folder in the Android Studio project explorer as shown in the next image.
Now select New|Java class then select …\app\source\main\java and click OK. Now enter Paddle as the name for our new class and click OK. We have now created a new Java class in a separate file called Paddle. The code is not amongst the rest of our code but we can still access it as we will soon see. This helps us to compartmentalize our code and keep it organized into logical areas. We will do the same for our ball and for a brick.
The code for the Paddle class
Let’s code this class in its entirety then we can switch back to the BreakoutGame class and its inner BreakoutView class and put our paddle to work.
Take a look through the entire code listing for the Paddle class. Be sure to read all the comments for clarification we will talk about it afterward. Copy and paste this code below the package declaration in your Paddle.java file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
import android.graphics.RectF; public class Paddle { // RectF is an object that holds four coordinates - just what we need private RectF rect; // How long and high our paddle will be private float length; private float height; // X is the far left of the rectangle which forms our paddle private float x; // Y is the top coordinate private float y; // This will hold the pixels per second speed that the paddle will move private float paddleSpeed; // Which ways can the paddle move public final int STOPPED = 0; public final int LEFT = 1; public final int RIGHT = 2; // Is the paddle moving and in which direction private int paddleMoving = STOPPED; // This the the constructor method // When we create an object from this class we will pass // in the screen width and height public Paddle(int screenX, int screenY){ // 130 pixels wide and 20 pixels high length = 130; height = 20; // Start paddle in roughly the sceen centre x = screenX / 2; y = screenY - 20; rect = new RectF(x, y, x + length, y + height); // How fast is the paddle in pixels per second paddleSpeed = 350; } // This is a getter method to make the rectangle that // defines our paddle available in BreakoutView class public RectF getRect(){ return rect; } // This method will be used to change/set if the paddle is going left, right or nowhere public void setMovementState(int state){ paddleMoving = state; } // This update method will be called from update in BreakoutView // It determines if the paddle needs to move and changes the coordinates // contained in rect if necessary public void update(long fps){ if(paddleMoving == LEFT){ x = x - paddleSpeed / fps; } if(paddleMoving == RIGHT){ x = x + paddleSpeed / fps; } rect.left = x; rect.right = x + length; } } |
Variables, access specifiers, and constants
First of all, before the class declaration we import a class called RectF. We will see RectF in action soon. It basically allows us to create a rectangle based on four float coordinates. This is perfect for representing the coordinates that we need to draw and as we will see when we handle collision detection the RectF class has a method to do all the hard work for us.
Next, we declare a whole bunch of member variables that are self-explanatory apart from one thing which we have not seen before but we did talk about in the Understanding OOP for Java games tutorial. All of the variables have an access specifier; either private or public. The private specifier means that the variable can only be read or changed within this ( Paddle) class and public means that any class that has an object of type Paddle can access it.
The private variables protect themselves from being changed in ways that they were not intended. By doing things this way we improve our code because we control how it operates to within the scope of just this class. It is called encapsulation and as our code gets longer and longer and we add more classes it is invaluable for keeping our code manageable. But if these variables are private, how on earth do we make use of them? We will see how very soon.
Before we do, it also raises the question of why are three of our variables STOPPED, LEFT and RIGHT declared as public. They are not technically variables, they are constants, as defined by the final keyword. They cannot be changed. What they do is they make obvious to classes that use the Paddle class exactly what three states a Paddle object can be in. They can then refer to those states without worrying about how they are used internally in the Paddle class. We will see exactly how they work later in this class and also back in the BreakoutView class when we handle the player’s input.
The Paddle class constructor
Next, we  have the constructor method that starts public void Paddle(...). This is the method that sets up the object when we initialize it. When we initialize an object of the type Paddle we need to pass in values that match those in the signature. In this case, two int variables, screenX and screenY. These variables will hold the screen’s horizontal and vertical resolution of pixels.
Inside the constructor, we then initialize the length and height variables for our future paddle, divide the screen width by two and subtract 20 from the height to get the approximate center bottom of the screen as a starting place for the paddle.
Then we initialized our RectF object by passing in four coordinates x, y, x+ length, y + height. This object now holds four coordinates that start with the top left corner of ( x,y)and completes with the bottom right corner of x+ length, y + height. The constructor will now alter the length and height variables to cope with positioning the paddle almost center bottom of the screen regardless of the device’s screen resolution.
Finally, in the constructor, we set the speed of the paddle to 350 pixels per second by initializing paddleSpeed to 350.
Accessing private variables with getters and setters
The next method is getRect. It is called a getter because it gets the value of variables and returns them. Notice it is public. This means that our BreakoutView class will be able to use it. And look what it does. Just one thing. It returns a copy of rect. BreakoutView will now be able to use this method to get the coordinates of the paddle so it can draw it to the screen or detect if it has hit the ball.
The next method setMovementState does just one thing. It receives a int parameter and assigns it to the private paddleMoving variable. In BreakoutView soon we will use the constant variables STOPPED, LEFT and RIGHT in conjunction with this method to alter the paddleMoving variable. When we do so it will control what happens when the next public method we will see is called.
The Paddle update method explained
The update method of the Paddle class is separate from the update method of our BreakoutView class. Once per frame, the update method of the BreakoutView class will call the update method of the Paddle class. In this update method, the paddle will be assigned new coordinates if necessary, ready for when the draw method is called.
In the update method, we check for two possible conditions paddleMoving == LEFT and paddleMoving == RIGHT. We then change the x coordinate by the speed per second divided by the frames per second passed into the method. After the two if statements we update the starting and finishing ( rect.left and rect.right) coordinates of rect. Notice that if paddleMoving == STOPPED is true then nothing would change that frame.
Now we have coded and discussed the Paddle class we can put it to use.
Using the Paddle class
We will do this in a few steps. As we need to insert code in various different places within our game engine (BreakoutGame.java) I will explain as clearly as possible where each bit of code goes. For absolute clarity check the code listing at the very end of the article where the finished code for the BreakoutGame class including the BreakoutView inner class is listed in its entirety.
First of all, we declare an object of the type Paddle called paddle. You can add this code anywhere after the BreakoutView declaration but before the constructor; I added it after the declaration of screenX and screenY.
1 2 |
// The player's paddle Paddle paddle; |
Now we need to instantiate it. As we need to pass in the screen’s horizontal and vertical resolution. The ideal place to do this is in the BreakoutView constructor after we initialized screenX and screenY.
1 |
paddle = new Paddle(screenX, screenY); |
Now we simply add a call to the paddle object’s update method. This code goes, as we might expect in the update method of the BreakoutView class.
1 2 |
// Move the paddle if required paddle.update(fps); |
Then, in the draw method, we can draw the rectangle that represents the paddle. Notice that when we use drawRect, compared to the Drawing graphics demo project, we replace the actual rectangle coordinates with a call to paddle.getRect. As we discussed this method returns whatever the current coordinates of the paddle are. Add this code to the draw method just after the call to paint.setColor.
1 2 |
// Draw the paddle canvas.drawRect(paddle.getRect(), paint); |
One more step before we can see our paddle in action.
Detecting input and moving the paddle.
Here we will add code to the onTouchEvent method. All we need to do is get the coordinates that the touch occurred at within the ACTION_DOWN case with motionEvent.getX(), we can then determine which half of the screen was pressed by determining if the coordinate is smaller or larger than screenX divided by two. If it’s larger we call setMovementState(paddle.RIGHT), if not we use paddle.LEFT. Also in, ACTION_DOWN case we set paused to false which will start our game engine updating because we wrapped a if(!paused) statement around the call to update in the run method.
Also, notice that for the, ACTION_UP case it doesn’t matter about the coordinates where the action happened we just call setMovementState(paddle.STOPPED).  Here is the entire code for the onTouchEvent method with the new code we just discussed as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// The SurfaceView class implements onTouchListener // So we can override this method and detect screen touches. @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { // Player has touched the screen case MotionEvent.ACTION_DOWN: paused = false; if(motionEvent.getX() > screenX / 2){ paddle.setMovementState(paddle.RIGHT); } else{ paddle.setMovementState(paddle.LEFT); } break; // Player has removed finger from screen case MotionEvent.ACTION_UP: paddle.setMovementState(paddle.STOPPED); break; } return true; } |
We now have full control over the paddle and can start the game. Run the game, tap the screen to un-pause, and move the paddle left and right by holding and releasing the appropriate half of the screen.
Let’s make a ball.
Creating the ball
As we did for our Paddle class, right-click the java folder in the Android Studio project explorer and select New|Java class then select …\app\source\main\java and click OK. Now enter Ball as the name for our new class and click OK. We have now created a new Java class in a separate file called Ball.
After everything, we learned while coding the Paddle class our Ball class will be quite straightforward. Let’s get an overview of what we need to do.
- Our ball will be square so it will need an RectF object and a getRect method to share the coordinates with BreakoutView.
- Our ball needs to move around in all four directions so it will need an x and a y velocity. In order to be able to update its coordinates as it moves around, it will need its own update method.
- Furthermore when our ball bumps into something it will need to reverse its velocity in the appropriate direction. The ball itself does not ‘know’ when it bumps into something so it will need public methods to reverse velocity; one for x and one for y.
- At the start of a game, the ball will need to reset its coordinates to a sensible starting situation sitting just above the bat and moving upwards.
- Also, because we are doing a very rudimentary implementation of the physics of bouncing we want the ball when it hits the paddle to bounce back in a random horizontal direction. We will need a method to create this randomness.
- Finally, from experience, I know that the ball will sometimes get stuck. For example, if we detect a collision when the ball is a couple of pixels into another object and reverse its velocity it is possible that it will remain stuck for eternity, constantly going back and forth. We need to be able to clear obstacles and we will write methods that achieve this for both the x and y-axis.
With these requirements in mind, we will need the following methods.
- A simple Ball constructor to give our ball its shape.
- A getRect method to pass the coordinates to BreakoutView
- AÂ update method to move our ball around based on its velocities.
- A reverseXVelocity and reverseYVelocity methods.
- A reset method to set the ball into its starting state each game.
- A setRandomXVelocity method to randomly choose which way the ball heads after hitting the paddle.
- And for when it gets stuck, clearObstacleX and clearObstacleY methods will do the job.
Here is the full code listing for the Ball class. We will look at each method in more depth, be sure to read the comments for clarification.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
import android.graphics.RectF; import java.util.Random; public class Ball { RectF rect; float xVelocity; float yVelocity; float ballWidth = 10; float ballHeight = 10; public Ball(int screenX, int screenY){ // Start the ball travelling straight up at 100 pixels per second xVelocity = 200; yVelocity = -400; // Place the ball in the centre of the screen at the bottom // Make it a 10 pixel x 10 pixel square rect = new RectF(); } public RectF getRect(){ return rect; } public void update(long fps){ rect.left = rect.left + (xVelocity / fps); rect.top = rect.top + (yVelocity / fps); rect.right = rect.left + ballWidth; rect.bottom = rect.top - ballHeight; } public void reverseYVelocity(){ yVelocity = -yVelocity; } public void reverseXVelocity(){ xVelocity = - xVelocity; } public void setRandomXVelocity(){ Random generator = new Random(); int answer = generator.nextInt(2); if(answer == 0){ reverseXVelocity(); } } public void clearObstacleY(float y){ rect.bottom = y; rect.top = y - ballHeight; } public void clearObstacleX(float x){ rect.left = x; rect.right = x + ballWidth; } public void reset(int x, int y){ rect.left = x / 2; rect.top = y - 20; rect.right = x / 2 + ballWidth; rect.bottom = y - 20 - ballHeight; } } |
First, we declare some variables to hold the coordinates, velocity, and size of the ball and in the constructor initialize the velocities and the rect object. Note that we have not yet assigned coordinates to the rect object, just initialized it with zero for each corner.
In update we change the coordinates of the ball with the same formula we used in the paddle class only without the conditions ( paddleMoving) and this time on both the x and y coordinates.
In getRect we return rect as we did for our Paddle class. In reverseYVelocity we make velocityY equal to -velocityY reversing whatever its current sign (+-) is and hence reversing the direction of the ball on the y-axis. In reverseXVelocity we do the same but for the x-axes of movement.
In setRandomXVelocity we use an object of type Random and generate a number with two possible values. If it is the first we reverse velocityX in the usual way if it is the second possible number we do nothing so velocityX remains the same.
To be clear, when the ball hits the left or right wall we will always reverse the velocity but when the ball hits the paddle we will randomly either change it or maintain it. This gives an effect of different types of impact with the paddle. It is scientifically inaccurate but is nice and simple. We will do some more advanced physics in the next full-game project.
The next methods we implemented were clearObstacleY and clearObstacleX where we respectively amend the vertical and horizontal coordinates of the ball. We will see soon where we use this but it is to avoid the ball getting stuck.
We can now go and play with our ball.
Using a ball object
Declare an object of type Ball below where we declared paddle.
1 2 |
// A ball Ball ball; |
Initialize ball right after the initialization of paddle.
1 2 |
// Create a ball ball = new Ball(screenX, screenY); |
Call the ball.update method below where we called the paddle.update method in the BreakoutView update method.
1 |
ball.update(fps); |
Use drawRect in exactly the same way as we did for the paddle but use the getRect method on ball. Add the code right after the code to draw the paddle.
1 2 |
// Draw the ball canvas.drawRect(ball.getRect(), paint); |
Now we need to create a new method which we will call each time a new game is started. We will add more code to this later in the project but for now, we just call ball.reset. Add the createBricksAndRestart method right after the constructor in BreakoutView. The method could actually go anywhere within the BreakoutView class but this seems like a logical place for it.
1 2 3 4 5 6 |
public void createBricksAndRestart(){ // Put the ball back to the start ball.reset(screenX, screenY); } |
Finally, for this part of the project, we want to call this new method as the very last line of code in the BreakoutView constructor.
1 |
createBricksAndRestart(); |
Now we can run the game, tap the screen to start, and watch the ball fly off into oblivion.
Creating some bricks
As we have done before to create a new class select right-click the java folder and select  New|Java class then select …\app\source\main\java and click OK. Now enter Brick as the name for our new class and click OK. We have now created a new Java class in a separate file called Brick.
Our Brick class is the simplest of them all. All that a brick needs to do is sit there looking brick-like until it is bashed by a ball at which time it should disappear. Knowing this we can work out that a brick will need an RectF object and a boolean variable so our game engine knows if it is destroyed or visible.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import android.graphics.RectF; public class Brick { private RectF rect; private boolean isVisible; public Brick(int row, int column, int width, int height){ isVisible = true; int padding = 1; rect = new RectF(column * width + padding, row * height + padding, column * width + width - padding, row * height + height - padding); } public RectF getRect(){ return this.rect; } public void setInvisible(){ isVisible = false; } public boolean getVisibility(){ return isVisible; } } |
In the class above we can see that we have an RectF as expected and a boolean isVisible. In the constructor, we can see that we pass in a row number, column number and a width and height for the brick. Next, in the constructor, we initialize the location of the brick using the row number, column number, width height and one pixel of padding so we can distinguish each individual brick from the others.
As we have come to expect rect and isVisible are private so we need a getRect method a setInvisible method for when a brick is hit by the ball and a getVisibility method which will let us check on the current visibility status of a brick.
Now we will see how we draw all our bricks.
Drawing the bricks
In order to manage our bricks, it will be really tidy to keep them in an array. Declare an array called bricks and a variable to keep track of its size called numBricks. Add this code after the ball declaration in the BreakoutView class.
1 2 3 |
// Up to 200 bricks Brick[] bricks = new Brick[200]; int numBricks = 0; |
Perhaps unsurprisingly we will create our bricks in the createBricksAndRestart method. First, we define the size of the bricks based on the resolution of the screen and initialize numBricks to zero so we can keep track of the number of bricks that we draw. We will use this variable in a number of places as we will see.
Next, we set a nested for loop an outer one for each column and the inner one for each row. The code below loops through 3 rows with 8 columns in each. In the centre of the two loops we create a new brick based on the column number, row number, width and height. And of course, our Brick class will use this information to set the coordinates of each accordingly. Each Brick object is neatly tucked away in our bricks array. After we declare and initialize each brick we increment numBricks to keep track of the number of bricks in the array. You can easily alter the number of rows and columns as well as the size of the bricks and the code will still work. Add this code after the code to reset the ball.
1 2 3 4 5 6 7 8 9 10 11 12 |
int brickWidth = screenX / 8; int brickHeight = screenY / 10; // Build a wall of bricks numBricks = 0; for(int column = 0; column < 8; column ++ ){ for(int row = 0; row < 3; row ++ ){ bricks[numBricks] = new Brick(row, column, brickWidth, brickHeight); numBricks ++; } } |
Now we will draw all our bricks, again using a for loop to loop through the bricks array. Just before we do so we change the color of the brush to make our bricks a different color than the paddle and ball. Add this code in the draw method just after we draw the ball. Notice that as we loop through the bricks array we first check if getVisibility returns true. Only if it does will the brick be drawn. We make sure we don’t access an empty slot in the array by using i < numBricks as the condition of the for loop.
1 2 3 4 5 6 7 8 9 |
// Change the brush color for drawing paint.setColor(Color.argb(255, 249, 129, 0)); // Draw the bricks if visible for(int i = 0; i < numBricks; i++){ if(bricks[i].getVisibility()) { canvas.drawRect(bricks[i].getRect(), paint); } } |
We can now run the game and see the bricks.
The problem, of course, is that the ball just flies straight through them. What we need is to detect when things bump into each other. When these collision events occur we can then take appropriate action. As these actions include things like playing a sound, changing the score, and restarting the game, let’s add some code to play sounds and handle the score then we will see how to detect the collision events.
Making some noise and keeping score
We will now add the ability to keep score and play sound FX. If you want to learn more details about how this sound code works have a look at the Playing sound FXÂ tutorial. Let’s get started because we are not far away from a complete working Breakout game. Add this code to hold references to a bunch of sound FX and to keep track of the score and lives that the player has. The code goes right after the declaration of numBricks in the BreakoutView class.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// For sound FX SoundPool soundPool; int beep1ID = -1; int beep2ID = -1; int beep3ID = -1; int loseLifeID = -1; int explodeID = -1; // The score int score = 0; // Lives int lives = 3; |
Next, in the BreakoutView constructor, just BEFORE the call to createBricksAndRestart add this code to load the sound FX from their files.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// Load the sounds // This SoundPool is deprecated but don't worry soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC,0); try{ // Create objects of the 2 required classes AssetManager assetManager = context.getAssets(); AssetFileDescriptor descriptor; // Load our fx in memory ready for use descriptor = assetManager.openFd("beep1.ogg"); beep1ID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("beep2.ogg"); beep2ID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("beep3.ogg"); beep3ID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("loseLife.ogg"); loseLifeID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("explode.ogg"); explodeID = soundPool.load(descriptor, 0); }catch(IOException e){ // Print an error message to the console Log.e("error", "failed to load sound files"); } |
Of course, we need to add the sound files to our project. You can create your own or download mine by right-clicking on the files listed below. Just make sure you use exactly the same file names. You can also listen to each of the sounds by using the media controls below the links.
beep1
beep2
beep3
explode
loseLife
When you have your preferred sound FX, using your operating system’s file browser go to the app\src\main folder of the project and create a folder called assets. Add your sound file to this folder.
Now at the very end of the createBricksAndRestart method, we can initialize our score and lives variables like this.
1 2 3 4 |
// Reset scores and lives score = 0; lives = 3; } |
Now in the draw method, near the end, just after we draw the bricks add this code to draw the score, and lives, and announce either victory or defeat based on clearing all the bricks or losing all their lives.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// Draw the HUD // Choose the brush color for drawing paint.setColor(Color.argb(255, 255, 255, 255)); // Draw the score paint.setTextSize(40); canvas.drawText("Score: " + score + " Lives: " + lives, 10,50, paint); // Has the player cleared the screen? if(score == numBricks * 10){ paint.setTextSize(90); canvas.drawText("YOU HAVE WON!", 10,screenY/2, paint); } // Has the player lost? if(lives <= 0){ paint.setTextSize(90); canvas.drawText("YOU HAVE LOST!", 10,screenY/2, paint); } |
Now we will see how we can detect collisions, play the sounds and change the score.
Collision detection
All of this code goes in the update method right after we update the paddle. I will present the code in manageable chunks in the order it should be entered. If at any time you are unsure of exactly where some code goes just jump to the end of this page and you can see the whole of the BreakoutGame class in a single listing.
Here we loop through the bricks array with a for loop. For each brick, we check if it is visible by calling getVisibility and if it is we use a method of the RectF class called intersects. The intersects method takes two RectF parameters so we pass in our ball and the brick currently being checked. If they intersect(have collided) it returns true and the code inside the if block will execute. Before we look at the code inside the if block you might notice the slightly strange-looking call to intersects.
The syntax is RectF.intersects(.... We are actually calling the method on the class, not on the object OF the class. This is a special type of method known as a static method. When a method is declared static it allows this functionality. Methods are often declared static when the action performed in the method is not actually on an individual object yet it makes sense for the functionality to be available with objects of that type.
Inside the if statement we set the brick to be invisible, reverse the balls y direction of travel, add ten to the score, and play the exploding sound.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Check for ball colliding with a brick for(int i = 0; i < numBricks; i++){ if (bricks[i].getVisibility()){ if(RectF.intersects(bricks[i].getRect(),ball.getRect())) { bricks[i].setInvisible(); ball.reverseYVelocity(); score = score + 10; soundPool.play(explodeID, 1, 1, 0, 0, 1); } } } |
In this next block of code, we again use the static intersects method to check for a collision between two objects of the type RectF. This time the paddle and the ball objects. If we have a collision we set a random x velocity so the ball could bounce off to either the left or the right and we reverse the y velocity so it heads back up the screen. Now we use our clearObstacleY method to make sure the ball doesn’t get stuck to the paddle and we pass in the position of the top of the paddle minus two pixels so the method will make sure that the ball resumes it’s upwards journey starting two pixels away from the top of the paddle. We play another beep and we are done here.
1 2 3 4 5 6 7 |
// Check for ball colliding with paddle if(RectF.intersects(paddle.getRect(),ball.getRect())) { ball.setRandomXVelocity(); ball.reverseYVelocity(); ball.clearObstacleY(paddle.getRect().top - 2); soundPool.play(beep1ID, 1, 1, 0, 0, 1); } |
Now we handle a collision with the bottom of the screen. The bottom of the screen is obviously not a RectF so we can’t use the intersects method but we do know the exact coordinate of the bottom of the screen; it is screenY. So we just test for the bottom of the ball being greater than screenY. If it is the ball has hit the bottom. We then reverse the y velocity use the clearYObstacle to clear the bottom of the screen by two pixels, deduct a life and play a gloomy thud sound. Finally in the block of code below we test to see if the player has zero lives and if they do we pause the game and call createBricksAndRestart to build the game again from scratch.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Bounce the ball back when it hits the bottom of screen // And deduct a life if(ball.getRect().bottom > screenY){ ball.reverseYVelocity(); ball.clearObstacleY(screenY - 2); // Lose a life lives --; soundPool.play(loseLifeID, 1, 1, 0, 0, 1); if(lives == 0){ paused = true; createBricksAndRestart(); } } |
The next block of code tests if the ball has hit the top of the screen. I love it when the ball bounces along the top of the blocks, I get a little dopamine rush and it reminds me of playing this game as a child. Yes, I am that old. Back to the code. We test for the top of the ball being less than zero and if so reverse the y velocity clear the top of the screen by 12 pixels and play a beep. The reason we cleared the top of the screen by 12 pixels is that the clearObstacleY method works on the bottom of the ball and the ball is ten pixels high.
1 2 3 4 5 6 |
// Bounce the ball back when it hits the top of screen if(ball.getRect().top < 0){ ball.reverseYVelocity(); ball.clearObstacleY(12); soundPool.play(beep2ID, 1, 1, 0, 0, 1); } |
The next block of code bounces the ball off of the left of the screen. All the code is self-explanatory at this point just note that we reverse the x velocity, not the y velocity.
// If the ball hits left wall bounce if(ball.getRect().left < 0){ ball.reverseXVelocity(); ball.clearObstacleX(2); soundPool.play(beep3ID, 1, 1, 0, 0, 1); }
1 |
The next block of code bounces the ball off of the right of the screen. All the self-explanatory at this point just again note that we reverse the x velocity not the y. |
1 2 3 4 5 6 |
// If the ball hits right wall bounce if(ball.getRect().right > screenX - 10){ ball.reverseXVelocity(); ball.clearObstacleX(screenX - 22); soundPool.play(beep3ID, 1, 1, 0, 0, 1); } |
Here we check if score equals numBricks multiplied by ten. This would indicate all the blocks have been cleared so we restart the game in the usual way.
1 2 3 4 5 |
// Pause if cleared screen if(score == numBricks * 10){ paused = true; createBricksAndRestart(); } |
You can now run the game and play it for real.
What next
Congratulations on completing the game! There will be some more complete game projects really soon. In these projects, we will increase the number and variety of objects in our game and we will also significantly enhance the features of the game engine. A good next step would be to try the Android Space Invaders project.
And finally as promised here is the complete listing for the BreakoutGame class and its BreakoutView inner class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
import android.app.Activity; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.RectF; import android.media.AudioManager; 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 java.io.IOException; public class BreakoutGame extends Activity { // gameView will be the view of the game // It will also hold the logic of the game // and respond to screen touches as well BreakoutView breakoutView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize gameView and set it as the view breakoutView = new BreakoutView(this); setContentView(breakoutView); } // Here is our implementation of BreakoutView // It is an inner class. // Note how the final closing curly brace } // is inside the BreakoutGame class // Notice we implement runnable so we have // A thread and can override the run method. class BreakoutView extends SurfaceView implements Runnable { // This is our thread Thread gameThread = null; // This is new. We need a SurfaceHolder // When we use Paint and Canvas in a thread // We will see it in action in the draw method soon. SurfaceHolder ourHolder; // A boolean which we will set and unset // when the game is running- or not. volatile boolean playing; // Game is paused at the start boolean paused = true; // A Canvas and a Paint object Canvas canvas; Paint paint; // This variable tracks the game frame rate long fps; // This is used to help calculate the fps private long timeThisFrame; // The size of the screen in pixels int screenX; int screenY; // The players paddle Paddle paddle; // A ball Ball ball; // Up to 200 bricks Brick[] bricks = new Brick[200]; int numBricks = 0; // For sound FX SoundPool soundPool; int beep1ID = -1; int beep2ID = -1; int beep3ID = -1; int loseLifeID = -1; int explodeID = -1; // The score int score = 0; // Lives int lives = 3; // When the we initialize (call new()) on gameView // This special constructor method runs public BreakoutView(Context context) { // The next line of code asks the // SurfaceView class to set up our object. // How kind. super(context); // Initialize ourHolder and paint objects ourHolder = getHolder(); paint = new Paint(); // Get a Display object to access screen details Display display = getWindowManager().getDefaultDisplay(); // Load the resolution into a Point object Point size = new Point(); display.getSize(size); screenX = size.x; screenY = size.y; paddle = new Paddle(screenX, screenY); // Create a ball ball = new Ball(screenX, screenY); // Load the sounds // This SoundPool is deprecated but don't worry soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0); try { // Create objects of the 2 required classes AssetManager assetManager = context.getAssets(); AssetFileDescriptor descriptor; // Load our fx in memory ready for use descriptor = assetManager.openFd("beep1.ogg"); beep1ID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("beep2.ogg"); beep2ID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("beep3.ogg"); beep3ID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("loseLife.ogg"); loseLifeID = soundPool.load(descriptor, 0); descriptor = assetManager.openFd("explode.ogg"); explodeID = soundPool.load(descriptor, 0); } catch (IOException e) { // Print an error message to the console Log.e("error", "failed to load sound files"); } createBricksAndRestart(); } public void createBricksAndRestart() { // Put the ball back to the start ball.reset(screenX, screenY); int brickWidth = screenX / 8; int brickHeight = screenY / 10; // Build a wall of bricks numBricks = 0; for (int column = 0; column < 8; column++) { for (int row = 0; row < 3; row++) { bricks[numBricks] = new Brick(row, column, brickWidth, brickHeight); numBricks++; } } // if game over reset scores and lives if (lives == 0) { score = 0; lives = 3; } } @Override public void run() { while (playing) { // Capture the current time in milliseconds in startFrameTime long startFrameTime = System.currentTimeMillis(); // Update the frame if (!paused) { update(); } // Draw the frame draw(); // Calculate the fps this frame // We can then use the result to // time animations and more. timeThisFrame = System.currentTimeMillis() - startFrameTime; if (timeThisFrame >= 1) { fps = 1000 / timeThisFrame; } } } // Everything that needs to be updated goes in here // Movement, collision detection etc. public void update() { // Move the paddle if required paddle.update(fps); ball.update(fps); // Check for ball colliding with a brick for (int i = 0; i < numBricks; i++) { if (bricks[i].getVisibility()) { if (RectF.intersects(bricks[i].getRect(), ball.getRect())) { bricks[i].setInvisible(); ball.reverseYVelocity(); score = score + 10; soundPool.play(explodeID, 1, 1, 0, 0, 1); } } } // Check for ball colliding with paddle if (RectF.intersects(paddle.getRect(), ball.getRect())) { ball.setRandomXVelocity(); ball.reverseYVelocity(); ball.clearObstacleY(paddle.getRect().top - 2); soundPool.play(beep1ID, 1, 1, 0, 0, 1); } // Bounce the ball back when it hits the bottom of screen if (ball.getRect().bottom > screenY) { ball.reverseYVelocity(); ball.clearObstacleY(screenY - 2); // Lose a life lives--; soundPool.play(loseLifeID, 1, 1, 0, 0, 1); if (lives == 0) { paused = true; createBricksAndRestart(); } } // Bounce the ball back when it hits the top of screen if (ball.getRect().top < 0) { ball.reverseYVelocity(); ball.clearObstacleY(12); soundPool.play(beep2ID, 1, 1, 0, 0, 1); } // If the ball hits left wall bounce if (ball.getRect().left < 0) { ball.reverseXVelocity(); ball.clearObstacleX(2); soundPool.play(beep3ID, 1, 1, 0, 0, 1); } // If the ball hits right wall bounce if (ball.getRect().right > screenX - 10) { ball.reverseXVelocity(); ball.clearObstacleX(screenX - 22); soundPool.play(beep3ID, 1, 1, 0, 0, 1); } // Pause if cleared screen if (score == numBricks * 10) { paused = true; createBricksAndRestart(); } } // Draw the newly updated scene public void draw() { // Make sure our drawing surface is valid or we crash if (ourHolder.getSurface().isValid()) { // Lock the canvas ready to draw canvas = ourHolder.lockCanvas(); // Draw the background color canvas.drawColor(Color.argb(255, 26, 128, 182)); // Choose the brush color for drawing paint.setColor(Color.argb(255, 255, 255, 255)); // Draw the paddle canvas.drawRect(paddle.getRect(), paint); // Draw the ball canvas.drawRect(ball.getRect(), paint); // Change the brush color for drawing paint.setColor(Color.argb(255, 249, 129, 0)); // Draw the bricks if visible for (int i = 0; i < numBricks; i++) { if (bricks[i].getVisibility()) { canvas.drawRect(bricks[i].getRect(), paint); } } // Choose the brush color for drawing paint.setColor(Color.argb(255, 255, 255, 255)); // Draw the score paint.setTextSize(40); canvas.drawText("Score: " + score + " Lives: " + lives, 10, 50, paint); // Has the player cleared the screen? if (score == numBricks * 10) { paint.setTextSize(90); canvas.drawText("YOU HAVE WON!", 10, screenY / 2, paint); } // Has the player lost? if (lives <= 0) { paint.setTextSize(90); canvas.drawText("YOU HAVE LOST!", 10, screenY / 2, paint); } // Draw everything to the screen ourHolder.unlockCanvasAndPost(canvas); } } // If SimpleGameEngine Activity is paused/stopped // shutdown our thread. public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { Log.e("Error:", "joining thread"); } } // If SimpleGameEngine Activity is started then // start our thread. public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } // The SurfaceView class implements onTouchListener // So we can override this method and detect screen touches. @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { // Player has touched the screen case MotionEvent.ACTION_DOWN: paused = false; if (motionEvent.getX() > screenX / 2) { paddle.setMovementState(paddle.RIGHT); } else { paddle.setMovementState(paddle.LEFT); } break; // Player has removed finger from screen case MotionEvent.ACTION_UP: paddle.setMovementState(paddle.STOPPED); break; } return true; } } // This is the end of our BreakoutView inner class // This method executes when the player starts the game @Override protected void onResume() { super.onResume(); // Tell the gameView resume method to execute breakoutView.resume(); } // This method executes when the player quits the game @Override protected void onPause() { super.onPause(); // Tell the gameView pause method to execute breakoutView.pause(); } } // This is the end of the BreakoutGame class |
hi john, also getting alot of red errors here too, would cleaning the project help?
Hi James,
Please give me an example of the errors. I appreciate the conversation as it helps make my website better.
Thanks.
Can you give me a source code completely running? i can pay you
Hi there,
Every line of code is on the page and the main class you can copy paste from the bottom of the article. No charge.
Hi John,
Can u make a tutorial for coding line98 game for android too ?
thanks
Hi Kelvin,
Just added it to my list of possibilities. Unfortunately it is looking like I might need to spend 6 months away from the site so it might not be soon. I will know more soon.
Thanks for your comment.
hi john, il list what they are in red in order……
paddle paddle //first word in red
ball ball //first word in red
brick [] //both words brick in array are red
paddle = new paddle //second word paddle in red
ball = new ball //second word ball in red
ball.reset //reset in red
bricks[numBricks] = new Brick //last word brick in red
paddle.update(fps); //both updates in red
ball.update(fps);
if (bricks[i].getVisibility()){ //get visability in red
if(RectF.intersects(bricks[i].getRect(), ball.getRect())) { //both getRect in red also setInvisible and reverseYVelocity
bricks[i].setInvisible();
ball.reverseYVelocity();
if(RectF.intersects(paddle.getRect(),ball.getRect())) { //getRect in red on all 3, as is setRandomVelocity and clearObstacle
ball.setRandomXVelocity(); //exactly the same for all If statements
ball.reverseYVelocity(); //and in the ourHolder if statement block
ball.clearObstacleY(paddle.getRect().top – 2);
setmovementstate right,left and stopped // are all in red as well
Hi James,
With that many errors and they all refer to brick, ball and paddle I have to ask if you have implemented the brick, ball and paddle classes? As games get more complicated we need to separate out the code into multiple files. So copy/pasting the main game engine class from the end of the tutorial isn’t enough to get it working any more. You need to step through the instructions and add the extra classes and the resources like sound FX. If I have completely missed the problem I apologise but it does seem like it might be what is going wrong.
I’d be really interested to know if this is the case because if it isn’t there must be a missing curly bracket somewhere which could be throwing the whole structure out. If that is the case I will look into this further.
Good luck and let me know how you get on.
Hey John, I don’t know if you are still active or not on this site but here goes.
I have the same problem as stated above. And I did make the paddle class. But the error is still there.
//Paddle paddle; the first paddle is red and says “Cannot resolve symbol Paddle”.
and when I go over to the Paddle class. and hover over the paddle class, it says “class Paddle is never used”. I guess the two classes are not merging with each other or something like that please help!!!
Many thanks for your comment. There are two possible solutions to your problem which I can think of.
1)The Paddle class has been created in the test module. If you look in the project explorer window (where the files and folders are shown on the left), you can expand the Java folder and there will be two options for placing new classes. All your Java files should be in the top one? Not the (androidTest) one.
2) The only other possibility I can think of is that the package declarations at the top of the file are different or there is a subtle typo in the class name.
I hope this helps. Let me know either way and I will try and think of some other possible causes if this is not the solution.
Thanks for the reply!
I think I found out the problem! The thing is the Paddle class is generated directly in the java folder instead of java/com.appname.BreakoutGame… Now how do I move the paddle class in the com.apk.BreakoutGame folder?
Try dragging and dropping or if that doesn’t work create a new class by right clicking on the folder you want the class in and choosing New | Class. Then copy & paste the code or type it again. This should work. Good luck.
Sorry but I have got one more problem. Actually two.
1. “Method does not override method from its superclass” for the @Override method for the public void run() class. I actually kind of solved it by removing the @Override from it. But does that affect anything?
2. “Cannot resolve constructor Thread(simplegames.breakoutgame.BreakoutGame.BreakoutView)” in the public void resume() class for the line gamethread = new Thread(this); The “this” is underlined for the error.
Sounds like the implements runnable from this line of code could be missing?
class BreakoutView extends SurfaceView implements Runnable {
Let me know if not and I will try and think of another possible cause.
Thank you! I solved the paddle class problem by directly dragging and dropping it in the folder.
We’re getting there!
Yeah! the error’s gone. Thanks a lot!!
Yay
just move it into com.domain.breakoutgame
Thanks for sharing the solution.
hi john, ive managed to get rid of the errors, can i ask some advice? ive read the book learning java by bulding android games and i have done a couple of game projects yet everything seems to be going right over my head and cant seem to memorize everything, im fine with the java i have learned but i want to be able to to start making my own games and knowing exactly what i am doing! i know about the life cycle of apps and games but wondering if there is a set order to buld a game from scratch? really hoping things clear up for me eventually but seems so confusing! do you have any reccomendations and next steps? any advice would be greatly appreciated.
regards
Just keep making games. I have left some specific responses to your air hockey question but practice is key. If you understand the Java then you should have no trouble handling slightly tougher projects.
Have a look at the spec of this book.
http://gamecodeschool.com/blog/android-game-programming-by-example/
It has 3 projects the first is probably of similar difficulty to the Space Invaders game on this site. The second is a fairly fully featured platform game and the third has limited features but is more complex because it uses OpenGL to draw the graphics. (And it covers radius overlap collision detection.)
I don’t like asking people to buy my books because I don’t like to be forward so you could contact Sunitha from Packt Publishing on sunithap@packtpub.com and see if she is still giving out review copies. Tell her that I suggested it.
Let me know how you get on and thanks for the conversation.
i.e id love to make a air hocky style game and learn the physics of using a round puck with good speeds
The basics of this are not too tough. You have round sprites to represent the puck and mallets. Use the radius overlap method for collision detection. Then when you have a collision you calculate the horizontal distance between the centre of the puck and mallet to determine an angle and combine that with the angle the puck was travelling at to determine the angle of reflection (the new angle the puck should be travelling at.)
Unfortunately I don’t have a tutorial on radius overlapping collision detection but here is one (unchecked)
http://gamedev.stackexchange.com/questions/74872/how-to-solve-the-overlap-of-two-circles-that-collide
The space invaders project uses sprites
http://gamecodeschool.com/android/coding-a-space-invaders-game/
The two introductory articles on trigonometric ratios will get you started on bouncing physics
http://gamecodeschool.com/essentials/calculating-heading-in-2d-games-using-trigonometric-functions-part-1/
Along with the related project
http://gamecodeschool.com/android/2d-rotation-and-heading-demo/
Hi john, been a year since last contact so just thought i would give you an update, since we last spoke i have managed to release some apps onto play store and am now learning unity! it was thanks to your books i was able to make some apps and get them out! i am now pushing towards game development as this was my original aim but by making apps i have been able to learn java and understand it better! i now to plan to work through your website tutorials and also unity to see where that leads! just feels great to know i can make and publish apps now! just wish i had some good ideas to make me rich lol
Hi James,
Really nice to hear from you again! Especially so to hear you have published some games. Re ideas, just think about what motivates you. Politics, a sport, family life, a simulation of a favorite/worst job? My problem is I have too many games that I want to make.
Keep in touch.
I have many ideas it is just a case of executing them! my problem is i get easily overwhelmed with ideas and find my self starting a project only to have another idea and then start that one. Im sure il get there at some stage!
In some ways, that’s a good thing and some ways not. It’s good because you are constantly reinforcing old concepts and trying new ones. It’s bad if finishing your project is important to you. So don’t beat yourself up about that as long as you are happy with the results.
thank you for this john i really appreciate it and i shall learn all of it.
best regards
i get these errors
breakout.java:183: error: method does not override or implement a method from a
supertype
@Override
^
breakout.java:185: error: cannot find symbol
super.onResume();
^
symbol: variable super
location: class BreakoutGame
breakout.java:192: error: method does not override or implement a method from a
supertype
@Override
^
…
…
63 errors
Hi there,
Seems the class isn’t valid at all. Probably because the class called BreakoutGame is in a file named breakout.java and it is required to be in a file with an identical name to the class. Try:
1) start again
2) follow carefully this part of the tutorial “Create a new project in Android Studio, call it Breakout Game and name the Activity BreakoutGame”.
Hopefully this will work for you.
Good luck!
hi there i have tried making your game and i was wondering if you could post how to make the paddle not move out of the screen and maby move with the motion of users finger
hope you will take the time to answer me
otherwise thanks for this awsome tutorial
Hi Jimmi,
To prevent the paddle going off the screen you could wrap the code that set the movement state in onTouchEvent method. For example to stop going off the right-hand side you could amend the code to look like this.
if(motionEvent.getX() > screenX / 2){ // Only set state if not too far over already! if(paddle.getRect().right < screenX){ paddle.setMovementState(paddle.RIGHT); }}
Have a go at working out the equivalent to stop it going off the left 😉
I haven’t had time to test this but it seems like it would work. Do let me know.
With regard to gestures it is hard for me to think of a gesture that is useful for this type of control. But what do you think?
Good luck.
I try it, but it doesn’t work. Help!
Hi there. Give me some details and I will try and help. Thanks for commenting.
Hi John!
I tried what you said above about the paddle going out of the screen.
But it doesn’t work. There is no error. It runs but to no effect. The paddle still goes of the screen. I think adding some kind of walls to the sides will do it. But then how to code them. Like adding two rectangles using Rectf or something like that will do…
Also I am unable to play any sound. Is it because of Soundpool class being deprecated as I run an android 4.2.2 Jellybean. Any alternative method for the sounds if it is the problem of SoundPool class..
Also I tried to bring the paddle to the starting point after it the game is over using the same structure used for the ball i.e reset method.
The paddle does come in between but now the ball bounces off the floor instead off the paddle as if the paddle doesn’t exist.
This is a flaw in the app and not easily fixed. I would recommend doing the Space Invaders demo which is structured differently and then try and start the Breakout game again using what you have learnt (if it is important to you).
Regarding the sound; the deprecated class should be fine. Try making sure the folder creation step was done exactly right and all the assets/sounds are named correctly.
Regarding the paddl; the code above should stop the x coordiante becoming larger than the screen width. So the paddle would still go off screen but it would(should) stop just off-screen. You could try changing the condition if(paddle.getRect().right < (screenX - 130)). This might do the trick.
Thanks for your comment!
The sounds started working. When declaring the sounds I typed in .ogg instead of .wav. Still the explode sound doesn’t work. But now worries.
The paddle still goes out of the screen so no luck there.
Also according to your code, the “You Have Won” & “You Lose” paints it on the screen but calling the createBricksAndRestart method happens too fast to ever see that paint it on your screen. So I added a sleep thread in between of nearly 2 secs and that did the trick.
One last thing, sorry. But i tried to add a splash screen to the game with all the sleep thread and stuff but the game crashes after the splash screen ends. Any suggestions…
Well, I am going to start with the space invaders project now. And come back to this game later.
Thanks for the feedback.
You could create a splash screen using a separate activity with a timer that starts the game activity after a short wait. I haven’t got a tutorial that does this on this site but you could search for “switching activities with the Intent class”.
Another way to stop the paddle going off the screen would be to add some code in the Paddle class’ update() method. Something like if (rect.right > ...) {rect.right = ...}. You could either hardcode the width of the screen or add a member variable that you could initialize with the screen width in the constructor of the Paddle class.
I am going to update these tutorials based on feedback like yours but I will probably not get round to it for a month or two.
Thanks again!
*no worries
If you want to make it so the paddle can’t move out of screen, just make somthing like this in paddle class:
if(paddleMoving == LEFT && x > 0){ ... }if(paddleMoving == RIGHT && x < 1657){ // (2nd value may be different for different phones). }
Not sure if it gona work for everyone but its working for me.
Thanks Forest. Sounds like a good tip.
Am i aloud to use your code as a basic structure to expand on this, to later release it on Google Play?
Hi Bill,
Thanks for the question. I make no claim to copyright on the use of the code. It is my interpretation of what I have learned from others over the years. The only thing that would make me grumpy is if it was made into another and not substantially different tutorial. I get a free thrill every time I hear someone has made a game and I might have helped a bit. Good luck and I would be glad to hear of your progress.
John
Is it possible to upload the full source code?
Hi there,
I hope to have a downloadable zip sometime in the future.
hello John,
have you upload the full cource code?
Hi Zahid,
Unfortunately I don’t have a download for this but you can copy & paste the code from the end of the article.
I’m getting the following error when I try to run the app on my Nexus 5 (not 5X) running Marshmallow:
java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
Please HALP!
Hi Raffi,
Which version of Activity does your code extend? Check that your BreakoutGame class starts like this:
public class BreakoutGame extends Activity {
….
And not like this:
public class BreakoutGame extends ActionBarActivity {
// gameView will be the view of the game
Let me know how you get on, good luck and thanks for the comment.
If you use AppCompatActivity, then you need to change some things in the styles.xml file.
In between the “” tags, replace what you have with the following:
true
false
true
@null
That should clear up the error you’re getting.
true false true @null
Hey my problem is that sometimes when the ball hits the paddle i lose one life.
sry for bad english. 😀
Hi Lukas,
Is it a low frame rate? This would cause the ball to travel further between collision checks. Or it could just be the very simplistic way this is implemented. Another way you could solve it is to amend the code to move the paddle off of the bottom of the screen?
Good luck, let me know how you get on.
Yes it was just the emulator. i tried it on my phone and it worked fine.
But another problem is that if i destroy all Bircks my game does reset but when i press the screen the ball doesnt move.
i hope you understand my question.
your tutorials are pretty great i learn a lot from them 😀
Hi Lukas,
Thanks very much for your kind comment. Yes, I think I understand your question. I have just been looking at the code because it has been a while and I have to say I can’t see why that is happening. If you are calling ball.reset all should be well. Try outputting some debugging variables to the screen. Like the x,y of the ball and the value of the paused variable. See if that turns up any solutions.
I would be interested to know if you can solve it. I have to be honest I don’t think I tested the game as far as restarting and the fault might well be mine.
Good luck and thanks!
I solved that question but now i wanted the height and lenght of the ball to be dependent on the size of the screen but if the ball gets bigger then 10 pixels. the Ball just doesnt bounce of the paddle.
i have a lot of fun with this game 😀 I invented a few new things.For example the game now has level where the ball gets faster and the paddle smaler and even more rows of bricks.
Thank you for your answers ;P
Try looking at the defence brick class in the space invaders project as a hint to achieve your ball requirements. But to be really accurate remember that there are small screens with a high resolution and big screens with low resolution so you need to get the screen size and come up with a formula based on both.
Hey,
I would like to add some background music, so where should I add the soundpool.play code? I tried adding it to the on resume code when the player starts the game, but the game doesn’t install. Any tips?
Hi Henry,
To play music in your game you really need to use some techniques I haven’t written about yet.
If the music sample is very short you might get away with using the SoundPool class as described.
It is probably best to Google and research the MediaPlayer class and use that instead.
Thanks for the question!
Hi, thanks for the reply!
Can I use soundPool and MediaPlayer in the code at the same time or do I have to replace soundPool with MediaPlayer?
They will work fine together so use SoundPool for fx and MediaPlayer for music.. I have added it to my todo list so my next Android tutorial will have music in it. Might be a month ish though.
And what to do with the xml file having the design view. As mine is still blank and is showing nothing but a “Hello World” text.
Help me out.
HI Aqsa,
You can safely ignore/delete the layout XML. If you look in the onCreate method you will see that the call to setContentView uses our custom class instead of the xml file.
Hope this helps.
So, we have to run this app on android studio. Right? As I am running there.
Yes. For more details on getting the project started check the links in the “Assumed previous experience column” near the top of the article.
Now i have rename my project to BreakJail and it’s paddle class is showing me an error over RectF. What should i now?
It depends how you renamed it. Are the package declarations at the top of the files the same?
Which RectF error?
Have you imported RectF.
Hope this helps. If not let me have a few more details and I’ll try again.
Hey John,
I am trying to make this game again using sprites and stuff that I learned in the Space Invaders tutorial. I did the paddle and ball successfully but I am stuck on the Bricks. I can’t seem to find out how to create a array of the bitmap. I am getting two errors:
In the BreakoutView class:
1.private Brick[] brick; — the variable is greyed out and says it says private field brick is never assigned.
2. In the draw method:
canvas.drawBitmap(brick.getBitmap(), brick.getX(), screenY – 520, paint); — the “.getBitmap()” and “.getX()” methods are red and says “cannot resolve
method”
In the Brick class:
public Bitmap getBitmap(){return bitmap;}
public float getX(){return x;}
— the getX() and getBitmap() methods are greyed out.
and i can’t find the way to get around this.
I tried stackoverflow.com, but it says about adding an arraylist but then more errors pop up.
Any help??
Hi there,
I see you have declared the array but have you initialized the array as well?
Perhaps something like this:
private Brick[] bricks = new Brick[400];
then prepare the array something like this:
// Build the array of bricks
int numBricks = 0;
for(int column = 0; column < 20; column ++ ){ for(int row = 0; row < 5; row ++ ){ bricks[numBricks] = new Brick(Whatever parameters your constructor takes); numBricks ++; } } Hope this helps
Well the “private Brick[] brick” is not greyed out now. But the “getBitmap()” and “getX()” errors still persists and the methods are still greyed out in the Bricks class… Help??
The methods would probably appear grayed out until they are used in some code somewhere.
Look at a snippet on how the invaders are drawn in the space invaders project.
// Draw the invaders
for(int i = 0; i < numInvaders; i++){ canvas.drawBitmap(invaders[i].getBitmap(), invaders[i].getX(), invaders[i].getY(), paint); } Can you adapt the above code to your situation? Do the methods still appear grayed out?
Thanks john.
The errors are gone.Well its not running though, it has some basic mistakes, I guess. I may post here again if I get stuck.
Sorry John but here I am again…
I can’t find a solution.
The app crashes on start up even though there is not a single error.
Please post the crash data from logcat and I will try and point you in the right direction.
The log cat is too big. How do I just post the crash data??
Hi Anurag,
Try and identify the part which has the crash in it. You can filter the logcat window with various dropdown options at the top of the window.
A crash like this is often something like a null pointer exception, perhaps because you have used an uninitialized object.
Or as you are dealing with an array, perhaps your code accidentally writes or reads past the end of it causing a array out of bounds exception.
The cause might be in red I can’t remember off hand.
When you find it, post the parts of the message that look like they might be related.
I think I found the crash data. Here it is:
12-19 09:16:03.141 14493-14493/? E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.avalanchestudios.breakoutparadise/com.avalanchestudios.breakoutparadise.BreakoutParadise}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2343)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2395)
at android.app.ActivityThread.access$600(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5371)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.avalanchestudios.breakoutparadise.Paddle.(Paddle.java:35)
at com.avalanchestudios.breakoutparadise.BreakoutParadiseView.prepareLevel(BreakoutParadiseView.java:67)
at com.avalanchestudios.breakoutparadise.BreakoutParadiseView.(BreakoutParadiseView.java:61)
at com.avalanchestudios.breakoutparadise.BreakoutParadise.onCreate(BreakoutParadise.java:20)
at android.app.Activity.performCreate(Activity.java:5122)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2307)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2395)Â
at android.app.ActivityThread.access$600(ActivityThread.java:162)Â
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)Â
at android.os.Handler.dispatchMessage(Handler.java:107)Â
at android.os.Looper.loop(Looper.java:194)Â
at android.app.ActivityThread.main(ActivityThread.java:5371)Â
at java.lang.reflect.Method.invokeNative(Native Method)Â
at java.lang.reflect.Method.invoke(Method.java:525)Â
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)Â
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)Â
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)Â
at dalvik.system.NativeStart.main(Native Method)Â
I removed all those variables that were not used but the app still crashes. It won’t look good if I just keep on posting the crash data in the comments. Any other way we could solve this. Help me please…
Hi Anurag. Other than discussing and seeing the errors/code I don’t know of another way to solve this. Once you solve this problem you will then be more aware of what caused it and less likely to do the same thing in the future. You will have learnt from experience.
I have looked at the output in your previous comment and it tells us that the problem is a null pointer exception.
Caused by: java.lang.NullPointerException
This means that you are attempting to use an object of a class that has not been initialized. I.e. you have declared an object perhaps something like this:
Paddle paddle;
But you haven’t initialized it, perhaps like this:
paddle = new Paddle(x, y, etc);
Please note the above paddle example is just a guess based on the errors you posted and is not definitely the solution.
The best places in your code to start looking for the error can also be determined from the output you posted.
at com.avalanchestudios.breakoutparadise.Paddle.(Paddle.java:35)
at com.avalanchestudios.breakoutparadise.BreakoutParadiseView.prepareLevel(BreakoutParadiseView.java:67)
This suggests looking for a problem like the one I describe at line 35 in the Paddle class and/or line 67 in the BreakoutParadiseView class.
Don’t be disheartened by setbacks like this, keep looking for a solution. The more frustration there is getting a game to work, the more satisfying it will be when it finally works.
If you can’t work out the problem from these tips then please post the Paddle class, the place you initialize any Paddle objects and a few lines of code around line 67 from BreakoutParadiseView class.
Good luck and have a good day.
John
I have initialized the paddle class already in the breakoutparadiseView class. Should I initialize it in the paddle class instead?
Thanks for the encouragement John. I was thinking of leaving this project and starting a new one. But well here I am pasting the code….
This is the paddle class constructor. And the first error at line 35 is where I assign the bitmap using bitmap factory.
public Paddle(Context context, int screenX, int screenY){
rect = new RectF();
length = screenX/10;
height = screenY/10;
x= screenX/2;
y = screenY – 20;
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.bat_orange);
bitmap = Bitmap.createScaledBitmap(bitmap,(int)(length),(int)(height),false);
Also it shows an error at one more place in the main activity class in the onCreate method:
breakoutParadiseView = new BreakoutParadiseView(this, size.x, size.y);
paddleSpeed = 350;
}
This is where I have initialized the paddle variable. The error points at the initialization of paddle.
private void prepareLevel() {
paddle = new Paddle(context, screenX, screenY);
ball = new Ball(context, screenX, screenY);
Thanks again!
This could be the problem. The only way I can see you getting a null pointer exception from that line of code is if context is not initialized.
You call the Paddle constructor from prepareLevel, so you must somehow have an initialized Context object available in prepare level? Your BreakoutParadiseView constructor does receive a context object but in that BreakoutParadiseView constructor, do you initialize the BreakoutParadiseView member Context? Perhaps like this:
this.context = context;
I am fairly sure this will be the problem, especially if you have used my breakout project as a kind of template. Take a look at the space invaders project again and you will see this happening.
In summary, Pass context from main activity to the class which extends SurfaceView, initialize a Context object of the SurfaceView class in the constructor:
BreakoutParadiseView extends SurfaceView etc…{
Context context;
…
public BreakoutParadiseView(Context context, int x, int y){ // Or simmilar
this.context = context;
…
Everything should now work.
Let me know if you don’t understand my explanation because I think it is the likely solution.
Good luck
Thanks John! It worked! The game is working!
YAY! The bigger the pain the more pleasant when it stops. Well done.
Well the game is running, but there are still some problems I’m facing like…
1. The ball is drawn a few pixels above the paddle and doesn’t move. I tried changing a few dimensions but to no avail. (By the way, I am using a portrait view in this app. I tried changing it to landscape yet nothing happens. The ball just hovers up there.)
2. It draws only one brick on the screen even if I have a declared a bitmap[]. Are there some other methods for bitmap arrays than our regular bitmap methods.
Are you using a Bitmap for the ball too? If so the answer for number 1 lies in studying the code for the player spaceship to see how we track and draw it in the right place.
The solution for number 2 would be to study way the invaders are drawn as they are contained in an array as well as using a Bitmap for each.
I am referring to the Space Invaders project in both possible solutions.
Hey John,
I followed and changed the code according to the Invaders class and the Bricks were a success. There’s just, it shows a gap in between the bricks but I think I can tweak it and make it work, no problem there.
But I am stuck on the ball. I tried tweaking the code according to the playership class. But well I don’t know where the problem arises…
The playership class demonstrates how to handle the moving bitmap but the ball class demonstrates the independent movement. So I guess the end result will be somewhere between the two. Make sure you are calling the ball.update as well, each frame.
Feel free to post some code if it doesn’t work out. And when you publish Breakout Paradise let me know and I will link to the play store listing.
Good luck.
Well I can’t seem to find why the ball isn’t moving…
Here is the code for the ball class:
public class Ball {
RectF rect;
private Bitmap bitmap;
float xVelocity;
float yVelocity;
float ballWidth = 10;
float ballHeight = 10;
float x;
float y;
public Ball(Context context, int screenX, int screenY){
rect = new RectF();
xVelocity = 200;
yVelocity = -400;
x = screenX/2;
y = screenY – 20;
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.ball_blue);
bitmap = Bitmap.createScaledBitmap(bitmap, (int)(ballWidth), (int)(ballHeight), false);
}
public RectF getRect(){return rect;}
public Bitmap getBitmap(){return bitmap;}
public float getX(){return x;}
public float getBallWidth(){return ballWidth;}
public void update(long fps){
rect.left = rect.left + (xVelocity/fps);
rect.top = rect.top + (yVelocity/fps);
rect.right = rect.left + ballWidth;
rect.bottom = rect.top – ballHeight;
}
public void reverseYVelocity(){yVelocity = – yVelocity;}
public void reverseXVelocity(){xVelocity = – xVelocity;}
public void setRandomXVelocity(){
Random generator = new Random();
int answer = generator.nextInt(2);
if(answer == 0){
reverseXVelocity();
}
}
public void clearObstacleY(float y){
rect.bottom = y;
rect.top = y – ballHeight;
}
public void clearObstacleX(float x){
rect.left = x;
rect.right = x + ballWidth;
}
public void reset() {
rect.left = x/2;
rect.top = y – 20;
rect.right = x/2 + ballWidth;
rect.bottom = y – 20 – ballHeight;
}
}
Assuming you are calling ball.update each frame, please show me the line of code which draws the ball in the draw method.
I called the update method by passing the fps variable if that is what you mean.
And here is the draw method for the ball sprite:
//Draw the ball sprite
canvas.drawBitmap(ball.getBitmap(), ball.getX(), screenY – 50, paint);
I think I see.
The update method is updating the RectF but you are using getX and the static screenY – 50 to position the bitmap.
You can either change the update method to work on x and y then add a getY method as well.
Or you could try the slightly convoluted (but it will probably work):
//Draw the ball sprite
canvas.drawBitmap(ball.getBitmap(), ball.getRect().left, ball.getRect().top, paint);
The getRect.top and getRect.left method doesn’t work, it just places the ball more to the left. What should I change in the update method for the getX and getY method to work.
Here is the update method:
public void update(long fps){
rect.left = rect.left + (xVelocity/fps);
rect.top = rect.top + (yVelocity/fps);
rect.right = rect.left + ballWidth;
rect.bottom = rect.top – ballHeight;
}
Hi Anurag,
I can’t think why that doesn’t work. So changing the class might just make things worse. Try adding some debugging text to the screen to see what is going on with those coordinates. If they aren’t moving then either update isn’t being called or perhaps one of the velocities has been corrupted somehow.
Add this after the score is drawn
canvas.drawText(“x: ” + ball.getRect().left + ” y: ” + ball.getRect().top, 10,150, paint);
See what information you get from it and if it gives a clue.
So it prints x:120.0 and y:804.0 . What does it mean??
Do I have to print that statement while using the getRect().left and getRect().top method??
It still prints the same statement after the getRect methods and the ball is shifted more to the right…
Sorry Anurag. Can’t think what is happening. The static coordinates mean the ball.update method either isn’t updating them or isn’t being called at all. I would look into that.
I think instead of using a sprite I may just use a rect for a ball. I was going to try and include power ups for the ball and using a sprite would have made it easier.
I don’t think it is the sprite. Even after changing the ball to a rect, it still doesn’t move. That means I am going wrong somewhere else and its not the ball.
Hi Anurag,
Go back to the last working state you had, even if that is the original breakout project. Then change one thing at a time and test at each step. If you get yourself a github account and put the project there I will be more than happy to look at the code and be able to help troubleshoot better as you progress.
A complete beginner at this and find your teach by doing approach very inspiring. Have followed all classes without problem but the breakout game
I cant get the paddle to display. there are no errors and ball and bricks work just no paddle. Any help would be welcome.
Neil
Hi Neil,
Thanks for your comment. The first thing to check is that you have read and completed the section “Making the game full screen landscape”. If not the the paddle might be hidden just off-screen.
The next check would be to the draw() method to make make sure that is exactly as it should be.
If you still can’t see it after trying these things I would try changing the starting y position of the paddle. You can do this in the Paddle constructor at this line:
y = screenY – 20; // y = 100;
This would make sure the Paddle is not still being hidden off screen.
If you still can’t see the Paddle get back to me and I will discuss doing a bit of debugging by outputting some extra text to the screen.
Good luck.
The paddle for me is off screen as well with:
y = screenY – 20;
I’ve messed around with it and the only way I can get it to appear is by dividing or multiplying the screenY variable, adding or subtracting doesn’t seem to do anything at all. And when I multiply or divide the paddle ends up in roughly the middle of the screen or higher. I don’t know what I can do to fix this besides putting a constant number, but I feel like that would cause problems on different screen sizes.
Hmm. Try…
// play around with the value of divisor
int divisor = 8;
y = screenY - (screenY / divisor);
What resolution is your screen?
Decided to read and tinker a bit and it worked itself out. that solution worked, but i Wasn’t in full screen mode, took the instructions too literal and put android:theme=”@android:style/Theme.NoTitleBar.Fullscreen” directly underneath it and not inside of the .
thank you very much for these tutorials, gonna get back to it.
A pleasure Brian.
Thanks John for your prompt reply. Yes the paddle was too low so working now. I am only working with an emulator so having to change speeds of ball and paddle but a learning curve for me so please bear with me if some of my questions seem very basic. I’ll try not to bother you too often.
Neil
Your oldest follower
Hi Neil,
No bother at all. Glad it worked out.
public void update(long fps){
rect.left = rect.left + (xVelocity / fps);
rect.top = rect.top + (yVelocity / fps);
rect.right = rect.left + ballWidth;
rect.bottom = rect.top – ballHeight;
}
Thanks John for making this great tutorial. I have a doubt in Ball class. Won’t the above code lead to different speed of ball in different phones as our position is being updated by pixel/frame whic will make it fps dependent? If yes, than how can it be resolved?
Hi Nick,
Thanks for your comment. Hopefully dividing the target velocity (xVelocity) by the current fps will mean that faster phones will move more frequently by smaller amounts and slower phones less frequently but by larger amounts. Unless I have made a mistake somewhere.
The faster the phone is the bigger the value of fps and therefore the smaller the value in pixels that is moved each frame.
Let me know if you still think I have an error (it wouldn’t be the first time).
John
Thanks for replying,
You are right, but wouldn’t it be better to update the game objects as pixels per second instead of pixels per frame? Then the updates won’t depend on frame rate.
Also I have tried to add a few extra things to game but now I am getting errors when I am trying to run it on emulator. Can you help me with this? Should I post a link to my project?
PS. This is my first android and java based project.
Hi nick,
You can lock the framerate but then poor performing phones will lag. You can also use the delta time which is the time since the last frame. This allows you to multiply by the target pixels per second and is probably faster than doing the divide calculation.
I used this slight adaptation of delta time because I hoped it would be transparent and easier to undestand as well as flexible.
How fast in pixels per second do you want an object to go? Simply set xVelocity to this value at any time and regardless of the fps, even if it varies then the pixels per second remain the same.
Of course what you should also do is use the resolution to initialize the xVelocity (with some formula) so that different screen resolutions have a simmilar experience. In addition you should take into account pixel density as well because there are small screens with high resolutions and large screens with relatively low. Furthrtmore to be really exact you need to consider the ratio of width to height (pixels and inches).
But this tutorial series is targetted at people who might never have programmed before and is just a first step. In the new year I will add a few new tutorials with more fun and advanced features.
Yes feel free to add a github or simmilar link. Or post a code snippet with problems here.
Nice to talk with you.
Hi John,
Thanks for helping me out. I have attached the project link below. I have not yet added sounds and In-game menu.
Project – https://github.com/IshankGulati/Breakout
Hi Nick,
Sorry, I haven’t looked at this yet. How are you getting on?
Hi John
Game is working but there are a few problems I want to share. Ball fails to bounce off the surface of paddle most of the times but collision detection with wall, ceiling and bricks is working just fine. Also, sometimes even after removing finger from the screen, paddle keeps on moving in that direction. It would be great if you can have a look at the code and suggest me some corrections. I have updated the link above with the latest code and Collision detection code is in Ball.java.
Thanks
H Nick,
I can’t see why that wouldn’t work. Why not add some debugging text on screen for things like when the rectangles intersect and the number of times they intersect. This might make it plain if the collision is detected and is simply not responding or whether the ball is passing straight through.
Hi John
Except for a few small bugs, game is working just fine :). Waiting for next tutorials.
Thanks for helping out
Well done Nick,
I am planning 2016 right now and hope to provide some new stuff soon.
Hi Jhon, excellent tutorials, well done !!! the game works, perfecktly. I have only 2 questions.
First: When i run the game on a the AVD, it works fine, but when i run it on a real device, when the ball hits the first lines of bricks in front of the paddle, the ball just go throught them and impact the inner once. Really strange. And the second one is, that when someone loses or wins the games, doesnt appear the text. I tried comment the createBricksAndRestart() method and it shows me the text, but when I un-comment that line of code, I dont see any text if the gamer lost or won. Also I tried to put this line of code: Thread.sleep(3000); surrended by try-catch block, and doesnt show me the text. Thanks in advantage
Hi Roger,
Regarding the end of game situation. It is just a over simplified/bad bit of code. What is happening is that the pause condition ends as soon as a touch is detected which is almost always straight away. You could modify the code to only end the pause condition when the very top part of the screen is touched. I will probably improve this tutorial to incorporate this soon.
Does the ball go through every time or occasionally? Is the device very slow? It is possible that if the frame rate is low then the amount the ball moves each frame could cause the ball to jump through the test for a collision.
Thanks for your comment hope my reply helps.
I solved the text not showing problem adding a block of try-catch cointaingin this line of code: game.Thread.sleep(3000); I put this block of code when the game asks if the gamer won or lost the game in the update method, right after paused=true, and before, createBricksAndRestart(); So now it is showing me the text. Bur i cant yet solve the problem with the ball not hidding or braking the first and some lines of bricks. I dont know really where to modify the code. If yopu could give an example, please. Sorry for my bad english!
Hi Roger,
Well done for solving the text problem. I can’t think why the brick problem would happen. The problem is usually on the emulator not the phone. Have you made any modifications to the code or is it a very low resolution phone? If so try making the ball smaller and the bricks a little higher.
Hi John.
Have got game installed on phone and running well. Would love some tips on how to restart if won with ball moving faster.
Only if it’s not too difficult and you have time. It would help my understanding of where code is placed.
Neil
Hi Neal,
You can increase the speed of the ball by changing the xVelocity and yVelocity member variables in Ball.
As these variables are private we will need a public method to do the work for us. Add a method something like this (untested) to the Ball class.
// Call this method from the game loop
// when you want to increase the speed
public void increaseVelocity(){
// Increase speed by 10%
xVelocity = xVelocity * 1.1f;
yVelocity = yVelocity * 1.1f;
}
You can also consider shrinking the paddle a little in a similar way. Hope this helps.
Thanks John
I have been playing with ball and paddle speeds so no problem there.
I will try your suggestion for ball class ,but to call this method from game loop do I need something like if(score >=240){
increaseVelocity;}
Sorry but by beginner I mean beginner.Do your books explain this type of basic question, think I had better start there.
Thanks for your time and have a great new year
Neil }
Hi Neil,
Yes, that’s exactly how you could use it. And in the if block you would call the method like this ball.incraseVelocity();.
Yes my books do explain this. Learning Java Building Android Games assumes zero Java knowledge an will explain absolutely everything from the start, but as a result the games built are very basic (pong, snake and even simpler games). Android Game Programming by Example assumes you know Java so doesn’t explain objects and basic syntax etc. This doesn’t mean you won’t pick-up the basics if you are feeling daring and want to go for the more adventurous book. I don’t like shamlessley promoting my stuff in the comments but if you are thinking about buying they are $5 each in ebook format (from packt not Amazon) for a few more days.
All the best,
John
Hello John,
I wish u a happy new year
I hope my question is not off topic. I tried to implement the “boolean isVisible” to the TappyDefenderGame. I tried to get it like this. If the player gets hit by an enemy he gets invisible. But it doesnt work. After the player got hit he kind of gets “invincible” (no more shield reduction).
here is what i did in the TDView:
if (player.getVisibility() {
if (hitDetected) {
player.setInvisible;
soundPool.play(bump, 1, 1, 0, 0, 1);
player.reduceShieldStrength();
if (player.getShieldStrength() < 0) {
soundPool.play(destroyed, 1, 1, 0, 0, 1);
gameEnded = true;
}
}
and i copied the "private boolean isVisible", "visible = true" and the rest which belongs to this method in the playerShip class as u did it, for example in the Brick Class. I dunno what i did wrong.
Greetings
Niclas
I solved it. I forgot to declare get.Visibility on the draw method -.-
Nice one Niclas!
Hi John,
I’m running the game on the android emulator that comes with Android Studio. The bricks and ball seem to work fine, but when the game starts, I can’t see my paddle. Could you help me with this? Thanks
Oh wait, I finally made it work. Instead of setting the paddle’s y value to y – 20, I had to make it y – 80. For some reason, the display size given by getSize was transcending the actual one.
Hi Anoop,
Congrats for solving this. Also check if the screen was set to full screen otherwise y will be hiding slightly off-screen.
Hey,
I want to add images to the paddle, bricks and ball but Im really stuck here. I cant figure out the part where I have to add the canvas.getBitmap, paddle.getX part like in the Space invaders tutorial. Can you help me out a little please
Thank you!
HI Henry,
Although the changes are possible they are reasonably extensive and in multiple places, making it tough to document in these comments.
What you need to do is add a getBitmap method to any class you want to draw as a bitmap as well as a Bitmap object. Then in the draw method you will then be able to use almost identical code to draw each object as in the Space Invaders project.
I would start by doing the Space Invaders project to get familiar with it and then revisit and improve (add bitmaps) to this project. You can also look further up in these comments to my discussion with Anurag where we discuss aspects of the same issue you are trying to solve.
I suppose the best solution is a more advanced tutorial that uses bitmaps and has some other more advanced features. I hope to do a scrolling shooter next and after that perhaps Breakout 2 would be a good idea.
Hope this helps,
John
Hey again!
I got the paddle and the ball working, and will try to put sprites on the blocks too, but now I have a different question. I want to add a background image, but when I change it in the .xml file, it still stays on the color and when i remove the paint, it starts glitching up. Any thoughts?
Hi Henry,
The game doesn’t use the XML layout it uses the BreakoutView class instead. If you look at the setContentView call in the onCreate method you can see this is so.
To draw a background create a Bitmap of the background image and draw it at coordinates 0,0 each and every frame in the draw() method. Draw the background first and everything else will be drawn on top of it.
canvas.drawBitmap(backgroundImage, 0, 0, null);
The image has to be the right size or it can be dynamically scaled using createScaledBitmap.
Hope this helps.
Hi John
Hope i’m not out of order asking this question here.
I have bought your book Learning java by building android games and have been working on the Snake game.
My problem is the home screen works fine but crashes as soon as touched. I first typed the game and then copied and pasted but same result
Don’t know what to try next any ideas would be welcome/
thanks
Neil
Hi Neil,
Thanks for your question.
In the logcat console window there will be a long description as to what is causing the crash. The text is called a trace, so it will refer to multiple lines of code which eventually lead back to one specific line and the cause. Have a go at deciphering it as it almost always holds the solution.
As a guess, I would say it’s a Null pointer exception. As you mention that you copy & pasted the Java, it is most likely the error is being caused by a problem in the related XML layout file. Perhaps a wrong id for a button or similar. Try copy and pasting the layout file as well to see if this fixes the problem.
Hope this helps,
John
Hi John
Thanks for your reply. Almost too embarrassed to tell you what I had missed but for the sake of other beginners…
I had not uncommented ….//i = new Intent(this, GameActivity.class); after running menu screen.
Hi score does not work but i’ll get back to you if I can’t work it out.
Thanks again
Neil
Thanks for letting me know Neil and congrats for solving it yourself.
Hi
I was wondering if you’re still active and could help me out.
I keep on getting the error that “You need to use a Theme.AppCompat theme (or descendant) with this activity.”
Thanks in advance!!!
Hi John,
Often this is caused by a conflict between the theme and activity class being used and can usually be solved by making sure you extend Activity and not whatever might have been auto-generated by the new project wizard. Thanks for the comment.
Hi John,
Firstly thank you for creating this great website! For anyone else who is interested, I’ve made a small adjustment to the code which makes the ball more controllable and the game a bit more enjoyable. This checks which end of the paddle the ball is hitting and only changes the direction if it hits the opposite half of the paddle to it’s direction of travel (ala classic breakout).
Update the if statement with checks for the ball colliding with the paddle as follows:
float paddleMiddle = (paddle.getRect().left + paddle.getRect().right) / 2;
float ballMiddle = (ball.getRect().left + ball.getRect().right) / 2;
ball.setXVelocity(paddleMiddle, ballMiddle);
And replace the setRandomXVelocity method in the ball.java file with the following:
public void setXVelocity(float paddleMiddle, float ballMiddle){
if((xVelocity > 0 && ballMiddle < paddleMiddle) || (xVelocity paddleMiddle)){
reverseXVelocity();
}
}
Secondly, it doesn’t appear that the Win or Lose parts of the draw method are ever called. I first tried adding a pause but when that didn’t work I added a logging line to the if(lives <= 0) check and noticed that it never writes anything to the logs before it resets. Any idea what is wrong here please?
Lastly, at least for me, your final code at the end of the tutorial is a bit jumbled with multiple lines of code appearing on one line in some spots. Not a huge deal just thought I'd mention it in case you'd missed it (it might just be me but I tried a few browsers and they all showed the same).
Cheers,
Bart
My bad, it looks like posting the comment trims the code for some reason – perhaps because the line is too long? Please feel free to delete my other post. Hopefully this one works but if not feel free to delete it as well!
public void setXVelocity(float paddleMiddle, float ballMiddle){
if((xVelocity > 0 && ballMiddle < paddleMiddle)
|| (xVelocity paddleMiddle)){
reverseXVelocity();
}
}
Thanks Bart that is really useful for people to use and improve on the tutorial code.
I am fixing the badly formatted text. Thanks for pointing it out to me!
Regarding the win and lose conditions I need to restructure the code a bit to make that viable. I hope to update things a bit soon.
Thanks very much for commenting.
No worries, I think my code is being messed up because the comments are posted as xml and it contains a less-than followed later by a greater-than symbol. I’m going to try it one more time using the escape strings then I give up!
if((xVelocity > 0 && ballMiddle < paddleMiddle) || (xVelocity < 0 && ballMiddle > paddleMiddle)){
reverseXVelocity();
}
looks ok to me. Thanks for the contribution
Oh also I tried the code to stop the paddle when it hits the edge of the screen.
if(motionEvent.getX() > screenX / 2){
// Only set state if not too far over already!
if(paddle.getRect().right < screenX){ paddle.setMovementState(paddle.RIGHT); } }
The reason this appears to not work as expected is because the initial motionEvent is still ongoing (if that makes sense) – if, when the paddle hits the edge of the screen, you lift your finger off the device and then try to move it again, it won't move, but if it's already moving it just continues off the screen. This is also the source of another small annoyance which I'm unsure how to fix – if you don't lift your finger off the right side of the screen before placing your finger on the left side of the screen (or vice-versa) the paddle will simply continue on in it's current direction. Is there a way to interrupt a motionEvent?
Thanks again,
Bart
hi. im having a problem with “Display.getSize(size)” its outlined in red. and i cant figure out how to fix it.
sorrry if i miss spelled something 😉
Hi Amandus,
Hover the mouse over the red error and it should tell you what exactly is wrong. If the error doesn’t help you solve it then post the error here and I will try and help.
Thanks for your comment.
when hovering over .getSize, it says “Cannot resolve symbole ‘.getSize'” and if i click the yellow bulb thingi, it says “insert App indexing API code” but when doing that it dosent even fix the problem, it just makes more errors. thanks for the fast reply.
i started i new project and found out that i had just placed it in the wrong place. thanks for the fast reply and keep up the good work.
Cannot resolve symbol is a round-about way of saying the method doesn’t exist. Have you copy & pasted the code or typed it?
I see from the last post you use Display.get…. This should be display.get…
Try copy and pasting it if not because the slightest error, for example the wrong capitalization will cause this error.
Good luck, keep at it, John.
Hi again, im having a problem with the paddle. i dont get a error, but when i run the game and press on on of the sides, it takes some time before it reacts. and when it does, it does not move, it just becomes longer. any idea what i have done wrong?
Sounds like the top left of the bat is getting updated when you move but the other coordinates are not being reassigned each frame. Try copy & pasting the Paddle class again, especially this line from the update method.
rect.right = x + length;
Hope that helps.
Hi, im sorry to informe that i did not work. i have retyed multiply times and just figure it out. but i noticed that in this tutorial you say that i should create the paddle class in the java folder, but not in the com.example.user.BreakoutGame subfolder. And i have put the paddle class in the subfolder because when i just had it in the java folder i had some problems in the BreakoutGame.java file. when i try to make the paddle object by writing “Paddle paddle;” i just says “can not resolve symbole ‘Paddle’. any ideas what im doing wrong. and thanks alot for the fast respond.
The other possibility I can think of that could cause this symptom is if the screen is not being cleared each frame. Try copy & pasting the draw() method again. Or check that it has this line
// Draw the background colorcanvas.drawColor(Color.argb(255, 26, 128, 182));
before anything else is drawn.
Another solution might be to copy & paste the entire project and get it working first. Then go back through the tutorial to find out how it all works.
Got it working somehow. thanks alot!
I’m programming this game for an old platform (Amiga with AMOS Basic).
The core of the code contains 2 joined loops, simplifying in metacode:
do
for k=1 to no_bricks
if spritecol(k,ball)
calculate ball direction
sprite off k
score=score+10
end if
next
draw ball
move ball
loop
this implementation needs too much resources of my poor Amiga because, for each main cycle time(for each step of movement of the ball,the “do loop”) there are no_bricks checks if collision is detected,which brick is involved,and, in case of collision,delete the brick.
In your opinion how I can optimize this code,using also any kind of trick.
Thank you
Regards
Hi Salvatore,
Fascinating question. It reminds me that even when we are programming so-called resource limited devices like phones, we have it so good today.
The honest answer to your question is that I don’t know. I would need to set myself up an amiga and get in the zone with it. I remember writing a text adventure on zx81 and even that had slow load time issues.
Sorry about that. Feel free to post an overview of your solution as a reply if you succeed. Good luck!
Thank you !
this tutorial is so good and so well made I would just like to congratulate you and say thank you again.
😀
Hey,
The games is working, everything is almost perfect, but I would like to fix two thngs:
1) When my lives run out, the YOU HAVE LOST text doesnt pop up,
2) When the game is over and I have won, the game just freezes on the YOU HAVE WON screen. I would like to restart it by pressing on the screen or making a restart button.
Any way to fix this?
Thanks,
Henry
Hi Henry,
Thanks for your question.
My code is flawed in this respect. I plan to modify it in a couple of months when I finish my current project. The solution lies in clearly defining the game states and wrapping parts of update, draw and the control handling to perform differently for each state. If you have learnt about enumerations you could use one of them. Otherwise you could declare some Booleans for paused and gameOver and then wrap the relevant parts of the game in blocks which only run when these various states are true.
Sorry I can’t give you the full solution right now but hopefully that gives you something to work with. Expect big improvements to existing content and new tutorials from June onwards.
Hi John:
Great tutorial overall; am looking forward to trying Space Invaders. Just fyi, it appears your final copy-paste version of the main class above is somewhat messed up, in terms of some methods not being nested correctly inside of inner classes or even perhaps the main class–there was a whole lot of red that I could never resolve, and various orphaned methods at the bottom once I’d collapsed the methods and then inner classes in A studio. However, I used Nick’s modified project posted above in the thread (where all classes are broken out into separate files) and it worked like a champ, or at least with some minor tweaks. Possibly an issue with the way your final BreakOutGame class code is posted is just that you have a lot of code not carriage-returned so it sometimes appears hidden behind comments. In any case, it’s a great basic engine and I was even able to replace the paddle and ball rectangles with bitmaps of a weasel (for the paddle) and a rabbit (for the ball). Request from my GF, don’t ask. Now I need to get the weasel to actually chase the rabbit around the surface, meaning I can keep the rabbit/ball random and bounce motion but need to kill the bricks, bounce off the bottom, and have some other event (killRabbit()) when the weasel collides with the rabbit. And of course modify the OnPress to do Y motion. Might get messy…
Hi Matt,
I will tidy up this code as soon as my current project is done and add lots more tutorials as well.
Thanks for your comment!
Hello John! I have purchased both ‘LJbBAG’ and Android Game Programming By example and love both of them. I am in the middle of finishing them but I had a question. In the books, there are instructions on how to upload the game after we are done. Is there special permission we have to get before we use any of the code? I’m not sure how the whole copyright thing works since there are two parties involved (both you and the publisher). Same with gamcodeschool.com. Are we allowed to use some of the code we learn here in our final project before we upload? Or is it assumed that we should start from scratch and only use the knowledge we obtained? (no methods, variable names, etc.) Thanks!
Hi Ant,
I know of at least a dozen people who have uploaded various games from my books without bother. I would think it should be 100% OK. How would it stand up legally if the publisher tried to claim you shouldn’t upload it when they have just sold you a book that teaches you how to do just that? I am sure it will be fine to publish your work even if it is based significantly, even wholly on the projects in the book. If you are feeling generous maybe credit the book in the app description? Go for it I say. The only thing I know they do take action against is publishing the code itself, especially in tutorial form.
Feel free to put a link to your game on the book’s page when you are done.
Good luck!
Thanks for the reply John!
I just wanted to be really clear about it out of respect for you and the publisher (and because it is a unique situation). Normally any replication without properly crediting the author would be frowned upon or illegal. It is unfortunate when people do claim others work as their own. I will definitely redirect credit to you in the code and in the appstore description when I get everything finished! It is the least I could do =) I will definitely put the link on the book’s page when I’m done too! Thanks again!
Hey John, I already combined the pong game and the brick breaker game into one game. I guess the next logical step would be to add item drops when the brick are hit. In the second game in Android Game Programming By Example, there are 3 drops (coin, machine gun upgrade, and the extra life). I like how they are broken up into 3 separate classes because it makes it easier when sifting through code. I was wondering if that concept is done with larger games/programs too?
For example, if we created a game that has 50 upgrades and 50 weapons and 50 other special items, would we create 150 classes all extending from GameObject? It seems like something is going to be a little cluttered either way you slice it(either the class list or if you combined all the weapons in a weapon list class, all the upgrades in a upgrades class, etc. and get have methods associated with each weapon.) Maybe I am misunderstanding the the importance of classes or assuming that there won’t be that many classes in a program since I am new to all this.
Thanks for your time!
Hi Ant,
Thanks for your comment/questions. It sounds like you are making fast progress.
The concept is used in all programs especially larger programs but probably not in the exact same way. The answer to your question “would we create 150 classes…” is probably no, but exactly what you would do depends on the rest of the game.
Possibly the toughest call for any game is the design pattern(s) used. Arguably the second project of the book should have done things differently, even if the project doesn’t grow any further. Certainly any ‘real’ game should have a selection of patterns carefully chosen specifically for it. The best discussion I have found so far about this is based in C++ but the vast majority of the discussion can be easily interpreted for Android and Java. Check this Game Programming Patterns out and see what you think.
Thanks again.
Thanks again John for the reply.
I feel like I am and it is a lot of fun! I will definitely check out the game programming patterns when I can. It can feel very overwhelming when there are over 20 classes and thousands of lines per class.
I had one last question which was prompted by recent events involving google. I’m not sure if you had heard but it appears that they are considering switching to swift. It obviously isn’t definite and if they do, there is no telling when the switch will occur but I am curious to know what your thoughts are on it. Should I start learning swift just in case? Does that mean I would have to get a mac and iphone to start out? Should I learn objective C first? Should I stick to learning c++? Will java and android studio become less marketable or obsolete? Are all the apps on the android market right now going to have to be rewritten?
Please don’t feel obligated to answer any of those questions. I am just trying to give you an idea of what is going through my head and what steps I can take right now to ensure i am headed in the best possible direction for mobile gaming. As always, thanks so much!
PS if swift replaces java, would you consider writing a book about swift? 😀
PSPS (Last thing I swear), in LJBBAG, you mentioned that you could use Libgdx to use java and have multi platform functionality. Is this something I should consider still especially now with javas future being uncertain?
Yes try LibGDX, it is a great cross platform solution and you can use all your Java skills and Android background knowledge. Swift, if it is introduced will not be a cross-platform solution, even though the language is the same. I don’t think Javas future is uncertain, massive parts of Android itself is Java.
Hi Ant,
This is an interesting development that I will look into properly in a few months.
Google do seem to be considering Swift. Perhaps as a “first class”/Primary language. If they do, It will be a while before it is implemented, it will be alongside existing Java and C++, almost certainly be used through Android Studio, probably work in conjunction with existing Java code, will probably have limitations for some game types.
So, keep learning it won’t be waisted and if and when it happens you will be well skilled to part/fully switch, if it is appropriate for your project at the time.
To use Swift for Apple you need a Mac but you won’t if it is implemented for Android.
“What steps I can take right now to ensure i am headed in the best possible direction for mobile gaming”. Keep learning, diversify a little but not too much.
“Will java and android studio become less marketable or obsolete?” Nope. It is highly likely that Android development companies will use both. If you know both your value increases.
“Should I learn objective C first?”. Nope. Objective C is to Swift what Java will be, if Swift is adopted.
“if swift replaces java, would you consider writing a book about swift?”. Swift, as suggested, will likely work alongside Java. I would start a tutorial series without delay.
Hope that helps. Obviously I can’t guarantee my answers. Just a best guess.
Bravo for the detailed response John! Thanks so much. This put my worries to rest =)
One thing I didn’t grasp too well was when you mentioned this: “…probably work in conjunction with existing Java code” and ” Swift, as suggested, will likely work alongside Java.” So if we were to compare this concept to random languages around the world (lets say Korean and Spanish) and Spanish is Swift and Korean is Java, would Koreans retain Korean as a language but have the option to speak Spanish as well? Or would they mix spanish and korean and create a new language? Or something completely different?
Thanks again!
Not sure how to fit the situation into an analogy but you will be able to code for Android in Java, c++ and Swift. Some apps might have different parts coded in different languages.
Hello John,
I have implemented the game with a few designing changes although i havent done any change in frame logic.
Now while I load the game, it works completely fine but the paddle is not visible on numerous occasions.
All the events related to paddle and ball works fine but there is no way to judge the position of paddle as it becomes invisible(i know it sounds crazy!)
Can you please help why such things happen? I am figuring out it as some error related to drawing of paddle on canvas.
Any visibility options or features that i should try?
Try outputting the paddle coordinates (and anything else that might be relevant) to the screen each frame. You can achieve this in exactly the same way that you draw the score to the screen. Perhaps wrap the new code in an if(debugging) block which you can then switch off by changing the value of a single variable.
Hi John,
first of all thank you for writing these awesome tutorials and taking the time to answer all the questions in the comments!
I have two concerning the constructor of Ball:
1. Why does the constructor take the two int parameters? I don’t see them used anywhere.
2. In your comment you say that the ball will be travelling at 100pix per second straight up, yet the xVelocity is 200, how does that work?
Cheers,
Stefan
Both errors! Thanks Stefan. I am going to be improving and adding to these tutorials starting in a couple of months time.
Thanks very much for taking the time to point this out and for your compliment.
Hi!
I have created my own version of breakout. It was done completely from scratch (i only use native libs – no libgdx or unity). This tutorial was a great inspiration. If you want to check the outcome its on google play under Paddle Clash (https://play.google.com/store/apps/details?id=pl.abductedpiggy.games.paddleclash.full). Thanks!
Hey John,
I’m making this game, and I got to the part where you finish making and displaying the Paddle Class. However, when I ran it, all that came up was a blue screen. The paddle did not show up at all.
I am confused as to what is wrong and was hoping you could help !!?
Have you made the game full-screen (described near top of article). If not the paddle would probably be off the bottom of the screen.
The less than sign give me errors in all lines for example : for(int i = 0; i < numBricks; i++). I tried to add equal sign after it the errors were off but this will affect code so please tell me what to do
Hi there,
That line of code looks OK to me. Perhaps there is an error before or after it. Is that a letter “O” rather than a number zero? Just a thought?
Hi john,
I tried to run the BreakoutGame.java and Paddle.java, just to check paddle’s working.
Got 2 errors. here is messages gradle build
Information:Gradle tasks [:app:generateDebugSources, :app:generateDebugAndroidTestSources]
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAnimatedVectorDrawable2321Library UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72321Library UP-TO-DATE
:app:prepareComAndroidSupportDesign2321Library UP-TO-DATE
:app:prepareComAndroidSupportRecyclerviewV72321Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42321Library UP-TO-DATE
:app:prepareComAndroidSupportSupportVectorDrawable2321Library UP-TO-DATE
:app:prepareDebugDependencies
:app:compileDebugAidl UP-TO-DATE
:app:compileDebugRenderscript UP-TO-DATE
:app:generateDebugBuildConfig
Error:Attribute “theme” bound to namespace “http://schemas.android.com/apk/res/android” was already specified for element “activity”.
Error:Cannot read packageName from C:\Users\L520X\AndroidStudioProjects\BreakoutGame\app\src\main\AndroidManifest.xml
Information:BUILD FAILED
Information:Total time: 6.648 secs
Information:2 errors
Information:0 warnings
Information:See complete output in console
Hi Jordi,
The most likely problem I can think of is quite easy to fix. Take a look at this article here. http://stackoverflow.com/questions/27378720/android-manifest-attribute-name-file-error
Hey John, I am trying to upload a background image for each level I created. As of right now, I created a bitmap array and am just drawing the bitmap before anything else is drawn in the draw method. There is a lot of lag whenever I do. Is there a standard way of uploading and associating an image with a level? Thanks!
Hi Ant,
It is probably worth having a loadLevel function where a levelNumber variable corresponds to an image. Each level you can load a different image into the same Bitmap object. Then the code in the game loop will never need to change. So, if one level runs smoothly then they all should. As long as the image isn’t to big this shouldn’t trouble even an older device. If it is still jerky, make sure you are not accidentally initializing the bitmap each frame. Showing the bitmap as the background should cause no frame rate problems.
One possible cause for bitmap jerkiness on newer devices is as follows: Some very high resolution screen devices automatically scale up any lower resolution bitmaps. The manufacturer makes this happen to make their devices look good with older apps. If your device is scaling an image (that you haven’t told it to) then this could cause problems. You can prevent this behaviour by putting the background images in the drawable xhdpi folder. This tells the system that the image is meant for screens with very high quality and the unwanted scaling will not take place.
Thanks John for the reply, I have a levelmanager with a switch statement. A number is passed into the switch statement and whichever number it is will load that specific level. The same is true with the levelmanager update and draw methods.
switch (level) {
case 1:
l1 = new LevelOne(parameters etc);
currentLevel = level;
break;
}
switch (level) {
case 2:
l2 = new LevelTwo(parameters etc);
currentLevel = level;
break;
}
}
Here is the update method. The draw method is similar:
switch (currentLevel) {
case 1:
l1.updateLevel(parameters etc);
break;
case 2:
l2.updateLevel(parameters etc);
break;
}
This definitely isn’t the most ideal way of doing it i’m sure. I’ll take any suggestions.
So then I would just load the bitmap when I load the level. If I can get rid of the laggy nature, I can definitely do what you suggested.
On to that now:
I have created a bitmap array right here which is initialized once when my viewclass is created:
bitmapsArray[3] = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.background), screenWidth, screenHeight, true);
I have scaled the picture to the size of the screen( hopefully).
Then I wanted to see if I could draw it:
public void drawCourt() {
if (ourHolder.getSurface().isValid()) {
canvas = ourHolder.lockCanvas();
//canvas.drawColor(Color.BLACK);//the background
canvas.drawBitmap(bitmapsArray[3], 0, 0, null);
paint.setColor(Color.argb(255, 0, 255, 0));
paint.setTextSize(45);
levelManager.drawCurrentLevel(canvas);
ourHolder.unlockCanvasAndPost(canvas);
}
}
As you can see, I commented out the
canvas.drawColor(Color.BLACK);//the background
…since it is no longer need because the background scrubs out the last frame.
I know ideally this should be in the levelOne’s draw method not in the main surface views draw method. It was just for convenience to see if I could get it to work.
Do you think the problem is that I have it in a draw method?
“If it is still jerky, make sure you are not accidentally initializing the bitmap each frame. ” I don’t believe I have but please correct if I am wrong. I guess it is drawing the background and scrubbing the background every time the draw method is called. Is that bad? Is there anyway we can draw it once? If we only draw it once however, how to we remove the old ball draw frame and the old player draw frame, etc? Prior to this, we just scrubbed it out with black but if we did this, then the background would be scrubbed as well?
Also, am I drawing too many things to the screen? I have noticed that Instead of having 200 bricks (which is roughly 40%of the screen), if I put 100, there is no lag. The more bricks I put the more it lags. Same with any other objects I have been drawing. Lastly, originally I placed it in a drawable-nodpi. I then placed the images in all of the dpi folders(a suggestion I found in a google search) No luck on either of those. I will try your suggestion and place it in the xhdpi folder. Last question is: since I forced the imaged to be scaled only once when initialized, is it possible it is scalling it again? (the image is 1 mb by the way but I have also tried it with one that is 100kb and it is exactly the same performance).
Thanks so much John!
From the code you have posted the initialization does not seem to be the problem. Just a thought. Is this running on the emulator? If so, this is likely the issue. Although there is always a “better” way to structure your code, it is much better (in my opinion) to charge ahead and add the functionality you require and worry about the pattern later. Otherwise you will be constantly fretting about patterns and design and you will learn nothing. The one exception to this suggestion is when you are being paid to write the code. I love this book Game Programming Patterns. Even though it is based around C++ a bit of googling to relate the C++ to Java makes it very useful even to Java games programmers. Good luck!
Sir can you post sample code for levels?
Hi Need,
This is all the code I have for the project at the moment.
switch (motionEvent.getAction() && MotionEvent.ACTION_MASK) {
too many &&s.
Many thanks. I clicked the wrong button in WordPress a while back and all the greater than, less than and ampersands got totally messed up. I finally got around to fixing it and obviously didn’t pay enough attention. Many thanks again, they are fixed now.
Hey the game works very well! I have only one problem, the bar the user moves with fingers it just goes to the right not to the left, dont know exactly where’s the code of that and how to solve it. It is extrange because I just copied and paste it.
Thanks dude.
The control code is very basic. Be sure to remove a finger from the right before holding left. See if that works. Many thanks.
Great Job! How can I implement a couple of IF’s that make the paddle not going out of the screen?
In the Paddleclass, add a MaxX and MinX variable. Initialize them in the constructor with the passed in ScreenX and ScreenY parameters.
Then in the Paddle update method you can do something like this:
if(x > MaxX) x = MaxX
And something simmilar for going off of the left
if(x < MinX) x = MinX Hope this helps.
it seems that in my code, all the methods and variables from other classes are red and says :”Cannot resolve method”. Do you know why this is happening?
nevermind, I figured it out. All I had to do was move the classes into tk.mypublicwebsites.breakoutgame
Thanku so much giving grt idea for developing Game…. thanks alot.
Great tutorial. I have one problem. In case when player lose, everything is fine except for message “you have lost” is not being shown (probably because switches too fast to createBricksAndRestart method), but when player wins, game is stuck with message “you have won”. It doesn’t matter where player tries to touch screen, game is still frozen.
Hi Artur,
The problem is my code. I really need to separate the different phases into states so that the draw method deals with them separately. At the end of the game you could set a boolean or enum to represent game over and in the draw, method draws the text when the state is game over. Then switch it back, perhaps the next time the player touches the screen. I am going to improve this as soon as I get a bit of time. Hope this helps a bit.
My game is really glitchy and sometimes may pass through a brick without hitting it or the ball touching the paddle but it still goes through and I lose a life. Can you fix these bugs?
Is this on an emulator? If so, it is the slow frame rate that causes the ball to move more than the thickness of the bat in some frames. If this is on a “real” device then let me have all the details and I will try and work it out. Thanks for letting me know.
It is on a real device and I use a 4.1.2 (Jellybean) phone.
Should run fine on even an old device. There are bugs, it is just a skeleton demo but it should run reasonably smoothly. Try this. Add an FPS counter and see what it is running at. Take a look at the building a simple game engine demo for how to achieve this.
Hi John
I got a problem with final stage (until Making some noise and keeping score evrything working). When i add noise and collision detection i get 7 errors abaut ” Error406, 15) error: class, interface, or enum expected ” . It got a problem with method super.onResume(); and super.onPause();. Do you have any ideea whats the problem ? (sorry for bad english).
Thanks for your question. My best guess is that somehow you have typed the method code outside of the Activity class body. This would cause the compiler to think you were overriding a method that doesn’t exist. Double check where your opening and closing curly brackets {} are and make sure onResume etc are inside the closing curly brace of the class that extends Activity class and not any other class or outside on their own. Hope this helps.
oh i doesnt past well in comments -.-
http://paste.ofcode.org/EdVatvD87v9HLEcdBBh9Xs
lane 12 has like 2 methods inside
I have just sorted out the jumbled formatting. Try copy & pasting now.
I made whole projekt since start and it worked just fine ;d. I had to made stupid error thanks for awsome tutorial.
Really pleased!
I followed the whole thing till the end, but for some reason, the paddle does not show up and I don’t know why
Hi Tro,
Have you completed the section about making the game full-screen? Its near the top of the article. If this doesn’t fix it try setting the paddle’s vertical position to something like 100 and seeing if you can see it then. I suspect it might be hiding just off-screen.
This blog awesome and i learn a lot about programming from here.The best thing about this blog is that you doing from beginning to experts level.
Thanks asad
Hi John, I’m trying to increase the size of the ball, but for some reason the bouncing mechanics don’t work anymore when I do, do you know how to increase the size of the ball without this happening??
Hi Tro,
Changing the ballWidth and ballHeight variables should be enough. What have you tried so far and what isn’t working/symptoms of problem.
hi john, great tutorial thank you!
i have a problem with the intersect between the ball and the paddle:
// Check for ball colliding with paddle
if (RectF.intersects(paddle.getRect(), ball.getRect())) {
ball.setRandomXVelocity();
ball.reverseYVelocity();
ball.clearObstacleY(paddle.getRect().top – 2);
}
sometimes it recognize intersect and some time it dosen’t, so the ball keep falling and the lives decrease.
any solution?
Are you running on an emulator? If the frames per second is too slow then collisions can often be missed.
Hi John, First of all i would like to express my gratitude for all the effort you have done to make this tutorial. Currently, I have a problem while following your tutorial to create the paddle. I have written all of the code in paddle class and also in BreakoutGame.java but when I test the code, nothing happen. There is no error notification but my emulator just show a blank blue screen. Are there any possible reason for this problem?
Thank you
Make sure to complete the section of the tutorial about making the app full screen. It could be hiding just off of the bottom of the screen.
Hi John,
Just wondering if you were able to help with any of the following?
Cheers.
1. Change BreakoutView so it is an external class (like paddle, brick & ball) rather than an
inner class within BreakoutGame
2. Fix the ball so it sits in the middle of the paddle at the beginning of the game.
3. Make the paddle return to the centre of the screen when the game restarts
4. Display a message to the user to tell them that they have died when three lives have
been lost
5. Stop the paddle from going off the side of the screen (at the moment it can ‘disappear’ off
the screen altogether)
Hi Phil, nice to hear from you. Here are a few pointers.
1) Check the SpaceInvaders tutorial that uses an external class for the view
2) In the ball constructor, initialize it with similar coordinates to the bat.
3 and 4) Need to code a slightly different structure that handles states like paused, playing and game over etc. I hope to get round to this.
5) Check earlier in these comments I think the solution is there.
Hope this helps a bit,
John
Hi John,
just wanna ask why my paddle cannot be seen, there was no error found, the game is running perfectly but the paddle seems to be invisible.
This problem is often caused by the paddle being drawn slightly off-screen. Have you completed the section titled “Making the game full-screen landscape?”
Hey John,
I went through you tutorial a couple of days ago and had some problems with collision, probably because I worked with a different screen resolution and changed some settings. That brought me into thinking, and I had an idea how to improve your collision methode:
Create a Rect between the point where the ball started, and where it finishes it move. Now check that Rect for intersection with the paddle and the blocks, instead of just the ball rect at the new position. This way, collision during traveling will be detected as well. I guess that’s the easy part, the harder part will be calculating the corrected “point of bounce” and the switch in direction within the movement (instead of switching direction for the next movement), but should be doable as well. Maybe I get to it this afternoon.
This sounds interesting. I would love to know your conclusion.
I’ll get to it when I’m home again.
Basically you always need to remember the last position of the ball to build the travel-rect.
One thing I’m not sure about is how to calculate the distance the ball travels before and after the collision, but I guess with a bit help from pythagoras this might be solved.
Also, determining with which side of the paddle/block the ball collides to calculate the correct distance is needed, I think (not sure how I’ll do that, yet).
Basically like this (though I’m not entirely sure on how to do the second step/determine which one is the correct side):
Also, you’d have to check all objects for collision and take the one with the smallest distance. After bouncing, you’d have to check again for further collisions, of course.
Maybe if there is something equal to the rect.intersects for lines(pair of points) that could be used?
Rect.Intersects uses lines(kind of) internally. See here. You gan get the lines using the rextWhateverObject.x etc. Hope that helps a bit.
Hi When i try to copy the code when the article ends the paddle is not there how can I add the paddle? sorry I’m new to android programming.
This sounds like the screen might not be set to full screen. Take a look at the part titled Making the game fullscreen and landscape.
oppp my mistake my only problem is that the paddle goes out of the screen.
Try wrapping the code which changes the paddles horizontal variable with an if if statement that checks the value is not too high first.
Hi John. I wanted to add text on each of the bricks created:
for (int i = 0; i < numBricks; i++) {
if (bricks[i].getVisibility()) {
paint.setColor(Color.BLACK);
canvas.drawRect(bricks[i].getRect(), paint);
paint.setTextSize(12);
paint.setColor(Color.WHITE);
canvas.drawText("Some Text Here",10,20,paint);
}
}
and on collision with the ball:
for (int i = 0; i < numBricks; i++) {
if (bricks[i].getVisibility()) {
if (RectF.intersects(bricks[i].getRect(), ball.getRect())) {
bricks[i].setInvisible();
ball.reverseYVelocity();
score = score + 10;
paint.setColor(Color.GREEN);
canvas.drawRect(screenX,screenY,screenX/8,screenY/10,paint);
soundPool.play(explodeID, 1, 1, 0, 0, 1);
}
}
}
But the text cannot be removed. Help.Thanks
Hi there,
Looks like you are drawing the text at the same place each time through the loop. To draw on the bricks you need to position each piece of text relative to each brick you want to draw on. Try
canvas.drawText("The Text",bricks[i].getRect().top,bricks[i].getRect().left, paint);
That might not be exactly syntactically correct but something close will probably work.
Good luck!
Thanks for replying John.
Incase that i have created a text, how can I remove it when it collides with the ball?
If you draw the text after the check for the block being active then the existing code structure should work as it is.
Hi John, could you point me in the right direction: I am trying to create buttons via xml but it is proving difficult because of this line
setContentView(breakoutView);
Maybe I am misunderstanding how this works but can you create buttoms with a custom view? In other words, Is the xml for the current activity still available to be used and if so how would I add a button so it can be seen while the game is being drawn.
I am trying to add a pause button that persists while the game is being played. I want to be able to position the button and adjust the padding, margins, use dp, etc. and not with the draw() method/canvas.
Thanks again!
Hi there,
It can be done but is usually better to draw the button each frame using the Canvas class like you do for the other game objects. The 2D scrolling shooter tutorial draws buttons to the screen so you could refer to that or if you have a reason that you must use XML defined buttons then experiment with gameView.addView(...). I googled “adding XML layer on top of canvas” and got quite a few useful articles.
I hope this helps and thanks for your question.
Thanks for the reply! This definitely does help and I will look at the 2d shooter tutorial as well. Is that how game buttons normally done? Things like “Resume”, “Sound”, “Quit” buttons when the pause menu is showing?
In your collaboration book Android Programming For Developers, a custom view is set for the paddle game (just like it is here) however later on in the mastering portion of the book for the space shooter, setContentView(R.layout.activity) is used instead setContentView(breakoutView) Is there a reason for the two different ways or is it based on preference? Thanks again!
Hi Ant,
I am not too familiar with that part of the book as I read it quite a while ago. I believe the author used XML layouts to include drawables, menus, and a pop-up dialog as well. He also designed a class based on Canvasand instead of setting it as the entire view (like the tutorials on this site) he positioned it within the XML and the other elements. Either approach is fine, especially for menu screens etc. My preference for any screen where the game is running would be to draw everything using Canvas (or OpenGL directly). But whatever suits the project is OK. Perhaps the other author wanted to show a diverse range of possibilities or just felt his way was more appropriate in the circumstances. Knowing both ways won’t hurt and might prove useful one day.
Does this answer your question?
All the best.
Running this gives me the errors: E/BD.Reporter: Can’t getService HwBDService
E/WVMExtractor: Failed to open libwvm.so: dlopen failed: library “libwvm.so” not found
Hi Jonathan,
This could be device/emulator specific. Try a different device or a different version of the emulator.
The game runs but there is no paddle. I checked for errors and the only one was
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
where it gave me an error on the second Soundpool
SoundPool(int, int, int)’ is deprecated less… (Ctrl+F1)
This inspection reports where deprecated code is used in the specified inspection scope
was wondering what is wrong
Hi Jack,
The error is OK it is just that there is a newer (but much longer) way to handle the sound. The most likely cause of the missing paddle is that you haven’t set the game to full-screen. Check the section Making the game full-screen landscape. Hope this fixes things. Thanks for your comment.
Hi John.
I also have the issue where the paddle is not showing. I tried the method you had and it didnt allow the game to open in an emulator. So i tried using :
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
but that still isn’t working. Do you know why or Is there anything else i could try?
Thank You
Try reducing the vertical position the paddle is drawn at. To make this dynamic you could perhaps use a value which is a percentage of the screen.
Thank You for the help!!
Hi John! I have already run the game but my problem is, the paddle is missing. There are no errors, however, it is useless because of the absence of the paddle. I hope you can answer me right away. I’m using this as my guide for my project to be passed next week. D: Thank you!
Hi Carla,
There are some suggestions to fix this in the comments. Let me know which ones you have tried already. Most likely the paddle is being drawn slightly off-screen.
Hello thanks for this great tutorial. I want to ask if is somehow possible to control paddle using accelerometer not with onTouchEvent.
I tried to implement SensorEventListener into GameActivity class but it’s not working…
Do you have any suggestions? Thank you so much.
Hi Tom,
There is surprisingly little content on the web for such a big topic. This is the best I could find. It uses a custom View rather than canvas but the point is that all the inputs are received in a seperate thread so the example should be adaptable to the game.
https://www.linux.com/learn/how-code-2d-drawing-android-motion-sensors
I will hopefully have time to do a tutorial but thought this might help as I can’t at the moment.
All the best,
John
Hi John,
I dont see Paddle, doesnt drow on the screen. Can you tell me how I can resolve this? I dont have idea what the reason may be. All code Copy / Paste.
Great tutorial but I have one little problem
Do you have any suggestions?
Thank You
Hi Pat, the most likely cause is that the device calculates the pixels slightly differently and it is placing the paddle just off-screen. Try lowering the y coordinate of the bat by a couple of hundred and see if it appears. If it does you can then manually tweak to get it just right.
Hi John,
I have one question about collisions. In your projects is only one collsions and change the dirrection of the ball ball.reverseYVelocity();
I want it to change the direction depending on where it hits. If in the side of the brick I would like ball.reverseXVelocity();
If in the top or bottom of the brick I would like ball.reverseYVelocity();
I dont have idea
Can You help me?
Hi Pat,
After you have detected a rectangle intersection:
if(RectF.intersects(bricks[i].getRect(),ball.getRect())) {
You could then probe further before taking action. Perhaps by testing if the middle of the ball (ball.getRect().bottom – ball.getRect().top) is in between the top and bottom of the brick thus indicating that the most likely collision was with the side.
Thanks for the question.
John
I completed all step but there is some issue.
{Game keep stopping.}
I don’t get it.
Can you give more details When does it stop, error messages etc.
Hi john, how can i create a main menu where i can deactivate music and start game?
Hi Tommasso,
Playing or not playing the sound is easy. You just wrap all code that plays a sound in an if statement that tests a Boolean. Switching the value of this Boolean is less straightforward. A button could trigger the switching of this value. To create a button you can create a Rect that you draw each frame and test for a finger press as well. On finger up in this Rect you switch the Boolean value. To create a very simple main menu screen you could use an enumeration that determines which screen the player is on: Menu, Game, Home etc and then you could vary what you draw and update each frame accordingly.
you are the best, it was super helpful, specially ClearYObstacle method, also how you handle colliding in update method. thanks much
i did exactly as you said and there is no error but app crashes as it lunches i don’t know what seems to be the problem