GAME DEVELOPMENT TUTORIAL: DAY 3-6: COLLISION DETECTION IIi
Welcome to Day 6, the third and final part of the discussion of Collision Detection.
In today's lesson, we will be wrapping up by discussing the following:
In addition, we will be adding a scoring system. For now, each time you hit the enemy, you will gain 1 point.
I am picking up exactly where we left off in Day 5. So if you grab the source code on this page you will be up to speed.
Before we move on, let's see what's coming up.
Day 7: Health System & Death (Dec 21)
Day 8: Enemy AI (Dec 22)
Day 9: Finishing Touches (Dec 23)
Unit 4 will begin on the 24th.
In today's lesson, we will be wrapping up by discussing the following:
- Making the bullets hit the enemy
- Checking for collision between the player and the enemy
In addition, we will be adding a scoring system. For now, each time you hit the enemy, you will gain 1 point.
I am picking up exactly where we left off in Day 5. So if you grab the source code on this page you will be up to speed.
Before we move on, let's see what's coming up.
Day 7: Health System & Death (Dec 21)
Day 8: Enemy AI (Dec 22)
Day 9: Finishing Touches (Dec 23)
Unit 4 will begin on the 24th.
Bullet Collision
The bullets we have created earlier in the tutorial are rectangular. Hence checking collision with them is very easy.
Here's the strategy we will implement:
1. Create a Rectangle object for each bullet in the projectiles ArrayList (which contains our bullets).
2. Create Rectangle objects for each enemy. We do not yet have an ArrayList for these Enemies. We will likely leave the enemies as they are until we move onto Android, because we will be rewriting this code from scratch.
3. While the bullets are on the screen (that is, bullets have an X value of 800 or less), check if their rectangles collide with the Rectangles from step 2.
4. If there is collision, make the bullet disappear.
Here's the strategy we will implement:
1. Create a Rectangle object for each bullet in the projectiles ArrayList (which contains our bullets).
2. Create Rectangle objects for each enemy. We do not yet have an ArrayList for these Enemies. We will likely leave the enemies as they are until we move onto Android, because we will be rewriting this code from scratch.
3. While the bullets are on the screen (that is, bullets have an X value of 800 or less), check if their rectangles collide with the Rectangles from step 2.
4. If there is collision, make the bullet disappear.
1. Creating a Rectangle Object
To create a rectangle for each Projectile object in the ArrayList, open up the Projectile class.
We only need to do a few things. To save time, I will provide the full class code here, and the changes I make will be in bold.
What we will do:
1. Import Rectangle
2. In the variable declaration section, create a new Rectangle
3. Initialize this new Rectangle in the constructor.
4. Update this rectangle's bounds in the update() method.
5. Set this rectangle to null when the bullet is no longer visible.
6. When collision occurs, call checkCollision method, which we will create.
7. Add 1 to the score.
We only need to do a few things. To save time, I will provide the full class code here, and the changes I make will be in bold.
What we will do:
1. Import Rectangle
2. In the variable declaration section, create a new Rectangle
3. Initialize this new Rectangle in the constructor.
4. Update this rectangle's bounds in the update() method.
5. Set this rectangle to null when the bullet is no longer visible.
6. When collision occurs, call checkCollision method, which we will create.
7. Add 1 to the score.
Projectile Class code - Changes in Bold.
package kiloboltgame;
import java.awt.Rectangle;
public class Projectile {
private int x, y, speedX;
private boolean visible;
private Rectangle r;
public Projectile(int startX, int startY){
x = startX;
y = startY;
speedX = 7;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update(){
x += speedX;
r.setBounds(x, y, 10, 5);
if (x > 800){
visible = false;
r = null;
}
if (x < 801){
checkCollision();
}
}
private void checkCollision() {
if(r.intersects(StartingClass.hb.r)){
visible = false;
StartingClass.score += 1;
}
if (r.intersects(StartingClass.hb2.r)){
visible = false;
StartingClass.score += 1;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
import java.awt.Rectangle;
public class Projectile {
private int x, y, speedX;
private boolean visible;
private Rectangle r;
public Projectile(int startX, int startY){
x = startX;
y = startY;
speedX = 7;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update(){
x += speedX;
r.setBounds(x, y, 10, 5);
if (x > 800){
visible = false;
r = null;
}
if (x < 801){
checkCollision();
}
}
private void checkCollision() {
if(r.intersects(StartingClass.hb.r)){
visible = false;
StartingClass.score += 1;
}
if (r.intersects(StartingClass.hb2.r)){
visible = false;
StartingClass.score += 1;
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
}
Fixing the Errors
Once you have updated your Projectile class as above, you will immediately get some errors.
These errors all deal with the StartingClass, so open that up.
1. The first error is with the visibility of hb and hb2. Right now they are both private, so we will change them to public static
As shown below (this is a small chunk of the upper part of StartingClass:
//More Code Precedes
...
public class StartingClass extends Applet implements Runnable, KeyListener {
private static Robot robot;
public static Heliboy hb, hb2;
...
//More Code Follows
These errors all deal with the StartingClass, so open that up.
1. The first error is with the visibility of hb and hb2. Right now they are both private, so we will change them to public static
As shown below (this is a small chunk of the upper part of StartingClass:
//More Code Precedes
...
public class StartingClass extends Applet implements Runnable, KeyListener {
private static Robot robot;
public static Heliboy hb, hb2;
...
//More Code Follows
2. The second error deals with the variable score, which we have not created yet. So we will create it by doing the following:
I. First: Directly below the line public static Heliboy hb, hb2; (or anywhere in the variable declarations section), add the following:
public static int score = 0;
private Font font = new Font(null, Font.BOLD, 30);
This creates the int variable that will store the score and a Font object that will be used to display it.
II. Second: scroll down to the paint method and add the following in BOLD (the last three lines):
@Override
public void paint(Graphics g) {
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
paintTiles(g);
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
g.setColor(Color.YELLOW);
g.fillRect(p.getX(), p.getY(), 10, 5);
}
g.drawImage(currentSprite, robot.getCenterX() - 61,
robot.getCenterY() - 63, this);
g.drawImage(hanim.getImage(), hb.getCenterX() - 48,
hb.getCenterY() - 48, this);
g.drawImage(hanim.getImage(), hb2.getCenterX() - 48,
hb2.getCenterY() - 48, this);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(Integer.toString(score), 740, 30);
}
The first of these will set the font of g (our painting Graphics object) to font which we gave the properties BOLD and size 30.
The second line sets g to white, so that whatever follows it will be done in white (unless it is an image).
The third line draws a String by parsing the integer score as a String object. It does this at the location 740, 30.
With that, we are done with the StartingClass, so close that up.
I. First: Directly below the line public static Heliboy hb, hb2; (or anywhere in the variable declarations section), add the following:
public static int score = 0;
private Font font = new Font(null, Font.BOLD, 30);
This creates the int variable that will store the score and a Font object that will be used to display it.
II. Second: scroll down to the paint method and add the following in BOLD (the last three lines):
@Override
public void paint(Graphics g) {
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
paintTiles(g);
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
g.setColor(Color.YELLOW);
g.fillRect(p.getX(), p.getY(), 10, 5);
}
g.drawImage(currentSprite, robot.getCenterX() - 61,
robot.getCenterY() - 63, this);
g.drawImage(hanim.getImage(), hb.getCenterX() - 48,
hb.getCenterY() - 48, this);
g.drawImage(hanim.getImage(), hb2.getCenterX() - 48,
hb2.getCenterY() - 48, this);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(Integer.toString(score), 740, 30);
}
The first of these will set the font of g (our painting Graphics object) to font which we gave the properties BOLD and size 30.
The second line sets g to white, so that whatever follows it will be done in white (unless it is an image).
The third line draws a String by parsing the integer score as a String object. It does this at the location 740, 30.
With that, we are done with the StartingClass, so close that up.
2. Creating Rectangles for the Enemy
We are still getting errors in the Projectile class, but that's okay. They will be gone after we make some changes to the Enemy class.
Recall that we created Heliboy objects by extending (inheritance) the Enemy class. Therefore whatever changes we make in the Enemy class will effect change for the Heliboy objects.
The goal is to create a bounding rectangle for each Enemy. As with tiles, we will only be checking those enemies that are in the yellowRed rectangle (the region of 25 tiles neighboring the robot). If any part of the robot (which is contained in the rectangles labeled rect, rect2, rect3, and rect4) hits the enemy, we will print "collision" to the console.
We will make three main changes to this class:
1. Create a Rectangle object called r.
2. Update this Rectangle's bounds in the update() method.
3. Create a method to checkCollision.
Look below for the changes:
Recall that we created Heliboy objects by extending (inheritance) the Enemy class. Therefore whatever changes we make in the Enemy class will effect change for the Heliboy objects.
The goal is to create a bounding rectangle for each Enemy. As with tiles, we will only be checking those enemies that are in the yellowRed rectangle (the region of 25 tiles neighboring the robot). If any part of the robot (which is contained in the rectangles labeled rect, rect2, rect3, and rect4) hits the enemy, we will print "collision" to the console.
We will make three main changes to this class:
1. Create a Rectangle object called r.
2. Update this Rectangle's bounds in the update() method.
3. Create a method to checkCollision.
Look below for the changes:
Enemy Class - Changes in Bold
package kiloboltgame;
import java.awt.Rectangle;
public class Enemy {
private int maxHealth, currentHealth, power, speedX, centerX, centerY;
private Background bg = StartingClass.getBg1();
public Rectangle r = new Rectangle(0,0,0,0);
// Behavioral Methods
public void update() {
centerX += speedX;
speedX = bg.getSpeedX()*5;
r.setBounds(centerX - 25, centerY-25, 50, 60);
if (r.intersects(Robot.yellowRed)){
checkCollision();
}
}
private void checkCollision() {
if (r.intersects(Robot.rect) || r.intersects(Robot.rect2) || r.intersects(Robot.rect3) || r.intersects(Robot.rect4)){
System.out.println("collision");
}
}
public void die() {
}
public void attack() {
}
public int getMaxHealth() {
return maxHealth;
}
public int getCurrentHealth() {
return currentHealth;
}
public int getPower() {
return power;
}
public int getSpeedX() {
return speedX;
}
public int getCenterX() {
return centerX;
}
public int getCenterY() {
return centerY;
}
public Background getBg() {
return bg;
}
public void setMaxHealth(int maxHealth) {
this.maxHealth = maxHealth;
}
public void setCurrentHealth(int currentHealth) {
this.currentHealth = currentHealth;
}
public void setPower(int power) {
this.power = power;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setCenterX(int centerX) {
this.centerX = centerX;
}
public void setCenterY(int centerY) {
this.centerY = centerY;
}
public void setBg(Background bg) {
this.bg = bg;
}
}
import java.awt.Rectangle;
public class Enemy {
private int maxHealth, currentHealth, power, speedX, centerX, centerY;
private Background bg = StartingClass.getBg1();
public Rectangle r = new Rectangle(0,0,0,0);
// Behavioral Methods
public void update() {
centerX += speedX;
speedX = bg.getSpeedX()*5;
r.setBounds(centerX - 25, centerY-25, 50, 60);
if (r.intersects(Robot.yellowRed)){
checkCollision();
}
}
private void checkCollision() {
if (r.intersects(Robot.rect) || r.intersects(Robot.rect2) || r.intersects(Robot.rect3) || r.intersects(Robot.rect4)){
System.out.println("collision");
}
}
public void die() {
}
public void attack() {
}
public int getMaxHealth() {
return maxHealth;
}
public int getCurrentHealth() {
return currentHealth;
}
public int getPower() {
return power;
}
public int getSpeedX() {
return speedX;
}
public int getCenterX() {
return centerX;
}
public int getCenterY() {
return centerY;
}
public Background getBg() {
return bg;
}
public void setMaxHealth(int maxHealth) {
this.maxHealth = maxHealth;
}
public void setCurrentHealth(int currentHealth) {
this.currentHealth = currentHealth;
}
public void setPower(int power) {
this.power = power;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setCenterX(int centerX) {
this.centerX = centerX;
}
public void setCenterY(int centerY) {
this.centerY = centerY;
}
public void setBg(Background bg) {
this.bg = bg;
}
}
In today's lesson, we modified three classes: StartingClass, Projectile, and Enemy.
The full source code for the Projectile and Enemy are above, so I will provide the StartingClass below:
The full source code for the Projectile and Enemy are above, so I will provide the StartingClass below:
StartingClass, end of Day 6 (NOT SYNTAX HIGHLIGHTED DUE TO LIMITATIONS IN LENGTH)
package kiloboltgame;
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import kiloboltgame.framework.Animation;
public class StartingClass extends Applet implements Runnable, KeyListener {
private static Robot robot;
public static Heliboy hb, hb2;
public static int score = 0;
private Font font = new Font(null, Font.BOLD, 30);
private Image image, currentSprite, character, character2, character3,
characterDown, characterJumped, background, heliboy, heliboy2,
heliboy3, heliboy4, heliboy5;
public static Image tilegrassTop, tilegrassBot, tilegrassLeft,
tilegrassRight, tiledirt;
private Graphics second;
private URL base;
private static Background bg1, bg2;
private Animation anim, hanim;
private ArrayList<Tile> tilearray = new ArrayList<Tile>();
@Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Q-Bot Alpha");
try {
base = getDocumentBase();
} catch (Exception e) {
// TODO: handle exception
}
// Image Setups
character = getImage(base, "data/character.png");
character2 = getImage(base, "data/character2.png");
character3 = getImage(base, "data/character3.png");
characterDown = getImage(base, "data/down.png");
characterJumped = getImage(base, "data/jumped.png");
heliboy = getImage(base, "data/heliboy.png");
heliboy2 = getImage(base, "data/heliboy2.png");
heliboy3 = getImage(base, "data/heliboy3.png");
heliboy4 = getImage(base, "data/heliboy4.png");
heliboy5 = getImage(base, "data/heliboy5.png");
background = getImage(base, "data/background.png");
tiledirt = getImage(base, "data/tiledirt.png");
tilegrassTop = getImage(base, "data/tilegrasstop.png");
tilegrassBot = getImage(base, "data/tilegrassbot.png");
tilegrassLeft = getImage(base, "data/tilegrassleft.png");
tilegrassRight = getImage(base, "data/tilegrassright.png");
anim = new Animation();
anim.addFrame(character, 1250);
anim.addFrame(character2, 50);
anim.addFrame(character3, 50);
anim.addFrame(character2, 50);
hanim = new Animation();
hanim.addFrame(heliboy, 100);
hanim.addFrame(heliboy2, 100);
hanim.addFrame(heliboy3, 100);
hanim.addFrame(heliboy4, 100);
hanim.addFrame(heliboy5, 100);
hanim.addFrame(heliboy4, 100);
hanim.addFrame(heliboy3, 100);
hanim.addFrame(heliboy2, 100);
currentSprite = anim.getImage();
}
@Override
public void start() {
bg1 = new Background(0, 0);
bg2 = new Background(2160, 0);
robot = new Robot();
// Initialize Tiles
try {
loadMap("data/map1.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
hb = new Heliboy(340, 360);
hb2 = new Heliboy(700, 360);
Thread thread = new Thread(this);
thread.start();
}
private void loadMap(String filename) throws IOException {
ArrayList lines = new ArrayList();
int width = 0;
int height = 0;
BufferedReader reader = new BufferedReader(new FileReader(filename));
while (true) {
String line = reader.readLine();
// no more lines to read
if (line == null) {
reader.close();
break;
}
if (!line.startsWith("!")) {
lines.add(line);
width = Math.max(width, line.length());
}
}
height = lines.size();
for (int j = 0; j < 12; j++) {
String line = (String) lines.get(j);
for (int i = 0; i < width; i++) {
if (i < line.length()) {
char ch = line.charAt(i);
Tile t = new Tile(i, j, Character.getNumericValue(ch));
tilearray.add(t);
}
}
}
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void run() {
while (true) {
robot.update();
if (robot.isJumped()) {
currentSprite = characterJumped;
} else if (robot.isJumped() == false && robot.isDucked() == false) {
currentSprite = anim.getImage();
}
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
if (p.isVisible() == true) {
p.update();
} else {
projectiles.remove(i);
}
}
updateTiles();
hb.update();
hb2.update();
bg1.update();
bg2.update();
animate();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void animate() {
anim.update(10);
hanim.update(50);
}
@Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
@Override
public void paint(Graphics g) {
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
paintTiles(g);
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
g.setColor(Color.YELLOW);
g.fillRect(p.getX(), p.getY(), 10, 5);
}
g.drawImage(currentSprite, robot.getCenterX() - 61,
robot.getCenterY() - 63, this);
g.drawImage(hanim.getImage(), hb.getCenterX() - 48,
hb.getCenterY() - 48, this);
g.drawImage(hanim.getImage(), hb2.getCenterX() - 48,
hb2.getCenterY() - 48, this);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(Integer.toString(score), 740, 30);
}
private void updateTiles() {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
t.update();
}
}
private void paintTiles(Graphics g) {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
g.drawImage(t.getTileImage(), t.getTileX(), t.getTileY(), this);
}
}
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Move up");
break;
case KeyEvent.VK_DOWN:
currentSprite = characterDown;
if (robot.isJumped() == false) {
robot.setDucked(true);
robot.setSpeedX(0);
}
break;
case KeyEvent.VK_LEFT:
robot.moveLeft();
robot.setMovingLeft(true);
break;
case KeyEvent.VK_RIGHT:
robot.moveRight();
robot.setMovingRight(true);
break;
case KeyEvent.VK_SPACE:
robot.jump();
break;
case KeyEvent.VK_CONTROL:
if (robot.isDucked() == false && robot.isJumped() == false
&& robot.isReadyToFire()) {
robot.shoot();
robot.setReadyToFire(false);
}
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Stop moving up");
break;
case KeyEvent.VK_DOWN:
currentSprite = anim.getImage();
robot.setDucked(false);
break;
case KeyEvent.VK_LEFT:
robot.stopLeft();
break;
case KeyEvent.VK_RIGHT:
robot.stopRight();
break;
case KeyEvent.VK_SPACE:
break;
case KeyEvent.VK_CONTROL:
robot.setReadyToFire(true);
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public static Background getBg1() {
return bg1;
}
public static Background getBg2() {
return bg2;
}
public static Robot getRobot() {
return robot;
}
}
import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import kiloboltgame.framework.Animation;
public class StartingClass extends Applet implements Runnable, KeyListener {
private static Robot robot;
public static Heliboy hb, hb2;
public static int score = 0;
private Font font = new Font(null, Font.BOLD, 30);
private Image image, currentSprite, character, character2, character3,
characterDown, characterJumped, background, heliboy, heliboy2,
heliboy3, heliboy4, heliboy5;
public static Image tilegrassTop, tilegrassBot, tilegrassLeft,
tilegrassRight, tiledirt;
private Graphics second;
private URL base;
private static Background bg1, bg2;
private Animation anim, hanim;
private ArrayList<Tile> tilearray = new ArrayList<Tile>();
@Override
public void init() {
setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
addKeyListener(this);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Q-Bot Alpha");
try {
base = getDocumentBase();
} catch (Exception e) {
// TODO: handle exception
}
// Image Setups
character = getImage(base, "data/character.png");
character2 = getImage(base, "data/character2.png");
character3 = getImage(base, "data/character3.png");
characterDown = getImage(base, "data/down.png");
characterJumped = getImage(base, "data/jumped.png");
heliboy = getImage(base, "data/heliboy.png");
heliboy2 = getImage(base, "data/heliboy2.png");
heliboy3 = getImage(base, "data/heliboy3.png");
heliboy4 = getImage(base, "data/heliboy4.png");
heliboy5 = getImage(base, "data/heliboy5.png");
background = getImage(base, "data/background.png");
tiledirt = getImage(base, "data/tiledirt.png");
tilegrassTop = getImage(base, "data/tilegrasstop.png");
tilegrassBot = getImage(base, "data/tilegrassbot.png");
tilegrassLeft = getImage(base, "data/tilegrassleft.png");
tilegrassRight = getImage(base, "data/tilegrassright.png");
anim = new Animation();
anim.addFrame(character, 1250);
anim.addFrame(character2, 50);
anim.addFrame(character3, 50);
anim.addFrame(character2, 50);
hanim = new Animation();
hanim.addFrame(heliboy, 100);
hanim.addFrame(heliboy2, 100);
hanim.addFrame(heliboy3, 100);
hanim.addFrame(heliboy4, 100);
hanim.addFrame(heliboy5, 100);
hanim.addFrame(heliboy4, 100);
hanim.addFrame(heliboy3, 100);
hanim.addFrame(heliboy2, 100);
currentSprite = anim.getImage();
}
@Override
public void start() {
bg1 = new Background(0, 0);
bg2 = new Background(2160, 0);
robot = new Robot();
// Initialize Tiles
try {
loadMap("data/map1.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
hb = new Heliboy(340, 360);
hb2 = new Heliboy(700, 360);
Thread thread = new Thread(this);
thread.start();
}
private void loadMap(String filename) throws IOException {
ArrayList lines = new ArrayList();
int width = 0;
int height = 0;
BufferedReader reader = new BufferedReader(new FileReader(filename));
while (true) {
String line = reader.readLine();
// no more lines to read
if (line == null) {
reader.close();
break;
}
if (!line.startsWith("!")) {
lines.add(line);
width = Math.max(width, line.length());
}
}
height = lines.size();
for (int j = 0; j < 12; j++) {
String line = (String) lines.get(j);
for (int i = 0; i < width; i++) {
if (i < line.length()) {
char ch = line.charAt(i);
Tile t = new Tile(i, j, Character.getNumericValue(ch));
tilearray.add(t);
}
}
}
}
@Override
public void stop() {
// TODO Auto-generated method stub
}
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void run() {
while (true) {
robot.update();
if (robot.isJumped()) {
currentSprite = characterJumped;
} else if (robot.isJumped() == false && robot.isDucked() == false) {
currentSprite = anim.getImage();
}
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
if (p.isVisible() == true) {
p.update();
} else {
projectiles.remove(i);
}
}
updateTiles();
hb.update();
hb2.update();
bg1.update();
bg2.update();
animate();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void animate() {
anim.update(10);
hanim.update(50);
}
@Override
public void update(Graphics g) {
if (image == null) {
image = createImage(this.getWidth(), this.getHeight());
second = image.getGraphics();
}
second.setColor(getBackground());
second.fillRect(0, 0, getWidth(), getHeight());
second.setColor(getForeground());
paint(second);
g.drawImage(image, 0, 0, this);
}
@Override
public void paint(Graphics g) {
g.drawImage(background, bg1.getBgX(), bg1.getBgY(), this);
g.drawImage(background, bg2.getBgX(), bg2.getBgY(), this);
paintTiles(g);
ArrayList projectiles = robot.getProjectiles();
for (int i = 0; i < projectiles.size(); i++) {
Projectile p = (Projectile) projectiles.get(i);
g.setColor(Color.YELLOW);
g.fillRect(p.getX(), p.getY(), 10, 5);
}
g.drawImage(currentSprite, robot.getCenterX() - 61,
robot.getCenterY() - 63, this);
g.drawImage(hanim.getImage(), hb.getCenterX() - 48,
hb.getCenterY() - 48, this);
g.drawImage(hanim.getImage(), hb2.getCenterX() - 48,
hb2.getCenterY() - 48, this);
g.setFont(font);
g.setColor(Color.WHITE);
g.drawString(Integer.toString(score), 740, 30);
}
private void updateTiles() {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
t.update();
}
}
private void paintTiles(Graphics g) {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
g.drawImage(t.getTileImage(), t.getTileX(), t.getTileY(), this);
}
}
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Move up");
break;
case KeyEvent.VK_DOWN:
currentSprite = characterDown;
if (robot.isJumped() == false) {
robot.setDucked(true);
robot.setSpeedX(0);
}
break;
case KeyEvent.VK_LEFT:
robot.moveLeft();
robot.setMovingLeft(true);
break;
case KeyEvent.VK_RIGHT:
robot.moveRight();
robot.setMovingRight(true);
break;
case KeyEvent.VK_SPACE:
robot.jump();
break;
case KeyEvent.VK_CONTROL:
if (robot.isDucked() == false && robot.isJumped() == false
&& robot.isReadyToFire()) {
robot.shoot();
robot.setReadyToFire(false);
}
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
System.out.println("Stop moving up");
break;
case KeyEvent.VK_DOWN:
currentSprite = anim.getImage();
robot.setDucked(false);
break;
case KeyEvent.VK_LEFT:
robot.stopLeft();
break;
case KeyEvent.VK_RIGHT:
robot.stopRight();
break;
case KeyEvent.VK_SPACE:
break;
case KeyEvent.VK_CONTROL:
robot.setReadyToFire(true);
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public static Background getBg1() {
return bg1;
}
public static Background getBg2() {
return bg2;
}
public static Robot getRobot() {
return robot;
}
}
That's it for today! Thank you for reading, and stay tuned! By this time next week, you will be almost done with porting this game to Android!
|
|

unit3day6corrected.zip | |
File Size: | 398 kb |
File Type: | zip |