jjzjj

javascript - spaceship 运动 - 模拟

coder 2025-01-19 原文

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

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 - spaceship 运动 - 模拟的更多相关文章

  1. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  2. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  3. ruby-on-rails - 在这种情况下我如何模拟一个对象?没有明显的方法可以用模拟替换对象 - 2

    假设我在Store的模型中有这个非常简单的方法:defgeocode_addressloc=Store.geocode(address)self.lat=loc.latself.lng=loc.lngend如果我想编写一些不受地理编码服务影响的测试脚本,这些脚本可能已关闭、有限制或取决于我的互联网连接,我该如何模拟地理编码服务?如果我可以将地理编码对象传递到该方法中,那将很容易,但我不知道在这种情况下该怎么做。谢谢!特里斯坦 最佳答案 使用内置模拟和stub的rspecs,你可以做这样的事情:setupdo@subject=MyCl

  4. ruby - "public/protected/private"方法是如何实现的,我该如何模拟它? - 2

    在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定

  5. ruby - 在 RSpec 中 stub /模拟全局常量 - 2

    我有一个gem,它有一个根据Rails.env的不同行为的方法:defself.envifdefined?(Rails)Rails.envelsif...现在我想编写一个规范来测试这个代码路径。目前我是这样做的:Kernel.const_set(:Rails,nil)Rails.should_receive(:env).and_return('production')...没关系,只是感觉很丑。另一种方法是在spec_helper中声明:moduleRails;end而且效果也很好。但也许有更好的方法?理想情况下,这应该有效:rails=double('Rails')rails.sho

  6. ruby-on-rails - 使用 javascript 更改数据方法不会更改 ajax 调用用户的什么方法? - 2

    我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的

  7. ruby-on-rails - rspec 模拟对象属性赋值 - 2

    我有一个rspec模拟对象,一个值赋给了属性。我正在努力在我的rspec测试中满足这种期望。只是想知道语法是什么?代码:defcreate@new_campaign=AdCampaign.new(params[:new_campaign])@new_campaign.creationDate="#{Time.now.year}/#{Time.now.mon}/#{Time.now.day}"if@new_campaign.saveflash[:status]="Success"elseflash[:status]="Failed"endend测试it"shouldabletocreat

  8. ruby - 如何使用 rspec stub /模拟对命令行的调用? - 2

    我正在尝试测试命令行工具的输出。如何使用rspec来“伪造”命令行调用?执行以下操作不起作用:it"shouldcallthecommandlineandreturn'text'"do@p=Pig.new@p.should_receive(:run).with('my_command_line_tool_call').and_return('resulttext')end如何创建stub? 最佳答案 使用newmessageexpectationsyntax:规范/虚拟规范.rbrequire"dummy"describeDummy

  9. ruby - 在 Mechanize 中使用 JavaScript 单击链接 - 2

    我有这个:AccountSummary我想单击该链接,但在使用link_to时出现错误。我试过:bot.click(page.link_with(:href=>/menu_home/))bot.click(page.link_with(:class=>'top_level_active'))bot.click(page.link_with(:href=>/AccountSummary/))我得到的错误是:NoMethodError:nil:NilClass的未定义方法“[]” 最佳答案 那是一个javascript链接。Mechan

  10. 建模分析 | 平面2R机器人(二连杆)运动学与动力学建模(附Matlab仿真) - 2

    目录0专栏介绍1平面2R机器人概述2运动学建模2.1正运动学模型2.2逆运动学模型2.3机器人运动学仿真3动力学建模3.1计算动能3.2势能计算与动力学方程3.3动力学仿真0专栏介绍?附C++/Python/Matlab全套代码?课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。?详情:图解自动驾驶中的运动规划(MotionPlanning),附几十种规划算法1平面2R机器人概述如图1所示为本文的研究本体——平面2R机器人。对参数进行如下定义:机器人广义坐标

随机推荐