当前位置: 首页 > 知识库问答 >
问题:

子弹弹道

夹谷成龙
2023-03-14

首先,我要用大炮射击一架飞机。我已经设定了弹道的时间线,但我没有看到子弹在我的现场。很可能我的轨迹代码不正确。我试着在网上看关于抛射运动的公式,但我对物理一无所知;

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Game_1 extends Application {

    private final double gravity = 9.81;
    private Timeline timeline;
    private ImageView plane;
    private Circle circle;
    private AnchorPane ap;

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Test");
        Group group = new Group();
        Scene scene = new Scene(group, 600, 350);
        scene.setFill(Color.BLACK);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void shoot() {
        double x = 65.0f;
        double y = 408;
        double speed = 200;
        double t = 2;
        double angle = -45;
        double dx = Math.cos(angle) * speed;
        double dy = Math.sin(angle) * speed;
        circle = new Circle(x, y, 5, Color.BLACK);
        double x2 = x + dx * t;
        double y2 = (Math.tan(angle) * y - (gravity / (2 * Math.pow(speed, 2) * Math.cos(angle))) * Math.pow(x, 2));
        timeline = new Timeline();
        KeyValue xKV = new KeyValue(circle.centerXProperty(), x2);
        KeyValue yKV = new KeyValue(circle.centerYProperty(), y2, new Interpolator() {
            @Override
            protected double curve(double t) {
                return y + dy * t - 0.5 * gravity * t * t;
            }
        });
        KeyFrame xKF = new KeyFrame(Duration.seconds(t), xKV);
        KeyFrame yKF = new KeyFrame(Duration.seconds(t), yKV);
        timeline.getKeyFrames().addAll(xKF, yKF);
        ap.getChildren().add(circle);
        timeline.play();
        collision();
    }

    private void collision() {
        circle.boundsInParentProperty().addListener((ObservableValue<? extends Bounds> arg0, Bounds oldValue2, Bounds newValue2) -> {
            if (circle.getBoundsInParent().intersects(plane.getBoundsInParent())) {
                timeline.stop();
                ap.getChildren().remove(circle);
            }
        });
    }
}

共有1个答案

公孙胡媚
2023-03-14

曲线方法应映射到时间间隔[0,1]。但是,您的方法映射到更高的值。对于给定起始值val0和结束值val1,从t0的内插器i动画的时间tvalt:

val = val0 + (val1 - val0) * i.curve((t - t0) / (t1 - t0))

曲线方法的参数是时间间隔中的相对位置(0=动画开始;1=动画结束)。方法的结果用于确定值与结束值的接近程度(0=仍然在起始值;1=在结束值)。

因此,您可能应该计算炮弹曲线中的顶点hmax(如维基百科所述),并使用不同的内插器:

Interpolator interpolator = new Interpolator() {
    @Override
    protected double curve(double t) {
        // parabola with zeros at t=0 and t=1 and a maximum of 1 at t=0.5
        return 4 * t * (1 - t);
    }
};

KeyValue yKV = new KeyValue(circle.centerYProperty(), hMax, interpolator);

注意,向上移动意味着减少UI的y坐标,因此在本例中hmax应该小于开始时的y值。

因为您的shoot方法从未被调用,并且某些字段没有被初始化,这将导致在调用时出现NPE。此外,如果这两个问题得到解决,黑色背景上的黑色圆圈将很难看到...

请注意,这没有使用任何物理fromulae,而是使用了我选择的一些值:

@Override
public void start(Stage primaryStage) {
    Circle circle = new Circle(10);
    circle.setManaged(false);
    Pane pane = new Pane(circle);

    circle.setCenterX(20);
    circle.setCenterY(800);

    Timeline timeline = new Timeline(new KeyFrame(Duration.ZERO,
            new KeyValue(circle.centerXProperty(), 20),
            new KeyValue(circle.centerYProperty(), 800)
        ), new KeyFrame(Duration.seconds(3),
            new KeyValue(circle.centerXProperty(), 380),
            new KeyValue(circle.centerYProperty(), 10, new Interpolator() {
                @Override
                protected double curve(double t) {
                    // parabola with zeros at t=0 and t=1 and a maximum of 1 at t=0.5
                    return 4 * t * (1 - t);
                }
            })
        )
    );

    Scene scene = new Scene(pane, 400, 800);
    scene.setOnMouseClicked(evt -> timeline.playFromStart());
    primaryStage.setScene(scene);
    primaryStage.show();
}

使用一半的时间间隔,每一个结束值的顶部和开始y坐标的曲线分别。

 类似资料:
  • 子弹图用作衡量标准或指标以显示措施的表现。它可以使用子弹图比较两种测量方法。 子弹图也是条形图的变体。在子弹图中,我们在找到第一个度量和第二个度量之间的差异的上下文中将一个度量的值与另一个度量进行比较。 它就像是两个相互绘制的条形图,用于在图形中的相同位置指示它们的值。它可以用作将两个图组合为一个以容易地查看比较结果。 例如,考虑数据源:Sample-Superstore,要将Estimated

  • CSS3 弹性盒子(Flex Box) 弹性盒子是 CSS3 的一种新的布局模式。 CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。 引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本号。

  • 弹性盒子(Flexible Box)是一种用于按行或按列布局元素的一维布局方法,使用该布局的组件即为弹性容器(flex container),容器内的直系子组件则是弹性项目(flex item),他们可以膨胀以填充额外的空间,收缩以适应更小的空间,它们在 CSS 属性都为初始的情况下都会有下列行为: 项目排列成一行。(容器的 flex-direction 属性的初始值是 row) 项目从主轴的起始

  • 文字提示(带标题) <div class="ui-dialog show"> <div class="ui-dialog-cnt"> <div class="ui-dialog-bd"> <h3>下线通知</h3> <p>你的账号于17:00在一台Android手机登录。如非本人操作,密码可能已泄露,建议立即冻结账号。

  • 发布弹幕 调用地址 http://api.bilibili.cn/comment/post 需要 App Key 并验证登录状态(Access key);要求应用申请弹幕权限 参数 字段 必选 传递方式 类型 说明 mid true POST int 发布帐号(必须和 access_key 帐号一致) cid true POST int 视频ID playTime true POST float

  • Barrage.New事件 Barrage.New事件会在收到新的弹幕时被触发 Mudu.MsgBus.On( // 事件名,值为"Barrage.New" "Barrage.New", // 事件处理函数,参数为弹幕对象 function (barrage) { barrage = JSON.parse(barrage) console.log('收到新的弹幕,