Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 7 – Collision Detection: Asteroids

Similar presentations


Presentation on theme: "Chapter 7 – Collision Detection: Asteroids"— Presentation transcript:

1 Chapter 7 – Collision Detection: Asteroids

2 The Asteroids Game

3 We handle a “space” input and call the fire() method.
How Are Bullets Fired? We handle a “space” input and call the fire() method.

4 How Are Asteroids Created?
We call the addAsteroids() method in the Space constructor

5 What does an Explosion do?
Placing an Explosion object creates the Explosion Visual and makes an Explosion Sound.

6 What does a Proton Wave do?
Placing a ProtonWave object has no effect except a ProtonWave visual.

7 What does the Counter do?
Apparently nothing No effect except a ProtonWave visual.

8 What is currently NOT coded?
When experimenting with the current scenario, you will notice that some fundamental functionality is missing. The rocket does not move. It cannot be turned, nor can it be moved forward. Nothing happens when an asteroid collides with the rocket. It flies straight through it, instead of damaging the rocket. As a result of this, you cannot lose. The game never ends, and a final score is never displayed. The ScoreBoard, Explosion, and ProtonWave classes, which we can see in the class diagram, do not seem to feature in the scenario.

9 What should be coded? Controls for the Rocket
Collision: Asteroid vs. Rocket Explosion Logic ScoreBoard/Counter Logic ProtonWave Logic

10 Turning the Rocket We want to make the rocket turn left or right using the left and right arrow keys.

11 The method checkKeys handles keyboard input
Handling Key Presses /* * Check whether there are any key pressed and react to them. */ private void checkKeys() { if (Greenfoot.isKeyDown("space")) fire(); } The method checkKeys handles keyboard input

12 Actor Class Methods

13 Turning the Rocket if (Greenfoot.isKeyDown("left"))
setRotation(getRotation() - 5); if (Greenfoot.isKeyDown("right")) setRotation(getRotation() + 5); Left: Negative Degrees Right: Positive Degrees

14 If left arrow key is down rotate left 5 degrees
Turning the Rocket /* * Check whether there are any key pressed and react to them. */ private void checkKeys() { if (Greenfoot.isKeyDown ("space")) fire(); } if (Greenfoot.isKeyDown ("left")) setRotation (getRotation() - 5); If left arrow key is down rotate left 5 degrees

15 Turning the Rocket

16 If right arrow key is down rotate right 5 degrees
Turning the Rocket /* * Check whether there are any key pressed and react to them. */ private void checkKeys() { if (Greenfoot.isKeyDown("space")) fire(); } if (Greenfoot.isKeyDown ("left")) setRotation (getRotation() - 5); if (Greenfoot.isKeyDown ("right")) setRotation (getRotation() + 5); If right arrow key is down rotate right 5 degrees

17 Turning the Rocket

18 Flying Forward Our Rocket class is a subclass of the SmoothMover class. This means that it holds a movement vector that determines its movement and that it has a move () method that makes it move according to this vector

19 Flying Forward The rocket does not move because we did not specify a movement vector yet.

20 Add an initial movement to the rocket constructor.
Flying Forward /* * Initialize this rocket. */ public Rocket() { reloadDelayCount = 5; addForce ( new Vector (13, 0.3)); //initially slow drifting } Add an initial movement to the rocket constructor.

21 Flying Forward /* * Do what a rocket's gotta do. (Which is: mostly
* flying about, and turning, * accelerating and shooting when the right keys are pressed.) */ public void act() { move (); checkKeys(); reloadDelayCount++; } Add the move () method

22 The rocket drifts slowly toward the right of the World
Flying Forward The rocket drifts slowly toward the right of the World

23 Ignite the Engines Ignite Algorithm
1) If “up” arrow key is pressed then 1.1) change image to show engine fire 1.2) add movement 2) If “up” arrow key is released then 2.1) change back to normal rocket image

24 Define a stub method for ignite
Ignite the Engines Define a stub method for ignite /* * Go with thrust on */ private void ignite (boolean boosterOn) { }

25 Ignite the Engines A boolean parameter /* * Go with thrust on */
private void ignite (boolean boosterOn) { if (boosterOn) setImage (rocketWithThrust); addForce (new Vector (getRotation(), 0.3)); } else setImage (rocket);

26 Ignite the Engines /* * Check whether there are any key pressed and react to them. */ private void checkKeys() { if (Greenfoot.isKeyDown("space")) fire(); ignite (Greenfoot.isKeyDown ("up")); if (Greenfoot.isKeyDown("left")) setRotation(getRotation() - 5); if (Greenfoot.isKeyDown("right")) setRotation(getRotation() + 5 } Add a call to ignite

27 Flying Forward

28 Colliding with Asteroids
Colliding Algorithm 1) If we have collided with an asteroid then 1.1) remove the rocket from the world 1.2) place an explosion into the world 1.3) show final score (game over)

29 Colliding with Asteroids
Define a stub method for checkCollision /* * Check for a collision with an Asteroid */ private void checkCollision() { }

30 Colliding with Asteroids
/* * Do what a rocket's gotta do. (Which is: mostly flying about, and turning, * accelerating and shooting when the right keys are pressed.) */ public void act() { move (); checkKeys(); checkCollision(); reloadDelayCount++; } Make a call to checkCollision from the Rocket Act method

31 Intersecting Objects Bounding Box Visible Image Intersection

32 Intersecting Objects Methods
List getIntersectingObjects (Class cls) Actor getOneIntersectingObject (Class cls) Intersection Bounding Boxes Visible Image

33 getOneIntersectingObject()
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); } Even though we can specify what class we are looking for, the method always returns an Actor object

34 getOneIntersectingObject()
/* * Check for a collision with an Asteroid */ private void checkCollision() { Asteroid a = (Asteroid) getOneIntersectingObject (Asteroid.class); } However, we can re-interpret the returned Actor to a more specific class via a process called “Casting”. More on that later.

35 getOneIntersectingObject()
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); if (a != null) } We have a collision if: a is not “null”, meaning if the getOneIntersectingObject has returned something

36 Colliding with Asteroids
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); if (a != null) World space = getWorld(); space.removeObject (this); space.addObject (new Explosion(), getX(), getY()); } Adding the Explosion and removing the Rocket has to be done via World-methods.

37 Colliding with Asteroids
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); if (a != null) World space = getWorld(); space.addObject (new Explosion(), getX(), getY()); space.removeObject (this); } The sequence of commands is very important when removing objects!

38 Colliding with Asteroids

39 Game Over After a collision, we want to show a ScoreBoard object in the middle of the Level

40 Game Over Method in the Space class
/* * This method is called when the game is over to display the final score. */ public void gameOver() { // TODO: show the score board here. Currently missing. }

41 ScoreBoard /* * Create a score board with dummy result for testing. */
public ScoreBoard() { this(100); } * Create a score board for the final result. public ScoreBoard(int score) makeImage("Game Over", "Score: ", score); The ScoreBoard class has two constructors, a Default Constructor and a second Constructor with parameters

42 Game Over /* * This method is called when the game is over to display the final score. */ public void gameOver() { addObject(new ScoreBoard(999), getWidth()/2, getHeight()/2); } Making sure that the Game Over screen appears right in the middle of the screen.

43 Game Over

44 Colliding with Asteroids II
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); if (a != null) World space = getWorld(); space.addObject (new Explosion(), getX(), getY()); space.removeObject (this); space.gameOver(); } Why does this code produce an error?

45 Colliding with Asteroids II
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); if (a != null) World space = getWorld(); space.addObject (new Explosion(), getX(), getY()); space.removeObject (this); space.gameOver(); } The gameOver() method is a method of the Space class. Our Compiler cannot find it in the World class. Thus, we cannot call it from objects of type World!

46 Colliding with Asteroids II
/* * Check for a collision with an Asteroid */ private void checkCollision() { Actor a = getOneIntersectingObject (Asteroid.class); if (a != null) Space space = (Space) getWorld(); space.addObject (new Explosion(), getX(), getY()); space.removeObject (this); space.gameOver(); } We can use Casting to specify that the object returned by the getWorld() method is not only a World object, but actually an object of the more specific Subclass Space. This does NOT change the actual type of the object, it only changes the information available to our program.

47 Painting Stars The Asteroid Scenario does not use an image file for the background. Instead, the background image is generated directly in the Constructor.

48 The Background is Created by These Three Statements.
Painting Stars The Background is Created by These Three Statements.

49 Code to Create the Background is Commented Out
Painting Stars Code to Create the Background is Commented Out

50 No Background

51 The GreenfootImage Class
Draw Line Draw Oval Draw Rectangle Fill Oval

52 Point Coordinates in Greenfoot
Each point of a World object can be identified using a Cartesian coordinate system The origin of the coordinate system (i.e. the point (0,0) ) is in the top-left corner

53 Drawing A Line drawLine(10, 20, 150, 45); or

54 Drawing A Rectangle drawRect (50, 20, 100, 40);

55 Drawing An Oval drawOval (175, 20, 50, 80);

56 Filling an Oval fillOval (175, 20, 50, 80);

57 Method to create stars /*
* Method to create stars. The integer number is how many. */ private void createStars(int number) { GreenfootImage background = getBackground(); for (int i = 0; i < number; i++) { } We want to draw a set amount of stars. This means that our new methods requires a parameter.

58 Method to create stars /*
* Method to create stars. The integer number is how many. */ private void createStars(int number) { GreenfootImage background = getBackground(); for (int i = 0; i < number; i++) { int x = Greenfoot.getRandomNumber( getWidth() ); int y = Greenfoot.getRandomNumber( getHeight() ); background.setColor (new Color(255, 255, 255)); background.fillOval(x, y, 2, 2); } Note the sequencing: We first specify the color, then what we want to draw in said color. Also note how we apply the operations to a specific image, using dot notation.

59 Calling the createStars methods in the Space constructor
Painting Stars Calling the createStars methods in the Space constructor

60 Painting Stars

61 Painting Stars With Random Brightness
/* * Method to create stars. The integer number is how many. */ private void createStars(int number) { GreenfootImage background = getBackground(); for (int i = 0; i < number; i++) int x = Greenfoot.getRandomNumber( getWidth() ); int y = Greenfoot.getRandomNumber( getHeight() ); int color = Greenfoot.getRandomNumber (256); background.setColor(new Color(color, color, color)); background.fillOval(x, y, 2, 2); } Generate a random number for color in the range 0 to 255 Will be more or less bright, but always on the white-black spectrum

62 Painting Stars With Random Brightness

63 Adding Fire Power: The Proton Wave
The idea is this: Our proton wave, once released, radiates outward from our rocket, damaging or destroying every asteroid in its path. Since it works in all directions simultaneously, it is a much more powerful weapon than our bullets.

64 The Proton Wave Does not Move Does not Disappear Does not cause Damage

65 The Proton Wave Already implemented code: Constructor
public ProtonWave() { initializeImages(); } public static void initializeImages() if(images == null) GreenfootImage baseImage = new GreenfootImage("wave.png"); images = new GreenfootImage[NUMBER_IMAGES]; int i = 0; while (i < NUMBER_IMAGES) int size = (i+1) * ( baseImage.getWidth() / NUMBER_IMAGES ); images[i] = new GreenfootImage(baseImage); images[i].scale(size, size); i++; public void act() Already implemented code: Constructor initializeImages () act ()

66 initializeImages() creates an Array of Growing Images
GreenfootImage [ ] images

67 Setting up The Proton Wave
/* * Index of the currently used image. */ private int imageCount = 0; * Create a new proton wave. public ProtonWave() { initializeImages(); setImage(images [0]); Greenfoot.playSound ("proton.wav"); }

68 The Proton Wave

69 The Proton Wave /* * Act for the proton wave is: grow and check whether we hit anything. */ public void act() { grow(); } * Grow the wave. If we get to full size remove it. private void grow ()

70 The Proton Wave Grow Algorithm
1) If our index has exceed the number of images then 1.1) Remove the wave from the world 2) Otherwise 2.1) set the next image in the array 2.2) increment the index

71 The Proton Wave /* * Grow the wave. If we get to full size remove it.
*/ private void grow () { if (imageCount >= NUMBER_IMAGES) getWorld().removeObject (this); else setImage(images[imageCount++]); }

72 The Proton Wave Create a new ProtonWave by hand
Click “> Act” to watch the wave grow sequentially

73 Create ProtonWave from Rocket
/* * Release a proton wave (if it is loaded). */ private void startProtonWave() { ProtonWave wave = new ProtonWave(); getWorld().addObject (wave, getX(), getY()); }

74 Create ProtonWave from Rocket
/* * Check whether there are any key pressed and react to them. */ private void checkKeys() { if (Greenfoot.isKeyDown("space")) fire(); if (Greenfoot.isKeyDown("z")) startProtonWave(); ignite (Greenfoot.isKeyDown ("up")); if (Greenfoot.isKeyDown("left")) setRotation(getRotation() - 5); if (Greenfoot.isKeyDown("right")) setRotation(getRotation() + 5); }

75 Test It

76 Test It Proton Wave Can Be Released Too Fast by Holding Down the z Key

77 A Delay Count of 200 Seems Reasonable
Managing Delays private static final int gunReloadTime = 5; // Minimum delay in firing gun. private static final int protonReloadTime = 200; // Minimum delay in proton wave bursts. private int reloadDelayCount; // How long ago we fired gun the last time. private int protonDelayCount; // How long ago we fired proton wave the last time. private GreenfootImage rocket = new GreenfootImage("rocket.png"); private GreenfootImage rocketWithThrust = new GreenfootImage("rocketWithThrust.png"); A Delay Count of 200 Seems Reasonable

78 Managing Delays /* * Do what a rocket's gotta do. (Which is: mostly flying about, and turning, * accelerating and shooting when the right keys are pressed.) */ public void act() { move (); checkKeys(); checkCollision(); reloadDelayCount++; protonDelayCount++; }

79 Managing Delays /* * Release a proton wave (if it is loaded). */
private void startProtonWave() { if (protonDelayCount >= protonReloadTime) ProtonWave wave = new ProtonWave(); getWorld().addObject (wave, getX(), getY()); protonDelayCount = 0; } The method only produces a new Proton Wave if sufficient time as passed since the last one

80 Test It

81 Interacting with Objects in Range
List getObjectsInRange (int radius, Class cls)

82 Check for ProtonWave Collisions
/* * Act for the proton wave is: grow and check whether we hit anything. */ public void act() { checkCollision(); grow(); } * Explode all intersecting asteroids. private void checkCollision()

83 ProtonWave Collisions
import greenfoot.*; // (World, Actor, GreenfootImage, and Greenfoot) import java.util.List; /* * Explode all intersecting asteroids. */ private void checkCollision() { int range = getImage().getWidth() / 2; List<Asteroid> asteroids = getObjectsInRange (range, Asteroid.class); for (Asteroid a : asteroids) { }

84 Parameter to determine the amount of damage
Asteroid Hit Method Parameter to determine the amount of damage /* * Hit this asteroid dealing the given amount of damage. */ public void hit(int damage) { stability = stability - damage; if(stability <= 0) breakUp (); } Every Asteroid has “hit points” in the form of an integer variable called stability. An Asteroid breaks up if the variable reaches 0 or less.

85 ProtonWave Collissions
/* The damage this wave will deal */ private static final int DAMAGE = 30; /* * Explode all intersecting asteroids. */ private void checkCollision() { int range = getImage().getWidth() / 2; List<Asteroid> asteroids = getObjectsInRange(range, Asteroid.class); for (Asteroid a : asteroids) { a.hit (DAMAGE); }

86 Extra: Hit Invincibility
The ProtonWave currently completely destroys all Asteroids it comes in contact with. Meaning it destroys both the Asteroids it hits and the Asteroids that are then spawned. Depending on how we want our game to function, this might not be desirable. How can we make sure that the ProtonWave does not destroy the new Asteroids?

87 Summary of Programming Techniques


Download ppt "Chapter 7 – Collision Detection: Asteroids"

Similar presentations


Ads by Google