螺旋效果

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Anwhere_jin/article/details/51822070

這裏寫圖片描述

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>.</title>
</head>
<style type="text/css">
    #stage{
        display:block;
        float:left;
        width:400px;
        height:300px;
        box-shadow:
            -2px -2px 4px rgba(0, 0, 0, 0.3),
            2px 2px 4px rgba(0, 0, 0, 0.6);
    }
    #hitck{
        display:block;
        float:left;
        width:400px;
        height:300px;
        box-shadow:
            -2px -2px 4px rgba(0, 0, 0, 0.3),
            2px 2px 4px rgba(0, 0, 0, 0.6);
    }
    #plane{
        display:block;
        float:left;
        width:48px;
        height:48px;
        box-shadow:
            -2px -2px 4px rgba(0, 0, 0, 0.3),
            2px 2px 4px rgba(0, 0, 0, 0.6);
    }
    #ammo{
        display:block;
        float:left;
        width:12px;
        height:12px;
        box-shadow:
            -2px -2px 4px rgba(0, 0, 0, 0.3),
            2px 2px 4px rgba(0, 0, 0, 0.6);
    }
</style>
<body>
    <canvas id="stage"></canvas>
    <canvas id="hitck"></canvas>
    <canvas id="plane"></canvas>
    <canvas id="ammo"></canvas>
</body>
<script type="text/javascript">

/*
 * 碰撞檢測 & 彈幕實例
 * [email protected]
 * 2013-8-26  
 */

    /**
     * 鍵盤狀態
     * @type {Object}
     */
    var Keyboard = {
        UP    : 87,
        DOWN  : 83,
        LEFT  : 65,
        RIGHT : 68,

        up    : false,
        down  : false,
        left  : false,
        right : false
    }

    /**
     * 鼠標狀態
     * @type {Object}
     */
    var Mouse = {
        downX : 0,
        downY : 0
    }

    /**
     * 遊戲狀態
     * @type {Object}
     */
    var Game = {
        playing : true
    }

    /**
     * 工具庫
     * @type {Object}
     */
    var Util = {
        /**
         * 是否在畫板範圍內
         * @param  {canvas}   canvas 
         * @param  {float}    x      
         * @param  {float}    y      
         * @return {bool}     
         */
        canvasInScope : function(canvas, x, y){
            x = x || Mouse.downX;
            y = y || Mouse.downY;
            return (
                x > canvas.offsetLeft && 
                x < canvas.offsetLeft + canvas.clientWidth &&
                y > canvas.offsetTop &&
                y < canvas.offsetTop + canvas.clientHeight
            );
        },
        /**
         * 位置在畫板上的座標偏移
         * @param  {canvas} canvas 
         * @param  {float}  x      
         * @param  {float}  y      
         * @return {Vect}        
         */
        offsetOnCanvas : function(canvas, x, y){
            x = x || Mouse.downX;
            y = y || Mouse.downY;
            var ratioX = canvas.width  / canvas.clientWidth;
            var ratioY = canvas.height / canvas.clientHeight;
            var offsetX = (x - canvas.offsetLeft) * ratioX;
            var offsetY = (y - canvas.offsetTop)  * ratioY;
            return new Vect(offsetX, offsetY);
        }
    }

    /**
     * 自機
     * @type {Object}
     */
    var plane = {
        x : 0,
        y : 0,

        speed : 2,

        map_data : []
    }

    /**
     * 繪製隊列
     * @type {Object}
     */
    var Queue = {
        ammo : [],
        initAmmo : function(maxAmmoCount){
            maxAmmoCount = maxAmmoCount || 512;
            for(var i = 0; i < maxAmmoCount; i ++){
                Queue.ammo[i] = null;
            }
        },
        init : function(){
            Queue.initAmmo();
        }
    }
    Queue.init();

    /**
     * 碰撞檢測矩陣
     * @type {Object}
     */
    var Matrix = {
        /**
         * 自機形狀
         * @type {Array}
         */
        plane : [],
        /**
         * 子彈形狀
         * @type {Array}
         */
        ammo  : [],
        /**
         * 舞臺MAP
         * @type {Array}
         */
        stage : [],
        /**
         * 碰撞位置
         * @type {Array}
         */
        hited : [],
        /**
         * 重置舞臺
         */
        init : function(){
            var i, 
                n = 800 * 600;
            for(i = 0; i < n; i ++){
                Matrix.stage[i] = 0;
            }
        },
        /**
         * 繪製子彈
         * @param  {float} x
         * @param  {float} y
         * @param  {int}   w
         * @param  {int}   h
         */
        drawAmmo : function(x, y, w, h){
            w = w || 12;
            h = h || 12;
            x = parseInt(x);
            y = parseInt(y);
            var i = 0,
                j = 0,
                k = 0,
                l = 0,
                m = 0,
                n = 0;
            for(i = 0; i < w; i ++){
                for(j = 0; j < h; j ++){
                    m = parseInt(j * w + i);
                    if(Matrix.ammo[m] > 0){
                        n = parseInt((j + y) * 800 + (i + x));
                        Matrix.stage[n] = 1;
                    }
                }
            }
        },
        /**
         * 繪製自機
         * @param  {float} x
         * @param  {float} y
         * @param  {int}   w
         * @param  {int}   h
         */
        drawPlane : function(x, y, w, h){
            w = w || 48;
            h = h || 48;
            x = parseInt(x);
            y = parseInt(y);
            var i = 0,
                j = 0,
                k = 0,
                l = 0,
                m = 0,
                n = 0,
                hit = false;
            Matrix.hited.length = 0;
            for(i = 0; i < w; i ++){
                for(j = 0; j < h; j ++){
                    m = parseInt(j * w + i);
                    if(Matrix.plane[m] > 0){
                        n = parseInt((j + y) * 800 + (i + x));
                        if(Matrix.stage[n] == 1){
                            Matrix.stage[n] = 2;
                            hit = true;
                            Matrix.hited.push(n);
                        }else{
                            Matrix.stage[n] = 3;
                        }
                    }
                }
            }
            return hit;
        }
    }
    Matrix.init();

    Vect = function(x, y){
        this.x = x || 0;
        this.y = y || 0;
    }

    /**
     * 加速度恆定的子彈
     * @param {float} x 
     * @param {float} y 
     * @param {float} vx
     * @param {float} vy
     * @param {float} ax
     * @param {float} ay
     */
    DirectAmmo = function(x, y, vx, vy, ax, ay){
        this.x   = x  || 400; // 橫座標
        this.y   = y  || 300; // 縱座標
        this.vx  = vx || 2;   // 橫向速度
        this.vy  = vy || 2;   // 縱向速度
        this.ax  = ax || 0;   // 橫向加速度
        this.ay  = ay || 0;   // 縱向加速度
        this.die = false;     // 子彈是否已消亡
    }
    /**
     * 加入到繪製隊列
     * @return {bool}
     */
    DirectAmmo.prototype.queue = function(){
        var i = 0;
        while(i < Queue.ammo.length){
            if(Queue.ammo[i] == null || Queue.ammo[i].die){
                Queue.ammo[i] = this;
                return true;
            }
            i ++;
        }
        return false;
    }
    /**
     * 移動
     * @return {DirectAmmo}
     */
    DirectAmmo.prototype.move = function(){
        this.vx += this.ax;
        this.vy += this.ay;
        this.x  += this.vx;
        this.y  += this.vy;

        if(this.x < 0){
            this.die = true;
        }
        if(this.y < 0){
            this.die = true;
        }
        if(this.x > 800){
            this.die = true;
        }
        if(this.y > 600){
            this.die = true;
        }
        if(this.vx == 0 && this.vy == 0 && this.ax == 0 && this.ay == 0){
            this.die = true;
        }
        return this;
    }
    /**
     * 一組環狀散開的DirectAmmo
     * @param {float} x    
     * @param {float} y    
     * @param {int}   count
     * @param {float} speed
     * @param {float} ax   
     * @param {float} ay   
     */
    RoundDirectAmmo = function(x, y, count, speed, ax, ay){
        x          = x || 400;
        y          = y || 300;
        count      = count || 32;
        speed      = speed || 2;
        ax         = ax || 0;
        ay         = ay || 0;
        var offset = 0.00001;
        var step   = Math.PI * 2 / count;
        var ammos  = [];
        var i, vx, vy, da;
        for(i = 0; i < count; i++){
            vx = speed * Math.cos(offset);
            vy = speed * Math.sin(offset);
            da = new DirectAmmo(x, y, vx, vy, ax, ay);
            offset += step;

            ammos[ammos.length] = da;
        }
        this.ammos = ammos;
    }
    /**
     * 加入繪製隊列
     * @return {RoundDirectAmmo}
     */
    RoundDirectAmmo.prototype.queue = function(){
        var i = 0, 
            j = 0;
        while(i < Queue.ammo.length && j < this.ammos.length){
            if(Queue.ammo[i] == null || Queue.ammo[i].die){
                Queue.ammo[i] = this.ammos[j];
                j ++;
            }
            i ++;
        }
        return this;
    }
    /**
     * 次第加入繪製隊列
     * @param  {int} n 加入延時
     * @param  {int} i 
     * @return {RoundDirectAmmo}
     */
    RoundDirectAmmo.prototype.queue_delay = function(n, i){
        n = n || 10;
        i = i || 0;
        if(this.ammos[i]){
            this.ammos[i].queue();
            var qr = this;
            setTimeout(function(){qr.queue_delay(n, i + 1)}, n);
        }
        return this;
    }
    /**
     * 圓周運動的子彈
     * @param {float} ox    圓心x
     * @param {float} oy    圓心y
     * @param {float} ow    初始角度
     * @param {float} speed 速度
     * @param {float} r     半徑
     * @param {float} a     半徑增長加速度
     */
    CircleAmmo = function(ox, oy, ow, speed, r, a){
        this.ox  = ox || 400;
        this.oy  = oy || 300;
        this.r   = r  || 5;
        this.a   = a  || 2;
        this.v   = speed || 0.2;
        this.w   = ow || 0.000001;
        this.x   = this.ox + this.r * Math.cos(this.w);
        this.y   = this.oy + this.r * Math.sin(this.w);
        this.die = false;
    }
    /**
     * 加入繪製隊列
     * @return {bool}
     */
    CircleAmmo.prototype.queue = function(){
        var i = 0;
        while(i < Queue.ammo.length){
            if(Queue.ammo[i] == null || Queue.ammo[i].die){
                Queue.ammo[i] = this;
                return true;
            }
            i ++;
        }
        return false;
    }
    /**
     * 移動
     */
    CircleAmmo.prototype.move = function(){
        this.w += this.v;
        this.r += this.a;
        this.x  = this.ox + this.r * Math.cos(this.w);
        this.y  = this.oy + this.r * Math.sin(this.w);
        if(this.x < 0){
            this.die = true;
        }
        if(this.y < 0){
            this.die = true;
        }
        if(this.x > 800){
            this.die = true;
        }
        if(this.y > 600){
            this.die = true;
        }
        return this;
    }
    /**
     * 一組環狀的CircleAmmo
     * @param {float} ox   
     * @param {float} oy   
     * @param {int}   count
     * @param {float} speed
     * @param {float} r    
     * @param {float} a    
     */
    RoundCircleAmmo = function(ox, oy, count, speed, r, a){
        count = count || 32;
        var i,
            ca,
            ammos = [],
            w = 0.00001,
            step = Math.PI * 2 / count;
        for(i = 0; i < count; i ++){
            ca = new CircleAmmo(ox, oy, w, speed, r, a);
            w += step;
            ammos[ammos.length] = ca;
        }
        this.ammos = ammos;
        return this;
    }
    /**
     * 加入繪製隊列
     * @return {RoundCircleAmmo}
     */
    RoundCircleAmmo.prototype.queue = function(){
        var i = 0, 
            j = 0;
        while(i < Queue.ammo.length && j < this.ammos.length){
            if(Queue.ammo[i] == null || Queue.ammo[i].die){
                Queue.ammo[i] = this.ammos[j];
                j ++;
            }
            i ++;
        }
        return this;
    }
    /**
     * 次第加入繪製隊列
     * @param  {int} n 加入延時
     * @param  {int} i 
     * @return {RoundDirectAmmo}
     */
    RoundCircleAmmo.prototype.queue_delay = function(n, i){
        n = n || 10;
        i = i || 0;
        if(this.ammos[i]){
            this.ammos[i].queue();
            var qr = this;
            setTimeout(function(){qr.queue_delay(n, i + 1)}, n);
        }
        return this;
    }


    function test_ammo(){
        var rca = new RoundCircleAmmo(Math.random() * 400 + 100, Math.random() * 300 + 100, 512);
        rca.queue_delay(10);
        setTimeout(function(){test_ammo()}, 8000);
    }
    test_ammo();

    var cvs_plane,  // 自機
        ctx_plane,

        cvs_ammo,   // 子彈
        ctx_ammo,

        cvs,        // 舞臺
        ctx,

        cvs_ck,     // 碰撞演示
        ctx_ck;

    cvs_plane = document.getElementById('plane');
    cvs_plane.height = 48;
    cvs_plane.width  = 48;
    ctx_plane = cvs_plane.getContext('2d');
    ctx_plane.fillStyle = 'rgba(0, 192, 248, 1)';
    ctx_plane.beginPath();
    ctx_plane.arc(24,24,24,0,Math.PI*2,true);
    ctx_plane.closePath();
    ctx_plane.fill();
    var plane_data = ctx_plane.getImageData(0, 0, 48, 48).data;
    for(var i = 0; i < 48 * 48; i ++){
        var dot = i * 4;
        if(plane_data[dot] > 0 || plane_data[dot + 1] > 0 || plane_data[dot + 2] > 0){
            Matrix.plane[i] = 1;
        }else{
            Matrix.plane[i] = 0;
        }
    }

    cvs_ammo = document.getElementById('ammo');
    cvs_ammo.height = 12;
    cvs_ammo.width  = 12;
    ctx_ammo = cvs_ammo.getContext('2d');
    ctx_ammo.fillStyle = 'rgba(255, 255, 255, 0.5)';
    ctx_ammo.beginPath();
    ctx_ammo.arc(6,6,6,0,Math.PI*2,true);
    ctx_ammo.closePath();
    ctx_ammo.fill();
    var ammo_data = ctx_ammo.getImageData(0, 0, 12, 12).data;
    for(var i = 0; i < 12 * 12; i ++){
        var dot = i * 4;
        if(ammo_data[dot] > 0 || ammo_data[dot + 1] > 0 || ammo_data[dot + 2] > 0){
            Matrix.ammo[i] = 1;
        }else{
            Matrix.ammo[i] = 0;
        }
    }

    cvs = document.getElementById('stage');
    cvs.height = 600;
    cvs.width  = 800;
    ctx = cvs.getContext('2d');
    ctx.fillStyle = '#000000';
    ctx.fillRect(0, 0, 800, 600);

    cvs_ck = document.getElementById('hitck');
    cvs_ck.height = 600;
    cvs_ck.width  = 800;
    ctx_ck = cvs_ck.getContext('2d');
    ctx_ck.fillStyle = '#000000';
    ctx_ck.fillRect(0, 0, 800, 600);

    run();

    window.onkeydown = function(e){
        switch(e.keyCode){
            case Keyboard.UP:
                Keyboard.up    = true;
                break;
            case Keyboard.DOWN:
                Keyboard.down  = true;
                break;
            case Keyboard.LEFT:
                Keyboard.left  = true
                break;
            case Keyboard.RIGHT:
                Keyboard.right = true;
                break;
            default:
                break;
        }
    }

    window.onkeyup = function(e){
        switch(e.keyCode){
            case Keyboard.UP:
                Keyboard.up    = false;
                break;
            case Keyboard.DOWN:
                Keyboard.down  = false;
                break;
            case Keyboard.LEFT:
                Keyboard.left  = false;
                break;
            case Keyboard.RIGHT:
                Keyboard.right = false;
                break;
            default:
                break;
        }
    }

    window.onclick = function(e){
        Game.playing = true;

        Mouse.downX = e.x || e.clientX;
        Mouse.downY = e.y || e.clientY;

        if(Util.canvasInScope(cvs)){
            var ammo2v = Util.offsetOnCanvas(cvs);
            new RoundDirectAmmo(ammo2v.x, ammo2v.y).queue();
        }

        if(Util.canvasInScope(cvs_ck)){
            var ammo2v = Util.offsetOnCanvas(cvs_ck);
            new RoundDirectAmmo(ammo2v.x, ammo2v.y).queue();
        }
    }

    function run(){

        if(!Game.playing){
            setTimeout(function(){run()}, 20);
            return;
        }

        if(Keyboard.up    && plane.y > 0){
            plane.y -= plane.speed;
        }
        if(Keyboard.down  && plane.y < 600){
            plane.y += plane.speed;
        }
        if(Keyboard.left  && plane.x > 0){
            plane.x -= plane.speed;
        }
        if(Keyboard.right && plane.x < 800){
            plane.x += plane.speed;
        }

        Matrix.init();

        ctx.fillStyle = '#000000';
        ctx.fillRect(0, 0, 800, 600);
        ctx.fillStyle = '#00ff00';
        ctx.drawImage(cvs_plane, plane.x, plane.y);
        var i, j;
        for(i = 0; i < Queue.ammo.length; i ++){
            if(Queue.ammo[i] != null && !Queue.ammo[i].die){
                Queue.ammo[i].move();
                ctx.drawImage(cvs_ammo, Queue.ammo[i].x, Queue.ammo[i].y);
                Matrix.drawAmmo(Queue.ammo[i].x, Queue.ammo[i].y);
            }
        }

        if(Matrix.drawPlane(plane.x, plane.y)){
            //碰撞發生時執行
            // Game.playing = false;
        }

        // 繪製碰撞演示內容
        var ck_data = ctx_ck.createImageData(800, 600);
        for(i = 0, j = 0; i < 480000; i++, j += 4){
            switch(Matrix.stage[i]){
                case 1:
                    ck_data.data[j] = 255;
                    ck_data.data[j + 1] = 0;
                    ck_data.data[j + 2] = 0;
                    ck_data.data[j + 3] = 255;
                    break;
                case 2:
                    ck_data.data[j] = 0;
                    ck_data.data[j + 1] = 0;
                    ck_data.data[j + 2] = 255;
                    ck_data.data[j + 3] = 255;
                    break;
                case 3:
                    ck_data.data[j] = 0;
                    ck_data.data[j + 1] = 255;
                    ck_data.data[j + 2] = 0;
                    ck_data.data[j + 3] = 255;
                    break;
                default:
                    ck_data.data[j] = 0;
                    ck_data.data[j + 1] = 0;
                    ck_data.data[j + 2] = 0;
                    ck_data.data[j + 3] = 255;
                    break;
            }
        }
        ctx_ck.putImageData(ck_data, 0, 0);

        setTimeout(function(){run()}, 20);
    }
</script>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章