Everything is working as supposed to with the exception of the bullet not shooting straight from the cannon. The cannon moves across the screen as it is supposed to but once the bullet is shot it doesn't travel at the angle in which the gun is pointed. Any ideas how to correct this so that it shoots at the same angle the cannon is set at?
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Exercise16_25 extends JFrame {
private Game board;
public Exercise16_25(int width, int height) {
board = new Game(width, height);
add( board );
board.setFocusable( true );
}
class Game extends JPanel {
//instance variables
private int ballonsHit = 0;
private int ballsShot = 0;
private int xCoordinate = 0;
private Point shootingFrom;
private boolean shooting = false;
Timer timer;
private Point balloonLocation;
////////////////////
//determines how big the gun is vertically
private int gunSize = 25;
////////////////////
//ensures that a balloon is drawn without appearing cutoff (over the edge)
private int padding = 25;
////////////////////
//flag to let paintComponent() know to draw the shatter visual
private boolean isShattered;
////////////////////
//this timer will end the shatter visual
private Timer stopShatter;
///////////////////
//the current distance of the mini-balloons from the shatter point
//slowly increases as shatter visual executes
private int shatterDistance;
////////////////////
//the bulletTilt helps guide the bullet in a diagonal path
//both are needed as you can change the tilt of the gun
//while a bullet is flying which require a constant tilt
private int gunTilt;
private int bulletTilt;
///////////////////////
//Make the radius one final size, don't use 'balloonRadius*4'
//Also lets make the balloon a little bigger
///////////////////////
private int balloonRadius = 25;
private int bulletRadius = 5;
public Game(int width, int height) {
/////////////////////////
//You must set the size of this panel so
//that you can give xCoordinate a value, otherwise
//getWidth() will equal 0.
//Since xCoordinate represents the x-coord of the gun,
//set it to the middle of the board
this.setSize(width, height);
xCoordinate = this.getWidth()/2-1;
/////////////////////////
////////////////////////
//Don't try this line before the constructor
//because it depends on the size of the panel
//which isn't set before setSize is called.
balloonLocation = setRandomBalloonLocation();
timer = new Timer( 25, new ActionListener() {
public void actionPerformed( ActionEvent e ) {
repaint();
}
} );
/////////////////////////
//repaint board every 25 milliseconds
timer.start();
/////////////////////////
///////////////////////
//initiate shatter timer.
stopShatter = new Timer(2000, new ShatterTerminator());
///////////////////////
addKeyListener( new KeyAdapter() {
public void keyPressed( KeyEvent e ) {
switch ( e.getKeyCode() ) {
case KeyEvent.VK_UP:
shootBall();
bulletTilt = gunTilt;
break;
case KeyEvent.VK_LEFT:
turnLeft();
break;
case KeyEvent.VK_RIGHT:
turnRight();
break;
}
}
} );
}
public Point setRandomBalloonLocation() {
//////////////////////////
//use java.util.Random to generate random location
//make x between 1 and the x-coordinate of the right hand edge of the JPanel
//padding is used so the ball doesn't appear cut off.
//make y between 1 and half of the y-coordinate of the lower hand edge of the JPanel
Random rand = new Random();
Point location = new Point( rand.nextInt(this.getX()+this.getWidth()-padding)+1, (rand.nextInt(this.getY()+this.getHeight())/2)+1);
return location;
}
public void shootBall() {
if ( !shooting ) {
shooting = true;
shootingFrom = new Point( xCoordinate, getHeight() - gunSize );
//shootingFrom = new Point( getWidth() / 2 + xCoordinate - bulletRadius / 2, getHeight() - y );
} else {
System.out.println( "The ball is already being shot!" );
}
}
public void turnLeft() {
xCoordinate -= 1;
gunTilt--;
}
public void turnRight() {
xCoordinate += 1;
gunTilt++;
}
///////////////////////////
//One of the biggest issues here is your use of constants (hard-coded values).
//Use all variables, because some variables will be used in several
//computations, e.g. balloonLocation, ballonRadius.
///////////////////////////
protected void paintComponent( Graphics g ) {
super.paintComponent( g );
///////////////////////
//Draw gun
//'xcoordinate' represents the position of the gun.
//turnLeft() and turnRight will control it
g.drawLine( xCoordinate, getHeight()-gunSize, getWidth() / 2, getHeight() );
///////////////////////
//To increase the thickness of the gun draw two more lines beside it
g.drawLine( xCoordinate-1, getHeight()-gunSize, getWidth() / 2-1, getHeight() );
g.drawLine( xCoordinate+1, getHeight()-gunSize, getWidth() / 2+1, getHeight() );
///////////////////////
///////////////////////
//Display mini-balloons if the balloon was hit, otherwise display balloon
if(isShattered) {
g.drawOval( balloonLocation.x+shatterDistance, balloonLocation.y, balloonRadius/2, balloonRadius/2);
g.drawOval( balloonLocation.x-shatterDistance, balloonLocation.y, balloonRadius/2, balloonRadius/2);
g.drawOval( balloonLocation.x, balloonLocation.y+shatterDistance, balloonRadius/2, balloonRadius/2);
g.drawOval( balloonLocation.x, balloonLocation.y-shatterDistance, balloonRadius/2, balloonRadius/2);
shatterDistance+=5; //move mini-balloons
}else {
g.drawOval( balloonLocation.x, balloonLocation.y, balloonRadius, balloonRadius);
}
/////////////////////
//////////////////
//Draw bullet
if ( shooting ) {
g.drawOval( shootingFrom.x, shootingFrom.y, bulletRadius, bulletRadius);
////////////////////////////
//Check if the bullet hit balloon
//bullet is between the left and right boundaries of balloon
//and bullet is between the lower and upper boundaries of balloon
if((shootingFrom.x >= balloonLocation.x && shootingFrom.x <= (balloonLocation.x+(balloonRadius)))
&& (shootingFrom.y >= balloonLocation.y && shootingFrom.y <= (balloonLocation.y+(balloonRadius)))
) {
System.out.println("Ballon Hit!");
shatterDistance = 0;
isShattered = true;
stopShatter.start();
shooting = false;
}
///////////////////////////
///////////////////////////
//Detect edge collision
//Hitting the left and right edge aren't even possible, since
//bullets shoot straight up
if(shootingFrom.y <= 0 //hits top
|| shootingFrom.x <= 0 //hits left edge
|| shootingFrom.x >= this.getX()+this.getWidth() //hits right edge
)
{
System.out.println("Hit Boundary!");
shooting = false;
}
///////////////////////////
////////////////////////////
//Continue to move bullet straight up
//To shoot diagonal, you set shootingFrom.x accordingly
shootingFrom.x += (bulletTilt/3);
shootingFrom.y -= 5;
////////////////////////////
}
}
private class ShatterTerminator implements ActionListener {
public void actionPerformed( ActionEvent e ) {
isShattered = false;
balloonLocation = setRandomBalloonLocation();
stopShatter.stop();
}
}
}
public static void main( String[] args ) {
int width = 200, height = 300;
Exercise16_25 frame = new Exercise16_25(width, height);
frame.setSize( 300, 200 );
frame.setLocationRelativeTo( null );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}