DIV+CSS+JS 导弹截击简单跟踪算法演示
[i=s] 本帖最后由 aa77dd@163.com 于 2015-7-22 14:30 编辑 [/i]请将下面代码保存为 HTML 文件运行, 本代码在最新版 Chrome 和 Firefox 浏览器中测试通过, 未考虑低版本浏览器(特别是IE)的兼容性
演示地址 [url=http://a7d.net46.net/MISSILE_php/MISSILE.php]http://a7d.net46.net/MISSILE_php/MISSILE.php[/url]
全代码+资源 包 下载 [url=http://pan.baidu.com/s/1dDsC2cT]http://pan.baidu.com/s/1dDsC2cT[/url]
[img]http://i.imgur.com/SlwUi5Q.png[/img][code]<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: content-box;
}
body {
background: url("Metro Bliss.jpg") no-repeat center center fixed;
background-size: cover;
overflow: hidden;
}
.enemy {
display: block;
position: absolute;
left: -9999px;
}
.missile {
display: block;
position: absolute;
/* background-color: red; */
left: -9999px;
}
.missile>img {
width: 7px;
height: 44px;
}
audio,#btn {
display: inline-block;
bottom: 0px;
position: absolute;
width: 0px;
}
#btn {
width: auto;
cursor: pointer;
color: white;
}
#btn:hover {
background-color: rgba(192, 192, 192, 0.3);
}
</style>
</head>
<body>
<div class=enemy>
<img src="JetFighter.png">
</div>
<div class=missile>
<img src="missile122x734.png">
</div>
<div id=btn onclick="$('audio').width(function (i, old) {return 300 - old});">
显/隐音效控件
</div>
<audio id=audio_hit controls>
<source src="CruiseMissileDeath.wav" type="audio/wav">
</audio>
<audio id=audio_miss controls>
<source src="JetFighterAttackMissile.wav" type="audio/wav">
</audio>
</body>
</html>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<!-- <script src="jquery-1.10.2.min.js"></script> -->
<script>
var vxe = [], vye = [], xe = [], ye = [];
vxe[0] = 10, vye[0] = 0, xe[0] = 0, ye[0] = document.documentElement.clientHeight * .8;
var vxm = [], vym = [], xm = [], ym = [];
xm[0] = document.documentElement.clientWidth / 2, ym[0] = 10;
var vwm = [], vm = [], am = [];
vwm[0] = 2 * Math.PI / 72; // 导弹转向角速度极限 5deg
vm[0] = 20; // 导弹飞行速度; vxm = vm * cos(am); vym = vm * sin(am);
am[0] = Math.PI / 2; // 导弹飞行角度
vxm[0] = vm[0] * Math.cos(am[0]);
vym[0] = vm[0] * Math.sin(am[0]);
var lastdistSQ = Array(1 + 1).join(Number.MAX_VALUE).split('');
var xOffs_e = -$('.enemy').width() / 2, yOffs_e = -$('.enemy').height() / 2;
var xOffs_m = -$('.missile').width() / 2, yOffs_m = -$('.missile').height() / 2;
var audio_hit = $('#audio_hit')[0], audio_miss = $('#audio_miss')[0];
$('audio').map(function (i) {
$(this).css('left', (120 + i * 300) + 'px');
$('audio')[i].muted = true;
});
window.setInterval('tick();', 1000 / 60);
function tick() {
$('.enemy').map(function (i) {
$(this).css({'left': (xe[i] + xOffs_e) + 'px',
'bottom': (ye[i] + yOffs_e) + 'px',
'transform': 'scaleX(' + (vxe[i] >= 0 ? 1 : -1) + ')'
});
xe[i] += vxe[i];
ye[i] += vye[i];
if (xe[i] >= document.documentElement.clientWidth) {
vxe[i] = -Math.abs(vxe[i]);
}
if (xe[i] <= 0) {
vxe[i] = Math.abs(vxe[i]);
}
});
$('.missile').map(function (i) {
$(this).css({'left': (xm[i] + xOffs_m) + 'px', 'bottom': (ym[i] + yOffs_m) + 'px',
'transform': 'rotate(' + ((Math.PI / 2 - angle(vxm[i], vym[i])) * 180 / Math.PI) + 'deg)'
});
xm[i] += vxm[i];
ym[i] += vym[i];
// 导弹相对速度方向调整为与敌位置方向一致
// 姿态角差 = 相对位置角 - 相对速度角
// 姿态调整角方向 = |姿态角差| <= PI ? 姿态角差方向 : 姿态角差负方向
// 姿态调整角模值 = min(|姿态角差|, 导弹转向角速度极限)
var distSQ = Math.pow(xe[i] - xm[i], 2) + Math.pow(ye[i] - ym[i], 2);
if (distSQ < 10 * 10) { // 目标距离在引爆半径内时引爆 引爆半径 10
audio_miss.pause();
audio_hit.load();
audio_hit.play();
} else if (distSQ < 40 * 40 && distSQ < lastdistSQ[i]) { // 逼近目标
audio_hit.pause();
audio_miss.load();
audio_miss.play();
}
lastdistSQ[i] = distSQ;
var a_pos = angle(xe[i] - xm[i], ye[i] - ym[i]);
if (a_pos != null) {
var a_vel = angle(vxm[i] - vxe[i], vym[i] - vye[i]); // 相对速度角
if (a_vel == null) {
// 导弹和目标等速度, 无法成功击中
} else {
var a_d = a_pos - a_vel;
// 计算姿态调整角
var a_adjust = (Math.abs(a_d) <= Math.PI ? (a_d >= 0 ? 1 : -1) : (a_d >= 0 ? -1 : 1))
* Math.min(Math.abs(a_d), vwm[i]);
am[i] += a_adjust;
vxm[i] = vm[i] * Math.cos(am[i]);
vym[i] = vm[i] * Math.sin(am[i]);
}
} else {
// 拦截成功, 引爆
}
});
}
// 角度计算
function angle(x, y) {
var ang;
return x == 0 ? (y == 0 ? null : (y > 0 ? Math.PI / 2 : -Math.PI / 2))
: (ang = Math.atan(Math.abs(y / x)), x > 0 ?
(y >= 0 ? ang : 2 * Math.PI - ang) :
(y >= 0 ? Math.PI - ang : ang + Math.PI));
}
</script>[/code] 无注释,无力吐槽…希望多年以后还看得懂。。。[code]var vxe = [], vye = [], xe = [], ye = [];
var vxm = [], vym = [], xm = [], ym = [];[/code]
页:
[1]