For the final part of this assignment I need to do the following:
Any help/advice/starting pointers would be great!
1) Create a row of Alien attackers, class RowOfAlien, patterned after the partially filled array. Put five Aliens in the row. When the row hits the left or right of the screen, the Aliens snake downwards (see demo). Note that this is different from the video game where the entire row bounces as one unit.
2) Left and right keys move the canon. The canon fires automatically (as in version 1) but the bullet is fired from the current position of the canon.Note that you must press space bar a couple of times to get keyboard interaction working.
To make it easier to debug your program, print a message in the console when each of the following happens:
* An alien is hit by a bullet
* The left or right keys are pressed
3) Modify GameDemo to:
* Play the game multiple times.
* Display the outcome of each game.
* At the conclusion of play, show the total number of games won and lost
Here are the pieces of code I have so far:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* @original author Kevin Glass
* @adapted by: Nikunj Raghuvanshi
* @adapted by: Kye Hedlund 3/2010
* @adapte by Wade Gobel 10/2010
*/
public class Game extends Canvas {
//*************** do not change between this line and the next one ***
// CONSTANTS
/** True if we're holding up game play until a key has been pressed */
private boolean waitingForKeyPress = false;//true;
/** True if the left cursor key is currently pressed */
private boolean leftPressed = false;
/** True if the right cursor key is currently pressed */
private boolean rightPressed = false;
/** True if we are firing */
private boolean firePressed = false;
// Graphics stuff
private Graphics2D g;
private BufferStrategy strategy; // Use accelerated page flipping
//***************** do not change above this line **********
// Your code goes below here
// Time (in ms) to pause after each step of the game loop.
// This, in part, determines the speed at which the game is
// updated on the screen.
public final int PAUSE_INTERVAL = 100;
public final int SCREEN_WIDTH = 800;
public final int SCREEN_HEIGHT = 500;
// VARIABLES
private RowOfAlien rowalien;
private Cannon cannon;
private Bullet bullet;
/*
* Create a new game that is ready to play
*/
public Game() {
graphicsInitialization();
initAllObjects();
}
public void playGame() {
boolean gameRunning = true;
while(gameRunning) {
moveAllObjects( );
//When the alien reaches the bottom of the screen, print out "Done" and terminate program.
if( alien.hitBottom() ){
gameRunning = false;
System.out.println("Done");
System.exit(0);
}
//When an bullet hits the alien, game is over
if(alien.hitBy(bullet)){
gameRunning = false;
}
graphicsUpdateStartOfLoop();
drawAllObjects();
graphicsUpdateEndOfLoop();
}
}
private void initAllObjects() {
final int ALIEN_X_POSITION = 20;
final int ALIEN_Y_POSITION = 40;
alien = new Alien(ALIEN_X_POSITION,ALIEN_Y_POSITION,
SCREEN_WIDTH,SCREEN_HEIGHT);
cannon = new Cannon(SCREEN_WIDTH/2, SCREEN_HEIGHT-25, SCREEN_WIDTH);
bullet = new Bullet(SCREEN_WIDTH/2, SCREEN_HEIGHT-30, SCREEN_HEIGHT);
leftPressed = false;
rightPressed = false;
firePressed = false;
}
private void moveAllObjects() {
alien.move();
bullet.move();
}
private void drawAllObjects() {
alien.draw(g);
cannon.draw(g);
bullet.draw(g);
}
//*************** do not change anything from here to the end of Game
// Do not change any of the methods whose names begin with "graphics"
public void graphicsUpdateStartOfLoop() {
// Get hold of a graphics context for the accelerated
// surface and blank it out
g = (Graphics2D) strategy.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
// Do not change any of the methods whose names begin with "graphics"
public void graphicsUpdateEndOfLoop() {
// Finally, we've completed drawing so clear up the graphics
// and flip the buffer over
g.dispose();
strategy.show();
// Finally pause for a bit. Note: this should run us at about
// 100 fps but on windows this might vary each loop due to
// a bad implementation of timer
//try {
// Thread.sleep(PAUSE_INTERVAL);
//} catch (Exception e) {
//}
}
// Do no change any of the methods whose names begin with "graphics"
public void graphicsInitialization() {
// Create a frame to contain our game
JFrame container = new JFrame("Space Invaders 110");
// Get the content of the frame and set up the resolution of the
// game
JPanel panel = (JPanel) container.getContentPane();
panel.setPreferredSize(new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT));
panel.setLayout(null);
// Setup our canvas size and put it into the content of the frame
setBounds(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
panel.add(this);
// Tell AWT not to bother repainting our canvas since we're
// going to do that ourself in accelerated mode
setIgnoreRepaint(true);
// Make the window visible
container.pack();
container.setResizable(false);
container.setVisible(true);
// Add a listener to respond to the user closing the window. If they
// do we'd like to exit the game
container.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
addKeyListener(new KeyInputHandler());
// Request the focus so key events come to us
requestFocus();
// Create the buffering strategy which will allow AWT
// to manage our accelerated graphics
createBufferStrategy(2);
strategy = getBufferStrategy();
}
/**
* A class to handle keyboard input from the user. The class handles both
* dynamic input during game play, i.e. left/right and shoot, and more
* static type input (i.e. press any key to continue)
*
* This has been implemented as an inner class more through habbit then
* anything else. Its perfectly normal to implement this as seperate class
* if slight less convienient.
*
* @author Kevin Glass
*/
private class KeyInputHandler extends KeyAdapter {
/**
* The number of key presses we've had while waiting for an "any key"
* press
*/
private int pressCount = 1;
/**
* Notification from AWT that a key has been pressed. Note that a key
* being pressed is equal to being pushed down but *NOT* released. Thats
* where keyTyped() comes in.
*
* @param e
* The details of the key that was pressed
*/
public void keyPressed(KeyEvent e) {
// if we're waiting for an "any key" typed then we don't
// want to do anything with just a "press"
if (waitingForKeyPress) {
return;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
//System.out.println("left pressed");
leftPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
//System.out.println("right pressed");
rightPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
//System.out.println("fire pressed");
firePressed = true;
}
}
/**
* Notification from AWT that a key has been released.
*
* @param e
* The details of the key that was released
*/
public void keyReleased(KeyEvent e) {
// if we're waiting for an "any key" typed then we don't
// want to do anything with just a "released"
if (waitingForKeyPress) {
return;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
firePressed = false;
}
}
/**
* Notification from AWT that a key has been typed. Note that typing a
* key means to both press and then release it.
*
* @param e
* The details of the key that was typed.
*/
public void keyTyped(KeyEvent e) {
// if we're waiting for a "any key" type then
// check if we've received any recently. We may
// have had a keyType() event from the user releasing
// the shoot or move keys, hence the use of the "pressCount"
// counter.
if (waitingForKeyPress) {
if (pressCount == 1) {
// since we've now recieved our key typed
// event we can mark it as such and start
// our new game
waitingForKeyPress = false;
pressCount = 0;
} else {
pressCount++;
}
}
}
}
}
import java.awt.Graphics;
import java.awt.Image;
/**
* A single alien in the Space Invaders game.
*
* @author Kevin Glass
*/
class Alien {
// CONSTANTS
private final String ALIEN_ICON = "alien.gif";
private final int MAX_WIDTH; // Size of canvas on which Alien is moving
private final int MAX_HEIGHT;
// Initial speed at which the alien moves horizontally
private final double INITIAL_X_SPEED = 0.5; ////********************************
private final int DROP_DOWN_AMOUNT = 30;
private final Sprite SPRITE; // Graphical representation of alien
// VARIABLES
private double upperLeftX, upperLeftY; // Position of alien on canvas
private int direction;
// Sound played when alien hit by missile
private final String EXPLOSION_WAV = "explosion.wav";
// Object that plays the explosion sound.
// This is analogous to SPRITE. One handles graphics details
// the other audio details.
private final Sound EXPLOSION;
/*
* Create a new alien object
*/
public Alien(int theX, int theY, int theMaxWidth, int theMaxHeight) {
upperLeftX = theX;
upperLeftY = theY;
MAX_WIDTH = theMaxWidth;
MAX_HEIGHT = theMaxHeight;
direction = 1;
// Get the graphical representation of the alien
SPRITE = SpriteStore.get().getSprite(ALIEN_ICON);
// Add the following lines to the constructor
// Get the sound to play when hit by missile
EXPLOSION = SoundStore.get().getSound(EXPLOSION_WAV);
}
public void draw(Graphics g) {
SPRITE.draw(g, (int) upperLeftX, (int) upperLeftY);
}
public boolean hitBottom() {
return upperLeftY >= MAX_HEIGHT - 2 * SPRITE.getHeight();
}
/*
* Has the alien hit the left or right side of the canvas?
*/
private boolean hitSide() {
final int LEFT_OFFSET_FROM_EDGE = 10;
return upperLeftX <= 0 ||
upperLeftX > MAX_WIDTH - SPRITE.getWidth();
}
public void move() {
upperLeftX += direction * INITIAL_X_SPEED;
// If alien has hit left or right side of canvas,
// change direction and drop down
if(hitSide()) {
direction = -direction;
upperLeftY += DROP_DOWN_AMOUNT;
}
}
// The graphic for a missile is small so we will treat it as a
// single point represented by its coordinates for its upper left corner.
// The alien is treated as a rectangle represented by the coordinates of
// its upper left corner, getHeight(), and getWidth().
// The hitBy member function determines if the point representing the
// missile is inside the rectangle representing the alien.
public boolean hitBy(Bullet b) {
if (b.upperLeftX() >= getUpperLeftX()){
if(b.upperLeftX() <= (getUpperLeftX() + getWidth())){
if(b.upperLeftY() >= getUpperLeftY()){
if(b.upperLeftY() <= (getUpperLeftY() + getHeight())){
EXPLOSION.playSound();
return true;
}
}
}
}
return false;
}
public int getHeight() {
return SPRITE.getHeight();
}
public int getWidth() {
return SPRITE.getWidth();
}
public double getUpperLeftX() {
return upperLeftX;
}
public void setUpperLeftX(int x) {
upperLeftX = x;
}
public double getUpperLeftY() {
return upperLeftY;
}
public void setUpperLeftY(int y) {
upperLeftY = y;
}
}
public class RowOfAlien {
// CONSTANTS
public final int EMPTY = -1;
// VARIABLES
private Alien[] row;
private int topIndex;
public RowOfAlien(int numberOfAliens) {
row = new Alien[numberOfAliens];
topIndex = EMPTY;
}
public void add( Alien alien ) {
// Put your code here
//alien = new Alien(ALIEN_X_POSITION,ALIEN_Y_POSITION, SCREEN_WIDTH,SCREEN_HEIGHT);
alien = new Alien(1,1,200,200);
}
public void draw(Graphics g) {
// Put your code here
}
public void move() {
// Put your code here
}
public void remove(int index) {
// Put your code here
}
}