除了直接从大炮直接射击的子弹外,一切都按预期工作。大炮按照预期的方式在屏幕上移动但是一旦子弹被射击,它就不会以枪指向的角度行进。任何想法如何纠正这个,以便它以相同的角度拍摄大炮的设定?
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 );
}
}
答案 0 :(得分:1)
确定子弹移动角度的线是:
shootingFrom.x += (bulletTilt/3);
除以3可能不是正确的计算方法。
您需要在拉动扳机时计算枪的角度,从中提取“子弹水平增量”并在每次刷新时将其添加到shootingFrom.x
。