Я разработал движок в моей простой игре, в которой у вас есть определенные координаты (x,y)
, и, нажав, вы можете перейти к любому месту назначения (x,y)
.Идея в том, что у вас есть speed
и fuel consumption
, также все движение основано на времени.Таким образом, в конце концов, если вы решите перейти из точки А в точку Б, потребуется 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);