好的,所以我正在尝试创建一个简单的游戏,在该游戏中,您发射导弹,并且如果它撞到了墙,则必须反弹,因为它会灭活导弹以允许我发射新导弹。
import java.awt.*;
public class Project2{
public static final int PANEL_WIDTH = 300;
public static final int PANEL_HEIGHT = 300;
public static final int SLEEP_TIME = 50;
public static final Color SHOOTER_COLOR = Color.RED;
public static final Color BACKGROUND_COLOR = Color.WHITE;
public static final int SHOOTER_SIZE = 20; //diameter of the shooter
public static final int GUN_SIZE = 10; //length og the gun
public static final int SHOOTER_POSITION_Y = PANEL_HEIGHT - SHOOTER_SIZE;
public static final int SHOOTER_INITIAL_POSITION_X = 150;
public static int shooterPositionX;
public static int gunPositionX;
public static int gunPositionY;
public static int targetPositionX;
public static final Color TARGET_COLOR = Color.BLUE;
public static final int TARGET_POSITION_Y = 50;
public static final int TARGET_SIZE = 20;
public static final int KEY_SPACE =32;
public static final int KEY_PAGE_UP = 33;
public static final int KEY_HOME = 36;
public static final int KEY_LEFT_ARROW = 37;
public static final int KEY_UP_ARROW = 38;
public static final int KEY_RIGHT_ARROW = 39;
public static final int KEY_DOWN_ARROW = 40;
public static double missilePositionX;
public static double missilePositionY;
public static double missileDeltaX;
public static double missileDeltaY;
public static boolean missileActive;
public static final Color MISSILE_COLOR = Color.BLACK;
public static final int MISSILE_SIZE =2;
public static final double MISSILE_SPEED =1.0;
public static int hitCount;
public static final int TARGET_DELTA_X= 1;
public static int targetDeltaX;
// public static final Random.nextDouble();
public static void initialize(){
shooterPositionX = SHOOTER_INITIAL_POSITION_X;
gunPositionX = 0;
gunPositionY = GUN_SIZE;
targetPositionX = 150;
missileActive = false;
hitCount = 0;
targetDeltaX = 0;
}
public static void main(String[] args) {
DrawingPanel panel = new DrawingPanel(PANEL_WIDTH, PANEL_HEIGHT);
Graphics g = panel.getGraphics( );
initialize();
startGame(panel, g);
}
public static void drawAll(Graphics g){
g.setColor(Color.BLACK);
g.drawString("Project 2 by JR", 10, 15); // fix ""
g.drawString("Hits: " + hitCount, 10, 30);
// for(int i=0, i<=hitCount; i++){
//
// }
// Hits: followed by a number of stars corresponding to the hit count.
//Do not do this by calling g.drawString in a loop. Instead, make a single string with a
//for loop, appending the appropriate number of stars. Then call g.drawString once.
drawShooter(g, SHOOTER_COLOR);
drawTarget(g, TARGET_COLOR);
}
public static void startGame(DrawingPanel panel, Graphics g) {
for (int i = 0; i <= 10000; i++) {
panel.sleep(SLEEP_TIME);
handleKeys(panel, g);
// moveTarget(g);
drawAll(g);
moveMissile(g);
}
}
public static void drawShooter(Graphics g, Color c){
g.setColor(c);
g.fillOval(shooterPositionX-SHOOTER_SIZE/2, SHOOTER_POSITION_Y-SHOOTER_SIZE, SHOOTER_SIZE, SHOOTER_SIZE);
g.drawLine(shooterPositionX, SHOOTER_POSITION_Y-SHOOTER_SIZE, shooterPositionX+gunPositionX, SHOOTER_POSITION_Y-SHOOTER_SIZE - GUN_SIZE);
}
public static void drawTarget(Graphics g, Color c){
g.setColor(c);
g.fillOval(targetPositionX-TARGET_SIZE/2, TARGET_POSITION_Y-TARGET_SIZE, TARGET_SIZE, TARGET_SIZE);
g.drawLine(targetPositionX-TARGET_SIZE, TARGET_POSITION_Y+TARGET_SIZE/2, targetPositionX+TARGET_SIZE, TARGET_POSITION_Y+TARGET_SIZE/2);
}
public static void moveShooter(Graphics g, int deltaX){
drawShooter(g, BACKGROUND_COLOR);
shooterPositionX += deltaX;
drawShooter(g, SHOOTER_COLOR);
//does not allow you to move any part of the shooter off the screen.
}
public static void handleKeys(DrawingPanel panel, Graphics g){
int keyCode = panel.getKeyCode();
if (keyCode == KEY_SPACE)
reset(g);
else if (keyCode == KEY_RIGHT_ARROW)
moveShooter(g,1);
else if (keyCode == KEY_LEFT_ARROW)
moveShooter(g,-1);
else if (keyCode == KEY_HOME)
moveGun(g,1);
else if (keyCode == KEY_PAGE_UP)
moveGun(g,-1);
else if(keyCode == KEY_UP_ARROW)
shootMissile(g);
}
public static void reset(Graphics g){
g.setColor(BACKGROUND_COLOR);
g.fillRect(0,0, PANEL_WIDTH, PANEL_HEIGHT);
initialize();
}
public static void moveGun(Graphics g, int deltaX){
drawShooter(g, BACKGROUND_COLOR);
gunPositionX += deltaX;
drawShooter(g, SHOOTER_COLOR);
//Do not let gunPositionX have an absolute value larger than SHOOTER_SIZE.
}
public static void shootMissile(Graphics g){
if(missileActive == false){
missileActive = true;
missilePositionX = shooterPositionX;
missilePositionY = SHOOTER_POSITION_Y-SHOOTER_SIZE;
missileDeltaX = 0;
missileDeltaY = 0;
missilePositionX += missileDeltaX;
missilePositionY += missileDeltaY;
}
}
public static void moveMissile(Graphics g){
if(missileActive){
drawMissile(g, BACKGROUND_COLOR);
missilePositionX += missileDeltaX;
missilePositionY += missileDeltaY;
drawMissile(g, MISSILE_COLOR);
if(missilePositionY <= 0){
missileDeltaY = -Math.abs(missileDeltaY);
missilePositionY += missileDeltaY;
}
else if(missilePositionX >= 300){
missilePositionX += missileDeltaX;
}
else if(missilePositionX <=0){
missileDeltaX = -Math.abs(missileDeltaX);
missilePositionX += missileDeltaX;
}
else if(missilePositionY >= 300){
drawMissile(g, BACKGROUND_COLOR);
missileActive = false;
}
if( detectHitTarget((int)missilePositionX, (int)missilePositionY, (int)MISSILE_SIZE/2, targetPositionX, TARGET_POSITION_Y, TARGET_SIZE/2)){
hitCount ++;
drawMissile(g, BACKGROUND_COLOR);//erase the missile;
missileActive = false;
}
}
}
public static void drawMissile(Graphics g, Color c){
g.setColor(c);
g.fillOval((int)missilePositionX, (int)missilePositionY, MISSILE_SIZE, MISSILE_SIZE);
missileDeltaY = - gunPositionY * MISSILE_SPEED;
missileDeltaX = gunPositionX * MISSILE_SPEED;
}
public static boolean detectHitTarget(int x1, int y1, int r1, int x2, int y2, int r2){
if(Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)) <= r1 + r2){
return true;
}else{
return false;}
}
public static void moveTarget(Graphics g){
// drawTarget(g, BACKGROUND_COLOR);
// targetPositionX += targetDeltaX;
// if(targetPositionX >= 0){
// targetPositionX = +Math.abs(targetDelta);
// }
// else if(targetPositionX <=300){
// targetPositionX = -Math.abs(targetDelta);
// }
// if(Random >= .98){
// targetDeltaX = 0;
// }
// else if(Random >= .96){
// targetDeltaX =1;
// }
// else if(Random >= .94){
// targetDleta = -1;
// }
}
}
到目前为止,球只是被“塞住”到顶壁上,或者甚至在侧壁刚从面板上掉下来的情况下也没有被“塞住”,而不是弹跳起来,我似乎无法弄清楚。
绘图面板
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.ArrayList;
public class DrawingPanel implements ActionListener {
private static final String versionMessage =
"Drawing Panel version 1.1, January 25, 2015";
private static final int DELAY = 100; // delay between repaints in millis
private static final boolean PRETTY = false; // true to anti-alias
private static boolean showStatus = false;
private static final int MAX_KEY_BUF_SIZE = 10;
private int width, height; // dimensions of window frame
private JFrame frame; // overall window frame
private JPanel panel; // overall drawing surface
private BufferedImage image; // remembers drawing commands
private Graphics2D g2; // graphics context for painting
private JLabel statusBar; // status bar showing mouse position
private volatile MouseEvent click; // stores the last mouse click
private volatile boolean pressed; // true if the mouse is pressed
private volatile MouseEvent move; // stores the position of the mouse
private ArrayList<KeyInfo> keys;
// construct a drawing panel of given width and height enclosed in a window
public DrawingPanel(int width, int height) {
this.width = width;
this.height = height;
keys = new ArrayList<KeyInfo>();
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
statusBar = new JLabel(" ");
statusBar.setBorder(BorderFactory.createLineBorder(Color.BLACK));
statusBar.setText(versionMessage);
panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
panel.setBackground(Color.WHITE);
panel.setPreferredSize(new Dimension(width, height));
panel.add(new JLabel(new ImageIcon(image)));
click = null;
move = null;
pressed = false;
// listen to mouse movement
MouseInputAdapter listener = new MouseInputAdapter() {
public void mouseMoved(MouseEvent e) {
pressed = false;
move = e;
if (showStatus)
statusBar.setText("moved (" + e.getX() + ", " + e.getY() + ")");
}
public void mousePressed(MouseEvent e) {
pressed = true;
move = e;
if (showStatus)
statusBar.setText("pressed (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseDragged(MouseEvent e) {
pressed = true;
move = e;
if (showStatus)
statusBar.setText("dragged (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseReleased(MouseEvent e) {
click = e;
pressed = false;
if (showStatus)
statusBar.setText("released (" + e.getX() + ", " + e.getY() + ")");
}
public void mouseEntered(MouseEvent e) {
// System.out.println("mouse entered");
panel.requestFocus();
}
};
panel.addMouseListener(listener);
panel.addMouseMotionListener(listener);
new DrawingPanelKeyListener();
g2 = (Graphics2D)image.getGraphics();
g2.setColor(Color.BLACK);
if (PRETTY) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(new BasicStroke(1.1f));
}
frame = new JFrame("Drawing Panel");
frame.setResizable(false);
try {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // so that this works in an applet
} catch (Exception e) {}
frame.getContentPane().add(panel);
frame.getContentPane().add(statusBar, "South");
frame.pack();
frame.setVisible(true);
toFront();
frame.requestFocus();
// repaint timer so that the screen will update
new Timer(DELAY, this).start();
}
public void showMouseStatus(boolean f) {
showStatus = f;
}
public void addKeyListener(KeyListener listener) {
panel.addKeyListener(listener);
panel.requestFocus();
}
// used for an internal timer that keeps repainting
public void actionPerformed(ActionEvent e) {
panel.repaint();
}
// obtain the Graphics object to draw on the panel
public Graphics2D getGraphics() {
return g2;
}
// set the background color of the drawing panel
public void setBackground(Color c) {
panel.setBackground(c);
}
// show or hide the drawing panel on the screen
public void setVisible(boolean visible) {
frame.setVisible(visible);
}
// makes the program pause for the given amount of time,
// allowing for animation
public void sleep(int millis) {
panel.repaint();
try {
Thread.sleep(millis);
} catch (InterruptedException e) {}
}
// close the drawing panel
public void close() {
frame.dispose();
}
// makes drawing panel become the frontmost window on the screen
public void toFront() {
frame.toFront();
}
// return panel width
public int getWidth() {
return width;
}
// return panel height
public int getHeight() {
return height;
}
// return the X position of the mouse or -1
public int getMouseX() {
if (move == null) {
return -1;
} else {
return move.getX();
}
}
// return the Y position of the mouse or -1
public int getMouseY() {
if (move == null) {
return -1;
} else {
return move.getY();
}
}
// return the X position of the last click or -1
public int getClickX() {
if (click == null) {
return -1;
} else {
return click.getX();
}
}
// return the Y position of the last click or -1
public int getClickY() {
if (click == null) {
return -1;
} else {
return click.getY();
}
}
// return true if a mouse button is pressed
public boolean mousePressed() {
return pressed;
}
public synchronized int getKeyCode() {
if (keys.size() == 0)
return 0;
return keys.remove(0).keyCode;
}
public synchronized char getKeyChar() {
if (keys.size() == 0)
return 0;
return keys.remove(0).keyChar;
}
public synchronized int getKeysSize() {
return keys.size();
}
private synchronized void insertKeyData(char c, int code) {
keys.add(new KeyInfo(c,code));
if (keys.size() > MAX_KEY_BUF_SIZE) {
keys.remove(0);
// System.out.println("Dropped key");
}
}
private class KeyInfo {
public int keyCode;
public char keyChar;
public KeyInfo(char keyChar, int keyCode) {
this.keyCode = keyCode;
this.keyChar = keyChar;
}
}
private class DrawingPanelKeyListener implements KeyListener {
int repeatCount = 0;
public DrawingPanelKeyListener() {
panel.addKeyListener(this);
panel.requestFocus();
}
public void keyPressed(KeyEvent event) {
// System.out.println("key pressed");
repeatCount++;
if ((repeatCount == 1) || (getKeysSize() < 2))
insertKeyData(event.getKeyChar(),event.getKeyCode());
}
public void keyTyped(KeyEvent event) {
}
public void keyReleased(KeyEvent event) {
repeatCount = 0;
}
}
}
最佳答案
您每次在drawMissile
方法内部调用的moveMissile
方法都会重新初始化missileDeltaY
和missileDeltaX
变量。
missileDeltaY = - gunPositionY * MISSILE_SPEED;
missileDeltaX = gunPositionX * MISSILE_SPEED;
因此,无论在
moveMissile
方法的其余主体中进行什么计算,这些变量都将采用其默认值,因此,在触及边界时不会改变轨迹。我对您的方法进行了一些更改,以帮助您找出解决方案,如果您将导弹射向左边界,则看起来它正在工作
射击导弹
public static void shootMissile(Graphics g){
if(missileActive == false){
missileActive = true;
missilePositionX = shooterPositionX;
missilePositionY = SHOOTER_POSITION_Y-SHOOTER_SIZE;
missileDeltaX = 0;
missileDeltaY = 0;
missilePositionX += missileDeltaX;
missilePositionY += missileDeltaY;
missileDeltaY = - gunPositionY * MISSILE_SPEED;
missileDeltaX = gunPositionX * MISSILE_SPEED;
}
}
移动导弹
public static void moveMissile(Graphics g){
if(missileActive){
drawMissile(g, BACKGROUND_COLOR);
missilePositionX += missileDeltaX;
missilePositionY += missileDeltaY;
drawMissile(g, MISSILE_COLOR);
if(missilePositionY <= 0){
missileDeltaY = Math.abs(missileDeltaY);
missilePositionY += missileDeltaY;
}
if(missilePositionX >= 300){
missilePositionX += -Math.abs(missileDeltaX);
}
if(missilePositionX <=0){
missileDeltaX = Math.abs(missileDeltaX);
missilePositionX += missileDeltaX;
}
if(missilePositionY >= 300){
drawMissile(g, BACKGROUND_COLOR);
missileActive = false;
}
if( detectHitTarget((int)missilePositionX, (int)missilePositionY, (int)MISSILE_SIZE/2, targetPositionX, TARGET_POSITION_Y, TARGET_SIZE/2)){
hitCount ++;
drawMissile(g, BACKGROUND_COLOR);//erase the missile;
missileActive = false;
}
}
}
绘制导弹
public static void drawMissile(Graphics g, Color c){
g.setColor(c);
g.fillOval((int)missilePositionX, (int)missilePositionY, MISSILE_SIZE, MISSILE_SIZE);
}