Java 游戏开发:图形

2024-05-18

我是新来的。希望您能够提供帮助。

Problem:在 JFrame 上显示动画时出现问题。看来我对 Java 图形的工作原理不够了解/不够了解。

全球理念:假设我想制作一个游戏/电影/剪辑。为此,我需要这个(不)简单的动画开始工作。

这个问题的一个例子:我得到了 Screen 类,它具有屏幕内容 - JFrame 的声明,设置其配置(大小、关闭操作等),然后创建 Box 类的对象,以显示在框架上。请检查此图像/类图(希望我以正确的方式编写):类图 http://s20.postimg.org/zc640x91p/Flow.png

现在,Box 类扩展了 JPanel。我从 JPanel 继承了 Paint() 方法并重写它,绘制框。

在 Screen 类中,创建两个 Box 后,我将它们 .add() 到 JFrame 中。接下来,启动一个循环 while(true),并通过使线程休眠该时间来每 200 毫秒更新框的位置。 (在这种情况下,简单的 x++ 或 y++ 取决于哪个框,box1 或 box2)。

主要问题1):程序运行,并显示 JFrame,但在 JFrame 上它显示only最后添加的对象/组件 - Box。它没有显示另一张。为什么?

我找到了一个话题,如何向 JFrame 添加多个组件? https://stackoverflow.com/questions/4186835/how-to-add-multiple-components-to-a-jframe,并尝试了投票最多的帖子给出的提示,作者:jjnguy 2010-11-15 17:02。 由于某种奇怪的原因,第一个或第二个技巧都不适合我。

主要问题2):据我了解,我需要布局管理器。如果我只想在框架上的特定 X,Y 处绘制(),为什么需要它?

找到其他帖子(找不到了)+Oracle关于布局的指南,建议我需要考虑使用setLayout(null);我尝试这样做,但问题又出现了。

主要问题3):JFrame 出现了,它只显示了 1 个框(无论你做什么,绿色的框都不会显示。不知道为什么),当它移动时 - 它会从另一侧被擦除。 这里:盒子运动 http://s20.postimg.org/egjtpocul/Object_Movement.png

预先感谢您提供的任何帮助、提示和解释!希望这篇文章清晰、有条理、美观。


public class Screen {

public static void main(String[] args) {
    new Screen();
}

private JFrame window;

public Screen() {
    window = new JFrame("Multiply components panel");
    //window.setLayout(null);
    window.setSize(200, 200);

    window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    Box b1 = new Box(10,10, "box1");
    //b1.setBounds(10, 10, 50, 50);

    Box b2 = new Box(100,100, "box2");
    //b2.setBounds(100, 100, 50, 50);


    window.add(b1);
    //window.add(b2);


    window.setVisible(true);

    while (true){

        b1.update();
        b2.update();

        try {
            Thread.sleep(200);
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

}
}

public class Box extends JPanel{

int x, y, w, h;
private String name;

public Box(int x, int y, String name) {
    this.x = x;
    this.y = y;
    this.w = 100;
    this.h = 100;
    this.name=name;
}


public void paint(Graphics g){
    System.out.println(this.name.equalsIgnoreCase("box1"));
    if(this.name.equalsIgnoreCase("box1")){
        g.setColor(Color.BLACK);
        g.fillRect(x, y, w, h);
    }else{
        g.setColor(Color.GREEN);
        g.fillRect(x, y, w, h);
    }


}


public void update() {
    if(this.name.equalsIgnoreCase("box1"))
        x++;
    else
        y++;
    //this.setBounds(x, y, w, h);
    System.out.println("Current "+name+": X: "+x+", Y: "+y+", W: "+w+", H: "+h);
    repaint();
}

}

主要问题1):程序运行,并显示JFrame,但是在 JFrame 它仅显示最后添加的对象/组件框。事实并非如此 显示另一张。为什么?

You do window.add(b1); window.add(b2);, 默认情况下JFrame has BorderLayout因此,当您这样做时,您将替换最后添加的框add(..).

主要问题2):据我了解,我需要布局管理器。为什么 如果我只想在框架上的特定 X,Y 处绘制(),我需要它吗?

如果您正在使用JPanels 作为游戏中的对象,这将是唯一使用的时间setLayout(null)因为我们想要完全控制JPanels 放置。

主要问题3):JFrame显示出来,它只显示1个框(绿色的 无论你做什么,一个人都不会出现。不知道为什么)以及何时 确实移动了——它从另一边被抹掉了。此处:盒子运动

因为你你这样做g.fillRect(x,y,w,h), 它应该是g.fillRect(0,0,w,h)

其他问题:

1)我认为你遇到的一个主要问题是:

public class Box extends JPanel{

    ...

    public void paint(Graphics g){

       ...
    }

}

你应该覆盖paintComponent of JPanel,并记得打电话super.paintComponent(g)作为重写方法中的第一次调用。

3)你应该覆盖getPreferredSize of JPanel并返回与图像或内容匹配的正确尺寸JPanel

4)不要打电话setSize on JFrame使用正确Layoutmanager和/或覆盖getPreferredSize必要的容器而不是简单地调用pack() on JFrame在将其设置为可见之前。

5)正如@MadProgrammer所说,请阅读Swing 中的并发 http://docs.oracle.com/javase/tutorial/uiswing/concurrency/但基本上所有 Swing 组件都应该通过 EDT 创建/操作SwingUtilities.inokeXXX block.

6)这样做肯定是不好的:

while (true){

    b1.update();
    b2.update();

    try {
        Thread.sleep(200);
    } catch (Exception e) {
        // TODO: handle exception
    }
}

因为您不仅创建了一个连续循环,而且还调用Thread.sleep在您创建的 GUY 线程上,这似乎会冻结。看一下如何使用 Swing 定时器 http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html,另见this https://stackoverflow.com/questions/14074329/using-sleep-for-a-single-thread/14074427#14074427关于上述主题的类似问题。

以下是已实施上述修复的代码:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Screen {

    private JFrame window;

    public static void main(String[] args) {

        //creat UI on EDT
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Screen();
            }
        });
    }

    public Screen() {
        window = new JFrame("Multiply components panel") {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(600, 400);
            }
        };

        window.setLayout(null);//only reason this is warrented is because its a gmae using JPanels as game objects thus we need full control over its placing
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//changed from DISPOSE to EXIT so Timers  will be exited too

        final Box b1 = new Box(10, 10, 50, 50, "box1");

        final Box b2 = new Box(100, 100, 50, 50, "box2");

        window.add(b1);
        window.add(b2);

        window.pack();
        window.setVisible(true);

        Timer timer = new Timer(200, new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                b1.update();
                b2.update();
            }
        });
        timer.setInitialDelay(0);
        timer.start();

    }
}

class Box extends JPanel {

    int x, y, w, h;
    private String name;

    public Box(int x, int y, int w, int h, String name) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.name = name;
        setBounds(x, y, w, h);//let the Box class handle setting the bounds more elegant OOP
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.println(this.name.equalsIgnoreCase("box1"));
        if (this.name.equalsIgnoreCase("box1")) {
            g.setColor(Color.BLACK);
            g.fillRect(0, 0, w, h);
        } else {
            g.setColor(Color.GREEN);
            g.fillRect(0, 0, w, h);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(w, h);
    }

    public void update() {
        if (this.name.equalsIgnoreCase("box1")) {
            x++;
        } else {
            y++;
        }
        this.setBounds(x, y, w, h);//set the new bounds so box may be updated
        System.out.println("Current " + name + ": X: " + x + ", Y: " + y + ", W: " + w + ", H: " + h);
        revalidate();
        repaint();
    }
}

最后看看我的教程/代码片段游戏开发循环、逻辑和碰撞检测 Java Swing 2D http://www.daniweb.com/software-development/java/code/444547/game-development-loop-logic-and-collision-detection-java-swing-2d.

它拥有启动简单 2D 游戏所需的一切,例如游戏循环、逻辑、像素碰撞检测、动画(即在多个精灵之间交换以创建精灵集的动画)等等,但根本区别在于它使用对象作为游戏实体,即一个类将保存要绘制的对象的所有所需信息,IMO,这就是游戏应该如何完成的,事情可能会变得图形密集,并且许多 JPanels 怀疑屏幕肯定会降低整体 FPS

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 游戏开发:图形 的相关文章

  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • Java - 将节点添加到列表的末尾?

    这是我所拥有的 public class Node Object data Node next Node Object data Node next this data data this next next public Object g
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • Android MediaExtractor seek() 对 MP3 音频文件的准确性

    我在使用 Android 时无法在eek 上获得合理的准确度MediaExtractor 对于某些文件 例如this one http www archive org download emma solo librivox emma 01
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • Java TestNG 与跨多个测试的数据驱动测试

    我正在电子商务平台中测试一系列商店 每个商店都有一系列属性 我正在考虑对其进行自动化测试 是否有可能有一个数据提供者在整个测试套件中提供数据 而不仅仅是 TestNG 中的测试 我尝试不使用 testNG xml 文件作为机制 因为这些属性
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 如何从泛型类调用静态方法?

    我有一个包含静态创建方法的类 public class TestClass public static
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 使用 JMF 创建 RTP 流时出现问题

    我正处于一个项目的早期阶段 需要使用 RTP 广播DataStream创建自MediaLocation 我正在遵循一些示例代码 该代码目前在rptManager initalize localAddress 出现错误 无法打开本地数据端口

随机推荐