我正在使用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函数继续运行时完成了一半。
答案 0 :(得分:2)
一些松散的想法(自从我在Swing中做了一些动画以来已经有好几年了),而且你没有发布一些可编译的代码。
Toolkit.getDefaultToolkit().sync()
如果没有帮助使用分析器找到瓶颈。 Visual VM非常好。 Visual VM也是jdk的一部分 - 只需进入bin文件夹并启动jvisualvm。
编辑:(主题问题)
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)
它是多余的,因为无论如何,它都被执行 - 只需将它移到条件之外。