我正在创建一个小型 Java Jpanel 游戏,其中我应该有一个通过箭头上下移动并通过空间发射的火箭。
发射方法应该像这样工作:按下空格键,物体发射并在屏幕上移动,然后当它击中某个 x 时,它就会消失。此外,你只能开火一次,直到另一颗子弹消失。
我不知道我做错了什么。首先,我的代码一启动,您就可以看到一颗子弹飞过屏幕。
第二,子弹没有消失。
第三,即使另一颗子弹仍然可见,它允许我再次开火。
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.*;
@SuppressWarnings("serial")
public class SpaceGame extends JPanel implements ActionListener{
Timer t = new Timer(2, this);
private ImageIcon rocket,asteroid,bullet;
private JLabel rocketlabel,ast1,ast2,ast3,bulletLabel;
public static int y=90,dy=0,bulletX=110,bulletY,i=0,canFire;
//public sound sound;
static boolean bulletFired=false;;
static JFrame f = new JFrame();
SpaceGame(){
this.setBackground(Color.black);
rocket = new ImageIcon(getClass().getResource("rocketFinal.png"));
rocketlabel= new JLabel(rocket);
this.add(rocketlabel);
asteroid = new ImageIcon(getClass().getResource("asteroid.png"));
ast1=new JLabel(asteroid);
ast2=new JLabel(asteroid);
ast3=new JLabel(asteroid);
bullet = new ImageIcon(getClass().getResource("bulletReal.png"));
bulletLabel = new JLabel(bullet);
canFire=1;
bulletLabel.setVisible(false);
this.add(ast1);this.add(ast2);this.add(ast3);this.add(bulletLabel);
f.addKeyListener(new controller());
this.setLayout(null);
this.setVisible(true);
}
public class controller implements KeyListener{
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode== KeyEvent.VK_UP) {
dy=-1;
}
if(keyCode== KeyEvent.VK_DOWN) {
dy=1;
}
if(keyCode== KeyEvent.VK_SPACE) {
if(canFire==0) {
System.out.println(String.valueOf(canFire));
bulletFired = true;
bulletY = y;
bulletX=110;
}canFire=1;
}
}
@Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch(key) {
case KeyEvent.VK_UP: dy=0; break;
case KeyEvent.VK_DOWN: dy=0; break;
}
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
rocketlabel.setBounds(45,y,rocket.getIconWidth(),80);
fireBullet();
paintStars(g);
t.start();
}
public void paintStars(Graphics g) {
g.setColor(Color.yellow);
for(int i=0; i<5;i++) {
Random rand = new Random();
int o = rand.nextInt(500);
int p = rand.nextInt(300);
g.fillOval(o, p, 3, 3);
}
}
public void actionPerformed(ActionEvent e) {
if(y==-20) y=249;
if(y==250)y=-20;
y+=dy;
if(bulletFired=true) {
bulletX++;
if(bulletX==455)bulletFired=false;bulletLabel.setVisible(false);System.out.println(String.valueOf(bulletX)); canFire=0;
}
repaint();
}
public void fireBullet(){
if(bulletFired=true) {
bulletLabel.setVisible(true);
bulletLabel.setBounds(bulletX,bulletY+25,bullet.getIconHeight(),bullet.getIconWidth());
}
}
public static void main(String[] args) {
String filepath = "SpaceGameMusic.wav";
musicStuff musicPlayer = new musicStuff();
musicPlayer.playMusic(filepath);
SpaceGame t = new SpaceGame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(t);
f.setSize(500,335);
f.setVisible(true);
f.setResizable(false);
}
}
最佳答案
For one, as soon as my code starts you can see a bullet flying across the screen.
paintComponent() 方法仅用于绘画。您无法控制 Swing 何时确定组件需要重新绘制。
例如:
t.start();
不应该出现在绘画方法中。一旦框架可见,面板将被绘制并且计时器将启动。
您的应用程序代码应该控制计时器何时启动。
其他问题:
您不应该使用静态变量。该变量应该只是您的类的实例。
paintStars() 方法不应生成随机位置。再次。绘画方法应该只绘制类的当前状态。因此,如果您想更改星星的位置,您应该使用像
randomizeStars()
这样的方法。在此方法中,您将更新 Point 对象的 ArrayList。每个 Point 实例代表一颗星星的位置。然后,paintStars() 方法将简单地迭代 ArrayList 并绘制每个星星。您不应该使用 KeyListener。 KeyListener 仅在组件具有焦点时才起作用。您不能保证您的组件会失去焦点。相反,您应该使用按键绑定(bind)。即使组件没有焦点,键绑定(bind)也允许您处理 KeyEvent。请参阅Motion Using the Keyboard了解更多信息和工作示例。
you can only fire once until the other bullet disappears
您的 canFire
变量应该是 boolean 变量,因此它只有 true/false 值。同样,您有一个设置状态的方法。然后,您的游戏逻辑将在再次发射子弹之前检查状态。
if(y==-20) y=249;
if(y==250)y=-20;
不要对值进行硬编码。该数字应根据面板的大小而定。因此,您可以使用 getWidth() 和 getHeight() 等方法来确定面板的当前大小。
关于java - 我不确定什么是不正确的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62009708/