gpt4 book ai didi

java - 从菜单切换到实际游戏

转载 作者:行者123 更新时间:2023-12-02 10:20:24 25 4
gpt4 key购买 nike

所以我正在制作一个太空入侵者克隆体。最初,我可以毫无问题地让我的游戏使用一个简单的主类来工作,该主类创建了框架,创建了游戏玩法并启动了线程。

但后来我尝试实现一个开始菜单,但一切都失败了。菜单成功显示,但当我按开始时,游戏玩法没有出现。

我已经没有想法了,我完全被难住了。我对 SO 也有点陌生,所以如果我遗漏了什么,我很感激任何帮助。

这是没有菜单的原始版本,效果很好:

    public static void main(String[] args) {

JFrame frame = new JFrame("SpaceRaiders");

frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Gameplay gameplay = new Gameplay();
frame.add(gameplay);
frame.setVisible(true);

Thread t1 = new Thread(gameplay);
t1.start();


}

但是,当我尝试实现一个菜单来玩游戏时,我遇到了各种各样的麻烦。我创建了一个 UI 类以及一个实际的“游戏”类,如下所示:

public class UI {

JFrame frame, f2;
JPanel titrePanel, startButtonPanel, loadButtonPanel, p2;
JLabel nomJeu;
JButton startButton, loadButton;
Font fontTitre, fontStart;
Gameplay gameplay;

public void createUI(ChoixJeu cj) {
frame = new JFrame("SpaceRaiders");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
frame.setResizable(false);

frame.setLayout(null);

frame.getContentPane().setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//------------------ECRAN MENU---------------------
//Titre
titrePanel = new JPanel();
titrePanel.setBounds(100, 100, 400, 100);
titrePanel.setBackground(Color.BLUE);

Font fontTitre = new Font("Times New Roman", Font.BOLD, 50);
Font fontStart = new Font("Times New Roman", Font.PLAIN, 20);
nomJeu = new JLabel("SpaceRaiders");
nomJeu.setForeground(Color.white);
nomJeu.setFont(fontTitre);
titrePanel.add(nomJeu);

//Start button
startButtonPanel = new JPanel();
startButtonPanel.setBounds(200, 400, 200, 40);
startButtonPanel.setBackground(Color.BLACK);

startButton = new JButton("START");
startButton.setBackground(Color.BLACK);
startButton.setForeground(Color.WHITE);
startButton.setFont(fontStart);
startButton.setFocusPainted(false);
startButton.addActionListener(cj);
startButton.setActionCommand("start");
startButtonPanel.add(startButton);

//Load Button
loadButtonPanel = new JPanel();
loadButtonPanel.setBounds(200, 440, 200, 100);
loadButtonPanel.setBackground(Color.BLACK);

loadButton = new JButton("LOAD");
loadButton.setBackground(Color.BLACK);
loadButton.setForeground(Color.WHITE);
loadButton.setFont(fontStart);
loadButton.setFocusPainted(false);
titrePanel.add(nomJeu);
loadButtonPanel.add(loadButton);

frame.add(startButtonPanel);
frame.add(titrePanel);

//------------------ECRAN MENU FIN---------------------
frame.setVisible(true);


}

还有游戏类...

public class Jeu {

ChoixJeu cj = new ChoixJeu();
UI ui = new UI();
Ecrans e = new Ecrans(ui);
Gameplay gp;

public static void main(String[] args) {

new Jeu();


}

public Jeu() {

ui.createUI(cj);
Gameplay gameplay = new Gameplay();
this.gp = gameplay;

}

public class ChoixJeu implements ActionListener {

@Override
public void actionPerformed(ActionEvent ae) {

String yourChoice = ae.getActionCommand();

switch (yourChoice) {
case "start":
e.montrerEcranJeu();
new Thread(gp).start();
ui.frame.add(gp);

break;
default:
break;
}

}

}

}

我还尝试创建一个隐藏菜单面板的类/方法

    public void montrerEcranJeu() {
//Cache Menu
ui.titrePanel.setVisible(false);
ui.startButtonPanel.setVisible(false);


//Montre Jeu
// ui.frame.add(gameplay);
}

以防万一游戏类。 run()方法在底部

public class Gameplay extends JPanel implements KeyListener, ActionListener, Runnable {

private Ship player = new Ship(new Point(200, 555));
Timer t = new Timer(5, this);


private ArrayList<Laser> lasers = new ArrayList<Laser>();
private int laserNb;
private boolean readytofire;
private boolean shot = false;


private ArrayList<Invader> invaders = new ArrayList<Invader>();

private boolean pause;

public Gameplay() {
super();
t.start();
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);

for (int j = 0; j < 80; j += 20) {
for (int i = 0; i < 20; i++) {
invaders.add(new Invader(5 + i * 30, j));
}
}
}

public boolean addLaser(Laser a) {
lasers.add(a);
return true;
}

public boolean addPlayer(Ship p) {

this.player = p;

return true;
}


@Override
public void keyTyped(KeyEvent ke) {

}

public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_RIGHT == e.getKeyCode()) {
moveRight();
}
if (KeyEvent.VK_LEFT == e.getKeyCode()) {
moveLeft();
}
if (KeyEvent.VK_SPACE == e.getKeyCode()) {
shoot();
System.out.println("Space Action from Gameplay is working");
}
}

@Override
public void keyReleased(KeyEvent e) {

}

@Override
public void actionPerformed(ActionEvent ae) {
repaint();
}


public void moveRight() {
if (player.getCentre().getX() >= 580) {
player.setX(580);
} else {
double movement = player.getCentre().getX();
movement += 10;
player.setX(movement);
}
this.repaint();
}

public void moveLeft() {
if (player.getCentre().getX() <= 20) {
player.setX(20);
} else {
double movement = player.getCentre().getX();
movement -= 10;
player.setX(movement);
}
this.repaint();
}


public void shoot() {

shot = true;
if (readytofire) {
Point top = new Point(player.getTopX(), player.getTopY());
Laser laser = new Laser(top);
addLaser(laser);

}
}


public void moveShot() {
if (shot) {
for (Laser l : lasers) {
l.setY(l.getTopLeft().getY() - 1);
}
}
}


@Override
public void paint(Graphics g) {
setBackground(Color.black);
super.paint(g);
player.draw(g);
for (Laser l : lasers) {
l.draw(g);
}
for (Invader i : invaders) {
i.draw(g);
}

}

// public void paintComponent (Graphics g){
// Controle Thread
public void run() {

while (true) {
moveShot();

for (Invader i : invaders) {
i.moveAndUpdate();

}
// for (Invader i : invaders) {
// if (){
// System.out.println("YOU ARE DEAD!");
// }

// }
try {
Thread.sleep(10);
readytofire = true;

} catch (InterruptedException ex) {
Logger.getLogger(Gameplay.class.getName()).log(Level.SEVERE, null, ex);
}
}

}

}

最佳答案

因此,使用 null 布局是问题的开始。我可能建议使用 CardLayout ,它旨在帮助您在 View 之间动态切换。请参阅How to Use CardLayout更多细节。我还建议花时间阅读 Laying Out Components Within a Container并找到一种或多种合适的布局来支持您的菜单。

你还犯了很多根本性的错误。 Swing 不是线程安全的,因此您应该避免从 EDT 上下文之外更新 UI(或 UI 所依赖的内容) - 请参阅 Concurrency in Swing欲了解更多信息和 How to Use Swing Timers寻找可能的解决方案。

作为一般建议,您应该避免重写 paint,并且对于从 JComponent 扩展的类,最好使用 paintComponent。您还应该避免调用可能会在绘制周期期间更改组件状态的方法,这会增加重绘请求的数量并降低程序的性能(即,不要在内部调用 setBackground油漆)。

看看Performing Custom PaintingPainting in AWT and Swing有关油漆系统如何工作以及如何最好地使用它的更多详细信息。

您还应该避免使用KeyListener,当您在图片中引入其他可聚焦的组件时,这可能会导致出现问题。相反,您应该选择 Key bindings API相反

I've read through [insert link or tutorial], but it still doesn't help...

如果这种情况不是一直发生,请原谅我。

向您提供教程链接的目的是鼓励您学习一些东西;

  • 了解在哪里可以找到问题的答案
  • 了解 API 的工作原理
  • 扩展您对 API 工作原理的了解和理解

话虽如此,他们的解决方案并不总是“显而易见”。当我处于这种情况时,我所做的就是从一个或多个新项目开始,专门致力于研究我想要理解的 API 的这一方面。因为在这里,我可以单独探索这些概念,当我“认为”我理解它们时,尝试将它们实现到我正在从事的项目中。这可能需要多次迭代,但一旦它起作用,我就对 API 有了更深入的理解和欣赏,然后我就可以从简单的“复制粘贴”解决方案中获得 yield

关于java - 从菜单切换到实际游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54383759/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com