既然是飞机大战 那必定少不了子弹追踪
那么添加子弹追踪功能的实现如下:
// 原文链接:https://blog.youkuaiyun.com/erweimac/article/details/82256087
// https://blog.youkuaiyun.com/weixin_30756499/article/details/97551805
// https://blog.youkuaiyun.com/looffer/article/details/8846159
// https://github.com/processing/p5.js
/**
* @description: 追踪目标
* @param {number} x1 追踪目标x轴
* @param {number} y1 追踪目标y轴
* @param {number} x2 追踪者x轴
* @param {number} y2 追踪者y轴
* @param {number} speed 追踪者速度
* @return {Object} {x, y} 返回下一次要移动的位置
*/
function FollowUpBullet(x1, y1, x2, y2, speed) {
// 向量
const deltaX = x1 - x2;
const deltaY = y1 - y2;
// 微小偏移
if (deltaX == 0) {
if (y1 >= y2) {
deltaX = 0.0000001;
} else {
deltaX = -0.0000001;
}
}
if (deltaY == 0) {
if (x1 >= x2) {
deltaY = 0.0000001;
} else {
deltaY = -0.0000001;
}
}
let angle = 0;
let π = Math.PI;
// 右下角
if (deltaX > 0 && deltaY > 0) {
angle = Math.atan(Math.abs(deltaY / deltaX)); // 第一项限
// 左下角
} else if (deltaX < 0 && deltaY > 0) {
angle = π - Math.atan(Math.abs(deltaY / deltaX)); // 第二项限
// 左上角
} else if (deltaX < 0 && deltaY < 0) {
angle = π + Math.atan(Math.abs(deltaY / deltaX)); // 第三项限
// 右上角
} else {
angle = 2 * π - Math.atan(Math.abs(deltaY / deltaX)); // 第四项限
}
let x = speed * Math.cos(angle);
let y = speed * Math.sin(angle);
return { x, y, angle: calAngle(x2, y2, x1, y1) };
}
// 参考:https://juejin.cn/post/6844903880493367304
// 计算角度
function calAngle(cx, cy, x, y) {
const radian = getCosBy2pt(x, y, cx, cy);
let angle = (Math.acos(radian) * 180) / Math.PI;
if (x < cx) angle = -angle;
return angle;
// 计算 点1指点2形成 的向量
function getCosBy2pt(x, y, cx, cy) {
let a = [x - cx, y - cy];
let b = [0, -1];
return calCos(a, b);
}
function calCos(a, b) {
// 点积
let dotProduct = a[0] * b[0] + a[1] * b[1];
let d =
Math.sqrt(a[0] * a[0] + a[1] * a[1]) *
Math.sqrt(b[0] * b[0] + b[1] * b[1]);
return dotProduct / d;
}
}
当然做之前肯定百度了一下 既然可以CV就尽量不自己写代码
跟踪代码有了 那么就是实装了
// 跟踪子弹
// 获取敌机的数据
const enemyStoreList = enemyStore.getStore();
const keys = Object.keys(enemyStoreList);
// 找到第一个幸运儿
const enemy = enemyStoreList[keys[0]];
// 如果没有敌机 子弹往前飞
if (enemy === undefined) {
// 数据移动
this.positionY -= this.bulletFlySpeed;
} else {
// 调用子弹追踪
const { x, y, angle } = FollowUpBullet(
enemy.positionX + containerInfo.offsetLeft + enemy.width / 2,
enemy.positionY + containerInfo.offsetTop + enemy.height / 2,
this.positionX,
this.positionY,
this.bulletFlySpeed
);
// 保存位置
this.positionY += y;
this.positionX += x;
// 子弹旋转
this.angle = angle;
那么就有了追踪效果了 方便的很
这只是当中一个方法 完整飞机大战项目可以查看:https://github.com/SDSGK/plane-ES6