Hello developers, I decided to post this Android Game Development Tutorial. In this Android Game Development Tutorial we are going to create a simple 2d game using android studio. We will not be using any third party library or game engines for this android game development tutorial. So lets begin.
Table of Contents
- 1 Android Game Development with Unity
- 2 Planning the Game Story
- 3 The Game Rules
- 4 Android Game Development Tutorial
- 4.1 Android Game Development Tutorial – Video Demo
- 4.2 Android Game Development Tutorial –Â Live Demo
- 4.3 Download the Images Used
- 4.4 Creating a New Project
- 4.5 Designing the Start Screen
- 4.6 Building Game View
- 4.7 Adding GameView to GameActivity
- 4.8 Creating Player
- 4.9 Drawing Player to GameView
- 4.10 Adding Controls
- 4.11 Adding Booster to Space Jet
- 4.12 Adding Background Stars
- 4.13 Adding Enemies
- 4.14 Detecting Collision
- 4.15 Adding Blast Effect
- 5 Android Game Development Tutorial – Summary
- 6 Android Game Development Tutorial –Â Final Words
Android Game Development with Unity
In this tutorial we are using Android Studio, and really that is not how actual games are build in the industry. If you are really serious about Mobile Game Development, and want to become a professional, or want to start your career in Game Development Industry; then you must learn some Game Engines. And the best Game Engine to start as a Student is Unity. It is one of the most popular Game Engines. It is also free. And I have a Complete Free Course about building Android Games with Unity. Check it out Here.
But if you are just casual learner and just want to learn some basics with Android Studio, keep reading the post.Â
Planning the Game Story
Every game start with a story. So you need to think. Not actually 😛 because I have already decided what we will be creating.
So In our game there will be a Space Jet, and the jet has to kill the enemies by hitting them. There will also be some good guys and our Space Jet should not kill them. So basically if our Space Jet  touches other character that will be destroyed. So we have to only kill the enemies.
The Game Rules
- Player ship has to kill the enemies by colliding with them.
- If player lets 3 enemies to go safely then the game is over.
- If player kills a good guy the game is over.
Android Game Development Tutorial
We have decided the game story and the rules. Now its time to create the game. We will use Android Studio. And I am assuming all of you got Android Studio and know the basics of it.
Android Game Development Tutorial – Video Demo
Before going ahead in this tutorial you can check out this video to know what you will get at the end of this Android Game Development Tutorial part 1.
Android Game Development Tutorial –Â Live Demo
You can also download the apk for this part of Android Game Development Tutorial from the link given below.
Download the Images Used
You can design and create your own character using Adobe Photoshop or other photo editing program. But if you don’t want to do it yourself you can download the images I used in this project from the link given below.
Android Game Development Images Download
Creating a New Project
- Open Android Studio and create a new project.
- Once the project is loaded you will get MainActivity.java and activity_main.xml
- First paste all the images that you downloaded inside the drawable folder of your project.
Designing the Start Screen
- Above you can see the first screen of the game. It has a nice background image with two ImageButtons. You already downloaded the images used in this screen.
- As you can see it is a full screen activity. So to make your application full screen, you need to go res->values->styles.xml and modify it as the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="windowNoTitle">true</item> <item name="windowActionBar">false</item> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> </style> </resources> |
- Inside activity_main.xml write the following xml code.
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 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:background="@drawable/splash" tools:context="net.simplifiedcoding.simplegame.MainActivity"> <ImageButton android:id="@+id/buttonPlay" android:background="@drawable/playnow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/buttonScore" android:layout_centerHorizontal="true" /> <ImageButton android:id="@+id/buttonScore" android:background="@drawable/highscore" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" /> </RelativeLayout> |
- When we tap the Play Now button our Game Activity will start.
- Now come inside MainActivity.java and write the following code.
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 |
package net.simplifiedcoding.simplegame; import android.content.Intent; import android.content.pm.ActivityInfo; import android.media.Image; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageButton; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ //image button private ImageButton buttonPlay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //setting the orientation to landscape setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); //getting the button buttonPlay = (ImageButton) findViewById(R.id.buttonPlay); //adding a click listener buttonPlay.setOnClickListener(this); } @Override public void onClick(View v) { //starting game activity startActivity(new Intent(this, GameActivity.class)); } } |
- Now you need to create a new activity named GameActivity. To create a new activity right click on the package name -> new -> activity -> empty activity
Building Game View
Now its time to build our Game View. We will be using SurfaceView for building our game view. Surfaceview provides a dedicated drawing surface.
- Create a new class named GameView and write the following code.
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 |
public class GameView extends SurfaceView implements Runnable { //boolean variable to track if the game is playing or not volatile boolean playing; //the game thread private Thread gameThread = null; //Class constructor public GameView(Context context) { super(context); } @Override public void run() { while (playing) { //to update the frame update(); //to draw the frame draw(); //to control control(); } } private void update() { } private void draw() { } private void control() { try { gameThread.sleep(17); } catch (InterruptedException e) { e.printStackTrace(); } } public void pause() { //when the game is paused //setting the variable to false playing = false; try { //stopping the thread gameThread.join(); } catch (InterruptedException e) { } } public void resume() { //when the game is resumed //starting the thread again playing = true; gameThread = new Thread(this); gameThread.start(); } } |
- The above class is our GameView class. It is the actual game panel where we will play the game. The class is implementing Runnable interface. We have a volatile boolean type variable running that will track whether the game is running or not. After that we have our gameThread, it is the main game loop. Then we have the constructor to the class. We are not doing anything inside the constructor right now. Then we have the overriden method run(), here we are running a loop until the playing variable running is true.  Inside the loop we are calling the following methods.
update() ->Â Here we will update the coordinate of our characters.
draw() -> Here we will draw the characters to the canvas.
control() -> This method will control the frames per seconds drawn. Here we are calling the delay method of Thread. And this is actually making our frame rate to aroud 60fps.
After these we have two more methods.
pause() -> To pause the game, we are stopping the gameThread here.
resume() -> To resume the game, here we are starting the gameThread.
Adding GameView to GameActivity
- After tapping the play now button we are launching the GameActivity. We will set our GameView to the content of this activity. So go to GameActivity.java and  modify the code as below.
I will be adding the comments only above the new code added so that you can understand what is new in this code so that you can modify your code easily.
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 |
package net.simplifiedcoding.spacefighter; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; public class GameActivity extends AppCompatActivity { //declaring gameview private GameView gameView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Initializing game view object gameView = new GameView(this); //adding it to contentview setContentView(gameView); } //pausing the game when activity is paused @Override protected void onPause() { super.onPause(); gameView.pause(); } //running the game when activity is resumed @Override protected void onResume() { super.onResume(); gameView.resume(); } } |
Creating Player
- Create a new class Player inside your package and write the following code.
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 |
package net.simplifiedcoding.spacefighter; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; /** * Created by Belal on 6/24/2016. */ public class Player { //Bitmap to get character from image private Bitmap bitmap; //coordinates private int x; private int y; //motion speed of the character private int speed = 0; //constructor public Player(Context context) { x = 75; y = 50; speed = 1; //Getting bitmap from drawable resource bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.player); } //Method to update coordinate of character public void update(){ //updating x coordinate x++; } /* * These are getters you can generate it autmaticallyl * right click on editor -> generate -> getters * */ public Bitmap getBitmap() { return bitmap; } public int getX() { return x; } public int getY() { return y; } public int getSpeed() { return speed; } } |
- The above code is very easy to understand. I have written comments to explain everything. So lets move ahead.
Drawing Player to GameView
- To draw the player to our GameView you need to come back to the GameView.java class and modify it as below.
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 |
public class GameView extends SurfaceView implements Runnable { volatile boolean playing; private Thread gameThread = null; //adding the player to this class private Player player; //These objects will be used for drawing private Paint paint; private Canvas canvas; private SurfaceHolder surfaceHolder; public GameView(Context context) { super(context); //initializing player object player = new Player(context); //initializing drawing objects surfaceHolder = getHolder(); paint = new Paint(); } @Override public void run() { while (playing) { update(); draw(); control(); } } private void update() { //updating player position player.update(); } private void draw() { //checking if surface is valid if (surfaceHolder.getSurface().isValid()) { //locking the canvas canvas = surfaceHolder.lockCanvas(); //drawing a background color for canvas canvas.drawColor(Color.BLACK); //Drawing the player canvas.drawBitmap( player.getBitmap(), player.getX(), player.getY(), paint); //Unlocking the canvas surfaceHolder.unlockCanvasAndPost(canvas); } } private void control() { try { gameThread.sleep(17); } catch (InterruptedException e) { e.printStackTrace(); } } public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { } } public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } } |
- Now try executing your application. Put your emulator in landscape mode. When you tap the play now button in the first activity you will see the moving Space Jet as shown below.
If you are getting the output as shown in the above image then Hurray!. You might have got the concept about drawing images in canvas using SurfaceView. And the movement is the magic of the coordinates. We are changing the x coordinate so it is moving horizontally ahead.
Now lets add control to our Space Jet.
Adding Controls
We will now add control to the player’s Space Jet. When the player will tap on the screen the Space Jet will boost up and after releasing the screen the Space Jet will boost down. The movement is inspired by the most popular game Flappy Bird.
To add this control we will need to detect touches of the screen. So lets begin.
- Come inside GameView.java file and override the method onTouchEvent().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
@Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: //When the user presses on the screen //we will do something here break; case MotionEvent.ACTION_DOWN: //When the user releases the screen //do something here break; } return true; } |
- Currently we need these two events only which are ACTION_UPÂ and ACTION_DOWN. Â What we need to do is we need to boost up the Space Jet on ACTION_UP and boost down the Space Jet on ACTION_DOWN.
Adding Booster to Space Jet
Now we will add the booster to our Space Jet so that our player can control the Space Jet. Follow these steps to do this.
- Modify the code of Player.java file as follows.
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 |
public class Player { private Bitmap bitmap; private int x; private int y; private int speed = 0; //boolean variable to track the ship is boosting or not private boolean boosting; //Gravity Value to add gravity effect on the ship private final int GRAVITY = -10; //Controlling Y coordinate so that ship won't go outside the screen private int maxY; private int minY; //Limit the bounds of the ship's speed private final int MIN_SPEED = 1; private final int MAX_SPEED = 20; public Player(Context context) { x = 75; y = 50; speed = 1; bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.player); //setting the boosting value to false initially boosting = false; } //setting boosting true public void setBoosting() { boosting = true; } //setting boosting false public void stopBoosting() { boosting = false; } public void update() { //if the ship is boosting if (boosting) { //speeding up the ship speed += 2; } else { //slowing down if not boosting speed -= 5; } //controlling the top speed if (speed > MAX_SPEED) { speed = MAX_SPEED; } //if the speed is less than min speed //controlling it so that it won't stop completely if (speed < MIN_SPEED) { speed = MIN_SPEED; } //moving the ship down y -= speed + GRAVITY; //but controlling it also so that it won't go off the screen if (y < minY) { y = minY; } if (y > maxY) { y = maxY; } } public Bitmap getBitmap() { return bitmap; } public int getX() { return x; } public int getY() { return y; } public int getSpeed() { return speed; } } |
- Â We also need to detect the size of screen so go inside GameActivity.java file and add the following code inside onCreate().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Getting display object Display display = getWindowManager().getDefaultDisplay(); //Getting the screen resolution into point object Point size = new Point(); display.getSize(size); //Initializing game view object //this time we are also passing the screen size to the GameView constructor gameView = new GameView(this, size.x, size.y); //adding it to contentview setContentView(gameView); } |
- In the above code we are passing screen size to GameView constructor, so we also need to change the GameView constructor. So change the GameView constructor as follow.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public GameView(Context context, int screenX, int screenY) { super(context); //initializing player object //this time also passing screen size to player constructor player = new Player(context, screenX, screenY); //initializing drawing objects surfaceHolder = getHolder(); paint = new Paint(); } |
- In the above code you can see we are passing the screen size to player constructor. So again we also need to modify the Player class constructor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public Player(Context context, int screenX, int screenY) { x = 75; y = 50; speed = 1; bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.player); //calculating maxY maxY = screenY - bitmap.getHeight(); //top edge's y point is 0 so min y will always be zero minY = 0; //setting the boosting value to false initially boosting = false; } |
- Now to complete adding the boosters come inside GameView.java file and modify the onTouchEvent() as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: //stopping the boosting when screen is released player.stopBoosting(); break; case MotionEvent.ACTION_DOWN: //boosting the space jet when screen is pressed player.setBoosting(); break; } return true; } |
Now execute your application again to test the boosters. If it is working fine then you can move ahead.
Adding Background Stars
Now we will add background stars to make the background looks animating.
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 |
package net.simplifiedcoding.spacefighter; import java.util.Random; /** * Created by Belal on 6/15/2016. */ public class Star { private int x; private int y; private int speed; private int maxX; private int maxY; private int minX; private int minY; public Star(int screenX, int screenY) { maxX = screenX; maxY = screenY; minX = 0; minY = 0; Random generator = new Random(); speed = generator.nextInt(10); //generating a random coordinate //but keeping the coordinate inside the screen size x = generator.nextInt(maxX); y = generator.nextInt(maxY); } public void update(int playerSpeed) { //animating the star horizontally left side //by decreasing x coordinate with player speed x -= playerSpeed; x -= speed; //if the star reached the left edge of the screen if (x < 0) { //again starting the star from right edge //this will give a infinite scrolling background effect x = maxX; Random generator = new Random(); y = generator.nextInt(maxY); speed = generator.nextInt(15); } } public float getStarWidth() { //Making the star width random so that //it will give a real look float minX = 1.0f; float maxX = 4.0f; Random rand = new Random(); float finalX = rand.nextFloat() * (maxX - minX) + minX; return finalX; } public int getX() { return x; } public int getY() { return y; } } |
- Now come inside GameView.java and modify it as follows.
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 |
public class GameView extends SurfaceView implements Runnable { volatile boolean playing; private Thread gameThread = null; private Player player; private Paint paint; private Canvas canvas; private SurfaceHolder surfaceHolder; //Adding an stars list private ArrayList<Star> stars = new ArrayList<Star>(); public GameView(Context context, int screenX, int screenY) { super(context); player = new Player(context, screenX, screenY); surfaceHolder = getHolder(); paint = new Paint(); //adding 100 stars you may increase the number int starNums = 100; for (int i = 0; i < starNums; i++) { Star s = new Star(screenX, screenY); stars.add(s); } } @Override public void run() { while (playing) { update(); draw(); control(); } } private void update() { player.update(); //Updating the stars with player speed for (Star s : stars) { s.update(player.getSpeed()); } } private void draw() { if (surfaceHolder.getSurface().isValid()) { canvas = surfaceHolder.lockCanvas(); canvas.drawColor(Color.BLACK); //setting the paint color to white to draw the stars paint.setColor(Color.WHITE); //drawing all stars for (Star s : stars) { paint.setStrokeWidth(s.getStarWidth()); canvas.drawPoint(s.getX(), s.getY(), paint); } canvas.drawBitmap( player.getBitmap(), player.getX(), player.getY(), paint); surfaceHolder.unlockCanvasAndPost(canvas); } } private void control() { try { gameThread.sleep(17); } catch (InterruptedException e) { e.printStackTrace(); } } public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { } } public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: player.stopBoosting(); break; case MotionEvent.ACTION_DOWN: player.setBoosting(); break; } return true; } } |
- Now execute your app again. You will see a infinite scrolling background this time as shown in the following image.
Adding Enemies
So far in this Android Game Development Tutorial, we have added our player, we added an infinite scrolling background. We also added controls to our player. Now we need to add some enemies. So lets start coding the enemies.
- Create a new java class named Enemy and write the following code.
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 |
package net.simplifiedcoding.spacefighter; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Rect; import java.util.Random; /** * Created by Belal on 6/15/2016. */ public class Enemy { //bitmap for the enemy //we have already pasted the bitmap in the drawable folder private Bitmap bitmap; //x and y coordinates private int x; private int y; //enemy speed private int speed = 1; //min and max coordinates to keep the enemy inside the screen private int maxX; private int minX; private int maxY; private int minY; public Enemy(Context context, int screenX, int screenY) { //getting bitmap from drawable resource bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.enemy); //initializing min and max coordinates maxX = screenX; maxY = screenY; minX = 0; minY = 0; //generating a random coordinate to add enemy Random generator = new Random(); speed = generator.nextInt(6) + 10; x = screenX; y = generator.nextInt(maxY) - bitmap.getHeight(); } public void update(int playerSpeed) { //decreasing x coordinate so that enemy will move right to left x -= playerSpeed; x -= speed; //if the enemy reaches the left edge if (x < minX - bitmap.getWidth()) { //adding the enemy again to the right edge Random generator = new Random(); speed = generator.nextInt(10) + 10; x = maxX; y = generator.nextInt(maxY) - bitmap.getHeight(); } } //getters public Bitmap getBitmap() { return bitmap; } public int getX() { return x; } public int getY() { return y; } public int getSpeed() { return speed; } } |
- We need to add the enemies in the GameView now. So come inside GameView.java and modify the code as follows.
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 |
public class GameView extends SurfaceView implements Runnable { volatile boolean playing; private Thread gameThread = null; private Player player; private Paint paint; private Canvas canvas; private SurfaceHolder surfaceHolder; //Adding enemies object array private Enemy[] enemies; //Adding 3 enemies you may increase the size private int enemyCount = 3; private ArrayList<Star> stars = new ArrayList<Star>(); public GameView(Context context, int screenX, int screenY) { super(context); player = new Player(context, screenX, screenY); surfaceHolder = getHolder(); paint = new Paint(); int starNums = 100; for (int i = 0; i < starNums; i++) { Star s = new Star(screenX, screenY); stars.add(s); } //initializing enemy object array enemies = new Enemy[enemyCount]; for(int i=0; i<enemyCount; i++){ enemies[i] = new Enemy(context, screenX, screenY); } } @Override public void run() { while (playing) { update(); draw(); control(); } } private void update() { player.update(); for (Star s : stars) { s.update(player.getSpeed()); } //updating the enemy coordinate with respect to player speed for(int i=0; i<enemyCount; i++){ enemies[i].update(player.getSpeed()); } } private void draw() { if (surfaceHolder.getSurface().isValid()) { canvas = surfaceHolder.lockCanvas(); canvas.drawColor(Color.BLACK); paint.setColor(Color.WHITE); for (Star s : stars) { paint.setStrokeWidth(s.getStarWidth()); canvas.drawPoint(s.getX(), s.getY(), paint); } canvas.drawBitmap( player.getBitmap(), player.getX(), player.getY(), paint); //drawing the enemies for (int i = 0; i < enemyCount; i++) { canvas.drawBitmap( enemies[i].getBitmap(), enemies[i].getX(), enemies[i].getY(), paint ); } surfaceHolder.unlockCanvasAndPost(canvas); } } private void control() { try { gameThread.sleep(17); } catch (InterruptedException e) { e.printStackTrace(); } } public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { } } public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: player.stopBoosting(); break; case MotionEvent.ACTION_DOWN: player.setBoosting(); break; } return true; } } |
- Execute your application again and you should see the following output.
So we are almost done at this part of the Android Game Development Tutorial. Only the last thing is left. When our Space Jet touches the enemy, the enemy ship should blast. So we need a blast image and you already got it inside your drawable folder. To show the blast image we need to detect the collision between the player and enemy jet. So lets do this.
Detecting Collision
- To detect collision we will use Rect object. So come inside Enemy class modify the code as follows.
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 |
public class Enemy { private Bitmap bitmap; private int x; private int y; private int speed = 1; private int maxX; private int minX; private int maxY; private int minY; //creating a rect object private Rect detectCollision; public Enemy(Context context, int screenX, int screenY) { bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.enemy); maxX = screenX; maxY = screenY; minX = 0; minY = 0; Random generator = new Random(); speed = generator.nextInt(6) + 10; x = screenX; y = generator.nextInt(maxY) - bitmap.getHeight(); //initializing rect object detectCollision = new Rect(x, y, bitmap.getWidth(), bitmap.getHeight()); } public void update(int playerSpeed) { x -= playerSpeed; x -= speed; if (x < minX - bitmap.getWidth()) { Random generator = new Random(); speed = generator.nextInt(10) + 10; x = maxX; y = generator.nextInt(maxY) - bitmap.getHeight(); } //Adding the top, left, bottom and right to the rect object detectCollision.left = x; detectCollision.top = y; detectCollision.right = x + bitmap.getWidth(); detectCollision.bottom = y + bitmap.getHeight(); } //adding a setter to x coordinate so that we can change it after collision public void setX(int x){ this.x = x; } //one more getter for getting the rect object public Rect getDetectCollision() { return detectCollision; } //getters public Bitmap getBitmap() { return bitmap; } public int getX() { return x; } public int getY() { return y; } public int getSpeed() { return speed; } } |
- The same thing you need to do inside the Player.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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
public class Player { private Bitmap bitmap; private int x; private int y; private int speed = 0; private boolean boosting; private final int GRAVITY = -10; private int maxY; private int minY; private final int MIN_SPEED = 1; private final int MAX_SPEED = 20; private Rect detectCollision; public Player(Context context, int screenX, int screenY) { x = 75; y = 50; speed = 1; bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.player); maxY = screenY - bitmap.getHeight(); minY = 0; boosting = false; //initializing rect object detectCollision = new Rect(x, y, bitmap.getWidth(), bitmap.getHeight()); } public void setBoosting() { boosting = true; } public void stopBoosting() { boosting = false; } public void update() { if (boosting) { speed += 2; } else { speed -= 5; } if (speed > MAX_SPEED) { speed = MAX_SPEED; } if (speed < MIN_SPEED) { speed = MIN_SPEED; } y -= speed + GRAVITY; if (y < minY) { y = minY; } if (y > maxY) { y = maxY; } //adding top, left, bottom and right to the rect object detectCollision.left = x; detectCollision.top = y; detectCollision.right = x + bitmap.getWidth(); detectCollision.bottom = y + bitmap.getHeight(); } //one more getter for getting the rect object public Rect getDetectCollision() { return detectCollision; } public Bitmap getBitmap() { return bitmap; } public int getX() { return x; } public int getY() { return y; } public int getSpeed() { return speed; } } |
- Now to complete the collision detection, again to inside GameView.java file and modify the update() method as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private void update() { player.update(); for (Star s : stars) { s.update(player.getSpeed()); } for(int i=0; i<enemyCount; i++){ enemies[i].update(player.getSpeed()); //if collision occurrs with player if (Rect.intersects(player.getDetectCollision(), enemies[i].getDetectCollision())) { //moving enemy outside the left edge enemies[i].setX(-200); } } } |
- Again execute the app. You should see the enemies getting hidden after collision. Now after collision we will show a blast image for a fraction of second to make it look like destroying.
Adding Blast Effect
Now we are at the last phase for this part of this Android Game Development Tutorial. We need to display a blast effect after collision.
We already have a blast image inside the drawable folder. We will use that image to display for a fraction of second after the collision. So follow the following step.
- Create a new java class named Boom and write the following code.
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 |
package net.simplifiedcoding.spacefighter; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; /** * Created by Belal on 6/15/2016. */ public class Boom { //bitmap object private Bitmap bitmap; //coordinate variables private int x; private int y; //constructor public Boom(Context context) { //getting boom image from drawable resource bitmap = BitmapFactory.decodeResource (context.getResources(), R.drawable.boom); //setting the coordinate outside the screen //so that it won't shown up in the screen //it will be only visible for a fraction of second //after collission x = -250; y = -250; } //setters for x and y to make it visible at the place of collision public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } //getters public Bitmap getBitmap() { return bitmap; } public void setBitmap(Bitmap bitmap) { this.bitmap = bitmap; } public int getX() { return x; } public int getY() { return y; } } |
- Now again come inside GameView.java file and modify the code as follow.
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 |
public class GameView extends SurfaceView implements Runnable { volatile boolean playing; private Thread gameThread = null; private Player player; private Paint paint; private Canvas canvas; private SurfaceHolder surfaceHolder; private Enemy[] enemies; private int enemyCount = 3; private ArrayList<Star> stars = new ArrayList<Star>(); //defining a boom object to display blast private Boom boom; public GameView(Context context, int screenX, int screenY) { super(context); player = new Player(context, screenX, screenY); surfaceHolder = getHolder(); paint = new Paint(); int starNums = 100; for (int i = 0; i < starNums; i++) { Star s = new Star(screenX, screenY); stars.add(s); } enemies = new Enemy[enemyCount]; for (int i = 0; i < enemyCount; i++) { enemies[i] = new Enemy(context, screenX, screenY); } //initializing boom object boom = new Boom(context); } @Override public void run() { while (playing) { update(); draw(); control(); } } private void update() { player.update(); //setting boom outside the screen boom.setX(-250); boom.setY(-250); for (Star s : stars) { s.update(player.getSpeed()); } for (int i = 0; i < enemyCount; i++) { enemies[i].update(player.getSpeed()); //if collision occurrs with player if (Rect.intersects(player.getDetectCollision(), enemies[i].getDetectCollision())) { //displaying boom at that location boom.setX(enemies[i].getX()); boom.setY(enemies[i].getY()); enemies[i].setX(-200); } } } private void draw() { if (surfaceHolder.getSurface().isValid()) { canvas = surfaceHolder.lockCanvas(); canvas.drawColor(Color.BLACK); paint.setColor(Color.WHITE); for (Star s : stars) { paint.setStrokeWidth(s.getStarWidth()); canvas.drawPoint(s.getX(), s.getY(), paint); } canvas.drawBitmap( player.getBitmap(), player.getX(), player.getY(), paint); for (int i = 0; i < enemyCount; i++) { canvas.drawBitmap( enemies[i].getBitmap(), enemies[i].getX(), enemies[i].getY(), paint ); } //drawing boom image canvas.drawBitmap( boom.getBitmap(), boom.getX(), boom.getY(), paint ); surfaceHolder.unlockCanvasAndPost(canvas); } } private void control() { try { gameThread.sleep(17); } catch (InterruptedException e) { e.printStackTrace(); } } public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { } } public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_UP: player.stopBoosting(); break; case MotionEvent.ACTION_DOWN: player.setBoosting(); break; } return true; } } |
- Now again execute the application and you will see a blast effect on collision.
Bingo! it is working absolutely fine. You can download my source code if having any troubles or confusion. Unlock the download link to get the source code of this Android Game Development Tutorial from below.
Android Game Development Part 1 – Source Code DownloadÂ
Android Game Development Tutorial – Summary
It is a really simple and small game we are creating in this Android Game Development Tutorial. This Android Game Development Tutorial is a two part series. This is the first part. In this part of this Android Game Development Tutorial we learnt:
- SurfaceView implementation
- Drawing Characters on Canvas using SurfaceView
- Creating an Infinite Scroll Background Loop
- Detecting Collision
- Adding Controlls
In the next part -> Android Game Development Tutorial Part 2,  we will finally complete this game by adding some text displaying high score and other game values. We will also add a game over option and some sound effects.
Android Game Development Tutorial –Â Final Words
So thats all for this Android Game Development Tutorial friends. This is a really long tutorial. Probably the longest one I’ve posted so far. So try it carefully. And share it among your friends if you liked this Android Game Development Tutorial. Thank You 🙂