繁体   English   中英

如何减少我的Java 2D Platformer的滞后?

[英]How to reduce lag in my java 2d platformer?

我正在使用Swing Java开发2D平台游戏,我想知道如何减少从它获得的延迟。 我的意思是,它并不会太落后,但值得注意的是它有时会变慢。 我有一个在12毫秒处滴答作响的Swing计时器,一个循环功能和一个绘画功能。

public void cycle() {
    if (guy.getJumpState() == false) {
        if (canExecuteMovement(0, 4)) {
            onGround = false;
            if (guy.getY() > 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() - 4);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(4);
            }
        } else {
            onGround = true;
        }
    } else {
        if (canExecuteMovement(0, -8)) {
            if (guy.getY() < 300) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setY(platform[i].getY() + 8);
                }
            } else {
                // or just move the guy if not.
                guy.moveY(-8);
            }
            jumpCount++;
            if (jumpCount >= 15) {
                jumpCount = 0;
                guy.setJumpState(false);
            }
        } else {
            jumpCount = 0;
            guy.setJumpState(false);
        }
    }

    if (guy.getDirection() == "left") {
        if (canExecuteMovement(-3, 0)) {
            if (guy.getX() < 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() + 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(-3);
            }
        }
    } else if (guy.getDirection() == "right") {
        if (canExecuteMovement(3, 0)) {
            if (guy.getX() > 450) {
                // if you are in the middle, move the platforms.
                for (int i = 0; i < platformCount; i++) {
                    platform[i].setX(platform[i].getX() - 3);
                }
            } else {
                // or just move the guy if not.
                guy.moveX(3);
            }
        }
    }
}


public void paint(Graphics g) {
    super.paint(g); // something important
    Graphics2D g2d = (Graphics2D) g;

    // draw platforms
    for (int i = 0; i < platformCount; i++) {
        if (platform[i].getX() > -50 && platform[i].getX() < 950 && platform[i].getY() > -50 && platform[i].getY() < 650) {
            g2d.drawImage(platform[i].getImage(), platform[i].getX(), platform[i].getY(), this);
        }
    }

    // draw guy
    g2d.drawImage(guy.getImage(), guy.getX(), guy.getY(), this);

    // destroy unneeded processes
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

我该怎么做才能优化这一点并减少延迟? 当我为循环功能本身创建线程时,平台有时会瞬间分开。 我假设是因为线程是异步的,所以它的一半是在paint函数打开时完成的。

一些松散的想法(自从我在Swing中制作动画以来已经有好几年了),并且您没有发布一些可编译的代码。

  • 您是否尝试过paintComponent()--- paint还有很多其他功能。 然后也许您需要将repaint()添加到tick函数。 每次我重新装油漆时,它都会变得一团糟。
  • 也可以尝试增加刻度时间---您浪费的时间更少。
  • 我还假设您正在按计时器进行滴答作响。
  • 我不知道为什么要放置图形对象
  • 也可以尝试仅删除同步(没有它,我就已经完成了可以在许多类中工作的动画) Toolkit.getDefaultToolkit().sync()

如果这样做没有帮助,请使用探查器查找瓶颈。 Visual VM非常不错。 另外,Visual VM在一段时间内还是jdk的一部分-只需进入bin文件夹并启动jvisualvm。

编辑:(线程问题)

  • 有人建议使用线程---我不同意。 如果要在EDT之外进行一些工作,请使用SwingWorker
  • 我假设您不是在调用paint()而是在调用repeaint() 如果您确实调用了paint() (无论您使用什么黑魔法都可以使它起作用),请仅调用repaint()即可在适当的时间安排修复。

我会在方法之外创建变量,以免每次调用该方法时都不会创建该变量。 编写游戏程序的最佳方法是重用事物而不是破坏和创造,因为破坏和创造会消耗大量的计算能力。

Graphics2D g2d = (Graphics2D) g; <---declare it outside your method.

并尝试查找多余的条件。 我在您说的地方看到了一个(如果向右的方向是...,否则向左的方向...); 只是说(如果方向正确,则...否则...)。 有条件的花费不多,但是当您每秒调用该有条件的1000次时,我认为它加起来了。 (虽然idk,但我这样做是为了以防万一,并使事情变得流畅)

在说setjumpstate(false)的地方,这是多余的,因为无论执行什么操作,都将其执行-只需将其移至条件setjumpstate(false)之外即可。

首先,这是一个问题:

// destroy unneeded processes
Toolkit.getDefaultToolkit().sync();
g.dispose();

通常,处置未创建的资源可能是个坏主意。 在这种特定情况下,传递给paint()Graphics可能会被层次结构中的所有其他组件使用,因此这可能会导致非常奇怪的结果。

我认为在这里调用Toolkit.sync()是您尝试消除在后台移动事物时看到的撕裂感的尝试。 但是,它所做的只是刷新所有未决的绘制指令。 这在这里没有效果,因为您可能正在绘制一个将在以后完全绘制的后缓冲Swing组件。

消除撕裂的正确方法是在事件线程上执行任何更新,以便在绘制时不会更改屏幕数据。 一种简单的实现方法是让您的计时器只调用repaint() ,并在执行任何操作之前让paint()方法调用cycle()。

为了处理延迟,一种解决方案可能是允许使用可变帧速率。 不必将所有内容每帧移动固定距离,而是计算自上一帧以来的时间并相应地移动所有内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM