You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

匀变速直线运动(UVRM)动画开发:小车停止控制与窗口适配问题求助

问题核心原因梳理

  1. Timer参数使用错误:Swing的Timer构造方法第一个入参是两次回调触发的间隔毫秒数,不是动画总运行时长,你之前把总时长传入会导致整个动画刷新逻辑完全不符合预期。
  2. 位移计算逻辑错误:匀变速直线运动的位移不能每次固定加加速度值,需要结合运行时间按物理公式计算,否则运动速度不符合匀变速规则。
  3. 停止判断逻辑缺失:原有逻辑只判断了距离阈值,没有加入时间耗尽、超出窗口边界的判断。

具体修改方案

1. 调整Timer初始化与动画逻辑

动画刷新间隔统一设为16ms(对应约60帧的流畅效果),新增变量记录动画开始时间、总运行时长,每次回调时计算已运行时间,再按匀变速公式计算位移。

2. 补充多条件停止判断

同时满足以下任意一个条件就停止动画:

  • 动画已运行时长 >= 设定的总时长
  • 小车右边缘 >= 目标距离阈值
  • 小车右边缘 >= 面板当前宽度(避免超出窗口)

3. 新增位置适配逻辑

每次计算位移后先判断是否超出面板边界,若超出则把小车位置固定在窗口右边缘内再停止。


修改后代码参考

Car类修改(新增重置位置方法)

public class Car {
    private final ImageIcon imagen;
    private double posx;
    private int width;

    public Car() {
        imagen = new ImageIcon(getClass().getResource("/images/carred.png"));
        posx = 10;
        width = 400;
    }

    // 新增重置位置方法,避免多次触发动画时位置累积
    public void resetPos() {
        posx = 10;
    }

    public double getPosx() {
        return posx;
    }

    public int getWidth() {
        return width;
    }

    public void setPosx(double posx) {
        this.posx = posx;
    }

    public void draw(Graphics g){
        g.drawImage(imagen.getImage(), (int) posx , 50, width, 300, null);
    }

    public void move(double x){
        posx+=x;
    }
}

JPanel相关代码修改

private void btnCalcActionPerformed(java.awt.event.ActionEvent evt) {                                        
    String text_vf = txfvf.getText();
    String text_v0 = txfv0.getText();
    String text_a = txfa.getText();
    String text_d = txfd.getText();
    String text_t = txft.getText();
    String res = "message.. res";

    // 原有计算逻辑保留
    // 注意:这里传入的t是秒数,后面转成毫秒作为总动画时长
    moveCarImage(t * 1000, Integer.parseInt(text_v0), a, Integer.parseInt(text_d));
}           


private void moveCarImage(double totalDurationMs, double v0, double acceleration, int fDistance) {
    // 先重置小车初始位置
    car.resetPos();
    // 记录动画开始时间
    long startTime = System.currentTimeMillis();
    // 动画刷新间隔设为16ms,约60帧
    int frameInterval = 16;
    
    // 如果之前有运行的timer先停止,避免多次点击生成多个timer
    if (timer != null && timer.isRunning()) {
        timer.stop();
    }

    timer = new Timer(frameInterval, (e) -> {
        // 计算已运行时长,单位转成秒用于物理计算
        double elapsedTimeS = (System.currentTimeMillis() - startTime) / 1000d;
        // 匀变速位移公式:s = v0*t + 0.5*a*t²
        double currentDisplacement = v0 * elapsedTimeS + 0.5 * acceleration * elapsedTimeS * elapsedTimeS;
        // 更新小车位置
        car.setPosx(10 + currentDisplacement);

        // 停止条件判断
        boolean isTimeOut = (System.currentTimeMillis() - startTime) >= totalDurationMs;
        boolean isReachDistance = (car.getPosx() + car.getWidth()) >= fDistance;
        boolean isOverFrame = (car.getPosx() + car.getWidth()) >= this.getWidth();
        
        if (isTimeOut || isReachDistance || isOverFrame) {
            timer.stop();
            // 超出窗口时把小车位置固定在右边缘内
            if (isOverFrame) {
                car.setPosx(this.getWidth() - car.getWidth());
            }
            System.out.println("Car Stopped.........");
        }
        repaint();
    });
    timer.start();
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    car.draw(g);
}

内容的提问来源于stack exchange,提问作者DarkVaderM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 12:57:00