我在我的简单游戏中设计了一个运动引擎,其中您具有特定的坐标(x,y)
,并且通过单击可以转到任何目的地(x,y)
。这个想法是您有speed
和fuel consumption
,整个动作都是基于时间的。因此,最后,如果您决定从A点到达B点,将需要X的时间(由速度决定)和X的燃料(由消耗决定)。我面临的问题是计算的准确性,可能不是到达目的地后停止旅行的最佳逻辑。
进行的计算是正确的,但是其准确性导致了一些问题。
在我所包含的演示中,可以看到我当前的取消逻辑正在产生剩余物(例如,应燃烧20升燃油,但我剩下0.12 ...):
if ( Math.floor( this.distance ) === 0 ) {
我的上一个永远不会结束(因为如果没有小数位数,它永远都不可能达到0):
if ( this.distance > 0 ) {
我的问题是,如何改进代码,使行程始终在正确的点结束,燃油始终处于应有的状态。
const tools = {
distance: (p1, p2) => Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)),
rftv: (p1, p2) => Math.atan2(p2.y - p1.y, p2.x - p1.x)
};
this.fuel = 200;
this.x = 100;
this.y = 50;
this.rad = 0; // radian angle between current and destination
this.speed = 100; // 100 pixels per second
this.consumption = 10; // 10 liters of fuel per 100 pixels
this.destination = {
x: 220,
y: 140
};
/*
Based on above
distance : 150
time : ( distance / speed ) => 150 / 100 => 1.5s
fuel : ( distance / consumption ) => 150 / 10 => 15 liters
So to summary, between two points we have 150 pixels of distance,
this trip should take 1.5s and burn 15 liters of fuel
*/
this.now = undefined;
this.delta = undefined;
this.then = Date.now();
this.setDelta = function() {
this.now = Date.now();
this.delta = (this.now - this.then) / 1000;
this.then = this.now;
};
this.update = function() {
this.rad = tools.rftv(
{ x: this.x, y: this.y },
{ x: this.destination.x, y: this.destination.y }
);
let step = this.speed * this.delta;
this.x += Math.cos(this.rad) * step;
this.y += Math.sin(this.rad) * step;
this.fuel -= step / this.consumption;
};
this.move = function() {
this.distance = tools.distance(
{ x: this.x, y: this.y },
{ x: this.destination.x, y: this.destination.y }
);
if ( Math.floor( this.distance ) === 0 ) {
clearInterval(tsid);
console.log('done', this.x, this.y, this.fuel, this.distance, '[ ' + (Date.now() - startedAt) + ' ]');
} else {
this.setDelta();
this.update();
console.log('going', this.x, this.y, this.fuel, this.distance, '[ ' + (Date.now() - startedAt) + ' ]');
}
};
let tsid;
let startedAt = Date.now();
tsid = setInterval(function() {
this.move();
}, 10);
答案 0 :(得分:1)
如果您的对象始终直接向目标行进,则不需要任何三角函数。只需使用向量数学即可。
逻辑上update
应该调用move
,而不是相反。
距离计算应与运动代码相同。
在move
中检查距离并设置完成标记。
一步使用的燃料=消耗(使用量/像素)×步长(以像素为单位),因此this.fuel -= step / this.consumption;
不正确。
代码:
this.fuel = 200;
this.x = 100;
this.y = 50;
// no need for rad
this.speed = 100;
this.consumption = 10;
this.destination = {
x: 220,
y: 140
};
this.complete = false; // completion flag
...
// swap functions
this.update = function() {
this.update();
if (this.complete) {
clearInterval(tsid);
console.log('done', this.x, this.y, this.fuel, this.distance, '[ ' + (Date.now() - startedAt) + ' ]');
} else {
this.setDelta();
this.move();
console.log('going', this.x, this.y, this.fuel, this.distance, '[ ' + (Date.now() - startedAt) + ' ]');
}
};
this.move = function() {
let step = this.speed * this.delta;
let dist = tools.distance(
{ x: this.x, y: this.y },
{ x: this.destination.x, y: this.destination.y }
);
/*
would be cleaner to replace this with:
Math.hypot(this.destination.x - this.x, this.destination.y - this.y);
*/
// check distance
if (dist <= step) {
step = dist;
this.complete = true;
}
// vector math not trigonometry
this.x += (this.destination.x - this.x) * (step / dist);
this.y += (this.destination.y - this.y) * (step / dist);
this.distance -= step;
this.fuel -= step * this.consumption; // should be * not /
};
...
tsid = setInterval(function() {
this.update();
}, 10);