java - Java 中的 2d 子弹游戏

标签 java optimization lag

我正在尝试用 Java 创建一个类似于东方的弹幕 hell 类型游戏。

我需要一些入门帮助,例如要遵循的示例。我尝试使用 JFrame 从头开始​​制作它,但我的主要问题是创建项目符号时的滞后。

我有一个项目符号类,带有参数使其从 A 到 B。但是每当程序创建或删除项目符号对象(存储在 ArrayList 中)时,它都会卡住一小部分时间,但是当有很多项目符号时,这种情况会变得非常明显。

我在这里使用 ArrayList 是错误的吗?建议使用哪些指南来学习如何正确执行此操作?

这是我的 Bullet 类:

    import java.awt.Graphics;

    public class Bullet
    {
      double x,y, xend, yend;
      int width, height;
      int life = 200;
      private static final double speed = 8;
      double dirX, dirY;

      public Bullet(double x, double y, double xend, double yend, int width, int height)
      {
        this.x=x;
        this.y=y;
        this.xend = xend;
        this.yend = yend;
        this.width = width;
        this.height = height;

        dirX = speed*Math.cos(getAngle());
        dirY = speed*Math.sin(getAngle());
      }

      public double getAngle()
      {
        double angle = (double) Math.toDegrees(Math.atan2(yend-y, xend - x));

        if(angle < 0){
            angle += 360;
        }
        System.out.println(angle);

        return Math.toRadians(angle);
      }

      public void tick()
      {
        life--;
        x+=dirX;
        y+=dirY;
      }

      public void draw (Graphics g)
      {
        g.fillRect((int) Math.round(this.x),(int) Math.round(this.y),this.width,this.height); 
      }
    }

这是用户创建项目符号时运行的代码。它使用 mouseListener 作为 xend Yend 坐标 - 查找子弹的目的地。

    public void fireNormal(double xend, double yend)
       {
          Bullet bullet= new Bullet (x,y,xend,yend,5,5);
          firedBullets.add(bullet);
        }
      }

我正在使用计时器来刷新游戏,但由于卡住,它的速度仍然不一致。

最佳答案

ArrayList.add() 通常应该非常快。有时,当实现必须添加新容量时,它将分配一个新的后备数组,将数据从一个数组复制到另一个数组,然后再继续。您可以通过在 ArrayList(int initialCapacity) 构造函数中指定合适的初始容量来避免这种情况。

但是,您需要数以万计的条目才能花费足够长的时间来增加明显的游戏延迟。

ArrayList.remove(int index) 必须将已删除项目上方的所有条目在后备数组中向下移动一个槽。然而,这是在 CPU 级别上进行了高度优化,并且除非您有数万颗子弹,否则不会增加明显的游戏延迟。

ArrayList.remove(Object o) 必须依次检查每个元素,并对每个元素运行 equals(),直到找到目标元素。避免这种情况!

<小时/>

您看到的暂停可能是由于垃圾收集造成的,这可能是因为您正在创建数千个短暂的Bullet对象。这些从他们被解雇的那一刻起一直持续到他们离开屏幕。当它们超出范围时,它们会保留在内存中,直到 GC 必须清除数千个它们。

您可以通过维护项目符号的对象池来避免这种情况。有些库具有对象池实现,或者您可以使用集合来推出自己的库。

在内存限制严格的环境中(例如 8 位游戏机),有必要确保游戏在固定内存中运行,这与这些平台上的程序所做的事情类似。

<小时/>

但是在尝试修复问题之前,您应该证明您的问题是什么,为此您需要使用 VisualVM 等分析器。这将显示您的执行在哪里花费了时间,以及它如何使用内存。不过,现代 Java 中的垃圾收集在大多数情况下都具有很高的性能 - 不要认为这是问题所在。

关于java - Java 中的 2d 子弹游戏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44138641/

相关文章:

java - 如何将多维json处理成3个数组

java - Java、C、C++等中十进制数的精度

javascript - 世界上有没有针对简单函数式语言自身的强大优化编译器?

c# - 如何优化和预编译这个 LINQ 表达式?

android - 极其滞后的 RecyclerView 性能

java - (Java) 在控制台中逐个字母地打印文本 - ft. Lag

java - 委派给抽象基类上的 setter 会导致加载时出现VerifyError

Java Swing : how to make scrollable view of items that may have buttons inside of them?

Java:如何有效地检查空指针

ios - 密集的数据处理使UI交互无法生效