太空飞船运动-模拟

时间:2018-10-11 16:27:22

标签: 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

2 个答案:

答案 0 :(得分:0)

我以前从未使用过p5js,但是我认为这是因为applyForce(),它在用户单击时不断增加新的力量。

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

答案 1 :(得分:0)

船舶物体越过目标的问题是由于幅度增量对于船舶进入的增量而言太小了。

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

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

对象以递增的速度移动,这可能导致期望的.mag随着对象接近而从大于.01的数字变为随着对象经过目标并移开而大于.01的另一个幅度。 / p>

修改

if (desired.mag() > .01)

if (desired.mag() > 2.0)

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

这是一个工作示例,其增量设置为等于目标的直径,以使船看起来像是降落在目标表面上。

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>