Java加速度物理引擎无法减速/停止问题求助
物理引擎减速逻辑不执行问题排查与修复
我开发了一款带加速度功能的物理引擎,但尝试让物体停止时,它既不减速也不停止。排查后发现if(deaccelerating) {...}代码块从未执行,试了多种方法都解决不了。相关代码如下:
原始Acceleration类代码
public class Acceleration { public float rateOfVelocity = 0.125f; public float rateOfAcceleration = 2; public int alternateRateOfVelocity = 1; public int alternateRateOfAcceleration = 2; public boolean accelerating; public boolean deaccelerating; public boolean alternateAccelerating; public boolean alternateDeaccelerating; public boolean loopedOnce; public void accelerate(float max, float min) { if(accelerating) { if(rateOfVelocity < max) { while(rateOfVelocity < max && !loopedOnce) { rateOfVelocity*=rateOfAcceleration; System.out.println(":)"); loopedOnce=true; } } if(rateOfVelocity >= max || !accelerating){ deaccelerating=true; System.out.println(deaccelerating); } } if(deaccelerating) { if(rateOfVelocity > min) { while(rateOfVelocity < min && !loopedOnce) { rateOfVelocity/=rateOfAcceleration; loopedOnce=true; } } else if(rateOfVelocity <= min) { deaccelerating=false; } } } public void alternateAccelerate(float max, float min) { if(alternateAccelerating) { if(alternateRateOfVelocity < max) { while(alternateRateOfVelocity < max && !loopedOnce) { alternateRateOfVelocity*=rateOfAcceleration; loopedOnce=true; } } } else if(alternateDeaccelerating) { while(rateOfVelocity > min && !loopedOnce) { alternateRateOfVelocity/=alternateRateOfAcceleration; loopedOnce=true; } } } }
原始调用代码(DisplayContents类)
public class DisplayContents extends JPanel implements Runnable{ Thread run; Acceleration a = new Acceleration(); float x=0,y=0; public boolean updateSpeed; public void startThread() { run = new Thread(this); run.start(); } public DisplayContents() { this.setBackground(Color.DARK_GRAY); this.setDoubleBuffered(true); this.setFocusable(true); this.addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_D) { a.accelerating=true; updateSpeed=true; } } @Override public void keyReleased(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_D) { a.accelerating=false; } } @Override public void keyTyped(KeyEvent e) {} }); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D draw = (Graphics2D) g; draw.setColor(Color.WHITE); draw.fillRect((int)x, 0, 100, 100); draw.dispose(); } @Override public void run() { boolean loopedOnce = false; while(run != null) { repaint(); a.accelerate(4, 0.125f); a.loopedOnce=false; while(updateSpeed&&!loopedOnce) { x+=a.rateOfVelocity; loopedOnce=true; } loopedOnce=false; try { Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace();} } } }
问题根源分析
- 减速触发逻辑被嵌套死:
deaccelerating=true的判断放在if(accelerating)代码块内部,只有当accelerating为true时才会执行这个分支。但松开按键后accelerating会被设为false,根本进不去这个代码块,永远无法激活减速状态。 - 减速循环条件完全写反:
while(rateOfVelocity < min && !loopedOnce)——减速需要速度从大于最小值降到阈值内,但这个条件要求速度已经低于最小值才执行循环,逻辑完全颠倒。 - loopedOnce重置时机错误:调用
a.accelerate()之后才重置loopedOnce,导致每次执行加速逻辑时,loopedOnce还是上一次的true状态,直接跳过循环,逻辑无法运行。
修复后的代码
Acceleration类修改版
public class Acceleration { public float rateOfVelocity = 0.125f; public float rateOfAcceleration = 2; public int alternateRateOfVelocity = 1; public int alternateRateOfAcceleration = 2; public boolean accelerating; public boolean deaccelerating; public boolean alternateAccelerating; public boolean alternateDeaccelerating; public boolean loopedOnce; public void accelerate(float max, float min) { if(accelerating) { deaccelerating = false; // 加速时强制关闭减速状态 if(rateOfVelocity < max) { while(rateOfVelocity < max && !loopedOnce) { rateOfVelocity *= rateOfAcceleration; System.out.println("加速中:" + rateOfVelocity); loopedOnce = true; } } // 达到最大速度后自动切换减速 if(rateOfVelocity >= max) { accelerating = false; deaccelerating = true; System.out.println("触发自动减速"); } } // 把减速逻辑移到外部,确保松开按键后能触发 if(deaccelerating || !accelerating) { if(!accelerating && !deaccelerating) { deaccelerating = true; } if(rateOfVelocity > min) { // 修正循环条件:速度大于最小值时才执行减速 while(rateOfVelocity > min && !loopedOnce) { rateOfVelocity /= rateOfAcceleration; System.out.println("减速中:" + rateOfVelocity); loopedOnce = true; } } else if(rateOfVelocity <= min) { deaccelerating = false; rateOfVelocity = min; // 固定到最小速度,避免过度减速 System.out.println("已停止"); } } } public void alternateAccelerate(float max, float min) { if(alternateAccelerating) { if(alternateRateOfVelocity < max) { while(alternateRateOfVelocity < max && !loopedOnce) { alternateRateOfVelocity *= rateOfAcceleration; loopedOnce = true; } } } else if(alternateDeaccelerating) { // 修正变量错误:使用alternateRateOfVelocity而非rateOfVelocity while(alternateRateOfVelocity > min && !loopedOnce) { alternateRateOfVelocity /= alternateRateOfAcceleration; loopedOnce = true; } } } }
DisplayContents类修改版
public class DisplayContents extends JPanel implements Runnable{ Thread run; Acceleration a = new Acceleration(); float x=0,y=0; public boolean updateSpeed; public void startThread() { run = new Thread(this); run.start(); } public DisplayContents() { this.setBackground(Color.DARK_GRAY); this.setDoubleBuffered(true); this.setFocusable(true); this.addKeyListener(new KeyListener() { @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_D) { a.accelerating=true; updateSpeed=true; } } @Override public void keyReleased(KeyEvent e) { if(e.getKeyCode()==KeyEvent.VK_D) { a.accelerating=false; a.deaccelerating = true; // 松开按键直接触发减速 } } @Override public void keyTyped(KeyEvent e) {} }); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D draw = (Graphics2D) g; draw.setColor(Color.WHITE); draw.fillRect((int)x, 0, 100, 100); // 移除手动dispose,交给Swing管理绘图资源 } @Override public void run() { boolean loopedOnce = false; while(run != null) { repaint(); // 先重置loopedOnce,再执行加速逻辑 a.loopedOnce = false; a.accelerate(4, 0.125f); while(updateSpeed&&!loopedOnce) { x += a.rateOfVelocity; loopedOnce=true; } loopedOnce=false; try { Thread.sleep(500); } catch (InterruptedException e) {e.printStackTrace();} } } }
关键修复点总结
- 将减速触发逻辑从
if(accelerating)代码块中移出,确保松开按键后能进入减速判断 - 修正减速循环条件,从
rateOfVelocity < min改为rateOfVelocity > min - 调整
loopedOnce的重置时机到accelerate方法调用之前,保证每次逻辑执行都是初始状态 - 在按键松开时直接设置
deaccelerating=true,让减速逻辑立刻触发 - 移除
paintComponent中的draw.dispose(),避免Swing绘图资源被提前释放
内容的提问来源于stack exchange,提问作者Grinding For Reputation
相关产品推荐
相关产品推荐

