运行Java 3D游戏引擎代码时Eclipse崩溃、Java无响应求助
问题分析与解决方案
你的问题根本不是按键索引的问题,而是Input类的update方法存在严重的性能瓶颈,这才导致了帧率暴跌和程序崩溃。咱们来拆解下原因:
为什么你的代码会卡?
你用了ArrayList的contains()方法来检查按键状态,而contains()是O(n)复杂度的操作——每次调用都要遍历整个列表找元素。你的update方法里有三重循环,每重都要跑256次,每次循环还可能触发多次contains(),这相当于每次update都要做几十万次无效遍历,CPU直接被拉满,帧率自然跌到2FPS,最后因为负载过高导致程序无响应。
作者的电脑可能性能更强,或者他的游戏循环逻辑里update的调用频率更低,所以没触发这个问题,但你的机器扛不住这种低效写法。
优化方案:用数组替代ArrayList
既然键码是固定的0-255范围,完全可以用布尔数组来存储按键状态,数组的访问是O(1)的,能把性能提升几个数量级。优化后的代码如下:
import java.util.Arrays; import org.lwjgl.input.Keyboard; public class Input { public static final int NUM_KEYCODES = 256; // 用布尔数组替代ArrayList,直接通过键码索引访问状态 private static boolean[] currentKeys = new boolean[NUM_KEYCODES]; private static boolean[] downKeys = new boolean[NUM_KEYCODES]; private static boolean[] upKeys = new boolean[NUM_KEYCODES]; public static void update() { // 先重置本次更新的down/up状态 Arrays.fill(downKeys, false); Arrays.fill(upKeys, false); // 遍历所有键码,对比当前状态和上一帧状态 for (int i = 0; i < NUM_KEYCODES; i++) { boolean isCurrentlyDown = Keyboard.isKeyDown(i); if (isCurrentlyDown != currentKeys[i]) { if (isCurrentlyDown) { // 按键刚被按下 downKeys[i] = true; } else { // 按键刚被释放 upKeys[i] = true; } // 更新当前状态为最新值 currentKeys[i] = isCurrentlyDown; } } } public static boolean getKey(int keyCode) { return currentKeys[keyCode]; } public static boolean getKeyDown(int keyCode) { return downKeys[keyCode]; } public static boolean getKeyUp(int keyCode) { return upKeys[keyCode]; } }
额外注意事项
- 确保你已经正确初始化了LWJGL的Keyboard模块——在游戏启动时要调用
Keyboard.create()(如果是旧版本LWJGL),否则Keyboard.isKeyDown()可能会返回异常结果。 - 检查你的游戏循环:确保
Input.update()只在每一帧调用一次,不要重复调用增加不必要的负载。
这个优化应该能立刻解决你的卡顿和崩溃问题,因为数组操作的效率比ArrayList的遍历高太多了。
内容的提问来源于stack exchange,提问作者Gentus72
相关产品推荐
相关产品推荐

