├── Chapter 01 ├── AndroidManifest.xml └── java │ └── SubHunter.java ├── Chapter 02 ├── AndroidManifest.xml └── java │ └── SubHunter.java ├── Chapter 03 ├── AndroidManifest.xml └── java │ └── SubHunter.java ├── Chapter 04 ├── AndroidManifest.xml ├── Method Overloading │ └── MainActivity.java └── java │ └── SubHunter.java ├── Chapter 05 ├── AndroidManifest.xml ├── Canvas Demo │ └── MainActivity.java └── java │ └── SubHunter.java ├── Chapter 06 ├── AndroidManifest.xml └── java │ └── SubHunter.java ├── Chapter 07 ├── AndroidManifest.xml └── java │ └── SubHunter.java ├── Chapter 08 ├── Access Scope This And Static │ └── AccessScopeThisAndStatic │ │ ├── AlienShip.java │ │ └── MainActivity.java ├── Basic Classes │ ├── MainActivity.java │ └── Soldier.java ├── C8Pong │ ├── AndroidManifest.xml │ ├── Ball.java │ ├── Bat.java │ ├── PongActivity.java │ └── PongGame.java └── InheritanceExample │ └── InheritanceExample │ ├── AlienShip.java │ ├── Bomber.java │ ├── Fighter.java │ └── MainActivity.java ├── Chapter 09 ├── AndroidManifest.xml └── java │ ├── Ball.java │ ├── Bat.java │ ├── PongActivity.java │ └── PongGame.java ├── Chapter 10 ├── AndroidManifest.xml └── java │ ├── Ball.java │ ├── Bat.java │ ├── PongActivity.java │ └── PongGame.java ├── Chapter 11 ├── AndroidManifest.xml ├── assets │ ├── beep.ogg │ ├── boop.ogg │ ├── bop.ogg │ └── miss.ogg └── java │ ├── Ball.java │ ├── Bat.java │ ├── PongActivity.java │ └── PongGame.java ├── Chapter 12 ├── C12BulletHell │ ├── AndroidManifest.xml │ └── java │ │ ├── Bob.java │ │ ├── Bullet.java │ │ ├── BulletHellActivity.java │ │ └── BulletHellGame.java ├── Dynamic Array Example │ └── MainActivity.java ├── Multidimensional Array Example │ └── MainActivity.java └── Simple Array Example │ └── MainActivity.java ├── Chapter 13 ├── AndroidManifest.xml ├── assets │ ├── beep.ogg │ └── teleport.ogg ├── drawable │ ├── bob.png │ └── ic_launcher_background.xml └── java │ ├── Bob.java │ ├── Bullet.java │ ├── BulletHellActivity.java │ └── BulletHellGame.java ├── Chapter 14 ├── AndroidManifest.xml ├── assets │ ├── get_apple.ogg │ └── snake_death.ogg └── java │ ├── Apple.java │ ├── Snake.java │ ├── SnakeActivity.java │ └── SnakeGame.java ├── Chapter 15 ├── AndroidManifest.xml ├── assets │ ├── get_apple.ogg │ └── snake_death.ogg ├── java │ ├── Apple.java │ ├── Snake.java │ ├── SnakeActivity.java │ └── SnakeGame.java ├── values-de │ └── strings.xml ├── values-es │ └── strings.xml └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── Chapter 16 ├── AndroidManifest.xml ├── assets │ ├── get_apple.ogg │ └── snake_death.ogg ├── drawable │ ├── apple.png │ ├── body.png │ └── head.png └── java │ ├── Apple.java │ ├── Snake.java │ ├── SnakeActivity.java │ └── SnakeGame.java ├── Chapter 17 ├── AndroidManifest.xml ├── assets │ ├── get_apple.ogg │ └── snake_death.ogg ├── drawable │ ├── apple.png │ ├── body.png │ └── head.png └── java │ ├── Apple.java │ ├── Snake.java │ ├── SnakeActivity.java │ └── SnakeGame.java ├── Chapter 18 ├── AndroidManifest.xml ├── assets │ ├── alien_explosion.ogg │ ├── player_explosion.ogg │ └── shoot.ogg └── java │ ├── GameActivity.java │ ├── GameEngine.java │ ├── GameStarter.java │ ├── GameState.java │ ├── HUD.java │ ├── Renderer.java │ └── SoundEngine.java ├── Chapter 19 ├── AndroidManifest.xml ├── assets │ ├── alien_explosion.ogg │ ├── player_explosion.ogg │ └── shoot.ogg └── java │ ├── GameActivity.java │ ├── GameEngine.java │ ├── GameEngineBroadcaster.java │ ├── GameStarter.java │ ├── GameState.java │ ├── HUD.java │ ├── InputObserver.java │ ├── Particle.java │ ├── ParticleSystem.java │ ├── PhysicsEngine.java │ ├── Renderer.java │ ├── SoundEngine.java │ └── UIController.java ├── Chapter 20 ├── assets │ ├── alien_explosion.ogg │ ├── player_explosion.ogg │ └── shoot.ogg ├── drawable │ ├── alien_laser.png │ ├── alien_ship1.png │ ├── alien_ship2.png │ ├── alien_ship3.png │ ├── background.png │ ├── player_laser.png │ └── player_ship.png └── java │ ├── AlienChaseSpec.java │ ├── AlienDiverSpec.java │ ├── AlienLaserSpec.java │ ├── AlienPatrolSpec.java │ ├── BackgroundGraphicsComponent.java │ ├── BackgroundMovementComponent.java │ ├── BackgroundSpawnComponent.java │ ├── BackgroundSpec.java │ ├── GameActivity.java │ ├── GameEngine.java │ ├── GameEngineBroadcaster.java │ ├── GameObject.java │ ├── GameObjectFactory.java │ ├── GameStarter.java │ ├── GameState.java │ ├── GraphicsComponent.java │ ├── HUD.java │ ├── InputComponent.java │ ├── InputObserver.java │ ├── LaserMovementComponent.java │ ├── LaserSpawnComponent.java │ ├── Level.java │ ├── MovementComponent.java │ ├── ObjectSpec.java │ ├── Particle.java │ ├── ParticleSystem.java │ ├── PhysicsEngine.java │ ├── PlayerInputComponent.java │ ├── PlayerLaserSpawner.java │ ├── PlayerLaserSpec.java │ ├── PlayerMovementComponent.java │ ├── PlayerSpawnComponent.java │ ├── PlayerSpec.java │ ├── Renderer.java │ ├── SoundEngine.java │ ├── SpawnComponent.java │ ├── StdGraphicsComponent.java │ ├── Transform.java │ └── UIController.java ├── Chapter 21 ├── assets │ ├── alien_explosion.ogg │ ├── player_explosion.ogg │ └── shoot.ogg ├── drawable │ ├── alien_laser.png │ ├── alien_ship1.png │ ├── alien_ship2.png │ ├── alien_ship3.png │ ├── background.png │ ├── ic_launcher_background.xml │ ├── player_laser.png │ └── player_ship.png └── java │ ├── AlienChaseMovementComponent.java │ ├── AlienChaseSpec.java │ ├── AlienDiverMovementComponent.java │ ├── AlienDiverSpec.java │ ├── AlienHorizontalSpawnComponent.java │ ├── AlienLaserSpawner.java │ ├── AlienLaserSpec.java │ ├── AlienPatrolMovementComponent.java │ ├── AlienPatrolSpec.java │ ├── AlienVerticalSpawnComponent.java │ ├── BackgroundGraphicsComponent.java │ ├── BackgroundMovementComponent.java │ ├── BackgroundSpawnComponent.java │ ├── BackgroundSpec.java │ ├── GameActivity.java │ ├── GameEngine.java │ ├── GameEngineBroadcaster.java │ ├── GameObject.java │ ├── GameObjectFactory.java │ ├── GameStarter.java │ ├── GameState.java │ ├── GraphicsComponent.java │ ├── HUD.java │ ├── InputComponent.java │ ├── InputObserver.java │ ├── LaserMovementComponent.java │ ├── LaserSpawnComponent.java │ ├── Level.java │ ├── MovementComponent.java │ ├── ObjectSpec.java │ ├── Particle.java │ ├── ParticleSystem.java │ ├── PhysicsEngine.java │ ├── PlayerInputComponent.java │ ├── PlayerLaserSpawner.java │ ├── PlayerLaserSpec.java │ ├── PlayerMovementComponent.java │ ├── PlayerSpawnComponent.java │ ├── PlayerSpec.java │ ├── Renderer.java │ ├── SoundEngine.java │ ├── SpawnComponent.java │ ├── StdGraphicsComponent.java │ ├── Transform.java │ └── UIController.java ├── LICENSE └── README.md /Chapter 01/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 01/java/SubHunter.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.subhunter; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | 6 | import android.os.Bundle; 7 | 8 | 9 | public class SubHunter extends Activity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | 15 | requestWindowFeature(Window.FEATURE_NO_TITLE); 16 | 17 | } 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 02/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 02/java/SubHunter.java: -------------------------------------------------------------------------------- 1 | // This is our package 2 | // If you are copy & pasting the code then this line will probably be different to yours 3 | // If so, keep YOUR line- not this one 4 | package com.gamecodeschool.c2subhunter; 5 | 6 | // These are all the classes of other people's 7 | // (Android) code that we use in Sub Hunt 8 | import android.app.Activity; 9 | import android.view.Window; 10 | 11 | import android.os.Bundle; 12 | import android.view.MotionEvent; 13 | import android.util.Log; 14 | import android.graphics.Bitmap; 15 | import android.graphics.Canvas; 16 | import android.graphics.Color; 17 | import android.graphics.Paint; 18 | import android.graphics.Point; 19 | import android.view.Display; 20 | import android.widget.ImageView; 21 | import java.util.Random; 22 | 23 | 24 | public class SubHunter extends Activity { 25 | 26 | /* 27 | Android runs this code just before 28 | the app is seen by the player. 29 | This makes it a good place to add 30 | the code that is needed for 31 | the one-time setup. 32 | */ 33 | 34 | @Override 35 | protected void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | 38 | requestWindowFeature(Window.FEATURE_NO_TITLE); 39 | 40 | Log.d("Debugging", "In onCreate"); 41 | newGame(); 42 | draw(); 43 | } 44 | 45 | /* 46 | This code will execute when a new 47 | game needs to be started. It will 48 | happen when the app is first started 49 | and after the player wins a game. 50 | */ 51 | void newGame(){ 52 | Log.d("Debugging", "In newGame"); 53 | 54 | } 55 | 56 | /* 57 | Here we will do all the drawing. 58 | The grid lines, the HUD and 59 | the touch indicator 60 | */ 61 | void draw() { 62 | Log.d("Debugging", "In draw"); 63 | } 64 | 65 | /* 66 | This part of the code will 67 | handle detecting that the player 68 | has tapped the screen 69 | */ 70 | @Override 71 | public boolean onTouchEvent(MotionEvent motionEvent) { 72 | Log.d("Debugging", "In onTouchEvent"); 73 | takeShot(); 74 | 75 | return true; 76 | } 77 | 78 | 79 | /* 80 | The code here will execute when 81 | the player taps the screen It will 82 | calculate distance from the sub' 83 | and determine a hit or miss 84 | */ 85 | void takeShot(){ 86 | Log.d("Debugging", "In takeShot"); 87 | draw(); 88 | } 89 | 90 | // This code says "BOOM!" 91 | void boom(){ 92 | 93 | } 94 | 95 | // This code prints the debugging text 96 | void printDebuggingText(){ 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Chapter 03/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 04/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 04/Method Overloading/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.exploringmethodoverloading; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | 7 | public class MainActivity extends Activity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | 13 | // Declare and initialize a String and an int 14 | int anInt = 10; 15 | String aString = "I am a string"; 16 | 17 | // Now call the different versions of printStuff 18 | // The name stays the same, only the parameters vary 19 | printStuff(anInt); 20 | printStuff(aString); 21 | printStuff(anInt, aString); 22 | 23 | } 24 | 25 | void printStuff(int myInt){ 26 | Log.i("info", "This is the int only version"); 27 | Log.i("info", "myInt = "+ myInt); 28 | } 29 | 30 | void printStuff(String myString){ 31 | Log.i("info", "This is the String only version"); 32 | Log.i("info", "myString = "+ myString); 33 | } 34 | 35 | void printStuff(int myInt, String myString){ 36 | Log.i("info", "This is the combined int and String version"); 37 | Log.i("info", "myInt = "+ myInt); 38 | Log.i("info", "myString = "+ myString); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Chapter 05/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 05/Canvas Demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.canvasdemo; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.os.Bundle; 9 | import android.widget.ImageView; 10 | 11 | public class MainActivity extends Activity { 12 | 13 | // Here are all the objects(instances) 14 | // of classes that we need to do some drawing 15 | ImageView myImageView; 16 | Bitmap myBlankBitmap; 17 | Canvas myCanvas; 18 | Paint myPaint; 19 | 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | 25 | // Initialize all the objects ready for drawing 26 | // We will do this inside the onCreate method 27 | int widthInPixels = 800; 28 | int heightInPixels = 600; 29 | 30 | // Create a new Bitmap 31 | myBlankBitmap = Bitmap.createBitmap(widthInPixels, 32 | heightInPixels, 33 | Bitmap.Config.ARGB_8888); 34 | 35 | // Initialize the Canvas and asociate it 36 | // with the Bitmap to draw on 37 | myCanvas = new Canvas(myBlankBitmap); 38 | 39 | // Initialize the ImageView and the Paint 40 | myImageView = new ImageView(this); 41 | myPaint = new Paint(); 42 | 43 | 44 | // Draw on the Bitmap 45 | // Wipe the Bitmap with a blue color 46 | myCanvas.drawColor(Color.argb(255, 0, 0, 255)); 47 | 48 | // Re-size the text 49 | myPaint.setTextSize(100); 50 | // Change the paint to white 51 | myPaint.setColor(Color.argb(255, 255, 255, 255)); 52 | // Actually draw the text 53 | myCanvas.drawText("Hello World!",100, 100, myPaint); 54 | 55 | // Change the paint to yellow 56 | myPaint.setColor(Color.argb(255, 212, 207, 62)); 57 | // Draw a circle 58 | myCanvas.drawCircle(400,250, 100, myPaint); 59 | 60 | // Associate the drawn upon Bitmap with the ImageView 61 | myImageView.setImageBitmap(myBlankBitmap); 62 | // Tell Android to set our drawing 63 | // as the view for this app 64 | // via the ImageView 65 | setContentView(myImageView); 66 | 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Chapter 06/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 07/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 14 | > 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Chapter 08/Access Scope This And Static/AccessScopeThisAndStatic/AlienShip.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.accessscopethisandstatic; 2 | 3 | import android.util.Log; 4 | 5 | public class AlienShip { 6 | private static int numShips; 7 | private int shieldStrength; 8 | public String shipName; 9 | 10 | public AlienShip(){ 11 | numShips++; 12 | //Can call private methods from here because I am part 13 | //of the class 14 | //If didn't have "this" then this call might be less clear 15 | //But this "this" isn't strictly necessary 16 | this.setShieldStrength(100); 17 | //Because of "this" I am sure I am setting the correct shieldStrength 18 | } 19 | 20 | public static int getNumShips(){ 21 | return numShips; 22 | 23 | } 24 | 25 | private void setShieldStrength(int shieldStrength){ 26 | //"this" distinguishes between the member variable shieldStrength 27 | //And the local variable/paramater of the same name 28 | this.shieldStrength = shieldStrength; 29 | } 30 | 31 | 32 | public int getShieldStrength(){ 33 | return this.shieldStrength; 34 | } 35 | 36 | public void hitDetected(){ 37 | 38 | shieldStrength -=25; 39 | Log.i("Incomiming: ","Bam!!"); 40 | if (shieldStrength == 0){ 41 | destroyShip(); 42 | } 43 | 44 | } 45 | 46 | private void destroyShip(){ 47 | numShips--; 48 | Log.i("Explosion: ", ""+this.shipName + " destroyed"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Chapter 08/Access Scope This And Static/AccessScopeThisAndStatic/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.accessscopethisandstatic; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | 15 | //every time we do this the constructor runs 16 | AlienShip girlShip = new AlienShip(); 17 | AlienShip boyShip = new AlienShip(); 18 | 19 | //Look no objects but using the static method 20 | Log.i("numShips: ", "" + AlienShip.getNumShips()); 21 | 22 | //This works because shipName is public 23 | girlShip.shipName = "Corrine Yu"; 24 | boyShip.shipName = "Andre LaMothe"; 25 | 26 | //This won't work because shieldStrenth is private 27 | //girlship.shieldStrength = 999; 28 | 29 | //But we have a public getter 30 | Log.i("girlShip shieldStrngth:", "" + girlShip.getShieldStrength()); 31 | Log.i("boyShip shieldStrngth: ", "" + boyShip.getShieldStrength()); 32 | 33 | //But we can't do this because it's private 34 | //boyship.setShieldStrength(1000000); 35 | 36 | //lets shoot some ships 37 | girlShip.hitDetected(); 38 | Log.i("girlShip shieldStrngth:", "" + girlShip.getShieldStrength()); 39 | Log.i("boyShip shieldStrngth: ", "" + boyShip.getShieldStrength()); 40 | boyShip.hitDetected(); 41 | boyShip.hitDetected(); 42 | boyShip.hitDetected(); 43 | Log.i("girlShip shieldStrngth:", "" + girlShip.getShieldStrength()); 44 | Log.i("boyShip shieldStrngth: ", "" + boyShip.getShieldStrength()); 45 | boyShip.hitDetected();//ahhh 46 | Log.i("girlShip shieldStrngth:", "" + girlShip.getShieldStrength()); 47 | Log.i("boyShip shieldStrngth: ", "" + boyShip.getShieldStrength()); 48 | Log.i("numShips: ", "" + AlienShip.getNumShips()); 49 | } 50 | } -------------------------------------------------------------------------------- /Chapter 08/Basic Classes/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.basicclasses; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | 14 | // first we make an object of type soldier 15 | Soldier rambo = new Soldier(); 16 | rambo.soldierType = "Green Beret"; 17 | rambo.health = 150; 18 | // It takes allot to kill Rambo 19 | 20 | // Now we make another Soldier object 21 | Soldier vassily = new Soldier(); 22 | vassily.soldierType = "Sniper"; 23 | vassily.health = 50; 24 | // Snipers have less health 25 | 26 | // And one more Soldier object 27 | Soldier wellington = new Soldier(); 28 | wellington.soldierType = "Sailor"; 29 | wellington.health = 100; 30 | // He's tough but no green beret 31 | 32 | //setContentView(R.layout.activity_main); 33 | 34 | Log.i("Rambo's health = ", "" + rambo.health); 35 | Log.i("Vassily's health = ", "" + vassily.health); 36 | Log.i("Wellington's health = ", "" + wellington.health); 37 | 38 | rambo.shootEnemy(); 39 | vassily.shootEnemy(); 40 | wellington.shootEnemy(); 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /Chapter 08/Basic Classes/Soldier.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.basicclasses; 2 | 3 | import android.util.Log; 4 | 5 | public class Soldier { 6 | int health; 7 | String soldierType; 8 | 9 | void shootEnemy(){ 10 | //let's print which type of soldier is shooting 11 | Log.d(soldierType, " is shooting"); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Chapter 08/C8Pong/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | > 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 08/C8Pong/Ball.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | public class Ball { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 08/C8Pong/Bat.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | public class Bat { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 08/C8Pong/PongActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | 6 | import android.os.Bundle; 7 | 8 | public class PongActivity extends Activity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | 14 | requestWindowFeature(Window.FEATURE_NO_TITLE); 15 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 08/C8Pong/PongGame.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | public class PongGame { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 08/InheritanceExample/InheritanceExample/AlienShip.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.inheritanceexample.app; 2 | 3 | import android.util.Log; 4 | 5 | public abstract class AlienShip { 6 | private static int numShips; 7 | private int shieldStrength; 8 | public String shipName; 9 | 10 | public AlienShip(int shieldStrength){ 11 | Log.i("Location: ", "AlienShip constructor"); 12 | numShips++; 13 | setShieldStrength(shieldStrength); 14 | } 15 | 16 | public abstract void fireWeapon();//Ahh my body 17 | 18 | public static int getNumShips(){ 19 | return numShips; 20 | } 21 | 22 | private void setShieldStrength(int shieldStrength){ 23 | this.shieldStrength = shieldStrength; 24 | } 25 | 26 | 27 | public int getShieldStrength(){ 28 | return this.shieldStrength; 29 | } 30 | 31 | public void hitDetected(){ 32 | shieldStrength -=25; 33 | Log.i("Incomiming: ", "Bam!!"); 34 | if (shieldStrength == 0){ 35 | destroyShip(); 36 | } 37 | 38 | } 39 | 40 | private void destroyShip(){ 41 | numShips--; 42 | Log.i("Explosion: ", ""+this.shipName + " destroyed"); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Chapter 08/InheritanceExample/InheritanceExample/Bomber.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.inheritanceexample.app; 2 | 3 | import android.util.Log; 4 | 5 | public class Bomber extends AlienShip { 6 | 7 | public Bomber(){ 8 | super(100); 9 | //Weak shields for a bomber 10 | Log.i("Location: ", "Bomber constructor"); 11 | } 12 | 13 | public void fireWeapon(){ 14 | Log.i("Firing weapon: ", "bombs away"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Chapter 08/InheritanceExample/InheritanceExample/Fighter.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.inheritanceexample.app; 2 | 3 | import android.util.Log; 4 | 5 | public class Fighter extends AlienShip{ 6 | 7 | public Fighter(){ 8 | super(400); 9 | //Strong shields for a fighter 10 | Log.i("Location: ", "Fighter constructor"); 11 | } 12 | 13 | public void fireWeapon(){ 14 | Log.i("Firing weapon: ", "lasers firing"); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 08/InheritanceExample/InheritanceExample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.inheritanceexample.app; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | 15 | Fighter aFighter = new Fighter(); 16 | Bomber aBomber = new Bomber(); 17 | 18 | //Can't do this AlienShip is abstract - 19 | //Literally speaking as well as in code 20 | //AlienShip alienShip = new AlienShip(500); 21 | 22 | //But our objects of the subclasses can still do 23 | //everything the AlienShip is meant to do 24 | aBomber.shipName = "Newell Bomber"; 25 | aFighter.shipName = "Meier Fighter"; 26 | 27 | //And because of the overiden constructor 28 | //That still calls the super constructor 29 | //They have unique properties 30 | Log.i("aFighter Shield:", ""+ aFighter.getShieldStrength()); 31 | Log.i("aBomber Shield:", ""+ aBomber.getShieldStrength()); 32 | 33 | //As well as certain things in certain ways 34 | //That are unique to the subclass 35 | aBomber.fireWeapon(); 36 | aFighter.fireWeapon(); 37 | 38 | //Take down those alien ships 39 | //Focus on the bomber it has a weaker shield 40 | aBomber.hitDetected(); 41 | aBomber.hitDetected(); 42 | aBomber.hitDetected(); 43 | aBomber.hitDetected(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Chapter 09/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | > 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 09/java/Ball.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | public class Ball { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 09/java/Bat.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | public class Bat { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 09/java/PongActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | 6 | import android.os.Bundle; 7 | 8 | import android.graphics.Point; 9 | import android.view.Display; 10 | 11 | 12 | public class PongActivity extends Activity { 13 | 14 | private PongGame mPongGame; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | requestWindowFeature(Window.FEATURE_NO_TITLE); 21 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 22 | 23 | Display display = getWindowManager().getDefaultDisplay(); 24 | Point size = new Point(); 25 | display.getSize(size); 26 | 27 | mPongGame = new PongGame(this, size.x, size.y); 28 | setContentView(mPongGame); 29 | 30 | } 31 | 32 | 33 | @Override 34 | protected void onResume() { 35 | super.onResume(); 36 | 37 | // More code here later in the chapter 38 | mPongGame.resume(); 39 | } 40 | 41 | @Override 42 | protected void onPause() { 43 | super.onPause(); 44 | 45 | // More code here later in the chapter 46 | mPongGame.pause(); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Chapter 10/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | > 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 10/java/Bat.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | import android.graphics.RectF; 4 | 5 | public class Bat { 6 | // These are the member variables (fields) 7 | // They all have the m prefix 8 | // They are all private 9 | // because direct access is not required 10 | private RectF mRect; 11 | private float mLength; 12 | private float mXCoord; 13 | private float mBatSpeed; 14 | private int mScreenX; 15 | 16 | // These variables are public and final 17 | // They can be directly accessed by 18 | // the instance (in PongGame) 19 | // because they are part of the same 20 | // package but cannot be changed 21 | final int STOPPED = 0; 22 | final int LEFT = 1; 23 | final int RIGHT = 2; 24 | 25 | // Keeps track of if an how the ball is moving 26 | // Starting with STOPPED 27 | private int mBatMoving = STOPPED; 28 | 29 | Bat(int sx, int sy){ 30 | 31 | // Bat needs to know the screen 32 | // horizontal resolution 33 | // Outside of this method 34 | mScreenX = sx; 35 | 36 | // Configure the size of the bat based on 37 | // the screen resolution 38 | // One eighth the screen width 39 | mLength = mScreenX / 8; 40 | // One fortieth the screen height 41 | float height = sy / 40; 42 | 43 | // Configure the starting location of the bat 44 | // Roughly the middle horizontally 45 | mXCoord = mScreenX / 2; 46 | // The height of the bat 47 | // off the bottom of the screen 48 | float mYCoord = sy - height; 49 | 50 | // Initialize mRect based on the size and position 51 | mRect = new RectF(mXCoord, mYCoord, 52 | mXCoord + mLength, 53 | mYCoord + height); 54 | 55 | // Configure the speed of the bat 56 | // This code means the bat can cover the 57 | // width of the screen in 1 second 58 | mBatSpeed = mScreenX; 59 | } 60 | 61 | // Return a reference to the mRect object 62 | RectF getRect(){ 63 | return mRect; 64 | } 65 | 66 | // Update the movement state passed 67 | // in by the onTouchEvent method 68 | void setMovementState(int state){ 69 | mBatMoving = state; 70 | } 71 | 72 | // Update the bat- Called each frame/loop 73 | void update(long fps){ 74 | 75 | // Move the bat based on the mBatMoving variable 76 | // and the speed of the previous frame 77 | if(mBatMoving == LEFT){ 78 | mXCoord = mXCoord - mBatSpeed / fps; 79 | } 80 | 81 | if(mBatMoving == RIGHT){ 82 | mXCoord = mXCoord + mBatSpeed / fps; 83 | } 84 | 85 | // Stop the bat going off the screen 86 | if(mXCoord < 0){ 87 | mXCoord = 0; 88 | } 89 | 90 | else if(mXCoord + mLength > mScreenX){ 91 | mXCoord = mScreenX - mLength; 92 | } 93 | 94 | // Update mRect based on the results from 95 | // the previous code in update 96 | mRect.left = mXCoord; 97 | mRect.right = mXCoord + mLength; 98 | } 99 | 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /Chapter 10/java/PongActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | 6 | import android.os.Bundle; 7 | 8 | import android.graphics.Point; 9 | import android.view.Display; 10 | 11 | 12 | public class PongActivity extends Activity { 13 | 14 | private PongGame mPongGame; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | requestWindowFeature(Window.FEATURE_NO_TITLE); 21 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 22 | 23 | Display display = getWindowManager().getDefaultDisplay(); 24 | Point size = new Point(); 25 | display.getSize(size); 26 | 27 | mPongGame = new PongGame(this, size.x, size.y); 28 | setContentView(mPongGame); 29 | 30 | } 31 | 32 | 33 | @Override 34 | protected void onResume() { 35 | super.onResume(); 36 | 37 | // More code here later in the chapter 38 | mPongGame.resume(); 39 | } 40 | 41 | @Override 42 | protected void onPause() { 43 | super.onPause(); 44 | 45 | // More code here later in the chapter 46 | mPongGame.pause(); 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /Chapter 11/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | > 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 11/assets/beep.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 11/assets/beep.ogg -------------------------------------------------------------------------------- /Chapter 11/assets/boop.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 11/assets/boop.ogg -------------------------------------------------------------------------------- /Chapter 11/assets/bop.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 11/assets/bop.ogg -------------------------------------------------------------------------------- /Chapter 11/assets/miss.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 11/assets/miss.ogg -------------------------------------------------------------------------------- /Chapter 11/java/Bat.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | import android.graphics.RectF; 4 | 5 | public class Bat { 6 | // These are the member variables (fields) 7 | // They all have the m prefix 8 | // They are all private 9 | // because direct access is not required 10 | private RectF mRect; 11 | private float mLength; 12 | private float mXCoord; 13 | private float mBatSpeed; 14 | private int mScreenX; 15 | 16 | // These variables are public and final 17 | // They can be directly accessed by 18 | // the instance (in PongGame) 19 | // because they are part of the same 20 | // package but cannot be changed 21 | final int STOPPED = 0; 22 | final int LEFT = 1; 23 | final int RIGHT = 2; 24 | 25 | // Keeps track of if an how the ball is moving 26 | // Starting with STOPPED 27 | private int mBatMoving = STOPPED; 28 | 29 | Bat(int sx, int sy){ 30 | 31 | // Bat needs to know the screen 32 | // horizontal resolution 33 | // Outside of this method 34 | mScreenX = sx; 35 | 36 | // Configure the size of the bat based on 37 | // the screen resolution 38 | // One eighth the screen width 39 | mLength = mScreenX / 8; 40 | // One fortieth the screen height 41 | float height = sy / 40; 42 | 43 | // Configure the starting location of the bat 44 | // Roughly the middle horizontally 45 | mXCoord = mScreenX / 2; 46 | // The height of the bat 47 | // off the bottom of the screen 48 | float mYCoord = sy - height; 49 | 50 | // Initialize mRect based on the size and position 51 | mRect = new RectF(mXCoord, mYCoord, 52 | mXCoord + mLength, 53 | mYCoord + height); 54 | 55 | // Configure the speed of the bat 56 | // This code means the bat can cover the 57 | // width of the screen in 1 second 58 | mBatSpeed = mScreenX; 59 | } 60 | 61 | // Return a reference to the mRect object 62 | RectF getRect(){ 63 | return mRect; 64 | } 65 | 66 | // Update the movement state passed 67 | // in by the onTouchEvent method 68 | void setMovementState(int state){ 69 | mBatMoving = state; 70 | } 71 | 72 | // Update the bat- Called each frame/loop 73 | void update(long fps){ 74 | 75 | // Move the bat based on the mBatMoving variable 76 | // and the speed of the previous frame 77 | if(mBatMoving == LEFT){ 78 | mXCoord = mXCoord - mBatSpeed / fps; 79 | } 80 | 81 | if(mBatMoving == RIGHT){ 82 | mXCoord = mXCoord + mBatSpeed / fps; 83 | } 84 | 85 | // Stop the bat going off the screen 86 | if(mXCoord < 0){ 87 | mXCoord = 0; 88 | } 89 | 90 | else if(mXCoord + mLength > mScreenX){ 91 | mXCoord = mScreenX - mLength; 92 | } 93 | 94 | // Update mRect based on the results from 95 | // the previous code in update 96 | mRect.left = mXCoord; 97 | mRect.right = mXCoord + mLength; 98 | } 99 | 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /Chapter 11/java/PongActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.pong; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | 6 | import android.os.Bundle; 7 | 8 | import android.graphics.Point; 9 | import android.view.Display; 10 | 11 | 12 | public class PongActivity extends Activity { 13 | 14 | private PongGame mPongGame; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | 20 | requestWindowFeature(Window.FEATURE_NO_TITLE); 21 | 22 | Display display = getWindowManager().getDefaultDisplay(); 23 | Point size = new Point(); 24 | display.getSize(size); 25 | 26 | mPongGame = new PongGame(this, size.x, size.y); 27 | setContentView(mPongGame); 28 | 29 | } 30 | 31 | 32 | @Override 33 | protected void onResume() { 34 | super.onResume(); 35 | 36 | // More code here later in the chapter 37 | mPongGame.resume(); 38 | } 39 | 40 | @Override 41 | protected void onPause() { 42 | super.onPause(); 43 | 44 | // More code here later in the chapter 45 | mPongGame.pause(); 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /Chapter 12/C12BulletHell/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter 12/C12BulletHell/java/Bob.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.bullethell; 2 | 3 | public class Bob { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 12/C12BulletHell/java/Bullet.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.bullethell; 2 | 3 | import android.graphics.RectF; 4 | 5 | class Bullet { 6 | 7 | // A RectF to represent the size and location of the bullet 8 | private RectF mRect; 9 | 10 | // How fast is the bullet traveling? 11 | private float mXVelocity; 12 | private float mYVelocity; 13 | 14 | // How big is a bullet 15 | private float mWidth; 16 | private float mHeight; 17 | 18 | 19 | 20 | // The constructor 21 | Bullet(int screenX){ 22 | 23 | // Configure the bullet based on 24 | // the screen width in pixels 25 | mWidth = screenX / 100; 26 | mHeight = screenX / 100; 27 | mRect = new RectF(); 28 | mYVelocity = (screenX / 5); 29 | mXVelocity = (screenX / 5); 30 | } 31 | 32 | // Return a reference to the RectF 33 | RectF getRect(){ 34 | return mRect; 35 | } 36 | 37 | // Move the bullet based on the speed and the frame rate 38 | void update(long fps){ 39 | // Update the left and top coordinates 40 | // based on the velocity and current frame rate 41 | mRect.left = mRect.left + (mXVelocity / fps); 42 | mRect.top = mRect.top + (mYVelocity / fps); 43 | 44 | mRect.right = mRect.left + mWidth; 45 | mRect.bottom = mRect.top - mHeight; 46 | } 47 | 48 | // Reverse the bullets vertical direction 49 | void reverseYVelocity(){ 50 | mYVelocity = -mYVelocity; 51 | } 52 | 53 | // Reverse the bullets horizontal direction 54 | void reverseXVelocity(){ 55 | mXVelocity = -mXVelocity; 56 | } 57 | 58 | // Spawn a new bullet 59 | void spawn(int pX, int pY, int vX, int vY){ 60 | 61 | // Spawn the bullet at the location 62 | // passed in as parameters 63 | mRect.left = pX; 64 | mRect.top = pY; 65 | mRect.right = pX + mWidth; 66 | mRect.bottom = pY + mHeight; 67 | 68 | // Head away from the player 69 | // It's only fair 70 | mXVelocity = mXVelocity * vX; 71 | mYVelocity = mYVelocity * vY; 72 | 73 | 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /Chapter 12/C12BulletHell/java/BulletHellActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.bullethell; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | import android.graphics.Point; 6 | import android.os.Bundle; 7 | import android.view.Display; 8 | 9 | 10 | // This class is almost exactly 11 | // the same as the Pong project 12 | public class BulletHellActivity extends Activity { 13 | 14 | // An instance of the main class of this project 15 | private BulletHellGame mBHGame; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | requestWindowFeature(Window.FEATURE_NO_TITLE); 21 | 22 | 23 | // Get the screen resolution 24 | Display display = getWindowManager(). 25 | getDefaultDisplay(); 26 | Point size = new Point(); 27 | display.getSize(size); 28 | 29 | // Call the constructor(initialize) 30 | // the BulletHellGame instance 31 | mBHGame = new BulletHellGame(this, size.x, size.y); 32 | setContentView(mBHGame); 33 | } 34 | 35 | @Override 36 | // Start the main game thread 37 | // when the game is launched 38 | protected void onResume() { 39 | super.onResume(); 40 | 41 | mBHGame.resume(); 42 | } 43 | 44 | @Override 45 | // Stop the thread when the player quits 46 | protected void onPause() { 47 | super.onPause(); 48 | 49 | mBHGame.pause(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Chapter 12/Dynamic Array Example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.packtpub.dynamicarrayexample.dynamicarrayexample; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | 7 | 8 | public class MainActivity extends Activity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | 15 | //Declaring and allocating in one step 16 | int[] ourArray = new int[1000]; 17 | 18 | //Let's initialize ourArray using a for loop 19 | //Because more than a few variables is allot of typing! 20 | for(int i = 0; i < 1000; i++){ 21 | //Put the value of ourValue into our array 22 | //At the position determined by i. 23 | ourArray[i] = i*5; 24 | 25 | //Output what is going on 26 | Log.i("info", "i = " + i); 27 | Log.i("info", "ourArray[i] = " + ourArray[i]); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Chapter 12/Multidimensional Array Example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.packtpub.dynamicarrayexample.dynamicarrayexample; 2 | 3 | import android.app.Activity; 4 | 5 | import android.os.Bundle; 6 | import android.util.Log; 7 | 8 | import java.util.Random; 9 | 10 | public class MainActivity extends Activity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | // Random object for generating question numbers 16 | Random randInt = new Random(); 17 | // a variable to hold the random value generated 18 | int questionNumber;// Declare and allocate in separate stages for clarity 19 | // but we don't have to 20 | String[][] countriesAndCities; 21 | // Now we have a 2-dimensional array 22 | 23 | countriesAndCities = new String[5][2]; 24 | // 5 arrays with 2 elements each 25 | // Perfect for 5 "What's the capital city" questions 26 | 27 | // Now we load the questions and answers into our arrays 28 | // You could do this with less questions to save typing 29 | // But don't do more or you will get an exception 30 | countriesAndCities [0][0] = "United Kingdom"; 31 | countriesAndCities [0][1] = "London"; 32 | 33 | countriesAndCities [1][0] = "USA"; 34 | countriesAndCities [1][1] = "Washington"; 35 | 36 | countriesAndCities [2][0] = "India"; 37 | countriesAndCities [2][1] = "New Delhi"; 38 | 39 | countriesAndCities [3][0] = "Brazil"; 40 | countriesAndCities [3][1] = "Brasilia"; 41 | 42 | countriesAndCities [4][0] = "Kenya"; 43 | countriesAndCities [4][1] = "Nairobi"; 44 | /* 45 | Now we know that the country is stored at element 0 46 | The matching capital at element 1 47 | Here are two variables that reflect this 48 | */ 49 | final int COUNTRY = 0; 50 | final int CAPITAL = 1; 51 | 52 | // A quick for loop to ask 3 questions 53 | for(int i = 0; i < 3; i++){ 54 | // get a random question number between 0 and 4 55 | questionNumber = randInt.nextInt(5); 56 | 57 | // and ask the question and in this case just 58 | // give the answer for the sake of brevity 59 | Log.d("info", "The capital of " 60 | +countriesAndCities[questionNumber][COUNTRY]); 61 | 62 | Log.d("info", "is " 63 | +countriesAndCities[questionNumber][CAPITAL]); 64 | 65 | } // end of for loop 66 | 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Chapter 12/Simple Array Example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.packtpub.simplearrayexample.simplearrayexample; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | 7 | 8 | public class MainActivity extends Activity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | 15 | //Declaring an array 16 | int[] ourArray; 17 | 18 | //Allocate memory for a maximum size of 5 elements 19 | ourArray = new int[5]; 20 | 21 | //Initialize ourArray with values 22 | //The values are arbitrary as long as they are int 23 | //The indexes are not arbitrary 0 through 4 or crash! 24 | ourArray[0] = 25; 25 | ourArray[1] = 50; 26 | ourArray[2] = 125; 27 | ourArray[3] = 68; 28 | ourArray[4] = 47; 29 | 30 | //Output all the stored values 31 | Log.i("info", "Here is ourArray:"); 32 | Log.i("info", "[0] = "+ourArray[0]); 33 | Log.i("info", "[1] = "+ourArray[1]); 34 | Log.i("info", "[2] = "+ourArray[2]); 35 | Log.i("info", "[3] = "+ourArray[3]); 36 | Log.i("info", "[4] = "+ourArray[4]); 37 | 38 | //We can do any calculation with an array element 39 | //As long as it is appropriate to the contained type 40 | //Like this: 41 | int answer = ourArray[0] + 42 | ourArray[1] + 43 | ourArray[2] + 44 | ourArray[3] + 45 | ourArray[4]; 46 | 47 | Log.i("info", "Answer = "+answer); 48 | } 49 | 50 | 51 | 52 | } 53 | -------------------------------------------------------------------------------- /Chapter 13/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | > 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Chapter 13/assets/beep.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 13/assets/beep.ogg -------------------------------------------------------------------------------- /Chapter 13/assets/teleport.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 13/assets/teleport.ogg -------------------------------------------------------------------------------- /Chapter 13/drawable/bob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 13/drawable/bob.png -------------------------------------------------------------------------------- /Chapter 13/java/Bob.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.bullethell; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.RectF; 7 | 8 | class Bob { 9 | 10 | RectF mRect; 11 | float mBobHeight; 12 | float mBobWidth; 13 | boolean mTeleporting = false; 14 | 15 | Bitmap mBitmap; 16 | 17 | public Bob(Context context, float screenX, float screenY){ 18 | mBobHeight = screenY / 10; 19 | mBobWidth = mBobHeight / 2; 20 | 21 | mRect = new RectF(screenX / 2, 22 | screenY / 2, 23 | (screenX / 2) + mBobWidth, 24 | (screenY / 2) + mBobHeight); 25 | 26 | // Prepare the bitmap 27 | // Load Bob from his .png file 28 | // Bob practices responsible encapsulation 29 | // looking after his own resources 30 | mBitmap = BitmapFactory.decodeResource 31 | (context.getResources(), R.drawable.bob); 32 | } 33 | 34 | boolean teleport(float newX, float newY){ 35 | 36 | // Did Bob manage to teleport? 37 | boolean success = false; 38 | 39 | // Move Bob to the new position 40 | // If not already teleporting 41 | if(!mTeleporting){ 42 | 43 | // Make him roughly central to the touch 44 | mRect.left = newX - mBobWidth / 2; 45 | mRect.top = newY - mBobHeight / 2; 46 | mRect.bottom = mRect.top + mBobHeight; 47 | mRect.right = mRect.left + mBobWidth; 48 | 49 | mTeleporting = true; 50 | 51 | // Notify BulletHellGame that teleport 52 | // attempt was successful 53 | success = true; 54 | } 55 | 56 | return success; 57 | } 58 | 59 | void setTelePortAvailable(){ 60 | mTeleporting = false; 61 | } 62 | 63 | // Return a reference to mRect 64 | RectF getRect(){ 65 | return mRect; 66 | } 67 | 68 | // Return a reference to bitmap 69 | Bitmap getBitmap(){ 70 | return mBitmap; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Chapter 13/java/Bullet.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.bullethell; 2 | 3 | import android.graphics.RectF; 4 | 5 | class Bullet { 6 | 7 | // A RectF to represent the size and location of the bullet 8 | private RectF mRect; 9 | 10 | // How fast is the bullet traveling? 11 | private float mXVelocity; 12 | private float mYVelocity; 13 | 14 | // How big is a bullet 15 | private float mWidth; 16 | private float mHeight; 17 | 18 | 19 | 20 | // The constructor 21 | Bullet(int screenX){ 22 | 23 | // Configure the bullet based on 24 | // the screen width in pixels 25 | mWidth = screenX / 100; 26 | mHeight = screenX / 100; 27 | mRect = new RectF(); 28 | mYVelocity = (screenX / 5); 29 | mXVelocity = (screenX / 5); 30 | } 31 | 32 | // Return a reference to the RectF 33 | RectF getRect(){ 34 | return mRect; 35 | } 36 | 37 | // Move the bullet based on the speed and the frame rate 38 | void update(long fps){ 39 | // Update the left and top coordinates 40 | // based on the velocity and current frame rate 41 | mRect.left = mRect.left + (mXVelocity / fps); 42 | mRect.top = mRect.top + (mYVelocity / fps); 43 | 44 | mRect.right = mRect.left + mWidth; 45 | mRect.bottom = mRect.top - mHeight; 46 | } 47 | 48 | // Reverse the bullets vertical direction 49 | void reverseYVelocity(){ 50 | mYVelocity = -mYVelocity; 51 | } 52 | 53 | // Reverse the bullets horizontal direction 54 | void reverseXVelocity(){ 55 | mXVelocity = -mXVelocity; 56 | } 57 | 58 | // Spawn a new bullet 59 | void spawn(int pX, int pY, int vX, int vY){ 60 | 61 | // Spawn the bullet at the location 62 | // passed in as parameters 63 | mRect.left = pX; 64 | mRect.top = pY; 65 | mRect.right = pX + mWidth; 66 | mRect.bottom = pY + mHeight; 67 | 68 | // Head away from the player 69 | // It's only fair 70 | mXVelocity = mXVelocity * vX; 71 | mYVelocity = mYVelocity * vY; 72 | 73 | 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /Chapter 13/java/BulletHellActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.bullethell; 2 | 3 | import android.app.Activity; 4 | import android.view.Window; 5 | import android.graphics.Point; 6 | import android.os.Bundle; 7 | import android.view.Display; 8 | 9 | 10 | // This class is almost exactly 11 | // the same as the Pong project 12 | public class BulletHellActivity extends Activity { 13 | 14 | // An instance of the main class of this project 15 | private BulletHellGame mBHGame; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | requestWindowFeature(Window.FEATURE_NO_TITLE); 21 | 22 | 23 | // Get the screen resolution 24 | Display display = getWindowManager(). 25 | getDefaultDisplay(); 26 | Point size = new Point(); 27 | display.getSize(size); 28 | 29 | // Call the constructor(initialize) 30 | // the BulletHellGame instance 31 | mBHGame = new BulletHellGame(this, size.x, size.y); 32 | setContentView(mBHGame); 33 | } 34 | 35 | @Override 36 | // Start the main game thread 37 | // when the game is launched 38 | protected void onResume() { 39 | super.onResume(); 40 | 41 | mBHGame.resume(); 42 | } 43 | 44 | @Override 45 | // Stop the thread when the player quits 46 | protected void onPause() { 47 | super.onPause(); 48 | 49 | mBHGame.pause(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Chapter 14/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | > 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter 14/assets/get_apple.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 14/assets/get_apple.ogg -------------------------------------------------------------------------------- /Chapter 14/assets/snake_death.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 14/assets/snake_death.ogg -------------------------------------------------------------------------------- /Chapter 14/java/Apple.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | public class Apple { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 14/java/Snake.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | public class Snake { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 14/java/SnakeActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class SnakeActivity extends Activity { 10 | 11 | // Declare an instance of SnakeGame 12 | SnakeGame mSnakeGame; 13 | 14 | // Set the game up 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | 18 | super.onCreate(savedInstanceState); 19 | requestWindowFeature(Window.FEATURE_NO_TITLE); 20 | 21 | // Get the pixel dimensions of the screen 22 | Display display = getWindowManager().getDefaultDisplay(); 23 | 24 | // Initialize the result into a Point object 25 | Point size = new Point(); 26 | display.getSize(size); 27 | 28 | // Create a new instance of the SnakeEngine class 29 | mSnakeGame = new SnakeGame(this, size); 30 | 31 | // Make snakeEngine the view of the Activity 32 | setContentView(mSnakeGame); 33 | } 34 | 35 | // Start the thread in snakeEngine 36 | @Override 37 | protected void onResume() { 38 | super.onResume(); 39 | mSnakeGame.resume(); 40 | } 41 | 42 | // Stop the thread in snakeEngine 43 | @Override 44 | protected void onPause() { 45 | super.onPause(); 46 | mSnakeGame.pause(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter 15/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | > 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter 15/assets/get_apple.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 15/assets/get_apple.ogg -------------------------------------------------------------------------------- /Chapter 15/assets/snake_death.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 15/assets/snake_death.ogg -------------------------------------------------------------------------------- /Chapter 15/java/Apple.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | public class Apple { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 15/java/Snake.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | public class Snake { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 15/java/SnakeActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class SnakeActivity extends Activity { 10 | 11 | // Declare an instance of SnakeGame 12 | SnakeGame mSnakeGame; 13 | 14 | // Set the game up 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | 18 | super.onCreate(savedInstanceState); 19 | requestWindowFeature(Window.FEATURE_NO_TITLE); 20 | 21 | // Get the pixel dimensions of the screen 22 | Display display = getWindowManager().getDefaultDisplay(); 23 | 24 | // Initialize the result into a Point object 25 | Point size = new Point(); 26 | display.getSize(size); 27 | 28 | // Create a new instance of the SnakeEngine class 29 | mSnakeGame = new SnakeGame(this, size); 30 | 31 | // Make snakeEngine the view of the Activity 32 | setContentView(mSnakeGame); 33 | } 34 | 35 | // Start the thread in snakeEngine 36 | @Override 37 | protected void onResume() { 38 | super.onResume(); 39 | mSnakeGame.resume(); 40 | } 41 | 42 | // Stop the thread in snakeEngine 43 | @Override 44 | protected void onPause() { 45 | super.onPause(); 46 | mSnakeGame.pause(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter 15/values-de/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tippen Sie, um zu spielen! 4 | 5 | -------------------------------------------------------------------------------- /Chapter 15/values-es/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Toque para jugar! 4 | 5 | -------------------------------------------------------------------------------- /Chapter 15/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #6200EE 4 | #3700B3 5 | #03DAC5 6 | -------------------------------------------------------------------------------- /Chapter 15/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Snake 3 | Tap To Play! 4 | 5 | -------------------------------------------------------------------------------- /Chapter 15/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /Chapter 16/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | > 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter 16/assets/get_apple.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 16/assets/get_apple.ogg -------------------------------------------------------------------------------- /Chapter 16/assets/snake_death.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 16/assets/snake_death.ogg -------------------------------------------------------------------------------- /Chapter 16/drawable/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 16/drawable/apple.png -------------------------------------------------------------------------------- /Chapter 16/drawable/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 16/drawable/body.png -------------------------------------------------------------------------------- /Chapter 16/drawable/head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 16/drawable/head.png -------------------------------------------------------------------------------- /Chapter 16/java/Apple.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.Point; 9 | import java.util.Random; 10 | 11 | class Apple { 12 | 13 | // The location of the apple on the grid 14 | // Not in pixels 15 | private Point mLocation = new Point(); 16 | 17 | // The range of values we can choose from 18 | // to spawn an apple 19 | private Point mSpawnRange; 20 | private int mSize; 21 | 22 | // An image to represent the apple 23 | private Bitmap mBitmapApple; 24 | 25 | /// Set up the apple in the constructor 26 | Apple(Context context, Point sr, int s){ 27 | 28 | // Make a note of the passed in spawn range 29 | mSpawnRange = sr; 30 | // Make a note of the size of an apple 31 | mSize = s; 32 | // Hide the apple off-screen until the game starts 33 | mLocation.x = -10; 34 | 35 | // Load the image to the bitmap 36 | mBitmapApple = BitmapFactory 37 | .decodeResource(context.getResources(), 38 | R.drawable.apple); 39 | 40 | // Resize the bitmap 41 | mBitmapApple = Bitmap 42 | .createScaledBitmap(mBitmapApple, s, s, false); 43 | } 44 | 45 | // This is called every time an apple is eaten 46 | void spawn(){ 47 | // Choose two random values and place the apple 48 | Random random = new Random(); 49 | mLocation.x = random.nextInt(mSpawnRange.x) + 1; 50 | mLocation.y = random.nextInt(mSpawnRange.y - 1) + 1; 51 | } 52 | 53 | // Let SnakeGame know where the apple is 54 | // SnakeGame can share this with the snake 55 | Point getLocation(){ 56 | return mLocation; 57 | } 58 | 59 | // Draw the apple 60 | void draw(Canvas canvas, Paint paint){ 61 | canvas.drawBitmap(mBitmapApple, 62 | mLocation.x * mSize, mLocation.y * mSize, paint); 63 | 64 | } 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Chapter 16/java/Snake.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | public class Snake { 4 | } 5 | -------------------------------------------------------------------------------- /Chapter 16/java/SnakeActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class SnakeActivity extends Activity { 10 | 11 | // Declare an instance of SnakeGame 12 | SnakeGame mSnakeGame; 13 | 14 | // Set the game up 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | 18 | super.onCreate(savedInstanceState); 19 | requestWindowFeature(Window.FEATURE_NO_TITLE); 20 | 21 | // Get the pixel dimensions of the screen 22 | Display display = getWindowManager().getDefaultDisplay(); 23 | 24 | // Initialize the result into a Point object 25 | Point size = new Point(); 26 | display.getSize(size); 27 | 28 | // Create a new instance of the SnakeEngine class 29 | mSnakeGame = new SnakeGame(this, size); 30 | 31 | // Make snakeEngine the view of the Activity 32 | setContentView(mSnakeGame); 33 | } 34 | 35 | // Start the thread in snakeEngine 36 | @Override 37 | protected void onResume() { 38 | super.onResume(); 39 | mSnakeGame.resume(); 40 | } 41 | 42 | // Stop the thread in snakeEngine 43 | @Override 44 | protected void onPause() { 45 | super.onPause(); 46 | mSnakeGame.pause(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter 17/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | > 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Chapter 17/assets/get_apple.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 17/assets/get_apple.ogg -------------------------------------------------------------------------------- /Chapter 17/assets/snake_death.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 17/assets/snake_death.ogg -------------------------------------------------------------------------------- /Chapter 17/drawable/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 17/drawable/apple.png -------------------------------------------------------------------------------- /Chapter 17/drawable/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 17/drawable/body.png -------------------------------------------------------------------------------- /Chapter 17/drawable/head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 17/drawable/head.png -------------------------------------------------------------------------------- /Chapter 17/java/Apple.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.Point; 9 | import java.util.Random; 10 | 11 | class Apple { 12 | 13 | // The location of the apple on the grid 14 | // Not in pixels 15 | private Point mLocation = new Point(); 16 | 17 | // The range of values we can choose from 18 | // to spawn an apple 19 | private Point mSpawnRange; 20 | private int mSize; 21 | 22 | // An image to represent the apple 23 | private Bitmap mBitmapApple; 24 | 25 | /// Set up the apple in the constructor 26 | Apple(Context context, Point sr, int s){ 27 | 28 | // Make a note of the passed in spawn range 29 | mSpawnRange = sr; 30 | // Make a note of the size of an apple 31 | mSize = s; 32 | // Hide the apple off-screen until the game starts 33 | mLocation.x = -10; 34 | 35 | // Load the image to the bitmap 36 | mBitmapApple = BitmapFactory 37 | .decodeResource(context.getResources(), 38 | R.drawable.apple); 39 | 40 | // Resize the bitmap 41 | mBitmapApple = Bitmap 42 | .createScaledBitmap(mBitmapApple, s, s, false); 43 | } 44 | 45 | // This is called every time an apple is eaten 46 | void spawn(){ 47 | // Choose two random values and place the apple 48 | Random random = new Random(); 49 | mLocation.x = random.nextInt(mSpawnRange.x) + 1; 50 | mLocation.y = random.nextInt(mSpawnRange.y - 1) + 1; 51 | } 52 | 53 | // Let SnakeGame know where the apple is 54 | // SnakeGame can share this with the snake 55 | Point getLocation(){ 56 | return mLocation; 57 | } 58 | 59 | // Draw the apple 60 | void draw(Canvas canvas, Paint paint){ 61 | canvas.drawBitmap(mBitmapApple, 62 | mLocation.x * mSize, mLocation.y * mSize, paint); 63 | 64 | } 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Chapter 17/java/SnakeActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.snake; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class SnakeActivity extends Activity { 10 | 11 | // Declare an instance of SnakeGame 12 | SnakeGame mSnakeGame; 13 | 14 | // Set the game up 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | 18 | super.onCreate(savedInstanceState); 19 | requestWindowFeature(Window.FEATURE_NO_TITLE); 20 | 21 | // Get the pixel dimensions of the screen 22 | Display display = getWindowManager().getDefaultDisplay(); 23 | 24 | // Initialize the result into a Point object 25 | Point size = new Point(); 26 | display.getSize(size); 27 | 28 | // Create a new instance of the SnakeEngine class 29 | mSnakeGame = new SnakeGame(this, size); 30 | 31 | // Make snakeEngine the view of the Activity 32 | setContentView(mSnakeGame); 33 | } 34 | 35 | // Start the thread in snakeEngine 36 | @Override 37 | protected void onResume() { 38 | super.onResume(); 39 | mSnakeGame.resume(); 40 | } 41 | 42 | // Stop the thread in snakeEngine 43 | @Override 44 | protected void onPause() { 45 | super.onPause(); 46 | mSnakeGame.pause(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter 18/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | > 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Chapter 18/assets/alien_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 18/assets/alien_explosion.ogg -------------------------------------------------------------------------------- /Chapter 18/assets/player_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 18/assets/player_explosion.ogg -------------------------------------------------------------------------------- /Chapter 18/assets/shoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 18/assets/shoot.ogg -------------------------------------------------------------------------------- /Chapter 18/java/GameActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class GameActivity extends Activity { 10 | 11 | GameEngine mGameEngine; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | requestWindowFeature(Window.FEATURE_NO_TITLE); 17 | 18 | Display display = getWindowManager() 19 | .getDefaultDisplay(); 20 | 21 | Point size = new Point(); 22 | display.getSize(size); 23 | mGameEngine = new GameEngine(this, size); 24 | setContentView(mGameEngine); 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | super.onResume(); 30 | mGameEngine.startThread(); 31 | } 32 | 33 | @Override 34 | protected void onPause() { 35 | super.onPause(); 36 | mGameEngine.stopThread(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter 18/java/GameEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Point; 5 | import android.util.Log; 6 | import android.view.MotionEvent; 7 | import android.view.SurfaceView; 8 | 9 | class GameEngine extends SurfaceView implements Runnable, GameStarter { 10 | private Thread mThread = null; 11 | private long mFPS; 12 | 13 | private GameState mGameState; 14 | private SoundEngine mSoundEngine; 15 | HUD mHUD; 16 | Renderer mRenderer; 17 | 18 | 19 | public GameEngine(Context context, Point size) { 20 | super(context); 21 | 22 | mGameState = new GameState(this, context); 23 | mSoundEngine = new SoundEngine(context); 24 | mHUD = new HUD(size); 25 | mRenderer = new Renderer(this); 26 | 27 | } 28 | 29 | @Override 30 | public void run() { 31 | while (mGameState.getThreadRunning()) { 32 | long frameStartTime = System.currentTimeMillis(); 33 | 34 | if (!mGameState.getPaused()) { 35 | // Update all the game objects here 36 | // in a new way 37 | } 38 | 39 | 40 | // Draw all the game objects here 41 | // in a new way 42 | mRenderer.draw(mGameState, mHUD); 43 | 44 | // Measure the frames per second in the usual way 45 | long timeThisFrame = System.currentTimeMillis() 46 | - frameStartTime; 47 | if (timeThisFrame >= 1) { 48 | final int MILLIS_IN_SECOND = 1000; 49 | mFPS = MILLIS_IN_SECOND / timeThisFrame; 50 | } 51 | } 52 | } 53 | 54 | @Override 55 | public boolean onTouchEvent(MotionEvent motionEvent) { 56 | // Handle the player's input here 57 | // But in a new way 58 | 59 | return true; 60 | } 61 | 62 | public void stopThread() { 63 | // New code here soon 64 | mGameState.stopEverything(); 65 | try { 66 | mThread.join(); 67 | } catch (InterruptedException e) { 68 | Log.e("Exception","stopThread()" 69 | + e.getMessage()); 70 | } 71 | } 72 | 73 | public void startThread() { 74 | // New code here soon 75 | mGameState.startThread(); 76 | mThread = new Thread(this); 77 | mThread.start(); 78 | } 79 | 80 | public void deSpawnReSpawn() { 81 | // Eventually this will despawn 82 | // and then respawn all the game objects 83 | } 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /Chapter 18/java/GameStarter.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameStarter { 4 | // This allows the State class to 5 | // spawn and despawn objects via the game engine 6 | 7 | public void deSpawnReSpawn(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Chapter 18/java/GameState.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | final class GameState { 7 | private static volatile boolean mThreadRunning = false; 8 | private static volatile boolean mPaused = true; 9 | private static volatile boolean mGameOver = true; 10 | private static volatile boolean mDrawing = false; 11 | 12 | // This object will have access to the deSpawnReSpawn method 13 | // in GameEngine- once it is initialized 14 | private GameStarter gameStarter; 15 | 16 | private int mScore; 17 | private int mHighScore; 18 | private int mNumShips; 19 | 20 | // This is how we will make all the high scores persist 21 | private SharedPreferences.Editor mEditor; 22 | 23 | GameState(GameStarter gs, Context context){ 24 | // This initializes the gameStarter reference 25 | gameStarter = gs; 26 | 27 | // Get the current high score 28 | SharedPreferences prefs; 29 | prefs = context.getSharedPreferences("HiScore", 30 | Context.MODE_PRIVATE); 31 | 32 | // Initialize the mEditor ready 33 | mEditor = prefs.edit(); 34 | 35 | // Load high score from a entry in the file 36 | // labeled "hiscore" 37 | // if not available highscore set to zero 0 38 | mHighScore = prefs.getInt("hi_score", 0); 39 | } 40 | 41 | private void endGame(){ 42 | mGameOver = true; 43 | mPaused = true; 44 | if(mScore > mHighScore){ 45 | mHighScore = mScore; 46 | // Save high score 47 | mEditor.putInt("hi_score", mHighScore); 48 | mEditor.commit(); 49 | } 50 | } 51 | 52 | void startNewGame(){ 53 | mScore = 0; 54 | mNumShips = 3; 55 | // Don't want to be drawing objects 56 | // while deSpawnReSpawn is 57 | // clearing them and spawning them again 58 | stopDrawing(); 59 | gameStarter.deSpawnReSpawn(); 60 | resume(); 61 | 62 | // Now we can draw again 63 | startDrawing(); 64 | } 65 | 66 | 67 | void loseLife(SoundEngine se){ 68 | mNumShips--; 69 | se.playPlayerExplode(); 70 | if(mNumShips == 0){ 71 | pause(); 72 | endGame(); 73 | } 74 | } 75 | 76 | int getNumShips(){ 77 | return mNumShips; 78 | } 79 | 80 | void increaseScore(){ 81 | mScore++; 82 | } 83 | 84 | int getScore(){ 85 | return mScore; 86 | } 87 | 88 | int getHighScore(){ 89 | return mHighScore; 90 | } 91 | 92 | void pause(){ 93 | mPaused = true; 94 | } 95 | 96 | void resume(){ 97 | mGameOver = false; 98 | mPaused = false; 99 | } 100 | 101 | void stopEverything(){ 102 | mPaused = true; 103 | mGameOver = true; 104 | mThreadRunning = false; 105 | } 106 | 107 | boolean getThreadRunning(){ 108 | return mThreadRunning; 109 | } 110 | 111 | void startThread(){ 112 | mThreadRunning = true; 113 | } 114 | 115 | private void stopDrawing(){ 116 | mDrawing = false; 117 | } 118 | 119 | private void startDrawing(){ 120 | mDrawing = true; 121 | } 122 | 123 | boolean getDrawing() { 124 | return mDrawing; 125 | } 126 | 127 | boolean getPaused(){ 128 | return mPaused; 129 | } 130 | 131 | boolean getGameOver(){ 132 | return mGameOver; 133 | } 134 | 135 | 136 | 137 | } -------------------------------------------------------------------------------- /Chapter 18/java/Renderer.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.view.SurfaceHolder; 7 | import android.view.SurfaceView; 8 | 9 | import java.util.ArrayList; 10 | 11 | class Renderer { 12 | private Canvas mCanvas; 13 | private SurfaceHolder mSurfaceHolder; 14 | private Paint mPaint; 15 | 16 | Renderer(SurfaceView sh){ 17 | mSurfaceHolder = sh.getHolder(); 18 | mPaint = new Paint(); 19 | } 20 | 21 | void draw(GameState gs, HUD hud) { 22 | if (mSurfaceHolder.getSurface().isValid()) { 23 | mCanvas = mSurfaceHolder.lockCanvas(); 24 | mCanvas.drawColor(Color.argb(255, 0, 0, 0)); 25 | 26 | if (gs.getDrawing()) { 27 | // Draw all the game objects here 28 | } 29 | 30 | if(gs.getGameOver()) { 31 | // Draw a background graphic here 32 | } 33 | 34 | // Draw a particle system explosion here 35 | 36 | // Now we draw the HUD on top of everything else 37 | hud.draw(mCanvas, mPaint, gs); 38 | 39 | mSurfaceHolder.unlockCanvasAndPost(mCanvas); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Chapter 18/java/SoundEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.content.res.AssetManager; 6 | import android.media.AudioAttributes; 7 | import android.media.AudioManager; 8 | import android.media.SoundPool; 9 | import android.os.Build; 10 | 11 | import java.io.IOException; 12 | 13 | class SoundEngine { 14 | // for playing sound effects 15 | private SoundPool mSP; 16 | private int mShoot_ID = -1; 17 | private int mAlien_Explode_ID = -1; 18 | private int mPlayer_explode_ID = -1; 19 | 20 | SoundEngine(Context c){ 21 | // Initialize the SoundPool 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 23 | AudioAttributes audioAttributes = 24 | new AudioAttributes.Builder() 25 | .setUsage(AudioAttributes.USAGE_MEDIA) 26 | .setContentType(AudioAttributes 27 | .CONTENT_TYPE_SONIFICATION) 28 | .build(); 29 | 30 | mSP = new SoundPool.Builder() 31 | .setMaxStreams(5) 32 | .setAudioAttributes(audioAttributes) 33 | .build(); 34 | } else { 35 | mSP = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); 36 | } 37 | try { 38 | AssetManager assetManager = c.getAssets(); 39 | AssetFileDescriptor descriptor; 40 | 41 | // Prepare the sounds in memory 42 | descriptor = assetManager.openFd("shoot.ogg"); 43 | mShoot_ID = mSP.load(descriptor, 0); 44 | 45 | descriptor = assetManager.openFd("alien_explosion.ogg"); 46 | mAlien_Explode_ID = mSP.load(descriptor, 0); 47 | 48 | descriptor = 49 | assetManager.openFd("player_explosion.ogg"); 50 | 51 | mPlayer_explode_ID = mSP.load(descriptor, 0); 52 | 53 | } catch (IOException e) { 54 | // Error 55 | } 56 | 57 | } 58 | 59 | void playShoot(){ 60 | mSP.play(mShoot_ID,1, 1, 0, 0, 1); 61 | } 62 | 63 | void playAlienExplode(){ 64 | mSP.play(mAlien_Explode_ID,1, 1, 0, 0, 1); 65 | } 66 | 67 | void playPlayerExplode(){ 68 | mSP.play(mPlayer_explode_ID,1, 1, 0, 0, 1); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Chapter 19/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 15 | > 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Chapter 19/assets/alien_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 19/assets/alien_explosion.ogg -------------------------------------------------------------------------------- /Chapter 19/assets/player_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 19/assets/player_explosion.ogg -------------------------------------------------------------------------------- /Chapter 19/assets/shoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 19/assets/shoot.ogg -------------------------------------------------------------------------------- /Chapter 19/java/GameActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class GameActivity extends Activity { 10 | 11 | GameEngine mGameEngine; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | requestWindowFeature(Window.FEATURE_NO_TITLE); 17 | 18 | Display display = getWindowManager() 19 | .getDefaultDisplay(); 20 | 21 | Point size = new Point(); 22 | display.getSize(size); 23 | mGameEngine = new GameEngine(this, size); 24 | setContentView(mGameEngine); 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | super.onResume(); 30 | mGameEngine.startThread(); 31 | } 32 | 33 | @Override 34 | protected void onPause() { 35 | super.onPause(); 36 | mGameEngine.stopThread(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter 19/java/GameEngineBroadcaster.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameEngineBroadcaster { 4 | void addObserver(InputObserver o); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 19/java/GameStarter.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameStarter { 4 | // This allows the State class to 5 | // spawn and despawn objects via the game engine 6 | 7 | public void deSpawnReSpawn(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Chapter 19/java/GameState.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | final class GameState { 7 | private static volatile boolean mThreadRunning = false; 8 | private static volatile boolean mPaused = true; 9 | private static volatile boolean mGameOver = true; 10 | private static volatile boolean mDrawing = false; 11 | 12 | // This object will have access to the deSpawnReSpawn method 13 | // in GameEngine- once it is initialized 14 | private GameStarter gameStarter; 15 | 16 | private int mScore; 17 | private int mHighScore; 18 | private int mNumShips; 19 | 20 | // This is how we will make all the high scores persist 21 | private SharedPreferences.Editor mEditor; 22 | 23 | GameState(GameStarter gs, Context context){ 24 | // This initializes the gameStarter reference 25 | gameStarter = gs; 26 | 27 | // Get the current high score 28 | SharedPreferences prefs; 29 | prefs = context.getSharedPreferences("HiScore", 30 | Context.MODE_PRIVATE); 31 | 32 | // Initialize the mEditor ready 33 | mEditor = prefs.edit(); 34 | 35 | // Load high score from a entry in the file 36 | // labeled "hiscore" 37 | // if not available highscore set to zero 0 38 | mHighScore = prefs.getInt("hi_score", 0); 39 | } 40 | 41 | private void endGame(){ 42 | mGameOver = true; 43 | mPaused = true; 44 | if(mScore > mHighScore){ 45 | mHighScore = mScore; 46 | // Save high score 47 | mEditor.putInt("hi_score", mHighScore); 48 | mEditor.commit(); 49 | } 50 | } 51 | 52 | void startNewGame(){ 53 | mScore = 0; 54 | mNumShips = 3; 55 | // Don't want to be drawing objects 56 | // while deSpawnReSpawn is 57 | // clearing them and spawning them again 58 | stopDrawing(); 59 | gameStarter.deSpawnReSpawn(); 60 | resume(); 61 | 62 | // Now we can draw again 63 | startDrawing(); 64 | } 65 | 66 | 67 | void loseLife(SoundEngine se){ 68 | mNumShips--; 69 | se.playPlayerExplode(); 70 | if(mNumShips == 0){ 71 | pause(); 72 | endGame(); 73 | } 74 | } 75 | 76 | int getNumShips(){ 77 | return mNumShips; 78 | } 79 | 80 | void increaseScore(){ 81 | mScore++; 82 | } 83 | 84 | int getScore(){ 85 | return mScore; 86 | } 87 | 88 | int getHighScore(){ 89 | return mHighScore; 90 | } 91 | 92 | void pause(){ 93 | mPaused = true; 94 | } 95 | 96 | void resume(){ 97 | mGameOver = false; 98 | mPaused = false; 99 | } 100 | 101 | void stopEverything(){ 102 | mPaused = true; 103 | mGameOver = true; 104 | mThreadRunning = false; 105 | } 106 | 107 | boolean getThreadRunning(){ 108 | return mThreadRunning; 109 | } 110 | 111 | void startThread(){ 112 | mThreadRunning = true; 113 | } 114 | 115 | private void stopDrawing(){ 116 | mDrawing = false; 117 | } 118 | 119 | private void startDrawing(){ 120 | mDrawing = true; 121 | } 122 | 123 | boolean getDrawing() { 124 | return mDrawing; 125 | } 126 | 127 | boolean getPaused(){ 128 | return mPaused; 129 | } 130 | 131 | boolean getGameOver(){ 132 | return mGameOver; 133 | } 134 | 135 | 136 | 137 | } -------------------------------------------------------------------------------- /Chapter 19/java/InputObserver.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | import java.util.ArrayList; 6 | 7 | interface InputObserver { 8 | 9 | void handleInput(MotionEvent event, GameState gs, 10 | ArrayList controls); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter 19/java/Particle.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class Particle { 6 | 7 | PointF mVelocity; 8 | PointF mPosition; 9 | 10 | Particle(PointF direction) 11 | { 12 | mVelocity = new PointF(); 13 | mPosition = new PointF(); 14 | 15 | // Determine the direction 16 | mVelocity.x = direction.x; 17 | mVelocity.y = direction.y; 18 | 19 | } 20 | 21 | void update() 22 | { 23 | // Move the particle 24 | mPosition.x += mVelocity.x; 25 | mPosition.y += mVelocity.y; 26 | } 27 | 28 | void setPosition(PointF position) 29 | { 30 | mPosition.x = position.x; 31 | mPosition.y = position.y; 32 | } 33 | 34 | PointF getPosition() 35 | { 36 | return mPosition; 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Chapter 19/java/ParticleSystem.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.PointF; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Random; 9 | 10 | class ParticleSystem { 11 | 12 | float mDuration; 13 | 14 | ArrayList mParticles; 15 | Random random = new Random(); 16 | boolean mIsRunning = false; 17 | 18 | void init(int numParticles){ 19 | 20 | mParticles = new ArrayList<>(); 21 | // Create the particles 22 | 23 | for (int i = 0; i < numParticles; i++) { 24 | float angle = (random.nextInt(360)) ; 25 | angle = angle * 3.14f / 180.f; 26 | float speed = (random.nextInt(20)+1); 27 | 28 | PointF direction; 29 | 30 | direction = new PointF((float)Math.cos(angle) * speed, 31 | (float)Math.sin(angle) * speed); 32 | 33 | mParticles.add(new Particle(direction)); 34 | } 35 | } 36 | void update(long fps){ 37 | 38 | mDuration -= (1f/fps); 39 | 40 | for(Particle p : mParticles){ 41 | p.update(); 42 | } 43 | 44 | if (mDuration < 0) 45 | { 46 | mIsRunning = false; 47 | } 48 | } 49 | 50 | void emitParticles(PointF startPosition){ 51 | 52 | mIsRunning = true; 53 | mDuration = 1f; 54 | 55 | for(Particle p : mParticles){ 56 | p.setPosition(startPosition); 57 | } 58 | } 59 | 60 | void draw(Canvas canvas, Paint paint){ 61 | 62 | for (Particle p : mParticles) { 63 | 64 | paint.setARGB(255, 65 | random.nextInt(256), 66 | random.nextInt(256), 67 | random.nextInt(256)); 68 | 69 | // Uncomment the next line to have plain white particles 70 | //paint.setColor(Color.argb(255,255,255,255)); 71 | canvas.drawRect(p.getPosition().x, 72 | p.getPosition().y, 73 | p.getPosition().x+25, 74 | p.getPosition().y+25, paint); 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Chapter 19/java/PhysicsEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class PhysicsEngine { 4 | 5 | // This signature and much more will 6 | //change later in the project 7 | boolean update(long fps, ParticleSystem ps){ 8 | 9 | if(ps.mIsRunning){ 10 | ps.update(fps); 11 | } 12 | 13 | return false; 14 | } 15 | 16 | // Collision detection method will go here 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /Chapter 19/java/Renderer.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.view.SurfaceHolder; 7 | import android.view.SurfaceView; 8 | 9 | import java.util.ArrayList; 10 | 11 | class Renderer { 12 | private Canvas mCanvas; 13 | private SurfaceHolder mSurfaceHolder; 14 | private Paint mPaint; 15 | 16 | Renderer(SurfaceView sh){ 17 | mSurfaceHolder = sh.getHolder(); 18 | mPaint = new Paint(); 19 | } 20 | 21 | void draw(GameState gs, HUD hud, ParticleSystem ps) { 22 | if (mSurfaceHolder.getSurface().isValid()) { 23 | mCanvas = mSurfaceHolder.lockCanvas(); 24 | mCanvas.drawColor(Color.argb(255, 0, 0, 0)); 25 | 26 | if (gs.getDrawing()) { 27 | // Draw all the game objects here 28 | } 29 | 30 | if(gs.getGameOver()) { 31 | // Draw a background graphic here 32 | } 33 | 34 | // Draw a particle system explosion here 35 | if(ps.mIsRunning){ 36 | ps.draw(mCanvas, mPaint); 37 | } 38 | 39 | 40 | // Now we draw the HUD on top of everything else 41 | hud.draw(mCanvas, mPaint, gs); 42 | 43 | mSurfaceHolder.unlockCanvasAndPost(mCanvas); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /Chapter 19/java/SoundEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.content.res.AssetManager; 6 | import android.media.AudioAttributes; 7 | import android.media.AudioManager; 8 | import android.media.SoundPool; 9 | import android.os.Build; 10 | 11 | import java.io.IOException; 12 | 13 | class SoundEngine { 14 | // for playing sound effects 15 | private SoundPool mSP; 16 | private int mShoot_ID = -1; 17 | private int mAlien_Explode_ID = -1; 18 | private int mPlayer_explode_ID = -1; 19 | 20 | SoundEngine(Context c){ 21 | // Initialize the SoundPool 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 23 | AudioAttributes audioAttributes = 24 | new AudioAttributes.Builder() 25 | .setUsage(AudioAttributes.USAGE_MEDIA) 26 | .setContentType(AudioAttributes 27 | .CONTENT_TYPE_SONIFICATION) 28 | .build(); 29 | 30 | mSP = new SoundPool.Builder() 31 | .setMaxStreams(5) 32 | .setAudioAttributes(audioAttributes) 33 | .build(); 34 | } else { 35 | mSP = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); 36 | } 37 | try { 38 | AssetManager assetManager = c.getAssets(); 39 | AssetFileDescriptor descriptor; 40 | 41 | // Prepare the sounds in memory 42 | descriptor = assetManager.openFd("shoot.ogg"); 43 | mShoot_ID = mSP.load(descriptor, 0); 44 | 45 | descriptor = assetManager.openFd("alien_explosion.ogg"); 46 | mAlien_Explode_ID = mSP.load(descriptor, 0); 47 | 48 | descriptor = 49 | assetManager.openFd("player_explosion.ogg"); 50 | 51 | mPlayer_explode_ID = mSP.load(descriptor, 0); 52 | 53 | } catch (IOException e) { 54 | // Error 55 | } 56 | 57 | } 58 | 59 | void playShoot(){ 60 | mSP.play(mShoot_ID,1, 1, 0, 0, 1); 61 | } 62 | 63 | void playAlienExplode(){ 64 | mSP.play(mAlien_Explode_ID,1, 1, 0, 0, 1); 65 | } 66 | 67 | void playPlayerExplode(){ 68 | mSP.play(mPlayer_explode_ID,1, 1, 0, 0, 1); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Chapter 19/java/UIController.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | import android.graphics.Point; 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | 6 | import java.util.ArrayList; 7 | 8 | class UIController implements InputObserver { 9 | 10 | public UIController(GameEngineBroadcaster b){ 11 | b.addObserver(this); 12 | } 13 | 14 | @Override 15 | public void handleInput(MotionEvent event, GameState gameState, ArrayList buttons) { 16 | 17 | int i = event.getActionIndex(); 18 | int x = (int) event.getX(i); 19 | int y = (int) event.getY(i); 20 | 21 | int eventType = event.getAction() & MotionEvent.ACTION_MASK; 22 | 23 | if(eventType == MotionEvent.ACTION_UP || 24 | eventType == MotionEvent.ACTION_POINTER_UP) { 25 | 26 | 27 | if (buttons.get(HUD.PAUSE).contains(x, y)){ 28 | // Player pressed the pause button 29 | // Respond differently depending 30 | // upon the game's state 31 | 32 | // If the game is not paused 33 | if (!gameState.getPaused()) { 34 | // Pause the game 35 | gameState.pause(); 36 | } 37 | 38 | // If game is over start a new game 39 | else if (gameState.getGameOver()) { 40 | 41 | gameState.startNewGame(); 42 | } 43 | 44 | // Paused and not game over 45 | else if (gameState.getPaused() 46 | && !gameState.getGameOver()) { 47 | 48 | gameState.resume(); 49 | } 50 | } 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Chapter 20/assets/alien_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/assets/alien_explosion.ogg -------------------------------------------------------------------------------- /Chapter 20/assets/player_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/assets/player_explosion.ogg -------------------------------------------------------------------------------- /Chapter 20/assets/shoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/assets/shoot.ogg -------------------------------------------------------------------------------- /Chapter 20/drawable/alien_laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/alien_laser.png -------------------------------------------------------------------------------- /Chapter 20/drawable/alien_ship1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/alien_ship1.png -------------------------------------------------------------------------------- /Chapter 20/drawable/alien_ship2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/alien_ship2.png -------------------------------------------------------------------------------- /Chapter 20/drawable/alien_ship3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/alien_ship3.png -------------------------------------------------------------------------------- /Chapter 20/drawable/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/background.png -------------------------------------------------------------------------------- /Chapter 20/drawable/player_laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/player_laser.png -------------------------------------------------------------------------------- /Chapter 20/drawable/player_ship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 20/drawable/player_ship.png -------------------------------------------------------------------------------- /Chapter 20/java/AlienChaseSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienChaseSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for an alien that chases the player 8 | private static final String tag = "Alien"; 9 | private static final String bitmapName = "alien_ship1"; 10 | private static final float speed = 4f; 11 | private static final PointF relativeScale = 12 | new PointF(15f, 15f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "AlienChaseMovementComponent", 17 | "AlienHorizontalSpawnComponent"}; 18 | 19 | AlienChaseSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 20/java/AlienDiverSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienDiverSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for an alien that dives 8 | private static final String tag = "Alien"; 9 | private static final String bitmapName = "alien_ship3"; 10 | private static final float speed = 4f; 11 | private static final PointF relativeScale = 12 | new PointF(60f, 30f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "AlienDiverMovementComponent", 17 | "AlienVerticalSpawnComponent"}; 18 | 19 | AlienDiverSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 20/java/AlienLaserSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienLaserSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for an alien laser 8 | private static final String tag = "Alien Laser"; 9 | private static final String bitmapName = "alien_laser"; 10 | private static final float speed = .75f; 11 | private static final PointF relativeScale = 12 | new PointF(14f, 160f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "LaserMovementComponent", 17 | "LaserSpawnComponent"}; 18 | 19 | AlienLaserSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Chapter 20/java/AlienPatrolSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienPatrolSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for a patrolling alien 8 | private static final String tag = "Alien"; 9 | private static final String bitmapName = "alien_ship2"; 10 | private static final float speed = 5f; 11 | private static final PointF relativeScale = 12 | new PointF(15f, 15f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "AlienPatrolMovementComponent", 17 | "AlienHorizontalSpawnComponent"}; 18 | 19 | AlienPatrolSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Chapter 20/java/BackgroundGraphicsComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Matrix; 8 | import android.graphics.Paint; 9 | import android.graphics.PointF; 10 | import android.graphics.Rect; 11 | 12 | class BackgroundGraphicsComponent implements GraphicsComponent { 13 | 14 | private Bitmap mBitmap; 15 | private Bitmap mBitmapReversed; 16 | 17 | @Override 18 | public void initialize(Context c, 19 | ObjectSpec s, 20 | PointF objectSize) { 21 | 22 | // Make a resource id out of the string of the file name 23 | int resID = c.getResources() 24 | .getIdentifier(s.getBitmapName(), 25 | "drawable", c.getPackageName()); 26 | 27 | // Load the bitmap using the id 28 | mBitmap = BitmapFactory 29 | .decodeResource(c.getResources(), resID); 30 | 31 | // Resize the bitmap 32 | mBitmap = Bitmap 33 | .createScaledBitmap(mBitmap, 34 | (int)objectSize.x, 35 | (int)objectSize.y, 36 | false); 37 | 38 | // Create a mirror image of the bitmap 39 | Matrix matrix = new Matrix(); 40 | matrix.setScale(-1, 1); 41 | mBitmapReversed = Bitmap 42 | .createBitmap(mBitmap, 43 | 0, 0, 44 | mBitmap.getWidth(), 45 | mBitmap.getHeight(), 46 | matrix, true); 47 | 48 | 49 | } 50 | 51 | @Override 52 | public void draw(Canvas canvas, 53 | Paint paint, 54 | Transform t) { 55 | 56 | int xClip = t.getXClip(); 57 | int width = mBitmap.getWidth(); 58 | int height = mBitmap.getHeight(); 59 | int startY = 0; 60 | int endY = (int)t.getmScreenSize().y +20; 61 | 62 | // For the regular bitmap 63 | Rect fromRect1 = new Rect(0, 0, width - xClip, height); 64 | Rect toRect1 = new Rect(xClip, startY, width, endY); 65 | 66 | // For the reversed background 67 | Rect fromRect2 = new Rect(width - xClip, 0, width, height); 68 | Rect toRect2 = new Rect(0, startY, xClip, endY); 69 | 70 | //draw the two background bitmaps 71 | if (!t.getReversedFirst()) { 72 | canvas.drawBitmap(mBitmap, 73 | fromRect1, toRect1, paint); 74 | 75 | canvas.drawBitmap(mBitmapReversed, 76 | fromRect2, toRect2, paint); 77 | 78 | } else { 79 | canvas.drawBitmap(mBitmap, fromRect2, 80 | toRect2, paint); 81 | 82 | canvas.drawBitmap(mBitmapReversed, 83 | fromRect1, toRect1, paint); 84 | } 85 | 86 | 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /Chapter 20/java/BackgroundMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class BackgroundMovementComponent implements MovementComponent { 4 | @Override 5 | public boolean move(long fps, 6 | Transform t, 7 | Transform playerTransform) { 8 | 9 | int currentXClip = t.getXClip(); 10 | 11 | if(playerTransform.getFacingRight()) { 12 | currentXClip -= t.getSpeed() / fps; 13 | t.setXClip(currentXClip); 14 | } 15 | else { 16 | currentXClip += t.getSpeed() / fps; 17 | t.setXClip(currentXClip); 18 | } 19 | 20 | if (currentXClip >= t.getSize().x) { 21 | t.setXClip(0); 22 | t.flipReversedFirst(); 23 | } 24 | else if (currentXClip <= 0) { 25 | t.setXClip((int)t.getSize().x); 26 | t.flipReversedFirst(); 27 | } 28 | 29 | 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter 20/java/BackgroundSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class BackgroundSpawnComponent implements SpawnComponent { 4 | @Override 5 | public void spawn(Transform playerLTransform, Transform t) { 6 | // Place the background in the top left corner 7 | t.setLocation(0f,0f); 8 | 9 | 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Chapter 20/java/BackgroundSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class BackgroundSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for the background 8 | private static final String tag = "Background"; 9 | private static final String bitmapName = "background"; 10 | private static final float speed = 2f; 11 | private static final PointF relativeScale = 12 | new PointF(1f, 1f); 13 | 14 | private static final String[] components = new String [] { 15 | "BackgroundGraphicsComponent", 16 | "BackgroundMovementComponent", 17 | "BackgroundSpawnComponent"}; 18 | 19 | BackgroundSpec() { 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 20/java/GameActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class GameActivity extends Activity { 10 | 11 | GameEngine mGameEngine; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | requestWindowFeature(Window.FEATURE_NO_TITLE); 17 | 18 | Display display = getWindowManager() 19 | .getDefaultDisplay(); 20 | 21 | Point size = new Point(); 22 | display.getSize(size); 23 | mGameEngine = new GameEngine(this, size); 24 | setContentView(mGameEngine); 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | super.onResume(); 30 | mGameEngine.startThread(); 31 | } 32 | 33 | @Override 34 | protected void onPause() { 35 | super.onPause(); 36 | mGameEngine.stopThread(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter 20/java/GameEngineBroadcaster.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameEngineBroadcaster { 4 | void addObserver(InputObserver o); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 20/java/GameObject.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.PointF; 7 | 8 | class GameObject { 9 | 10 | private Transform mTransform; 11 | private boolean isActive = false; 12 | private String mTag; 13 | 14 | private GraphicsComponent graphicsComponent; 15 | private MovementComponent movementComponent; 16 | private SpawnComponent spawnComponent; 17 | 18 | void setSpawner(SpawnComponent s) { 19 | spawnComponent = s; 20 | } 21 | 22 | void setGraphics(GraphicsComponent g, Context c, 23 | ObjectSpec spec, PointF objectSize) { 24 | 25 | graphicsComponent = g; 26 | g.initialize(c, spec, objectSize); 27 | } 28 | 29 | void setMovement(MovementComponent m) { 30 | movementComponent = m; 31 | } 32 | 33 | void setInput(InputComponent s) { 34 | s.setTransform(mTransform); 35 | } 36 | 37 | void setmTag(String tag) { 38 | mTag = tag; 39 | } 40 | 41 | void setTransform(Transform t) { 42 | mTransform = t; 43 | } 44 | 45 | void draw(Canvas canvas, Paint paint) { 46 | graphicsComponent.draw(canvas, paint, mTransform); 47 | } 48 | 49 | void update(long fps, Transform playerTransform) { 50 | if (!(movementComponent.move(fps, 51 | mTransform, playerTransform))) { 52 | // Component returned false 53 | isActive = false; 54 | } 55 | } 56 | 57 | boolean spawn(Transform playerTransform) { 58 | // Only spawnComponent if not already active 59 | if (!isActive) { 60 | spawnComponent.spawn(playerTransform, mTransform); 61 | isActive = true; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | boolean checkActive() { 68 | return isActive; 69 | } 70 | 71 | String getTag() { 72 | return mTag; 73 | } 74 | 75 | void setInactive() { 76 | isActive = false; 77 | } 78 | 79 | Transform getTransform() { 80 | return mTransform; 81 | } 82 | 83 | 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Chapter 20/java/GameObjectFactory.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.PointF; 5 | 6 | class GameObjectFactory { 7 | private Context mContext; 8 | private PointF mScreenSize; 9 | private GameEngine mGameEngineReference; 10 | 11 | GameObjectFactory(Context c, PointF screenSize, 12 | GameEngine gameEngine) { 13 | 14 | this.mContext = c; 15 | this.mScreenSize = screenSize; 16 | mGameEngineReference = gameEngine; 17 | } 18 | 19 | GameObject create(ObjectSpec spec) { 20 | 21 | GameObject object = new GameObject(); 22 | 23 | int numComponents = spec.getComponents().length; 24 | 25 | final float HIDDEN = -2000f; 26 | 27 | object.setmTag(spec.getTag()); 28 | 29 | // Configure the speed relative to the screen size 30 | float speed = mScreenSize.x / spec.getSpeed(); 31 | 32 | // Configure the object size relative to screen size 33 | PointF objectSize = 34 | new PointF(mScreenSize.x / spec.getScale().x, 35 | mScreenSize.y / spec.getScale().y); 36 | 37 | // Set the location to somewhere off-screen 38 | PointF location = new PointF(HIDDEN, HIDDEN); 39 | 40 | object.setTransform(new Transform(speed, objectSize.x, 41 | objectSize.y, location, mScreenSize)); 42 | 43 | // More code here next... 44 | // Loop through and add/initialize all the components 45 | for (int i = 0; i < numComponents; i++) { 46 | switch (spec.getComponents()[i]) { 47 | case "PlayerInputComponent": 48 | object.setInput(new PlayerInputComponent 49 | (mGameEngineReference)); 50 | break; 51 | case "StdGraphicsComponent": 52 | object.setGraphics(new StdGraphicsComponent(), 53 | mContext, spec, objectSize); 54 | break; 55 | case "PlayerMovementComponent": 56 | object.setMovement(new PlayerMovementComponent()); 57 | break; 58 | case "LaserMovementComponent": 59 | object.setMovement(new LaserMovementComponent()); 60 | break; 61 | case "PlayerSpawnComponent": 62 | object.setSpawner(new PlayerSpawnComponent()); 63 | break; 64 | case "LaserSpawnComponent": 65 | object.setSpawner(new LaserSpawnComponent()); 66 | break; 67 | case "BackgroundGraphicsComponent": 68 | object.setGraphics(new BackgroundGraphicsComponent(), 69 | mContext, spec, objectSize); 70 | break; 71 | case "BackgroundMovementComponent": 72 | object.setMovement(new BackgroundMovementComponent()); 73 | break; 74 | case "BackgroundSpawnComponent": 75 | object.setSpawner(new BackgroundSpawnComponent()); 76 | break; 77 | 78 | default: 79 | // Error unidentified component 80 | break; 81 | } 82 | } 83 | // Return the completed GameObject to the Level class 84 | return object; 85 | 86 | } 87 | 88 | } 89 | 90 | -------------------------------------------------------------------------------- /Chapter 20/java/GameStarter.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameStarter { 4 | // This allows the State class to 5 | // spawn and despawn objects via the game engine 6 | 7 | public void deSpawnReSpawn(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Chapter 20/java/GameState.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | final class GameState { 7 | private static volatile boolean mThreadRunning = false; 8 | private static volatile boolean mPaused = true; 9 | private static volatile boolean mGameOver = true; 10 | private static volatile boolean mDrawing = false; 11 | 12 | // This object will have access to the deSpawnReSpawn method 13 | // in GameEngine- once it is initialized 14 | private GameStarter gameStarter; 15 | 16 | private int mScore; 17 | private int mHighScore; 18 | private int mNumShips; 19 | 20 | // This is how we will make all the high scores persist 21 | private SharedPreferences.Editor mEditor; 22 | 23 | GameState(GameStarter gs, Context context){ 24 | // This initializes the gameStarter reference 25 | gameStarter = gs; 26 | 27 | // Get the current high score 28 | SharedPreferences prefs; 29 | prefs = context.getSharedPreferences("HiScore", 30 | Context.MODE_PRIVATE); 31 | 32 | // Initialize the mEditor ready 33 | mEditor = prefs.edit(); 34 | 35 | // Load high score from a entry in the file 36 | // labeled "hiscore" 37 | // if not available highscore set to zero 0 38 | mHighScore = prefs.getInt("hi_score", 0); 39 | } 40 | 41 | private void endGame(){ 42 | mGameOver = true; 43 | mPaused = true; 44 | if(mScore > mHighScore){ 45 | mHighScore = mScore; 46 | // Save high score 47 | mEditor.putInt("hi_score", mHighScore); 48 | mEditor.commit(); 49 | } 50 | } 51 | 52 | void startNewGame(){ 53 | mScore = 0; 54 | mNumShips = 3; 55 | // Don't want to be drawing objects 56 | // while deSpawnReSpawn is 57 | // clearing them and spawning them again 58 | stopDrawing(); 59 | gameStarter.deSpawnReSpawn(); 60 | resume(); 61 | 62 | // Now we can draw again 63 | startDrawing(); 64 | } 65 | 66 | 67 | void loseLife(SoundEngine se){ 68 | mNumShips--; 69 | se.playPlayerExplode(); 70 | if(mNumShips == 0){ 71 | pause(); 72 | endGame(); 73 | } 74 | } 75 | 76 | int getNumShips(){ 77 | return mNumShips; 78 | } 79 | 80 | void increaseScore(){ 81 | mScore++; 82 | } 83 | 84 | int getScore(){ 85 | return mScore; 86 | } 87 | 88 | int getHighScore(){ 89 | return mHighScore; 90 | } 91 | 92 | void pause(){ 93 | mPaused = true; 94 | } 95 | 96 | void resume(){ 97 | mGameOver = false; 98 | mPaused = false; 99 | } 100 | 101 | void stopEverything(){ 102 | mPaused = true; 103 | mGameOver = true; 104 | mThreadRunning = false; 105 | } 106 | 107 | boolean getThreadRunning(){ 108 | return mThreadRunning; 109 | } 110 | 111 | void startThread(){ 112 | mThreadRunning = true; 113 | } 114 | 115 | private void stopDrawing(){ 116 | mDrawing = false; 117 | } 118 | 119 | private void startDrawing(){ 120 | mDrawing = true; 121 | } 122 | 123 | boolean getDrawing() { 124 | return mDrawing; 125 | } 126 | 127 | boolean getPaused(){ 128 | return mPaused; 129 | } 130 | 131 | boolean getGameOver(){ 132 | return mGameOver; 133 | } 134 | 135 | 136 | 137 | } -------------------------------------------------------------------------------- /Chapter 20/java/GraphicsComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.PointF; 7 | 8 | interface GraphicsComponent { 9 | 10 | void initialize(Context c, 11 | ObjectSpec s, 12 | PointF screensize); 13 | 14 | void draw(Canvas canvas, 15 | Paint paint, 16 | Transform t); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 20/java/InputComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | interface InputComponent { 4 | 5 | void setTransform(Transform t); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Chapter 20/java/InputObserver.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | import java.util.ArrayList; 6 | 7 | interface InputObserver { 8 | 9 | void handleInput(MotionEvent event, GameState gs, 10 | ArrayList controls); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter 20/java/LaserMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class LaserMovementComponent implements MovementComponent { 6 | 7 | @Override 8 | public boolean move(long fps, 9 | Transform t, 10 | Transform playerTransform) { 11 | 12 | // Laser can only travel two screen widths 13 | float range = t.getmScreenSize().x * 2; 14 | 15 | // Where is the laser 16 | PointF location = t.getLocation(); 17 | 18 | // How fast is it going 19 | float speed = t.getSpeed(); 20 | 21 | if(t.headingRight()){ 22 | location.x += speed / fps; 23 | } 24 | else if(t.headingLeft()){ 25 | location.x -= speed / fps; 26 | } 27 | 28 | // Has the laser gone out of range 29 | if(location.x < - range || location.x > range){ 30 | // disable the laser 31 | return false; 32 | } 33 | 34 | t.updateCollider(); 35 | 36 | 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter 20/java/LaserSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class LaserSpawnComponent implements SpawnComponent { 6 | 7 | @Override 8 | public void spawn(Transform playerTransform, 9 | Transform t) { 10 | 11 | PointF startPosition = 12 | playerTransform.getFiringLocation(t.getSize().x); 13 | 14 | t.setLocation((int)startPosition.x, (int)startPosition.y); 15 | 16 | if(playerTransform.getFacingRight()){ 17 | t.headRight(); 18 | } 19 | else{ 20 | t.headLeft(); 21 | } 22 | 23 | 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Chapter 20/java/Level.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.PointF; 5 | 6 | import java.util.ArrayList; 7 | 8 | class Level { 9 | 10 | // Keep track of specific types 11 | public static final int BACKGROUND_INDEX = 0; 12 | public static final int PLAYER_INDEX = 1; 13 | public static final int FIRST_PLAYER_LASER = 2; 14 | public static final int LAST_PLAYER_LASER = 4; 15 | public static int mNextPlayerLaser; 16 | public static final int FIRST_ALIEN = 5; 17 | public static final int SECOND_ALIEN = 6; 18 | public static final int THIRD_ALIEN = 7; 19 | public static final int FOURTH_ALIEN = 8; 20 | public static final int FIFTH_ALIEN = 9; 21 | public static final int SIXTH_ALIEN = 10; 22 | public static final int LAST_ALIEN = 10; 23 | public static final int FIRST_ALIEN_LASER = 11; 24 | public static final int LAST_ALIEN_LASER = 15; 25 | public static int mNextAlienLaser; 26 | 27 | // This will hold all the instances of GameObject 28 | private ArrayList objects; 29 | public Level(Context context, 30 | PointF mScreenSize, 31 | GameEngine ge){ 32 | 33 | objects = new ArrayList<>(); 34 | GameObjectFactory factory = new GameObjectFactory( 35 | context, mScreenSize, ge); 36 | 37 | buildGameObjects(factory); 38 | } 39 | 40 | ArrayList buildGameObjects( 41 | GameObjectFactory factory){ 42 | 43 | objects.clear(); 44 | objects.add(BACKGROUND_INDEX, factory 45 | .create(new BackgroundSpec())); 46 | 47 | objects.add(PLAYER_INDEX, factory 48 | .create(new PlayerSpec())); 49 | 50 | // Spawn the player's lasers 51 | for (int i = FIRST_PLAYER_LASER; 52 | i != LAST_PLAYER_LASER + 1; i++) { 53 | 54 | objects.add(i, factory 55 | .create(new PlayerLaserSpec())); 56 | } 57 | 58 | mNextPlayerLaser = FIRST_PLAYER_LASER; 59 | 60 | // Create some aliens 61 | 62 | // Create some alien lasers 63 | 64 | return objects; 65 | } 66 | 67 | ArrayList getGameObjects(){ 68 | return objects; 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Chapter 20/java/MovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | interface MovementComponent { 4 | 5 | boolean move(long fps, 6 | Transform t, 7 | Transform playerTransform); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter 20/java/ObjectSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | abstract class ObjectSpec { 6 | 7 | private String mTag; 8 | private String mBitmapName; 9 | private float mSpeed; 10 | private PointF mSizeScale; 11 | private String[] mComponents; 12 | 13 | ObjectSpec(String tag, String bitmapName, 14 | float speed, PointF relativeScale, 15 | String[] components) { 16 | 17 | mTag = tag; 18 | mBitmapName = bitmapName; 19 | mSpeed = speed; 20 | mSizeScale = relativeScale; 21 | mComponents = components; 22 | } 23 | 24 | String getTag() { 25 | return mTag; 26 | } 27 | 28 | String getBitmapName() { 29 | return mBitmapName; 30 | } 31 | 32 | float getSpeed() { 33 | return mSpeed; 34 | } 35 | 36 | PointF getScale() { 37 | return mSizeScale; 38 | } 39 | 40 | String[] getComponents() { 41 | return mComponents; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter 20/java/Particle.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class Particle { 6 | 7 | PointF mVelocity; 8 | PointF mPosition; 9 | 10 | Particle(PointF direction) 11 | { 12 | mVelocity = new PointF(); 13 | mPosition = new PointF(); 14 | 15 | // Determine the direction 16 | mVelocity.x = direction.x; 17 | mVelocity.y = direction.y; 18 | 19 | } 20 | 21 | void update() 22 | { 23 | // Move the particle 24 | mPosition.x += mVelocity.x; 25 | mPosition.y += mVelocity.y; 26 | } 27 | 28 | void setPosition(PointF position) 29 | { 30 | mPosition.x = position.x; 31 | mPosition.y = position.y; 32 | } 33 | 34 | PointF getPosition() 35 | { 36 | return mPosition; 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Chapter 20/java/ParticleSystem.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.PointF; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Random; 9 | 10 | class ParticleSystem { 11 | 12 | float mDuration; 13 | 14 | ArrayList mParticles; 15 | Random random = new Random(); 16 | boolean mIsRunning = false; 17 | 18 | void init(int numParticles){ 19 | 20 | mParticles = new ArrayList<>(); 21 | // Create the particles 22 | 23 | for (int i = 0; i < numParticles; i++) { 24 | float angle = (random.nextInt(360)) ; 25 | angle = angle * 3.14f / 180.f; 26 | float speed = (random.nextInt(20)+1); 27 | 28 | PointF direction; 29 | 30 | direction = new PointF((float)Math.cos(angle) * speed, 31 | (float)Math.sin(angle) * speed); 32 | 33 | mParticles.add(new Particle(direction)); 34 | } 35 | } 36 | void update(long fps){ 37 | 38 | mDuration -= (1f/fps); 39 | 40 | for(Particle p : mParticles){ 41 | p.update(); 42 | } 43 | 44 | if (mDuration < 0) 45 | { 46 | mIsRunning = false; 47 | } 48 | } 49 | 50 | void emitParticles(PointF startPosition){ 51 | 52 | mIsRunning = true; 53 | mDuration = 1f; 54 | 55 | for(Particle p : mParticles){ 56 | p.setPosition(startPosition); 57 | } 58 | } 59 | 60 | void draw(Canvas canvas, Paint paint){ 61 | 62 | for (Particle p : mParticles) { 63 | 64 | paint.setARGB(255, 65 | random.nextInt(256), 66 | random.nextInt(256), 67 | random.nextInt(256)); 68 | 69 | // Uncomment the next line to have plain white particles 70 | //paint.setColor(Color.argb(255,255,255,255)); 71 | canvas.drawRect(p.getPosition().x, 72 | p.getPosition().y, 73 | p.getPosition().x+25, 74 | p.getPosition().y+25, paint); 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Chapter 20/java/PhysicsEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import java.util.ArrayList; 4 | 5 | class PhysicsEngine { 6 | 7 | // This signature and much more will 8 | //change later in the project 9 | boolean update(long fps, ArrayList objects, 10 | GameState gs, SoundEngine se, 11 | ParticleSystem ps){ 12 | 13 | // Update all the GameObjects 14 | for (GameObject object : objects) { 15 | if (object.checkActive()) { 16 | object.update(fps, objects .get(Level.PLAYER_INDEX) 17 | .getTransform()); 18 | } 19 | } 20 | 21 | if(ps.mIsRunning){ 22 | ps.update(fps); 23 | } 24 | 25 | return false; 26 | } 27 | 28 | 29 | // Collision detection method will go here 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /Chapter 20/java/PlayerInputComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | 6 | import java.util.ArrayList; 7 | 8 | class PlayerInputComponent implements InputComponent, 9 | InputObserver { 10 | 11 | private Transform mTransform; 12 | private PlayerLaserSpawner mPLS; 13 | 14 | PlayerInputComponent(GameEngine ger) { 15 | 16 | ger.addObserver(this); 17 | mPLS = ger; 18 | 19 | } 20 | 21 | @Override 22 | public void setTransform(Transform transform) { 23 | mTransform = transform; 24 | 25 | } 26 | 27 | // Required method of InputObserver 28 | // interface called from the onTouchEvent method 29 | @Override 30 | public void handleInput(MotionEvent event, 31 | GameState gameState, 32 | ArrayList buttons) { 33 | 34 | int i = event.getActionIndex(); 35 | int x = (int) event.getX(i); 36 | int y = (int) event.getY(i); 37 | 38 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 39 | 40 | case MotionEvent.ACTION_UP: 41 | if (buttons.get(HUD.UP).contains(x,y) 42 | || buttons.get(HUD.DOWN).contains(x,y)) { 43 | 44 | // Player has released either up or down 45 | mTransform.stopVertical(); 46 | } 47 | break; 48 | 49 | case MotionEvent.ACTION_DOWN: 50 | if (buttons.get(HUD.UP).contains(x,y)) { 51 | // Player has pressed up 52 | mTransform.headUp(); 53 | } else if (buttons.get(HUD.DOWN).contains(x,y)) { 54 | // Player has pressed down 55 | mTransform.headDown(); 56 | } else if (buttons.get(HUD.FLIP).contains(x,y)) { 57 | // Player has released the flip button 58 | mTransform.flip(); 59 | } else if (buttons.get(HUD.SHOOT).contains(x,y)) { 60 | mPLS.spawnPlayerLaser(mTransform); 61 | } 62 | break; 63 | 64 | case MotionEvent.ACTION_POINTER_UP: 65 | if (buttons.get(HUD.UP).contains(x, y) 66 | || 67 | buttons.get(HUD.DOWN).contains(x, y)) { 68 | 69 | // Player has released either up or down 70 | mTransform.stopVertical(); 71 | } 72 | break; 73 | 74 | case MotionEvent.ACTION_POINTER_DOWN: 75 | if (buttons.get(HUD.UP).contains(x, y)) { 76 | // Player has pressed up 77 | mTransform.headUp(); 78 | } else if (buttons.get(HUD.DOWN).contains(x, y)) { 79 | // Player has pressed down 80 | mTransform.headDown(); 81 | } else if (buttons.get(HUD.FLIP).contains(x, y)) { 82 | // Player has released the flip button 83 | mTransform.flip(); 84 | } else if (buttons.get(HUD.SHOOT).contains(x, y)) { 85 | mPLS.spawnPlayerLaser(mTransform); 86 | } 87 | break; 88 | } 89 | 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Chapter 20/java/PlayerLaserSpawner.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface PlayerLaserSpawner { 4 | boolean spawnPlayerLaser(Transform transform); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 20/java/PlayerLaserSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class PlayerLaserSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for a player laser 8 | private static final String tag = "Player Laser"; 9 | private static final String bitmapName = "player_laser"; 10 | private static final float speed = .65f; 11 | private static final PointF relativeScale = 12 | new PointF(8f, 160f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "LaserMovementComponent", 17 | "LaserSpawnComponent"}; 18 | 19 | PlayerLaserSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 20/java/PlayerMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class PlayerMovementComponent implements MovementComponent { 6 | 7 | @Override 8 | public boolean move(long fps, Transform t, 9 | Transform playerTransform){ 10 | // How high is the screen? 11 | float screenHeight = t.getmScreenSize().y; 12 | // Where is the player? 13 | PointF location = t.getLocation(); 14 | // How fast is it going 15 | float speed = t.getSpeed(); 16 | // How tall is the ship 17 | float height = t.getObjectHeight(); 18 | 19 | // Move the ship up or down if needed 20 | if(t.headingDown()){ 21 | location.y += speed / fps; 22 | } 23 | else if(t.headingUp()){ 24 | location.y -= speed / fps; 25 | } 26 | 27 | // Make sure the ship can't go off the screen 28 | if(location.y > screenHeight - height){ 29 | location.y = screenHeight - height; 30 | } 31 | else if(location.y < 0){ 32 | location.y = 0; 33 | } 34 | 35 | // Update the collider 36 | t.updateCollider(); 37 | 38 | 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Chapter 20/java/PlayerSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class PlayerSpawnComponent implements SpawnComponent { 4 | 5 | @Override 6 | public void spawn(Transform playerTransform, Transform t) { 7 | 8 | // Spawn in the centre of the screen 9 | t.setLocation( 10 | t.getmScreenSize().x/2, 11 | t.getmScreenSize().y/2); 12 | 13 | 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Chapter 20/java/PlayerSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class PlayerSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for a player 8 | private static final String tag = "Player"; 9 | private static final String bitmapName = "player_ship"; 10 | private static final float speed = 1f; 11 | private static final PointF relativeScale = 12 | new PointF(15f, 15f); 13 | 14 | private static final String[] components = new String [] { 15 | "PlayerInputComponent", 16 | "StdGraphicsComponent", 17 | "PlayerMovementComponent", 18 | "PlayerSpawnComponent"}; 19 | 20 | PlayerSpec() { 21 | super(tag, bitmapName, 22 | speed, relativeScale, 23 | components); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Chapter 20/java/Renderer.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.view.SurfaceHolder; 7 | import android.view.SurfaceView; 8 | 9 | import java.util.ArrayList; 10 | 11 | class Renderer { 12 | private Canvas mCanvas; 13 | private SurfaceHolder mSurfaceHolder; 14 | private Paint mPaint; 15 | 16 | Renderer(SurfaceView sh){ 17 | mSurfaceHolder = sh.getHolder(); 18 | mPaint = new Paint(); 19 | } 20 | 21 | void draw(ArrayList objects, GameState gs, 22 | HUD hud, ParticleSystem ps) { 23 | 24 | if (mSurfaceHolder.getSurface().isValid()) { 25 | mCanvas = mSurfaceHolder.lockCanvas(); 26 | mCanvas.drawColor(Color.argb(255, 0, 0, 0)); 27 | 28 | if (gs.getDrawing()) { 29 | // Draw all the game objects here 30 | for (GameObject object : objects) { 31 | if(object.checkActive()) { 32 | object.draw(mCanvas, mPaint); 33 | } 34 | } 35 | 36 | } 37 | 38 | if(gs.getGameOver()) { 39 | // Draw just a background graphic here 40 | objects.get(Level.BACKGROUND_INDEX) 41 | .draw(mCanvas, mPaint); 42 | 43 | } 44 | 45 | // Draw a particle system explosion here 46 | if(ps.mIsRunning){ 47 | ps.draw(mCanvas, mPaint); 48 | } 49 | 50 | 51 | // Now we draw the HUD on top of everything else 52 | hud.draw(mCanvas, mPaint, gs); 53 | 54 | mSurfaceHolder.unlockCanvasAndPost(mCanvas); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Chapter 20/java/SoundEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.content.res.AssetManager; 6 | import android.media.AudioAttributes; 7 | import android.media.AudioManager; 8 | import android.media.SoundPool; 9 | import android.os.Build; 10 | 11 | import java.io.IOException; 12 | 13 | class SoundEngine { 14 | // for playing sound effects 15 | private SoundPool mSP; 16 | private int mShoot_ID = -1; 17 | private int mAlien_Explode_ID = -1; 18 | private int mPlayer_explode_ID = -1; 19 | 20 | SoundEngine(Context c){ 21 | // Initialize the SoundPool 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 23 | AudioAttributes audioAttributes = 24 | new AudioAttributes.Builder() 25 | .setUsage(AudioAttributes.USAGE_MEDIA) 26 | .setContentType(AudioAttributes 27 | .CONTENT_TYPE_SONIFICATION) 28 | .build(); 29 | 30 | mSP = new SoundPool.Builder() 31 | .setMaxStreams(5) 32 | .setAudioAttributes(audioAttributes) 33 | .build(); 34 | } else { 35 | mSP = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); 36 | } 37 | try { 38 | AssetManager assetManager = c.getAssets(); 39 | AssetFileDescriptor descriptor; 40 | 41 | // Prepare the sounds in memory 42 | descriptor = assetManager.openFd("shoot.ogg"); 43 | mShoot_ID = mSP.load(descriptor, 0); 44 | 45 | descriptor = assetManager.openFd("alien_explosion.ogg"); 46 | mAlien_Explode_ID = mSP.load(descriptor, 0); 47 | 48 | descriptor = 49 | assetManager.openFd("player_explosion.ogg"); 50 | 51 | mPlayer_explode_ID = mSP.load(descriptor, 0); 52 | 53 | } catch (IOException e) { 54 | // Error 55 | } 56 | 57 | } 58 | 59 | void playShoot(){ 60 | mSP.play(mShoot_ID,1, 1, 0, 0, 1); 61 | } 62 | 63 | void playAlienExplode(){ 64 | mSP.play(mAlien_Explode_ID,1, 1, 0, 0, 1); 65 | } 66 | 67 | void playPlayerExplode(){ 68 | mSP.play(mPlayer_explode_ID,1, 1, 0, 0, 1); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Chapter 20/java/SpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | interface SpawnComponent { 4 | void spawn(Transform playerTransform, Transform t); 5 | 6 | } -------------------------------------------------------------------------------- /Chapter 20/java/StdGraphicsComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Matrix; 8 | import android.graphics.Paint; 9 | import android.graphics.PointF; 10 | 11 | class StdGraphicsComponent implements GraphicsComponent { 12 | 13 | private Bitmap mBitmap; 14 | private Bitmap mBitmapReversed; 15 | 16 | @Override 17 | public void initialize(Context context, 18 | ObjectSpec spec, 19 | PointF objectSize){ 20 | // Make a resource id out of the string of the file name 21 | int resID = context.getResources() 22 | .getIdentifier(spec.getBitmapName(), 23 | "drawable", 24 | context.getPackageName()); 25 | 26 | // Load the bitmap using the id 27 | mBitmap = BitmapFactory.decodeResource( 28 | context.getResources(), resID); 29 | 30 | // Resize the bitmap 31 | mBitmap = Bitmap 32 | .createScaledBitmap(mBitmap, 33 | (int)objectSize.x, 34 | (int)objectSize.y, 35 | false); 36 | 37 | // Create a mirror image of the bitmap if needed 38 | Matrix matrix = new Matrix(); 39 | matrix.setScale(-1, 1); 40 | mBitmapReversed = Bitmap.createBitmap(mBitmap, 41 | 0, 0, 42 | mBitmap.getWidth(), 43 | mBitmap.getHeight(), 44 | matrix, true); 45 | } 46 | 47 | @Override 48 | public void draw(Canvas canvas, 49 | Paint paint, 50 | Transform t) { 51 | 52 | if(t.getFacingRight()) 53 | canvas.drawBitmap(mBitmap, 54 | t.getLocation().x, 55 | t.getLocation().y, 56 | paint); 57 | 58 | else 59 | canvas.drawBitmap(mBitmapReversed, 60 | t.getLocation().x, 61 | t.getLocation().y, 62 | paint); 63 | 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Chapter 20/java/UIController.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | import android.graphics.Point; 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | 6 | import java.util.ArrayList; 7 | 8 | class UIController implements InputObserver { 9 | 10 | public UIController(GameEngineBroadcaster b){ 11 | b.addObserver(this); 12 | } 13 | 14 | @Override 15 | public void handleInput(MotionEvent event, GameState gameState, ArrayList buttons) { 16 | 17 | int i = event.getActionIndex(); 18 | int x = (int) event.getX(i); 19 | int y = (int) event.getY(i); 20 | 21 | int eventType = event.getAction() & MotionEvent.ACTION_MASK; 22 | 23 | if(eventType == MotionEvent.ACTION_UP || 24 | eventType == MotionEvent.ACTION_POINTER_UP) { 25 | 26 | 27 | if (buttons.get(HUD.PAUSE).contains(x, y)){ 28 | // Player pressed the pause button 29 | // Respond differently depending 30 | // upon the game's state 31 | 32 | // If the game is not paused 33 | if (!gameState.getPaused()) { 34 | // Pause the game 35 | gameState.pause(); 36 | } 37 | 38 | // If game is over start a new game 39 | else if (gameState.getGameOver()) { 40 | 41 | gameState.startNewGame(); 42 | } 43 | 44 | // Paused and not game over 45 | else if (gameState.getPaused() 46 | && !gameState.getGameOver()) { 47 | 48 | gameState.resume(); 49 | } 50 | } 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /Chapter 21/assets/alien_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/assets/alien_explosion.ogg -------------------------------------------------------------------------------- /Chapter 21/assets/player_explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/assets/player_explosion.ogg -------------------------------------------------------------------------------- /Chapter 21/assets/shoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/assets/shoot.ogg -------------------------------------------------------------------------------- /Chapter 21/drawable/alien_laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/alien_laser.png -------------------------------------------------------------------------------- /Chapter 21/drawable/alien_ship1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/alien_ship1.png -------------------------------------------------------------------------------- /Chapter 21/drawable/alien_ship2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/alien_ship2.png -------------------------------------------------------------------------------- /Chapter 21/drawable/alien_ship3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/alien_ship3.png -------------------------------------------------------------------------------- /Chapter 21/drawable/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/background.png -------------------------------------------------------------------------------- /Chapter 21/drawable/player_laser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/player_laser.png -------------------------------------------------------------------------------- /Chapter 21/drawable/player_ship.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Learning-Java-by-Building-Android-Games-Third-Edition/9e56a97be80dcca7c697937a046b4a43b250e29f/Chapter 21/drawable/player_ship.png -------------------------------------------------------------------------------- /Chapter 21/java/AlienChaseSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienChaseSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for an alien that chases the player 8 | private static final String tag = "Alien"; 9 | private static final String bitmapName = "alien_ship1"; 10 | private static final float speed = 4f; 11 | private static final PointF relativeScale = 12 | new PointF(15f, 15f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "AlienChaseMovementComponent", 17 | "AlienHorizontalSpawnComponent"}; 18 | 19 | AlienChaseSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienDiverMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | import java.util.Random; 5 | 6 | class AlienDiverMovementComponent implements MovementComponent { 7 | 8 | @Override 9 | public boolean move(long fps, Transform t, Transform playerTransform) { 10 | 11 | // Where is the ship? 12 | PointF location = t.getLocation(); 13 | // How fast is the ship? 14 | float speed = t.getSpeed(); 15 | 16 | // Relative speed difference with player 17 | float slowDownRelativeToPlayer = 1.8f; 18 | 19 | // Compensate for movement relative to player- 20 | // but only when in view. 21 | // Otherwise alien will disappear miles off to one side 22 | if(!playerTransform.getFacingRight()){ 23 | location.x += speed * slowDownRelativeToPlayer / fps; 24 | } else{ 25 | location.x -= speed * slowDownRelativeToPlayer / fps; 26 | } 27 | 28 | // Fall down then respawn at the top 29 | location.y += speed / fps; 30 | 31 | if(location.y > t.getmScreenSize().y){ 32 | // Respawn at top 33 | Random random = new Random(); 34 | location.y = random.nextInt(300) - t.getObjectHeight(); 35 | location.x = random.nextInt((int)t.getmScreenSize().x); 36 | } 37 | 38 | // Update the collider 39 | t.updateCollider(); 40 | 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienDiverSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienDiverSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for an alien that dives 8 | private static final String tag = "Alien"; 9 | private static final String bitmapName = "alien_ship3"; 10 | private static final float speed = 4f; 11 | private static final PointF relativeScale = 12 | new PointF(60f, 30f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "AlienDiverMovementComponent", 17 | "AlienVerticalSpawnComponent"}; 18 | 19 | AlienDiverSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienHorizontalSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | import java.util.Random; 5 | 6 | class AlienHorizontalSpawnComponent implements SpawnComponent { 7 | @Override 8 | public void spawn(Transform playerLTransform, Transform t) { 9 | // Get the screen size 10 | PointF ss = t.getmScreenSize(); 11 | 12 | // Spawn just off screen randomly left or right 13 | Random random = new Random(); 14 | boolean left = random.nextBoolean(); 15 | // How far away? 16 | float distance = random.nextInt(2000) 17 | + t.getmScreenSize().x; 18 | 19 | // Generate a height to spawn at where 20 | // the entire ship is vertically on-screen 21 | float spawnHeight = random.nextFloat() 22 | * ss.y - t.getSize().y; 23 | 24 | // Spawn the ship 25 | if(left){ 26 | t.setLocation(-distance, spawnHeight); 27 | t.headRight(); 28 | }else{ 29 | t.setLocation(distance, spawnHeight); 30 | t.headingLeft(); 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienLaserSpawner.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | // This allows an alien to communicate with the game engine 4 | // and spawn a laser 5 | interface AlienLaserSpawner { 6 | void spawnAlienLaser(Transform transform); 7 | } 8 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienLaserSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienLaserSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for an alien laser 8 | private static final String tag = "Alien Laser"; 9 | private static final String bitmapName = "alien_laser"; 10 | private static final float speed = .75f; 11 | private static final PointF relativeScale = 12 | new PointF(14f, 160f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "LaserMovementComponent", 17 | "LaserSpawnComponent"}; 18 | 19 | AlienLaserSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienPatrolSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class AlienPatrolSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for a patrolling alien 8 | private static final String tag = "Alien"; 9 | private static final String bitmapName = "alien_ship2"; 10 | private static final float speed = 5f; 11 | private static final PointF relativeScale = 12 | new PointF(15f, 15f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "AlienPatrolMovementComponent", 17 | "AlienHorizontalSpawnComponent"}; 18 | 19 | AlienPatrolSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Chapter 21/java/AlienVerticalSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import java.util.Random; 4 | 5 | class AlienVerticalSpawnComponent implements SpawnComponent { 6 | 7 | public void spawn(Transform playerLTransform, Transform t) { 8 | 9 | // Spawn just off screen randomly but 10 | // within the screen width 11 | Random random = new Random(); 12 | float xPosition = random.nextInt((int)t 13 | .getmScreenSize().x); 14 | 15 | // Set the height to vertically 16 | // just above the visible game 17 | float spawnHeight = random 18 | .nextInt(300) - t.getObjectHeight(); 19 | 20 | // Spawn the ship 21 | t.setLocation(xPosition, spawnHeight); 22 | // Always going dowm 23 | t.headDown(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Chapter 21/java/BackgroundGraphicsComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Matrix; 8 | import android.graphics.Paint; 9 | import android.graphics.PointF; 10 | import android.graphics.Rect; 11 | 12 | class BackgroundGraphicsComponent implements GraphicsComponent { 13 | 14 | private Bitmap mBitmap; 15 | private Bitmap mBitmapReversed; 16 | 17 | @Override 18 | public void initialize(Context c, 19 | ObjectSpec s, 20 | PointF objectSize) { 21 | 22 | // Make a resource id out of the string of the file name 23 | int resID = c.getResources() 24 | .getIdentifier(s.getBitmapName(), 25 | "drawable", c.getPackageName()); 26 | 27 | // Load the bitmap using the id 28 | mBitmap = BitmapFactory 29 | .decodeResource(c.getResources(), resID); 30 | 31 | // Resize the bitmap 32 | mBitmap = Bitmap 33 | .createScaledBitmap(mBitmap, 34 | (int)objectSize.x, 35 | (int)objectSize.y, 36 | false); 37 | 38 | // Create a mirror image of the bitmap 39 | Matrix matrix = new Matrix(); 40 | matrix.setScale(-1, 1); 41 | mBitmapReversed = Bitmap 42 | .createBitmap(mBitmap, 43 | 0, 0, 44 | mBitmap.getWidth(), 45 | mBitmap.getHeight(), 46 | matrix, true); 47 | 48 | 49 | } 50 | 51 | @Override 52 | public void draw(Canvas canvas, 53 | Paint paint, 54 | Transform t) { 55 | 56 | int xClip = t.getXClip(); 57 | int width = mBitmap.getWidth(); 58 | int height = mBitmap.getHeight(); 59 | int startY = 0; 60 | int endY = (int)t.getmScreenSize().y +20; 61 | 62 | // For the regular bitmap 63 | Rect fromRect1 = new Rect(0, 0, width - xClip, height); 64 | Rect toRect1 = new Rect(xClip, startY, width, endY); 65 | 66 | // For the reversed background 67 | Rect fromRect2 = new Rect(width - xClip, 0, width, height); 68 | Rect toRect2 = new Rect(0, startY, xClip, endY); 69 | 70 | //draw the two background bitmaps 71 | if (!t.getReversedFirst()) { 72 | canvas.drawBitmap(mBitmap, 73 | fromRect1, toRect1, paint); 74 | 75 | canvas.drawBitmap(mBitmapReversed, 76 | fromRect2, toRect2, paint); 77 | 78 | } else { 79 | canvas.drawBitmap(mBitmap, fromRect2, 80 | toRect2, paint); 81 | 82 | canvas.drawBitmap(mBitmapReversed, 83 | fromRect1, toRect1, paint); 84 | } 85 | 86 | 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /Chapter 21/java/BackgroundMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class BackgroundMovementComponent implements MovementComponent { 4 | @Override 5 | public boolean move(long fps, 6 | Transform t, 7 | Transform playerTransform) { 8 | 9 | int currentXClip = t.getXClip(); 10 | 11 | if(playerTransform.getFacingRight()) { 12 | currentXClip -= t.getSpeed() / fps; 13 | t.setXClip(currentXClip); 14 | } 15 | else { 16 | currentXClip += t.getSpeed() / fps; 17 | t.setXClip(currentXClip); 18 | } 19 | 20 | if (currentXClip >= t.getSize().x) { 21 | t.setXClip(0); 22 | t.flipReversedFirst(); 23 | } 24 | else if (currentXClip <= 0) { 25 | t.setXClip((int)t.getSize().x); 26 | t.flipReversedFirst(); 27 | } 28 | 29 | 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Chapter 21/java/BackgroundSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class BackgroundSpawnComponent implements SpawnComponent { 4 | @Override 5 | public void spawn(Transform playerLTransform, Transform t) { 6 | // Place the background in the top left corner 7 | t.setLocation(0f,0f); 8 | 9 | 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Chapter 21/java/BackgroundSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class BackgroundSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for the background 8 | private static final String tag = "Background"; 9 | private static final String bitmapName = "background"; 10 | private static final float speed = 2f; 11 | private static final PointF relativeScale = 12 | new PointF(1f, 1f); 13 | 14 | private static final String[] components = new String [] { 15 | "BackgroundGraphicsComponent", 16 | "BackgroundMovementComponent", 17 | "BackgroundSpawnComponent"}; 18 | 19 | BackgroundSpec() { 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 21/java/GameActivity.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Point; 5 | import android.os.Bundle; 6 | import android.view.Display; 7 | import android.view.Window; 8 | 9 | public class GameActivity extends Activity { 10 | 11 | GameEngine mGameEngine; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | requestWindowFeature(Window.FEATURE_NO_TITLE); 17 | 18 | Display display = getWindowManager() 19 | .getDefaultDisplay(); 20 | 21 | Point size = new Point(); 22 | display.getSize(size); 23 | mGameEngine = new GameEngine(this, size); 24 | setContentView(mGameEngine); 25 | } 26 | 27 | @Override 28 | protected void onResume() { 29 | super.onResume(); 30 | mGameEngine.startThread(); 31 | } 32 | 33 | @Override 34 | protected void onPause() { 35 | super.onPause(); 36 | mGameEngine.stopThread(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter 21/java/GameEngineBroadcaster.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameEngineBroadcaster { 4 | void addObserver(InputObserver o); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 21/java/GameObject.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.PointF; 7 | 8 | class GameObject { 9 | 10 | private Transform mTransform; 11 | private boolean isActive = false; 12 | private String mTag; 13 | 14 | private GraphicsComponent graphicsComponent; 15 | private MovementComponent movementComponent; 16 | private SpawnComponent spawnComponent; 17 | 18 | void setSpawner(SpawnComponent s) { 19 | spawnComponent = s; 20 | } 21 | 22 | void setGraphics(GraphicsComponent g, Context c, 23 | ObjectSpec spec, PointF objectSize) { 24 | 25 | graphicsComponent = g; 26 | g.initialize(c, spec, objectSize); 27 | } 28 | 29 | void setMovement(MovementComponent m) { 30 | movementComponent = m; 31 | } 32 | 33 | void setInput(InputComponent s) { 34 | s.setTransform(mTransform); 35 | } 36 | 37 | void setmTag(String tag) { 38 | mTag = tag; 39 | } 40 | 41 | void setTransform(Transform t) { 42 | mTransform = t; 43 | } 44 | 45 | void draw(Canvas canvas, Paint paint) { 46 | graphicsComponent.draw(canvas, paint, mTransform); 47 | } 48 | 49 | void update(long fps, Transform playerTransform) { 50 | if (!(movementComponent.move(fps, 51 | mTransform, playerTransform))) { 52 | // Component returned false 53 | isActive = false; 54 | } 55 | } 56 | 57 | boolean spawn(Transform playerTransform) { 58 | // Only spawnComponent if not already active 59 | if (!isActive) { 60 | spawnComponent.spawn(playerTransform, mTransform); 61 | isActive = true; 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | boolean checkActive() { 68 | return isActive; 69 | } 70 | 71 | String getTag() { 72 | return mTag; 73 | } 74 | 75 | void setInactive() { 76 | isActive = false; 77 | } 78 | 79 | Transform getTransform() { 80 | return mTransform; 81 | } 82 | 83 | 84 | 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Chapter 21/java/GameStarter.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface GameStarter { 4 | // This allows the State class to 5 | // spawn and despawn objects via the game engine 6 | 7 | public void deSpawnReSpawn(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Chapter 21/java/GameState.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | final class GameState { 7 | private static volatile boolean mThreadRunning = false; 8 | private static volatile boolean mPaused = true; 9 | private static volatile boolean mGameOver = true; 10 | private static volatile boolean mDrawing = false; 11 | 12 | // This object will have access to the deSpawnReSpawn method 13 | // in GameEngine- once it is initialized 14 | private GameStarter gameStarter; 15 | 16 | private int mScore; 17 | private int mHighScore; 18 | private int mNumShips; 19 | 20 | // This is how we will make all the high scores persist 21 | private SharedPreferences.Editor mEditor; 22 | 23 | GameState(GameStarter gs, Context context){ 24 | // This initializes the gameStarter reference 25 | gameStarter = gs; 26 | 27 | // Get the current high score 28 | SharedPreferences prefs; 29 | prefs = context.getSharedPreferences("HiScore", 30 | Context.MODE_PRIVATE); 31 | 32 | // Initialize the mEditor ready 33 | mEditor = prefs.edit(); 34 | 35 | // Load high score from a entry in the file 36 | // labeled "hiscore" 37 | // if not available highscore set to zero 0 38 | mHighScore = prefs.getInt("hi_score", 0); 39 | } 40 | 41 | private void endGame(){ 42 | mGameOver = true; 43 | mPaused = true; 44 | if(mScore > mHighScore){ 45 | mHighScore = mScore; 46 | // Save high score 47 | mEditor.putInt("hi_score", mHighScore); 48 | mEditor.commit(); 49 | } 50 | } 51 | 52 | void startNewGame(){ 53 | mScore = 0; 54 | mNumShips = 3; 55 | // Don't want to be drawing objects 56 | // while deSpawnReSpawn is 57 | // clearing them and spawning them again 58 | stopDrawing(); 59 | gameStarter.deSpawnReSpawn(); 60 | resume(); 61 | 62 | // Now we can draw again 63 | startDrawing(); 64 | } 65 | 66 | 67 | void loseLife(SoundEngine se){ 68 | mNumShips--; 69 | se.playPlayerExplode(); 70 | if(mNumShips == 0){ 71 | pause(); 72 | endGame(); 73 | } 74 | } 75 | 76 | int getNumShips(){ 77 | return mNumShips; 78 | } 79 | 80 | void increaseScore(){ 81 | mScore++; 82 | } 83 | 84 | int getScore(){ 85 | return mScore; 86 | } 87 | 88 | int getHighScore(){ 89 | return mHighScore; 90 | } 91 | 92 | void pause(){ 93 | mPaused = true; 94 | } 95 | 96 | void resume(){ 97 | mGameOver = false; 98 | mPaused = false; 99 | } 100 | 101 | void stopEverything(){ 102 | mPaused = true; 103 | mGameOver = true; 104 | mThreadRunning = false; 105 | } 106 | 107 | boolean getThreadRunning(){ 108 | return mThreadRunning; 109 | } 110 | 111 | void startThread(){ 112 | mThreadRunning = true; 113 | } 114 | 115 | private void stopDrawing(){ 116 | mDrawing = false; 117 | } 118 | 119 | private void startDrawing(){ 120 | mDrawing = true; 121 | } 122 | 123 | boolean getDrawing() { 124 | return mDrawing; 125 | } 126 | 127 | boolean getPaused(){ 128 | return mPaused; 129 | } 130 | 131 | boolean getGameOver(){ 132 | return mGameOver; 133 | } 134 | 135 | 136 | 137 | } -------------------------------------------------------------------------------- /Chapter 21/java/GraphicsComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.PointF; 7 | 8 | interface GraphicsComponent { 9 | 10 | void initialize(Context c, 11 | ObjectSpec s, 12 | PointF screensize); 13 | 14 | void draw(Canvas canvas, 15 | Paint paint, 16 | Transform t); 17 | } 18 | -------------------------------------------------------------------------------- /Chapter 21/java/InputComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | interface InputComponent { 4 | 5 | void setTransform(Transform t); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /Chapter 21/java/InputObserver.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | import java.util.ArrayList; 6 | 7 | interface InputObserver { 8 | 9 | void handleInput(MotionEvent event, GameState gs, 10 | ArrayList controls); 11 | } 12 | -------------------------------------------------------------------------------- /Chapter 21/java/LaserMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class LaserMovementComponent implements MovementComponent { 6 | 7 | @Override 8 | public boolean move(long fps, 9 | Transform t, 10 | Transform playerTransform) { 11 | 12 | // Laser can only travel two screen widths 13 | float range = t.getmScreenSize().x * 2; 14 | 15 | // Where is the laser 16 | PointF location = t.getLocation(); 17 | 18 | // How fast is it going 19 | float speed = t.getSpeed(); 20 | 21 | if(t.headingRight()){ 22 | location.x += speed / fps; 23 | } 24 | else if(t.headingLeft()){ 25 | location.x -= speed / fps; 26 | } 27 | 28 | // Has the laser gone out of range 29 | if(location.x < - range || location.x > range){ 30 | // disable the laser 31 | return false; 32 | } 33 | 34 | t.updateCollider(); 35 | 36 | 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Chapter 21/java/LaserSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class LaserSpawnComponent implements SpawnComponent { 6 | 7 | @Override 8 | public void spawn(Transform playerTransform, 9 | Transform t) { 10 | 11 | PointF startPosition = 12 | playerTransform.getFiringLocation(t.getSize().x); 13 | 14 | t.setLocation((int)startPosition.x, (int)startPosition.y); 15 | 16 | if(playerTransform.getFacingRight()){ 17 | t.headRight(); 18 | } 19 | else{ 20 | t.headLeft(); 21 | } 22 | 23 | 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Chapter 21/java/Level.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.PointF; 5 | 6 | import java.util.ArrayList; 7 | 8 | class Level { 9 | 10 | // Keep track of specific types 11 | public static final int BACKGROUND_INDEX = 0; 12 | public static final int PLAYER_INDEX = 1; 13 | public static final int FIRST_PLAYER_LASER = 2; 14 | public static final int LAST_PLAYER_LASER = 4; 15 | public static int mNextPlayerLaser; 16 | public static final int FIRST_ALIEN = 5; 17 | public static final int SECOND_ALIEN = 6; 18 | public static final int THIRD_ALIEN = 7; 19 | public static final int FOURTH_ALIEN = 8; 20 | public static final int FIFTH_ALIEN = 9; 21 | public static final int SIXTH_ALIEN = 10; 22 | public static final int LAST_ALIEN = 10; 23 | public static final int FIRST_ALIEN_LASER = 11; 24 | public static final int LAST_ALIEN_LASER = 15; 25 | public static int mNextAlienLaser; 26 | 27 | // This will hold all the instances of GameObject 28 | private ArrayList objects; 29 | public Level(Context context, 30 | PointF mScreenSize, 31 | GameEngine ge){ 32 | 33 | objects = new ArrayList<>(); 34 | GameObjectFactory factory = new GameObjectFactory( 35 | context, mScreenSize, ge); 36 | 37 | buildGameObjects(factory); 38 | } 39 | 40 | ArrayList buildGameObjects( 41 | GameObjectFactory factory){ 42 | 43 | objects.clear(); 44 | objects.add(BACKGROUND_INDEX, factory 45 | .create(new BackgroundSpec())); 46 | 47 | objects.add(PLAYER_INDEX, factory 48 | .create(new PlayerSpec())); 49 | 50 | // Spawn the player's lasers 51 | for (int i = FIRST_PLAYER_LASER; 52 | i != LAST_PLAYER_LASER + 1; i++) { 53 | 54 | objects.add(i, factory 55 | .create(new PlayerLaserSpec())); 56 | } 57 | 58 | mNextPlayerLaser = FIRST_PLAYER_LASER; 59 | 60 | // Create some aliens 61 | objects.add(FIRST_ALIEN, factory 62 | .create(new AlienChaseSpec())); 63 | objects.add(SECOND_ALIEN, factory 64 | .create(new AlienPatrolSpec())); 65 | objects.add(THIRD_ALIEN, factory 66 | .create(new AlienPatrolSpec())); 67 | objects.add(FOURTH_ALIEN, factory 68 | .create(new AlienChaseSpec())); 69 | objects.add(FIFTH_ALIEN, factory 70 | .create(new AlienDiverSpec())); 71 | objects.add(SIXTH_ALIEN, factory 72 | .create(new AlienDiverSpec())); 73 | 74 | // Create some alien lasers 75 | for (int i = FIRST_ALIEN_LASER; i != LAST_ALIEN_LASER + 1; i++) { 76 | objects.add(i, factory 77 | .create(new AlienLaserSpec())); 78 | } 79 | mNextAlienLaser = FIRST_ALIEN_LASER; 80 | 81 | 82 | return objects; 83 | } 84 | 85 | ArrayList getGameObjects(){ 86 | return objects; 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /Chapter 21/java/MovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | interface MovementComponent { 4 | 5 | boolean move(long fps, 6 | Transform t, 7 | Transform playerTransform); 8 | } 9 | -------------------------------------------------------------------------------- /Chapter 21/java/ObjectSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | abstract class ObjectSpec { 6 | 7 | private String mTag; 8 | private String mBitmapName; 9 | private float mSpeed; 10 | private PointF mSizeScale; 11 | private String[] mComponents; 12 | 13 | ObjectSpec(String tag, String bitmapName, 14 | float speed, PointF relativeScale, 15 | String[] components) { 16 | 17 | mTag = tag; 18 | mBitmapName = bitmapName; 19 | mSpeed = speed; 20 | mSizeScale = relativeScale; 21 | mComponents = components; 22 | } 23 | 24 | String getTag() { 25 | return mTag; 26 | } 27 | 28 | String getBitmapName() { 29 | return mBitmapName; 30 | } 31 | 32 | float getSpeed() { 33 | return mSpeed; 34 | } 35 | 36 | PointF getScale() { 37 | return mSizeScale; 38 | } 39 | 40 | String[] getComponents() { 41 | return mComponents; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter 21/java/Particle.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class Particle { 6 | 7 | PointF mVelocity; 8 | PointF mPosition; 9 | 10 | Particle(PointF direction) 11 | { 12 | mVelocity = new PointF(); 13 | mPosition = new PointF(); 14 | 15 | // Determine the direction 16 | mVelocity.x = direction.x; 17 | mVelocity.y = direction.y; 18 | 19 | } 20 | 21 | void update() 22 | { 23 | // Move the particle 24 | mPosition.x += mVelocity.x; 25 | mPosition.y += mVelocity.y; 26 | } 27 | 28 | void setPosition(PointF position) 29 | { 30 | mPosition.x = position.x; 31 | mPosition.y = position.y; 32 | } 33 | 34 | PointF getPosition() 35 | { 36 | return mPosition; 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Chapter 21/java/ParticleSystem.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Paint; 5 | import android.graphics.PointF; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Random; 9 | 10 | class ParticleSystem { 11 | 12 | float mDuration; 13 | 14 | ArrayList mParticles; 15 | Random random = new Random(); 16 | boolean mIsRunning = false; 17 | 18 | void init(int numParticles){ 19 | 20 | mParticles = new ArrayList<>(); 21 | // Create the particles 22 | 23 | for (int i = 0; i < numParticles; i++) { 24 | float angle = (random.nextInt(360)) ; 25 | angle = angle * 3.14f / 180.f; 26 | float speed = (random.nextInt(20)+1); 27 | 28 | PointF direction; 29 | 30 | direction = new PointF((float)Math.cos(angle) * speed, 31 | (float)Math.sin(angle) * speed); 32 | 33 | mParticles.add(new Particle(direction)); 34 | } 35 | } 36 | void update(long fps){ 37 | 38 | mDuration -= (1f/fps); 39 | 40 | for(Particle p : mParticles){ 41 | p.update(); 42 | } 43 | 44 | if (mDuration < 0) 45 | { 46 | mIsRunning = false; 47 | } 48 | } 49 | 50 | void emitParticles(PointF startPosition){ 51 | 52 | mIsRunning = true; 53 | mDuration = 1f; 54 | 55 | for(Particle p : mParticles){ 56 | p.setPosition(startPosition); 57 | } 58 | } 59 | 60 | void draw(Canvas canvas, Paint paint){ 61 | 62 | for (Particle p : mParticles) { 63 | 64 | paint.setARGB(255, 65 | random.nextInt(256), 66 | random.nextInt(256), 67 | random.nextInt(256)); 68 | 69 | // Uncomment the next line to have plain white particles 70 | //paint.setColor(Color.argb(255,255,255,255)); 71 | canvas.drawRect(p.getPosition().x, 72 | p.getPosition().y, 73 | p.getPosition().x+25, 74 | p.getPosition().y+25, paint); 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Chapter 21/java/PhysicsEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | import android.graphics.RectF; 5 | 6 | import java.util.ArrayList; 7 | 8 | class PhysicsEngine { 9 | 10 | // This signature and much more will 11 | //change later in the project 12 | boolean update(long fps, ArrayList objects, 13 | GameState gs, SoundEngine se, 14 | ParticleSystem ps){ 15 | 16 | // Update all the GameObjects 17 | for (GameObject object : objects) { 18 | if (object.checkActive()) { 19 | object.update(fps, objects .get(Level.PLAYER_INDEX) 20 | .getTransform()); 21 | } 22 | } 23 | 24 | if(ps.mIsRunning){ 25 | ps.update(fps); 26 | } 27 | 28 | return detectCollisions(gs, objects, se, ps); 29 | } 30 | 31 | 32 | // Collision detection method will go here 33 | private boolean detectCollisions( 34 | GameState mGameState, 35 | ArrayList objects, 36 | SoundEngine se, 37 | ParticleSystem ps ){ 38 | 39 | boolean playerHit = false; 40 | for(GameObject go1 : objects) { 41 | 42 | if(go1.checkActive()){ 43 | // The ist object is active 44 | // so worth checking 45 | 46 | for(GameObject go2 : objects) { 47 | 48 | if(go2.checkActive()){ 49 | 50 | // The 2nd object is active 51 | // so worth checking 52 | if(RectF.intersects( 53 | go1.getTransform().getCollider(), 54 | go2.getTransform().getCollider())){ 55 | 56 | // switch goes here 57 | // There has been a collision 58 | // - but does it matter 59 | switch (go1.getTag() + " with " + go2.getTag()){ 60 | case "Player with Alien Laser": 61 | playerHit = true; 62 | mGameState.loseLife(se); 63 | 64 | break; 65 | 66 | case "Player with Alien": 67 | playerHit = true; 68 | mGameState.loseLife(se); 69 | 70 | break; 71 | 72 | case "Player Laser with Alien": 73 | mGameState.increaseScore(); 74 | // Respawn the alien 75 | ps.emitParticles( 76 | new PointF( 77 | go2.getTransform().getLocation().x, 78 | go2.getTransform().getLocation().y 79 | 80 | ) 81 | ); 82 | go2.setInactive(); 83 | go2.spawn(objects.get(Level 84 | .PLAYER_INDEX).getTransform()); 85 | 86 | go1.setInactive(); 87 | se.playAlienExplode(); 88 | 89 | break; 90 | 91 | default: 92 | break; 93 | } 94 | 95 | 96 | } 97 | } 98 | } 99 | } 100 | } 101 | return playerHit; 102 | } 103 | 104 | 105 | } 106 | 107 | -------------------------------------------------------------------------------- /Chapter 21/java/PlayerInputComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | 6 | import java.util.ArrayList; 7 | 8 | class PlayerInputComponent implements InputComponent, 9 | InputObserver { 10 | 11 | private Transform mTransform; 12 | private PlayerLaserSpawner mPLS; 13 | 14 | PlayerInputComponent(GameEngine ger) { 15 | 16 | ger.addObserver(this); 17 | mPLS = ger; 18 | 19 | } 20 | 21 | @Override 22 | public void setTransform(Transform transform) { 23 | mTransform = transform; 24 | 25 | } 26 | 27 | // Required method of InputObserver 28 | // interface called from the onTouchEvent method 29 | @Override 30 | public void handleInput(MotionEvent event, 31 | GameState gameState, 32 | ArrayList buttons) { 33 | 34 | int i = event.getActionIndex(); 35 | int x = (int) event.getX(i); 36 | int y = (int) event.getY(i); 37 | 38 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 39 | 40 | case MotionEvent.ACTION_UP: 41 | if (buttons.get(HUD.UP).contains(x,y) 42 | || buttons.get(HUD.DOWN).contains(x,y)) { 43 | 44 | // Player has released either up or down 45 | mTransform.stopVertical(); 46 | } 47 | break; 48 | 49 | case MotionEvent.ACTION_DOWN: 50 | if (buttons.get(HUD.UP).contains(x,y)) { 51 | // Player has pressed up 52 | mTransform.headUp(); 53 | } else if (buttons.get(HUD.DOWN).contains(x,y)) { 54 | // Player has pressed down 55 | mTransform.headDown(); 56 | } else if (buttons.get(HUD.FLIP).contains(x,y)) { 57 | // Player has released the flip button 58 | mTransform.flip(); 59 | } else if (buttons.get(HUD.SHOOT).contains(x,y)) { 60 | mPLS.spawnPlayerLaser(mTransform); 61 | } 62 | break; 63 | 64 | case MotionEvent.ACTION_POINTER_UP: 65 | if (buttons.get(HUD.UP).contains(x, y) 66 | || 67 | buttons.get(HUD.DOWN).contains(x, y)) { 68 | 69 | // Player has released either up or down 70 | mTransform.stopVertical(); 71 | } 72 | break; 73 | 74 | case MotionEvent.ACTION_POINTER_DOWN: 75 | if (buttons.get(HUD.UP).contains(x, y)) { 76 | // Player has pressed up 77 | mTransform.headUp(); 78 | } else if (buttons.get(HUD.DOWN).contains(x, y)) { 79 | // Player has pressed down 80 | mTransform.headDown(); 81 | } else if (buttons.get(HUD.FLIP).contains(x, y)) { 82 | // Player has released the flip button 83 | mTransform.flip(); 84 | } else if (buttons.get(HUD.SHOOT).contains(x, y)) { 85 | mPLS.spawnPlayerLaser(mTransform); 86 | } 87 | break; 88 | } 89 | 90 | 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Chapter 21/java/PlayerLaserSpawner.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | public interface PlayerLaserSpawner { 4 | boolean spawnPlayerLaser(Transform transform); 5 | } 6 | -------------------------------------------------------------------------------- /Chapter 21/java/PlayerLaserSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class PlayerLaserSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for a player laser 8 | private static final String tag = "Player Laser"; 9 | private static final String bitmapName = "player_laser"; 10 | private static final float speed = .65f; 11 | private static final PointF relativeScale = 12 | new PointF(8f, 160f); 13 | 14 | private static final String[] components = new String [] { 15 | "StdGraphicsComponent", 16 | "LaserMovementComponent", 17 | "LaserSpawnComponent"}; 18 | 19 | PlayerLaserSpec(){ 20 | super(tag, bitmapName, 21 | speed, relativeScale, 22 | components); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 21/java/PlayerMovementComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class PlayerMovementComponent implements MovementComponent { 6 | 7 | @Override 8 | public boolean move(long fps, Transform t, 9 | Transform playerTransform){ 10 | // How high is the screen? 11 | float screenHeight = t.getmScreenSize().y; 12 | // Where is the player? 13 | PointF location = t.getLocation(); 14 | // How fast is it going 15 | float speed = t.getSpeed(); 16 | // How tall is the ship 17 | float height = t.getObjectHeight(); 18 | 19 | // Move the ship up or down if needed 20 | if(t.headingDown()){ 21 | location.y += speed / fps; 22 | } 23 | else if(t.headingUp()){ 24 | location.y -= speed / fps; 25 | } 26 | 27 | // Make sure the ship can't go off the screen 28 | if(location.y > screenHeight - height){ 29 | location.y = screenHeight - height; 30 | } 31 | else if(location.y < 0){ 32 | location.y = 0; 33 | } 34 | 35 | // Update the collider 36 | t.updateCollider(); 37 | 38 | 39 | return true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Chapter 21/java/PlayerSpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | class PlayerSpawnComponent implements SpawnComponent { 4 | 5 | @Override 6 | public void spawn(Transform playerTransform, Transform t) { 7 | 8 | // Spawn in the centre of the screen 9 | t.setLocation( 10 | t.getmScreenSize().x/2, 11 | t.getmScreenSize().y/2); 12 | 13 | 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Chapter 21/java/PlayerSpec.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.PointF; 4 | 5 | class PlayerSpec extends ObjectSpec { 6 | // This is all the unique specifications 7 | // for a player 8 | private static final String tag = "Player"; 9 | private static final String bitmapName = "player_ship"; 10 | private static final float speed = 1f; 11 | private static final PointF relativeScale = 12 | new PointF(15f, 15f); 13 | 14 | private static final String[] components = new String [] { 15 | "PlayerInputComponent", 16 | "StdGraphicsComponent", 17 | "PlayerMovementComponent", 18 | "PlayerSpawnComponent"}; 19 | 20 | PlayerSpec() { 21 | super(tag, bitmapName, 22 | speed, relativeScale, 23 | components); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /Chapter 21/java/Renderer.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.graphics.Canvas; 4 | import android.graphics.Color; 5 | import android.graphics.Paint; 6 | import android.view.SurfaceHolder; 7 | import android.view.SurfaceView; 8 | 9 | import java.util.ArrayList; 10 | 11 | class Renderer { 12 | private Canvas mCanvas; 13 | private SurfaceHolder mSurfaceHolder; 14 | private Paint mPaint; 15 | 16 | Renderer(SurfaceView sh){ 17 | mSurfaceHolder = sh.getHolder(); 18 | mPaint = new Paint(); 19 | } 20 | 21 | void draw(ArrayList objects, GameState gs, 22 | HUD hud, ParticleSystem ps) { 23 | 24 | if (mSurfaceHolder.getSurface().isValid()) { 25 | mCanvas = mSurfaceHolder.lockCanvas(); 26 | mCanvas.drawColor(Color.argb(255, 0, 0, 0)); 27 | 28 | if (gs.getDrawing()) { 29 | // Draw all the game objects here 30 | for (GameObject object : objects) { 31 | if(object.checkActive()) { 32 | object.draw(mCanvas, mPaint); 33 | } 34 | } 35 | 36 | } 37 | 38 | if(gs.getGameOver()) { 39 | // Draw just a background graphic here 40 | objects.get(Level.BACKGROUND_INDEX) 41 | .draw(mCanvas, mPaint); 42 | 43 | } 44 | 45 | // Draw a particle system explosion here 46 | if(ps.mIsRunning){ 47 | ps.draw(mCanvas, mPaint); 48 | } 49 | 50 | 51 | // Now we draw the HUD on top of everything else 52 | hud.draw(mCanvas, mPaint, gs); 53 | 54 | mSurfaceHolder.unlockCanvasAndPost(mCanvas); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Chapter 21/java/SoundEngine.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.content.res.AssetManager; 6 | import android.media.AudioAttributes; 7 | import android.media.AudioManager; 8 | import android.media.SoundPool; 9 | import android.os.Build; 10 | 11 | import java.io.IOException; 12 | 13 | class SoundEngine { 14 | // for playing sound effects 15 | private SoundPool mSP; 16 | private int mShoot_ID = -1; 17 | private int mAlien_Explode_ID = -1; 18 | private int mPlayer_explode_ID = -1; 19 | 20 | SoundEngine(Context c){ 21 | // Initialize the SoundPool 22 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 23 | AudioAttributes audioAttributes = 24 | new AudioAttributes.Builder() 25 | .setUsage(AudioAttributes.USAGE_MEDIA) 26 | .setContentType(AudioAttributes 27 | .CONTENT_TYPE_SONIFICATION) 28 | .build(); 29 | 30 | mSP = new SoundPool.Builder() 31 | .setMaxStreams(5) 32 | .setAudioAttributes(audioAttributes) 33 | .build(); 34 | } else { 35 | mSP = new SoundPool(5, AudioManager.STREAM_MUSIC, 0); 36 | } 37 | try { 38 | AssetManager assetManager = c.getAssets(); 39 | AssetFileDescriptor descriptor; 40 | 41 | // Prepare the sounds in memory 42 | descriptor = assetManager.openFd("shoot.ogg"); 43 | mShoot_ID = mSP.load(descriptor, 0); 44 | 45 | descriptor = assetManager.openFd("alien_explosion.ogg"); 46 | mAlien_Explode_ID = mSP.load(descriptor, 0); 47 | 48 | descriptor = 49 | assetManager.openFd("player_explosion.ogg"); 50 | 51 | mPlayer_explode_ID = mSP.load(descriptor, 0); 52 | 53 | } catch (IOException e) { 54 | // Error 55 | } 56 | 57 | } 58 | 59 | void playShoot(){ 60 | mSP.play(mShoot_ID,1, 1, 0, 0, 1); 61 | } 62 | 63 | void playAlienExplode(){ 64 | mSP.play(mAlien_Explode_ID,1, 1, 0, 0, 1); 65 | } 66 | 67 | void playPlayerExplode(){ 68 | mSP.play(mPlayer_explode_ID,1, 1, 0, 0, 1); 69 | } 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Chapter 21/java/SpawnComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | interface SpawnComponent { 4 | void spawn(Transform playerTransform, Transform t); 5 | 6 | } -------------------------------------------------------------------------------- /Chapter 21/java/StdGraphicsComponent.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Canvas; 7 | import android.graphics.Matrix; 8 | import android.graphics.Paint; 9 | import android.graphics.PointF; 10 | 11 | class StdGraphicsComponent implements GraphicsComponent { 12 | 13 | private Bitmap mBitmap; 14 | private Bitmap mBitmapReversed; 15 | 16 | @Override 17 | public void initialize(Context context, 18 | ObjectSpec spec, 19 | PointF objectSize){ 20 | // Make a resource id out of the string of the file name 21 | int resID = context.getResources() 22 | .getIdentifier(spec.getBitmapName(), 23 | "drawable", 24 | context.getPackageName()); 25 | 26 | // Load the bitmap using the id 27 | mBitmap = BitmapFactory.decodeResource( 28 | context.getResources(), resID); 29 | 30 | // Resize the bitmap 31 | mBitmap = Bitmap 32 | .createScaledBitmap(mBitmap, 33 | (int)objectSize.x, 34 | (int)objectSize.y, 35 | false); 36 | 37 | // Create a mirror image of the bitmap if needed 38 | Matrix matrix = new Matrix(); 39 | matrix.setScale(-1, 1); 40 | mBitmapReversed = Bitmap.createBitmap(mBitmap, 41 | 0, 0, 42 | mBitmap.getWidth(), 43 | mBitmap.getHeight(), 44 | matrix, true); 45 | } 46 | 47 | @Override 48 | public void draw(Canvas canvas, 49 | Paint paint, 50 | Transform t) { 51 | 52 | if(t.getFacingRight()) 53 | canvas.drawBitmap(mBitmap, 54 | t.getLocation().x, 55 | t.getLocation().y, 56 | paint); 57 | 58 | else 59 | canvas.drawBitmap(mBitmapReversed, 60 | t.getLocation().x, 61 | t.getLocation().y, 62 | paint); 63 | 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Chapter 21/java/UIController.java: -------------------------------------------------------------------------------- 1 | package com.gamecodeschool.scrollingshooter; 2 | import android.graphics.Point; 3 | import android.graphics.Rect; 4 | import android.view.MotionEvent; 5 | 6 | import java.util.ArrayList; 7 | 8 | class UIController implements InputObserver { 9 | 10 | public UIController(GameEngineBroadcaster b){ 11 | b.addObserver(this); 12 | } 13 | 14 | @Override 15 | public void handleInput(MotionEvent event, GameState gameState, ArrayList buttons) { 16 | 17 | int i = event.getActionIndex(); 18 | int x = (int) event.getX(i); 19 | int y = (int) event.getY(i); 20 | 21 | int eventType = event.getAction() & MotionEvent.ACTION_MASK; 22 | 23 | if(eventType == MotionEvent.ACTION_UP || 24 | eventType == MotionEvent.ACTION_POINTER_UP) { 25 | 26 | 27 | if (buttons.get(HUD.PAUSE).contains(x, y)){ 28 | // Player pressed the pause button 29 | // Respond differently depending 30 | // upon the game's state 31 | 32 | // If the game is not paused 33 | if (!gameState.getPaused()) { 34 | // Pause the game 35 | gameState.pause(); 36 | } 37 | 38 | // If game is over start a new game 39 | else if (gameState.getGameOver()) { 40 | 41 | gameState.startNewGame(); 42 | } 43 | 44 | // Paused and not game over 45 | else if (gameState.getPaused() 46 | && !gameState.getGameOver()) { 47 | 48 | gameState.resume(); 49 | } 50 | } 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------