如何减少我的java 2d平台游戏中的延迟?

时间:2012-01-23 23:36:39

标签: java scroll 2d

我正在使用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函数继续运行时完成了一半。

3 个答案:

答案 0 :(得分:2)

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

  • 你有没有尝试过paintComponent()--- paint做了很多其他的事情。然后你可能需要在tick函数中添加repaint()。每当我重装油漆时,它就会变得一团糟。
  • 同时尝试增加刻度时间 - 你会浪费更少的时间来修复。
  • 我还假设你正在做计时器的滴答声。
  • 我不知道你为什么要处理图形对象
  • 还可以尝试删除同步(我已经完成了可以在没有它的情况下处理许多事情的动画)Toolkit.getDefaultToolkit().sync()

如果没有帮助使用分析器找到瓶颈。 Visual VM非常好。 Visual VM也是jdk的一部分 - 只需进入bin文件夹并启动jvisualvm。

编辑:(主题问题)

  • 有些人建议使用线程---我是diasgree。如果您想在EDT之外做一些工作,请使用SwingWorker
  • 我假设您没有致电paint()但只是致电repeaint()。如果你打电话给paint()(无论你做了什么黑魔法让它起作用),请拨打repaint(),安排在适当的时间进行修复。

答案 1 :(得分:1)

首先,这里有一个问题:

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

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

在这里拨打paint()我认为你试图消除你在后台移动东西时所看到的撕裂。但它所做的只是刷新任何待处理的绘图指令。这对此没有任何影响,因为您可能正在绘制一个后缓冲的Swing组件,该组件将在稍后完全绘制。

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

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

答案 2 :(得分:1)

我会在方法之外创建变量,这样每次调用该方法时都不会创建变量。编程游戏的最佳方法是重复使用而不是破坏和创建,因为破坏和破坏游戏。创造成本很多的计算能力。

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

并尝试寻找冗余条件。我看到你说的一个(如果方向正确那么......,否则如果方向离开......);只是说(如果方向正确那么......其他......)。条件不会花费太多,但是当你每秒调用1000次条件时,我认为它会增加。 (尽管如此,但我这样做只是为了以防万一,并且让事情变得流畅)

你说setjumpstate(false)它是多余的,因为无论如何,它都被执行 - 只需将它移到条件之外。