javascript - spaceship 运动 - 模拟

标签 javascript p5.js

我已经编写了一些代码来模拟带有单个推进器的船的无重力运动。大多数时候它都能正常工作,而且船会完美地到达目的地,但有时它会无限加速。但我想不通,为什么?

seek(target) {
    var desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
    if (desired.mag()>0.1){

        this.orientation = desired;
        if (this.velocity.heading() - desired.heading() > 0.01 && this.velocity.mag() >0.01) {
            this.orientation = this.velocity.copy().mult(-1);
        }

        if ((this.velocity.mag()*this.velocity.mag())/(2*(this.maxForce/this.mass)) > desired.mag()) {
                this.orientation.mult(-1);
        }

        this.applyForce(this.orientation.normalize().mult(this.maxForce/this.mass));
    } else {
        this.velocity = createVector(0,0);
    }
}

你可以在这里测试结果:

https://editor.p5js.org/Ahiru/sketches/r1rQ9-T5m

最佳答案

船舶物体越过目标的问题是由于幅度增量对于船舶移动的增量太小造成的。

为了让飞船对象降落在选定的点上,您需要修改 seek 方法:

seek(target) {
    var desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target
    if (desired.mag()>.01){

物体正在以增量方式移动,这会导致 desired.mag 从物体接近时大于 .01 的数值变为物体经过目标并移开时大于 .01 的另一个数值。

修改

if (desired.mag() > .01)

if (desired.mag() > 2.0)

例如,船只将被捕获并降落在目标上并停留在那里直到选择另一个目标。

这是一个工作示例,其中 delta 设置为等于目标的直径,这样飞船看起来就停在了目标的表面上。

let v;
var targetDiameter = 12;
function setup() {
  pixelDensity(1);
  createCanvas(1000, 1000);
  v = new Vehicle(width / 2, height / 2);
  target = createVector(200, 200);
}

function draw() {
  background(51);

  // Draw an ellipse at the mouse position
  fill(127);
  stroke(200);
  strokeWeight(2);
  ellipse(target.x, target.y, targetDiameter, targetDiameter);

  // Call the appropriate steering behaviors for our agents
  v.seek(target);
  v.update();
  v.display();
}

function mouseClicked() {
  target = createVector(mouseX, mouseY);
  hex = find_HexCoordinates(100, target);
  console.log("click " + hex.x + " " + hex.y + " " + hex.z);
}
class ThrustList {
  constructor(thrust, time) {
    this.thrust = createVector(thrust);
    this.time = time;
  }

  set(thrust, time) {
    this.thrust.set(thrust);
    this.time = time;
  }
}

class ThrustParams {
  constructor (deltaPosition, deltaVelocity, maxForce, mass) {
    this.deltaPosition = createVector(deltaPosition);
    this.deltaVelocity = createVector(deltaVelocity);
    this.maxForce = maxForce;
    this.mass = mass;
  }
}

class hexmetrics {
  constructor (radius) {
    this.outerRadius = radius;
    this.innerRadius = this.outerradius * sqrt(3)/2; 
  }
 
}   

function find_HexCoordinates (radius, position) {
  this.innerRadius = radius;
  this.outerRadius = this.innerRadius * sqrt(3)/2;
  this.px = position.x - 1000/2;
  this.py = position.y - 1000/2;
  this.x = px / this.innerRadius * 2;
  this.y = -x;
  this.offset = py / this.outerRadius * 3;
  this.x -= offset;
  this.y -= offset;
  this.iX = Math.round(x);
  this.iY = Math.round(y);
  this.iZ = Math.round(-x -y);
  if (iX + iY + iZ != 0) {
    dX = Math.abs(x-iX);
    dY = Math.abs(y-iY);
    dZ = Math.abs(-x -y -iZ);
    if (dX > dY && dX > dZ) {
      iX = -iY -iZ;
    }
    else if (dZ > dY) {
      iZ = -iX -iY;
    }
  }
    
  return createVector(this.iX, this.iY, this.iZ);
}

class Vehicle {
  constructor(x, y){
    this.mass = 1;
    this.orientation = createVector(0,1);
    this.turning_speed = 90;
    this.acceleration = createVector(0, 0);
    this.maxForce = .02;
    this.position = createVector(x, y);
    this.r = 3;
    this.velocity = createVector(0, 0);
    } 

  // Method to update location
  update() {
  // Update velocity
  this.velocity.add(this.acceleration);
  // Limit speed
  this.position.add(this.velocity);
  // Reset accelerationelertion to 0 each cycle
  this.acceleration.mult(0);
}

  applyForce(force) {
    this.acceleration.add(force);
  }

  // A method that calculates a steering force towards a target
  // STEER = DESIRED MINUS VELOCITY
  seek(target) {
    var desired = p5.Vector.sub(target, this.position); // A vector pointing from the location to the target

    if (desired.mag() > targetDiameter){
      this.orientation = desired;
      if (Math.abs(this.velocity.heading() - desired.heading()) > 0.01 && this.velocity.mag() >0.01) {
        this.orientation = this.velocity.copy().mult(-1);
      }

      if ((this.velocity.mag()*this.velocity.mag())/(2*(this.maxForce/this.mass)) > desired.mag()) {
        this.orientation.mult(-1);
      }

      this.applyForce(this.orientation.normalize().mult(this.maxForce/this.mass));
    } else {

    this.velocity = createVector(0,0);
   }
}

  display() {
    // Draw a triangle rotated in the direction of velocity
    var theta = this.orientation.heading() + PI / 2;
    fill(127);
    stroke(200);
    strokeWeight(1);
    push();
    translate(this.position.x, this.position.y);
    rotate(theta);
    beginShape();
    vertex(0, -this.r * 2);
    vertex(-this.r, this.r * 2);
    vertex(this.r, this.r * 2);
    endShape(CLOSE);
    pop();
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>

关于javascript - spaceship 运动 - 模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52764885/

相关文章:

javascript - 本地存储适配器简介

javascript - JQuery 动画中的 setTimeout

javascript - 在没有设置/绘图格式的情况下使用 p5 的功能

javascript - 在draw()中调用draw()以提高速度

javascript - 在 p5.js 中使用来自 Datamuse API 的 JSON 数据时遇到问题

javascript - 我将如何处理二维的侧向碰撞?

javascript - 由于交叉问题,nodejs无法加载URL

javascript - 样式使 javascript 代码无法正常运行

javascript - 如何在 p5.js 中旋转图像

javascript - 为什么我得到整数 NaN?