批处理之家's Archiver

aa77dd@163.com 发表于 2015-7-22 13:20

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]

yu2n 发表于 2015-7-22 18:00

无注释,无力吐槽…希望多年以后还看得懂。。。[code]var vxe = [], vye = [], xe = [], ye = [];
var vxm = [], vym = [], xm = [], ym = [];[/code]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.