我一直在努力渲染一个能够准确地从敌人身上射出射弹的动画。节点到"播放器" JS / Canvas中2D 11:11网格(0:0 =左上角)中的节点。 After a lot of reading up我设法让镜头接近,但不是很好。我认为我的速度函数有点偏,但我真的不知道为什么。这是三角函数:
this.getVelocityComponents = function(speed){
// loc (location of enemy actor) = array(2) [X_coord, Y_coord]
// des (destination (ie. player in this instance)) = array(2) [X_coord, Y_coord]
var i, sum, hyp, output = [], dis = [];
var higher = false;
for (i in loc) {
sum = 0;
if (loc[i] > des[i])
sum = loc[i] - des[i];
if (loc[i] < des[i])
sum = des[i] - loc[i];
dis.push(sum);
}
hyp = Math.sqrt(Math.pow(dis[X], 2) + Math.pow(dis[Y], 2));
if (dis[X] > dis[Y]) {
output[X] = (speed * Math.cos(dis[X]/hyp))
output[Y] = (speed * Math.sin(dis[Y]/hyp))
} else if (dis[X] < dis[Y]) {
output[X] = (speed * Math.cos(dis[Y]/hyp))
output[Y] = (speed * Math.sin(dis[X]/hyp))
}
return output;
}
这是指示射弹框架的X和Y前进的指令:
var distance = [];
for (i in loc) {
var sum = 0;
if (loc[i] > des[i])
sum = loc[i] - des[i];
if (loc[i] < des[i])
sum = des[i] - loc[i];
distance.push(sum);
}
if (distance[X] > distance[Y]) {
frm[X] += (loc[X] < des[X]) ? v[X] : -v[X];
frm[Y] += (loc[Y] < des[Y]) ? v[Y] : -v[Y];
} else {
frm[Y] += (loc[Y] < des[Y]) ? v[X] : -v[X];
frm[X] += (loc[X] < des[X]) ? v[Y] : -v[Y];
}
下面是截图。蓝色是玩家,粉红色的敌人,黄色的圆圈是射弹
正如你所看到的,它几乎已经出现了。
我做错了吗?我需要做什么?
答案 0 :(得分:2)
要计算从敌人到玩家的方向,你可以稍微简化计算。
var diffX = Player.x - Enemy.x, // difference in position
diffY = Player.y - Enemy.y,
angle = Math.atan2(diffY, diffX); // atan2 will give the angle in radians
请注意,对于atan2,Y首先出现差异,因为画布朝向0°,指向右侧。
然后使用角度和速度计算速度矢量:
// calculate velocity vector
var speed = 8,
vx = Math.cos(angle) * speed, // angle x speed
vy = Math.sin(angle) * speed;
如果这很重要,您可能需要考虑使用时间作为因素。您可以在此处查看 my answer ,以获取此示例。
使用这些计算,您将能够始终用弹丸“击中”玩家(重新加载演示以将敌人的位置改为随机y):
var ctx = document.querySelector("canvas").getContext("2d"),
Player = {
x: 470,
y: 75
},
Enemy = {
x: 100,
y: Math.random() * 150 // reload demo to change y-position
};
// calculate angle
var diffX = Player.x - Enemy.x,
diffY = Player.y - Enemy.y,
angle = Math.atan2(diffY, diffX);
// calculate velocity vector
var speed = 8,
vx = Math.cos(angle) * speed, // angle x speed
vy = Math.sin(angle) * speed,
x = Enemy.x, // projectil start
y = Enemy.y + 50;
// render
(function loop() {
ctx.clearRect(0, 0, 500, 300);
ctx.fillRect(Player.x, Player.y, 30, 100);
ctx.fillRect(Enemy.x, Enemy.y, 30, 100);
ctx.fillRect(x - 3, y -3, 6, 6);
x += vx;
y += vy;
if (x < 500) requestAnimationFrame(loop);
})();
<canvas width=500 height=300></canvas>
答案 1 :(得分:1)
解决方案比这简单得多。
你应该怎么做?
1)计算从敌人到玩家的向量。这将是拍摄方向。
2)规范化向量:意味着你构建一个长度为1且方向相同的向量。
3)将该向量乘以你的速度:现在你有一个正确的速度向量,具有正确的标准,针对玩家。
下面的一些代码可以帮助您理解:
function spawnBullet(enemy, player) {
var shootVector = [];
shootVector[0] = player[0] - enemy[0];
shootVector[1] = player[1] - enemy[1];
var shootVectorLength = Math.sqrt(Math.pow(shootVector[0], 2) + Math.pow(shootVector[1],2));
shootVector[0]/=shootVectorLength;
shootVector[1]/=shootVectorLength;
shootVector[0]*=bulletSpeed;
shootVector[1]*=bulletSpeed;
// ... here return an object that has the enemy's coordinate
// and shootVector as speed
}
然后,由于你没有在你的计算中使用时间(!! wrooong !! ;-)),你将使子弹移动直截了当:
bullet[0] += bullet.speed[0];
bullet[1] += bullet.speed[1];
现在固定步骤的问题是你的游戏在30fps设备上运行速度比在60fps设备上慢两倍。解决方案是计算自上次刷新以来经过的时间,让我们这次拨打电话&#39; dt&#39;。使用该时间将引导您进行如下更新:
bullet[0] += dt * bullet.speed[0];
bullet[1] += dt * bullet.speed[1];
现在你将与帧率无关,你的游戏在任何设备上都会有同样的感觉。