【问题标题】:Game In Java Not Adding JLabel With IconJava中的游戏不添加带有图标的JLabel
【发布时间】:2014-11-17 23:09:38
【问题描述】:

我正在用 Java 开发一个基本游戏,类似于 2d 游戏,您可以在太空飞船中躲避小行星。

我的问题是,由于某种原因,我的一些小行星没有正确添加到我的 JFrame 中。

这是我添加 JLabel(小行星)的方法:

注意:SpriteSheet.java 是一个有效且正常运行的类,它确实成功返回了图像。

@SuppressWarnings("serial")
class Entity extends JLabel {

    private int asteroidSizeW = 72;
    private int asteroidSizeH = 72;
    private int entities = 5;

    public Entity() {
        List<Integer> asteroidLocations = new ArrayList<Integer>();
        Random ran = new Random();

        for (int i = 0; i < entities; i++) {
            if (asteroidLocations.size() > 0) {
                for (int j = 0; j < asteroidLocations.size(); j++) {
                    int chosenSpawn = ran.nextInt(Frame.WIDTH - 72);
                    if (chosenSpawn > (asteroidLocations.get(j) + 72) || chosenSpawn < (asteroidLocations.get(j) - 72)) {
                        System.out.println("Made it!");
                        System.out.println(asteroidLocations);
                        asteroidLocations.add(chosenSpawn);
                        setIcon(new SpriteSheet().load("asteroids.png", 0, 0, asteroidSizeW, asteroidSizeH));
                        setLocation(chosenSpawn, 0);
                        setSize(asteroidSizeW, asteroidSizeH);
                        break;
                    }
                }
            } else {
                int x = ran.nextInt(Frame.WIDTH - 72);
                asteroidLocations.add(x);

                setIcon(new SpriteSheet().load("asteroids.png", 0, 0, asteroidSizeW, asteroidSizeH));
                setLocation(x, 0);
                setSize(asteroidSizeW, asteroidSizeH);
            }
        }
    }
}

经过测试我发现第一个JLabel正在被添加(else in):

if (asteroidLocations.size() > 0) {
} else {
// this is being executed once (like it should)
}

换句话说,第一张图片 (JLabel) 确实会显示在游戏中。

其他一切都按照输出的预期工作:

Made it!
[181]
Made it!
[181, 273]
Made it!
[181, 273, 452]
Made it!
[181, 273, 452, 627]

在嵌套循环中返回 JLabel 似乎有问题。

有人可以帮帮我吗?谢谢。

全班:

package main;

import java.awt.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.List;
import javax.swing.*;

@SuppressWarnings("serial")
class Frame extends JFrame {

    public static final int WIDTH = 800;
    public static final int HEIGHT = 800;
    private String TITLE = "Asteroid Killer";

    public static void main(String args[]) {
        Frame f = new Frame();
        f.createFrame();
        f.showFrame();
    }

    private void createFrame() {
        setTitle(TITLE);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        add(new MainPanel());
        setSize(WIDTH, HEIGHT);
    }

    private void showFrame() {
        this.setVisible(true);
    }

}

@SuppressWarnings("serial")
class MainPanel extends JPanel {
    public MainPanel() {
        setLayout(null);
        setBackground(Color.GRAY);
        //add(new Minimap());
        add(new Entity());
    }
}

/*@SuppressWarnings("serial")
class Minimap extends JPanel {
    public Minimap() {
        setBounds(284, 0, 100, 100); // x,y,width,height
        setBackground(Color.RED); 
    }
}*/

@SuppressWarnings("serial")
class Entity extends JLabel {

    private int asteroidSizeW = 72;
    private int asteroidSizeH = 72;
    private int entities = 5;

    public Entity() {
        List<Integer> asteroidLocations = new ArrayList<Integer>();
        Random ran = new Random();

        for (int i = 0; i < entities; i++) {
            if (asteroidLocations.size() > 0) {
                for (int j = 0; j < asteroidLocations.size(); j++) {
                    int chosenSpawn = ran.nextInt(Frame.WIDTH - 72);
                    if (chosenSpawn > (asteroidLocations.get(j) + 72) || chosenSpawn < (asteroidLocations.get(j) - 72)) {
                        System.out.println("Made it!");
                        System.out.println(asteroidLocations);
                        asteroidLocations.add(chosenSpawn);
                        setIcon(new SpriteSheet().load("asteroids.png", 0, 0, asteroidSizeW, asteroidSizeH));
                        setLocation(chosenSpawn, 0);
                        setSize(asteroidSizeW, asteroidSizeH);
                        break;
                    }
                }
            } else {
                int x = ran.nextInt(Frame.WIDTH - 72);
                asteroidLocations.add(x);

                setIcon(new SpriteSheet().load("asteroids.png", 0, 0, asteroidSizeW, asteroidSizeH));
                setLocation(x, 0);
                setSize(asteroidSizeW, asteroidSizeH);
            }
        }
    }
}

【问题讨论】:

  • 我可以说出几十、几千个为什么这可能不起作用的原因,或者你可以考虑提供一个 runnable example 来证明你的问题。这将导致更少的混乱和更好的响应。在您告诉我们它太大之前,可运行示例的目的是成为一个简化版本,以展示您面临的问题......
  • 我已经在帖子末尾发布了完整的课程,不包括 spritesheet 课程。

标签: java swing


【解决方案1】:

你的逻辑是倒退的。您只需要在容器中添加一个 JLabel...

add(new Entity());

实际上,Entity 类除了自身的单一表示之外,没有办法将任何东西放到屏幕上……这通常是它在 for 循环中创建的最后一件事……

不要尝试在您的 Entity 类中创建多个实体(我知道,您只是设置属性,但意图是相同的),而是将创建过程移到 MainPanel 并物理创建每个循环都有一个新的Entity

现在,话虽如此,以这种方式拧组件可能不是最好的解决方案。您应该考虑使用自定义绘制方法,您会发现管理所有实体更容易,并且可能还会消耗更少的开销...

考虑看看

更多详情

【讨论】:

  • 这意味着我无法定义我的asteroidLocations 列表,否则每次运行循环时都会重置它。我怎么能躲开呢?我不想在任何其他类中定义它。
  • 假设您想继续使用基于组件的实体,您可以通过多种方式解决该问题。您可以定义一个实体管理器,负责管理系统中的所有实体,包括创建、更新和销毁它们。同样,您可以创建一个LayoutManager,它允许您定义各个实体的属性并允许您在现有的基于组件的 API 的范围内工作。或者您可以简单地遍历当前容器中包含的所有组件并手动修改它们。
猜你喜欢
  • 2017-03-28
  • 2014-06-30
  • 1970-01-01
  • 2022-06-19
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
  • 2012-09-23
  • 2010-10-10
相关资源
最近更新 更多