两点之间的正弦曲线或其他自定义移动类型
Sinusoidal or other custom move type between two points
我正在尝试构建一个在小游戏中移动子弹的功能。目前我正在以非常简单的方式进行。
具有计算两点间弧度角的功能:
this.rftv = (p1, p2) => Math.atan2(p2.y - p1.y, p2.x - p1.x);
需要不同的点并计算它们之间的角度:
var x = objects[this.destination].x,
y = objects[this.destination].y,
rad = tools.rftv( { x: this.x, y: this.y }, { x: x, y: y } );
定义速度提升:
this.attack_speed = 2.5;
使用角度和速度提升移动子弹:
this.x += Math.cos(rad) * this.attack_speed;
this.y += Math.sin(rad) * this.attack_speed;
我想做的是不以线性方式移动子弹,而是尝试使用正弦波移动子弹,以实现类似这样的效果:
我不知道如何开始构建它,也许有人可以帮助并编写一个函数,该函数需要两个点并使对象在它们之间以正弦曲线移动。
我建议您为每个实例添加更多变量:
// initialization
this.distance = 0;
// have a max amplitude of about 30-50 depending on how you want it to look
this.amplitude = (Math.random() * 2 - 1) * MAX_AMPLITUDE;
// have a fixed period somewhere between 10-50 depending on how you want it to look
this.period = 30;
this.initial = { x: this.x, y: this.y };
// on each frame
this.distance += this.attack_speed;
this.x = this.initial.x + Math.cos(this.rad) * this.distance;
this.y = this.initial.y + Math.sin(this.rad) * this.distance;
const deviation = Math.sin(this.distance * Math.PI / this.period) * this.amplitude;
this.x += Math.sin(this.rad) * deviation;
this.y -= Math.cos(this.rad) * deviation;
原来我在数学上有一点小错误,现在已经更正了,下面还有一个非常基本的演示。
正振幅应该使子弹的初始轨迹与从 A 点到 B 点的角度相比稍微逆时针移动一个角度,然后在到达 B 的途中来回摆动。
class Bullet {
constructor({initial = {}, destination = {}, amplitude = 50, period = 30, speed = 2.5} = {}) {
let { x: ix, y: iy } = this.initial = initial;
let { x: dx, y: dy } = this.destination = destination;
this.amplitude = (Math.random() * 2 - 1) * amplitude;
this.period = period;
this.speed = speed;
this.distance = 0;
this.x = ix;
this.y = iy;
this.rad = Math.atan2(dy - iy, dx - ix);
}
update() {
this.distance += this.speed;
this.x = this.initial.x + Math.cos(this.rad) * this.distance;
this.y = this.initial.y + Math.sin(this.rad) * this.distance;
const deviation = Math.sin(this.distance * Math.PI / this.period) * this.amplitude;
this.x += Math.sin(this.rad) * deviation;
this.y -= Math.cos(this.rad) * deviation;
}
}
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let initial = {
x: canvas.width / 4,
y: canvas.height * 3 / 4
};
let destination = {
x: canvas.width * 3 / 4,
y: canvas.height / 4
};
let bullet = new Bullet({initial, destination});
console.log(bullet.amplitude);
function draw() {
requestAnimationFrame(draw);
// ctx.clearRect(0, 0, canvas.width, canvas.height);
bullet.update();
ctx.fillStyle = '#0000FF';
ctx.fillRect(bullet.x, bullet.y, 1, 1);
ctx.fillStyle = '#FF0000';
ctx.fillRect(canvas.width / 4, canvas.height * 3 / 4, 1, 1);
ctx.fillStyle = '#00FF00';
ctx.fillRect(canvas.width *3 / 4, canvas.height / 4, 1, 1);
}
draw();
<canvas width="500" height="200"></canvas>
我正在尝试构建一个在小游戏中移动子弹的功能。目前我正在以非常简单的方式进行。
具有计算两点间弧度角的功能:
this.rftv = (p1, p2) => Math.atan2(p2.y - p1.y, p2.x - p1.x);
需要不同的点并计算它们之间的角度:
var x = objects[this.destination].x,
y = objects[this.destination].y,
rad = tools.rftv( { x: this.x, y: this.y }, { x: x, y: y } );
定义速度提升:
this.attack_speed = 2.5;
使用角度和速度提升移动子弹:
this.x += Math.cos(rad) * this.attack_speed;
this.y += Math.sin(rad) * this.attack_speed;
我想做的是不以线性方式移动子弹,而是尝试使用正弦波移动子弹,以实现类似这样的效果:
我不知道如何开始构建它,也许有人可以帮助并编写一个函数,该函数需要两个点并使对象在它们之间以正弦曲线移动。
我建议您为每个实例添加更多变量:
// initialization
this.distance = 0;
// have a max amplitude of about 30-50 depending on how you want it to look
this.amplitude = (Math.random() * 2 - 1) * MAX_AMPLITUDE;
// have a fixed period somewhere between 10-50 depending on how you want it to look
this.period = 30;
this.initial = { x: this.x, y: this.y };
// on each frame
this.distance += this.attack_speed;
this.x = this.initial.x + Math.cos(this.rad) * this.distance;
this.y = this.initial.y + Math.sin(this.rad) * this.distance;
const deviation = Math.sin(this.distance * Math.PI / this.period) * this.amplitude;
this.x += Math.sin(this.rad) * deviation;
this.y -= Math.cos(this.rad) * deviation;
原来我在数学上有一点小错误,现在已经更正了,下面还有一个非常基本的演示。
正振幅应该使子弹的初始轨迹与从 A 点到 B 点的角度相比稍微逆时针移动一个角度,然后在到达 B 的途中来回摆动。
class Bullet {
constructor({initial = {}, destination = {}, amplitude = 50, period = 30, speed = 2.5} = {}) {
let { x: ix, y: iy } = this.initial = initial;
let { x: dx, y: dy } = this.destination = destination;
this.amplitude = (Math.random() * 2 - 1) * amplitude;
this.period = period;
this.speed = speed;
this.distance = 0;
this.x = ix;
this.y = iy;
this.rad = Math.atan2(dy - iy, dx - ix);
}
update() {
this.distance += this.speed;
this.x = this.initial.x + Math.cos(this.rad) * this.distance;
this.y = this.initial.y + Math.sin(this.rad) * this.distance;
const deviation = Math.sin(this.distance * Math.PI / this.period) * this.amplitude;
this.x += Math.sin(this.rad) * deviation;
this.y -= Math.cos(this.rad) * deviation;
}
}
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let initial = {
x: canvas.width / 4,
y: canvas.height * 3 / 4
};
let destination = {
x: canvas.width * 3 / 4,
y: canvas.height / 4
};
let bullet = new Bullet({initial, destination});
console.log(bullet.amplitude);
function draw() {
requestAnimationFrame(draw);
// ctx.clearRect(0, 0, canvas.width, canvas.height);
bullet.update();
ctx.fillStyle = '#0000FF';
ctx.fillRect(bullet.x, bullet.y, 1, 1);
ctx.fillStyle = '#FF0000';
ctx.fillRect(canvas.width / 4, canvas.height * 3 / 4, 1, 1);
ctx.fillStyle = '#00FF00';
ctx.fillRect(canvas.width *3 / 4, canvas.height / 4, 1, 1);
}
draw();
<canvas width="500" height="200"></canvas>