【屌絲之作】3D遙控坦克大戰


昨天參加了hack day的一個比賽,賽制大致是:24小時,自由組隊2~4人,任意發揮。運氣比較好,拿了第三名和最佳創意獎。

建議先看看這個demo,bug是有的,chrome下玩玩,測試測試就行,O(∩_∩)O~

  DEMO:http://qianduannotes.sinaapp.com/3dtank/html/index.html

 基本效果:

 

關於

懶得去SAE上折騰,沒把那另外一半的功能補上,不過我還是介紹下這幾個沒補上功能吧。

  1. 音效。開始音樂是比較古老的坦克大戰開機音樂。

    ① 開始音效 點擊播放

    ② 發子彈    點擊播放

    ③ 擊中坦克 點擊播放

    ④ 爆炸       點擊播放

  ②和③是自己錄制的,呵呵,DIY的東西才好玩。

 

  2. 登錄驗證

  

  采用的是解鎖,這個創意應該是非常不錯的,當登錄的時候,A、B玩家下方會生成一個如上圖的canvas解鎖塊,當然這個解鎖卡也會通過socket傳送到手機遙控端,手機解鎖成功后方可登錄。

  

 

  3. 坦克360°旋轉

  由於鍵盤控制只能上下左右,所以360°是轉不出來的..剛想截一張手機控制游戲的圖,總是報錯...囧(后台用的是php,socket控制信號傳輸,剛打開手機端網頁的時候php socket報錯)。

手機遙控端視圖:

  這里主要利用的是手機多點觸控,touchstart,touchmove,touchend這三個事件。

function canvasAddListener() {
    canvas.addEventListener('touchstart', onTouchStart, false);
    canvas.addEventListener('touchmove', onTouchMove, false);
    canvas.addEventListener('touchend', onTouchEnd, false);
}

 

  4. 重新開始游戲和打死坦克添加效果等

 

以上都是沒有公開顯示出來的效果,下次弄好了再上傳吧,嘻嘻。

 

先說說前台

前台主要采用的是css3和js(這是廢話)。

1. css3構建一個3D游戲場地

效果:

.box {
    width:500px;
    height:500px;
    position:relative;
    -webkit-transform-style: preserve-3d;
    /*-webkit-transform: rotateY(40deg);*/
    -webkit-transition:all 1s ease-in-out;
}
.inBox {
    width:300px;
    height:300px;
    overflow: hidden;
    text-align: center;
    box-shadow: 0px 0px 2px white;
    background:rgba(255,255,255,.2);
    /*background:#779443;*/
    position:absolute;
    top:100px;
    left:100px;
    color:white;
}
.box-forward {
    -webkit-transform: rotateY(0deg) translateZ(150px);
}
.box-back {
    -webkit-transform: rotateY(180deg) translateZ(150px);
}
.box-left {
    -webkit-transform: rotateY(270deg) translateZ(150px);
}
.box-right {
    -webkit-transform: rotateY(90deg) translateZ(150px);
}
.box-top {
    -webkit-transform:rotateX(90deg) translateZ(150px);
}
.box-bottom {
    -webkit-transform:rotateX(-90deg) translateZ(150px);
}

上面是css部分,比賽過程中,參看了下張鑫旭大哥的文章(之前這塊還不是很了解的),文章鏈接。就不細說了。

下面是HTML部分:

<div class="w">
    <div class="box">
        <div class="inBox box-forward" data-num="upF rightF downF leftF" data-v="1"><div></div></div>
        <div class="inBox box-back" data-num="upF leftF downF rightF" data-v="2"><div></div></div>
        <div class="inBox box-left" data-num="upF forwardF downF backF" data-v="3"><div></div></div>
        <div class="inBox box-right" data-num="upF backF downF forwardF" data-v="4"><div></div></div>
        <div class="inBox box-top" data-num="backF rightF forwardF leftF" data-v="5"><div></div></div>
        <div class="inBox box-bottom" data-num="backF leftF forwardF rightF" data-v="6"><div></div></div>
    </div>
</div>

 

2. JS這塊,寫了比較多。

var $ = document.querySelectorAll.bind(document);

/**
* @description core part
* @author hustskyking
*/
var faces = $(".inBox"),
    bloodA = $(".bloodA div")[0],
    bloodB = $(".bloodB div")[0],

    box = $(".box")[0],
    upF = $(".box-top")[0],
    downF = $(".box-bottom")[0],
    leftF = $(".box-left")[0],
    rightF = $(".box-right")[0],
    forwardF = $(".box-forward")[0],
    backF = $(".box-back")[0],

    cSize = upF.clientWidth,
    datas = {
        "upF": upF,
        "downF": downF,
        "leftF": leftF,
        "rightF": rightF,
        "forwardF": forwardF,
        "backF": backF
    },
    stopN = 0,
    tanks = {},  
    randomTank = 2,
    tankLimit  = 20,
                    //a   w   d  s   j      ←   ↑   →  ↓   p
    debug_keySet = [[65, 87, 68, 83, 74], [37, 38, 39, 40, 80]];

/**
* @Class Tank
* @attrs width, height, currentX, currentY, speedX, speedY, angleX, angleY, plusy, plusx
*        container, dataset, stopN, tank, tankId, life, bulletBox, color, timerLimit, timer, gap,
         sTime
*/
var Tank = function(setting){
    var opts = setting || {};
    this.container = opts.container || forwardF;
    this.dataset   = this.container.getAttribute('data-num').split(" ");
    this.belong = 0;
    this.grade  = 0;
    this.debug  = false;
    this.width  = opts.width || 14;
    this.height = opts.height || 18;
    this.stopN  = "keyup" + (window.stopN++);
    this.gap    = opts.gap || 30;
    this.speed  = opts.speed || 3;
    this.ax     = 0;
    this.ay     = 0;
    this.cx     = opts.cx || (cSize - this.width) / 2;
    this.cy     = opts.cy || (cSize - this.height) / 2;
    this.sx     = 0;
    this.sy     = 0;

    this.tank   = null;
    this.tankId = "";
    this.life   = 100;
    this.color  = opts.color || "#0047B3";

    this.bulletBox = [];
    this.bColor = opts.bColor || "#0047B3";
    this.timerLimit= 400;
    this.gunAngle  = 0;
    this.timer     = null;
    this.sTime     = 0;
}

Tank.prototype = {
    init: function(tankId, debug){
        if(tankId){
            this.tankId = tankId;
            this.belong = (Number(tankId) > 2 ? 2 :Number(tankId));
        }else{
            throw new Error("必須設置tank ID");
        }

        var this_ = this;

        //繪制坦克
        this.paintTank();

        if(debug){
            this.debug = true;
            this.keySet = debug.keySet;
            window.addEventListener("keydown", function(){
                this_.move_debug();
            }, false);
        }

        window.addEventListener(this.stopN, function(){
            clearInterval(this_.timer);
        }, false);

    },
    paintTank: function(){
        var tank = document.createElement("span");
        var circle = document.createElement("span");
        var gun = document.createElement("span");

        gun.setAttribute("class", "gun");
        tank.setAttribute("class", "tank");
        circle.setAttribute("class", "circle");
        tank.setAttribute("id", "tank" + this.tankId);

        gun.style.borderColor = this.color;
        circle.style.borderColor = this.color;
        tank.style.cssText = "width:" + this.width + "px;height:" + this.height + 
                             "px;top:" + this.cy + "px;left:" + this.cx + "px;border-color:" 
                             + this.color;

        tank.appendChild(gun);
        tank.appendChild(circle);

        this.container.getElementsByTagName("div")[0].appendChild(tank);

        this.tank = tank;

        return tank;
    },
    switchPainter: function(N){
        //N  1->up 2->right 3->down 4->down
        this.ay %= 360;
        var r = false,
            a = 0;
        if (this.ay > 180) {
            this.ay -= 360;
            r = true;
        }
        if (this.ay < -180) this.ay += 360;
        this.container = datas[this.dataset[N]];
        this.dataset   = this.container.getAttribute('data-num').split(" ");
        this.container.getElementsByTagName("div")[0].appendChild(this.tank);
        if(this.belong >= 2) return;

        box.style.cssText = "-webkit-transform: rotateY(" + (this.ay + (r ? -a : a)) + "deg);";
    },
    setAngle: function(x, y, ang){
        this.sx = x;
        this.sy = y;
        this.gunAngle = 90 - ang / Math.PI * 180;
        $("#tank" + this.tankId)[0].style.cssText += "-webkit-transform: rotate(" + this.gunAngle + "deg);";
    },
    move: function(ang){
        this.setAngle(Math.cos(ang), -Math.sin(ang), ang);
        
        this.stopAni();
        this.ani();
    },
    direction_debug: function(){
        switch(event.keyCode) {
            case this.keySet[0]:
                return "left";
            case this.keySet[1]:
                return "up";
            case this.keySet[2]:
                return "right";
            case this.keySet[3]:
                return "down";
            case this.keySet[4]:
                return "shooter";
        }
    },
    move_debug: function(){
        this.stopAni();
        switch(this.direction_debug()) {
            case "up":
                console.log("up");
                this.setAngle(0, -1, Math.PI / 2);
                this.gunAngle_debug = 0;
                break;
            case "down":
                console.log("down");
                this.setAngle(0, 1, Math.PI / 2 * 3);
                this.gunAngle_debug = 180;
                break;
            case "left":
                console.log("left");
                this.setAngle(-1, 0, Math.PI);
                this.gunAngle_debug = 90;
                break;
            case "right":
                console.log("right");
                this.setAngle(1, 0, Math.PI * 2);
                this.gunAngle_debug = -90;
                break;
            case "shooter":
                console.log("shooter");
                this.shooter();
            default:
                return;
        }
        this.ani();
    },
    ani: function(){
        var this_ = this;
        this.timer = setInterval(function(){
            this_.detective();
            // this_.detectiveTank();  

            this_.cx += this_.sx * this_.speed;
            this_.cy += this_.sy * this_.speed;

            this_.detective();

            this_.tank.style.top = this_.cy + "px";
            this_.tank.style.left = this_.cx + "px";

        }, this.gap);
    },
    stopAni: function(){
        var event = document.createEvent('HTMLEvents');
        event.initEvent(this.stopN, true, true);
      event.eventName = this.stopN;
        window.dispatchEvent(event);
    }, 
    detective: function(){
        if(this.cx - this.width >= cSize){  //right
            this.ay += -90;
            this.ax += 0;
            this.switchPainter(1);
            this.cx = 1;
        }
        if(this.cx + this.width <= 0){      //left
            this.ay += 90;
            this.ax += 0;
            this.switchPainter(3);
            this.cx = cSize + this.width - 1;
        }
        if(this.cy <= 0){                   //top
            this.sy = 0;
            this.cy = 4;
        }
        if(this.cy + this.width >= cSize){  //bottom
            this.sy = 0;
            this.cy = cSize - this.width - 8;
        }
    },
    
    detectiveTank: function(){
        
        if(this.cx - this.width >= cSize){  //right
            this.ay += -90;
            this.ax += 0;
            this.switchPainter(1);
            this.cx = 1;
        }
        if(this.cx + this.width <= 0){      //left
            this.ay += 90;
            this.ax += 0;
            this.switchPainter(3);
            this.cx = cSize + this.width - 1;
        }
        if(this.cy <= 0){                   //top
            this.sy = 0;
            this.cy = 4;
        }
        if(this.cy + this.width >= cSize){  //bottom
            this.sy = 0;
            this.cy = cSize - this.width - 8;
        }
    },
    
    shooter: function(){
        if((new Date()).getTime() - this.sTime < this.timerLimit) return;
        var bullet = new Bullet(this.gunAngle, this.cx, this.cy, this.tankId);
        this.container.getElementsByTagName("div")[0].appendChild(bullet.bullet);
        bullet.move();
        this.sTime = (new Date()).getTime();
    },
    destroy: function(){
        this.stopAni();
        this.shooterTimer && clearInterval(this.shooterTimer);  
        this.moveTimer && clearInterval(this.moveTimer);  
        if(this.tankId >= 2 && randomTank <= tankLimit) createRandomTank();
        delete tanks[this.tankId];
        this.tank.parentNode && this.tank.parentNode.removeChild(this.tank);
        delete this;
    }
}


/**
* @Bullet Tank
* @attrs bullet, timer, gap, x, yadsjsw
*/
var Bullet = function(gA, x, y, tankId){  
    this.bullet = document.createElement("span");
    this.timer  = null;
    this.gap    = 30;
    this.passed = 0;

    var a = Math.cos(gA / 180 * Math.PI - Math.PI / 2), 
        b = Math.sin(gA / 180 * Math.PI - Math.PI / 2);
    if(Math.abs(a) > 1) a = a > 0 ? Math.floor(a) : Math.ceil(a);
    if(Math.abs(b) > 1) b = b > 0 ? Math.floor(b) : Math.ceil(b);
    this.a = a;
    this.b = b;

    this.x = x + 6;
    this.y = y + 7;
    this.bullet.setAttribute("class", "bullet");
    this.bullet.style.top = -10 + "px";
    this.bullet.style.left = -10 + "px";
    this.bullet.style.borderColor = tanks[tankId].bColor;
    this.tankId = tankId;
    this.container = $("#tank" + this.tankId)[0].parentNode.parentNode;
    this.belong = tanks[this.tankId].belong;  
}
Bullet.prototype = {
    bSwitchPainter: function(N){
        this.container = this.bullet.parentNode.parentNode;
        this.dataset   = this.container.getAttribute('data-num').split(" ");
        this.container = datas[this.dataset[N]];
        this.dataset   = this.container.getAttribute('data-num').split(" ");
        this.container.getElementsByTagName("div")[0].appendChild(this.bullet);
        this.passed++;
        if(this.passed == 4){
            this.destroy();
        }
    },
    detective: function(){
        if(this.x - 2 >= cSize){      //right
            this.bSwitchPainter(1);
            this.x = 1;
        }
        if(this.y - 2 >= cSize){      //bottom
            this.destroy();
        }
        if(this.x + 2 <= 0){          //left
            this.bSwitchPainter(3); 
            this.x = cSize + 3;
        }
        if(this.y + 2 <= 0){          //top
            this.destroy();
        }
    },
    move: function(){
        var this_ = this;
        this.timer = setInterval(function(){
            this_.detective();
            this_.x += this_.a * 5;
            this_.y += this_.b * 5;
            this_.checkHit();
            this_.bullet.style.top = this_.y + "px";
            this_.bullet.style.left = this_.x + "px";
        }, this.gap);
    },
    checkHit: function(){
        for (var i in tanks) { 
            if (i == this.tankId) continue;
            if (tanks[i].belong == this.belong) continue;  

            var tx = tanks[i].cx,
                ty = tanks[i].cy,
                bc = this.container.getAttribute("data-v"),
                tc = tanks[i].container.getAttribute("data-v"),
                w = 14;

            if ((bc == tc) && (this.x < tx + w) && (this.x > tx - w) && (this.y < ty + w) && (this.y > ty - w) ) {
                console.log(i, tanks[i].life);
                this.hit(tanks[i]);
                this.destroy();
            }
        }
    },
    hit: function(tTank){
        tTank.life -= 20;
        if(tTank.belong == 0){
            console.log("1掉血");
            bloodA.style.bottom = 300 * tTank.life / 100 + "px";
            if(tTank.life == 0){
                setTimeout(function(){
                    $(".pujieL")[0].style.display = "block";
                }, 2000);
            }
        }else if(tTank.belong == 1){
            console.log("2掉血");
            bloodB.style.bottom = 300 * tTank.life / 100 + "px";
            if(tTank.life == 0){
                setTimeout(function(){
                    $(".pujieR")[0].style.display = "block";
                }, 2000);
            }
        }else {
            var add = 5;
            if(tanks[this.tankId].belong == 0){
                if(tTank.life == 0){
                    add = 20;
                    //window.addTankGrade(0);
                }
                tanks[this.tankId].grade += add;
                $("#gradeA")[0].innerHTML = tanks[this.tankId].grade;
            }else{
                if(tTank.life == 0){
                    add = 20;
                    //window.addTankGrade(1);
                }
                tanks[this.tankId].grade += add;
                $("#gradeB")[0].innerHTML = tanks[this.tankId].grade;
            }
        }

        if(tTank.life <= 0){
            tTank.destroy();
            console.log("destroyed");
        }
    },
    destroy: function(){
        clearInterval(this.timer);
        if (typeof tanks[this.tankId] != 'undefined') {
            var tankArr = tanks[this.tankId].bulletBox;
            tankArr.splice(tankArr.indexOf(this),1);
        }
        this.bullet.parentNode && this.bullet.parentNode.removeChild(this.bullet);
    }
}

/*
function createTank(color){
    var tank = document.createElement("span");
    var circle = document.createElement("span");
    var gun = document.createElement("span");

    gun.setAttribute("class", "gun");
    tank.setAttribute("class", "tank");
    circle.setAttribute("class", "circle");

    gun.style.borderColor = color;
    circle.style.borderColor = color;
    tank.style.cssText = "width:14px;height:18px;position:relative;border-color:" + color;

    tank.appendChild(gun);
    tank.appendChild(circle);

    return tank;
}


function addTankGrade(N){
    var box, color, tank;
    if(N == 0) {
        box = $("#tankBoxA")[0];
        color = "#8500FF";
    }else{
        box = $("#tankBoxB")[0];
        color = "#6D6D27";
    }
    tank = createTank(color);
    box.appendChild(tank);

}
*/
function createRandomTank(obj) {
    var obj = obj || {cx: 150, cy: 150, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF};
    var rTank = new Tank(obj);
    rTank.init(String(randomTank));
    rTank.shooterTimer = null;
    rTank.shooterTimer = setInterval(function(){
        if(Math.random() > 0.8){
            rTank.shooter();   
        }
    }, 200);

    rTank.moveTimer = null;
    rTank.moveTimer = setInterval(function(){
        if(Math.random() > 0.4){
            var ang = Math.PI * 2 * Math.random();
            rTank.move.call(rTank, ang);
        }
    }, 1200);
    tanks[randomTank] = rTank;
    randomTank++;
}


function run_debug(){
    tanks[0] = new Tank({cx: 50, cy: 220, color:"red", bColor:"red"});
    tanks[0].init('0', {
        keySet:debug_keySet[0]
    });
    tanks[1] = new Tank();
    tanks[1].init('1', {
        keySet:debug_keySet[1]
    });

    createRandomTank({cx: 250, cy: 220, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF});
    createRandomTank({cx: 220, cy: 220, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF});
    createRandomTank({cx: 190, cy: 220, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF});
    createRandomTank({cx: 160, cy: 220, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF});
    createRandomTank({cx: 130, cy: 220, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF});
    createRandomTank({cx: 100, cy: 220, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF});
}

/*
window.onload = function(){
    var layer = document.createElement("div");
    layer.setAttribute("id", "layer");

    var stripe = document.createElement("div");
    stripe.setAttribute("id", "stripe");

    stripe.style.top = (document.clientHeight - 250) / 2 + "px";

    document.body.appendChild(layer);
    document.body.appendChild(stripe);
}*/
$("#gradeA")[0].innerHTML = $("#gradeB")[0].innerHTML = 0;

//run_debug();

function showMsg(msgContent){   
    var box = document.createElement("div");
    var msg = document.createElement("div");
    box.setAttribute("id", "showMsgBox");
    msg.setAttribute("id", "msgBox");
    with(box.style){
        position = "absolute";
        top = 0;
        left = 0;
        bottom = 0;
        right = 0;
    }
    with(msg.style){
        margin = "0 auto";
        width = "500px";
        height = "400px";
        marginTop = "100px";
        padding = "55px";
        fontSize = "30px";
        fontFamily = "微軟雅黑";
        lineHeight = "40px";
    }

    msg.innerHTML = msgContent || "空";
    box.appendChild(msg);
    document.body.appendChild(box);
}

showMsg("<b style='color:white'>[測試版本]</b>本版本只實現了一半的功能,最終版本是手機控制,並且有音效、登錄驗證、坦克可以360°旋轉,因為需要配置環境,沒有公開。左右邊界可以穿過,為3D效果。5槍可以搞定一個坦克。" + 
"<p style='color:yellow;text-align:center'>按鍵 ctrl+alt+J 開始</p><p>①:WSAD 控制上下左右,J發子彈</p><p>②:↑↓←→ 控制上下左右,p發子彈</p>")

window.onkeydown = function(){
    if(event.ctrlKey && event.altKey && event.keyCode == 74){
        $("#showMsgBox")[0].style.display = "none";
        $("#msgBox")[0].style.display = "none";
        run_debug();
    }
}
3D Tank JavaScript

拆開分析下:

  ① Tank對象

DIY坦克(還行,哈哈哈~):

var Tank = function(setting){
    var opts = setting || {};
    this.container = opts.container || forwardF;
    this.dataset   = this.container.getAttribute('data-num').split(" ");
       //....
}

Tank.prototype = {
    init: function(tankId, debug){
        //....

        if(debug){
            this.debug = true;
            this.keySet = debug.keySet;
            window.addEventListener("keydown", function(){
                this_.move_debug();
            }, false);
        }

        window.addEventListener(this.stopN, function(){
            clearInterval(this_.timer);
        }, false);

    },
    paintTank: function(){
       //....
    },
    switchPainter: function(N){
        //....
    },
    direction_debug: function(){
        //....
    },
    move_debug: function(){
        //....
    },
    ani: function(){
        //....
    },
    stopAni: function(){
        var event = document.createEvent('HTMLEvents');
        event.initEvent(this.stopN, true, true);
      event.eventName = this.stopN;
        window.dispatchEvent(event);
    }, 
    detective: function(){
 //....
    },
    
    detectiveTank: function(){
        
       //....
    },
    
    shooter: function(){
       //....
    },
    destroy: function(){
       //....
    }
}

  

  難點在於一些邊界的判斷,但是好好考慮下也不算什么難點咯~這些代碼中應該看到了很多debug之類的變量和函數,因為我寫了兩種模式,一種是手機端玩,一中是電腦鍵盤控制(debug模式)。

 

  ②子彈對象

/**
* @Bullet Tank
* @attrs bullet, timer, gap, x, yadsjsw
*/
var Bullet = function(gA, x, y, tankId){  
           //....
};

Bullet.prototype = { move:
function(){ //.... }, checkHit: function(){ //.... }, hit: function(tTank){ //.... }, destroy: function(){ clearInterval(this.timer); if (typeof tanks[this.tankId] != 'undefined') { var tankArr = tanks[this.tankId].bulletBox; tankArr.splice(tankArr.indexOf(this),1); } this.bullet.parentNode && this.bullet.parentNode.removeChild(this.bullet); } }

 

   和坦克一樣,都有一個destroy函數,銷毀對象。

 

  ③ 構建AI對象

function createRandomTank(obj) {
    var obj = obj || {cx: 150, cy: 150, color:"#ECFF0B", bColor:"#ECFF0B", speed: 1, container: backF};
    var rTank = new Tank(obj);
    rTank.init(String(randomTank));
    rTank.shooterTimer = null;
    rTank.shooterTimer = setInterval(function(){
        if(Math.random() > 0.8){
            rTank.shooter();   
        }
    }, 200);

    rTank.moveTimer = null;
    rTank.moveTimer = setInterval(function(){
        if(Math.random() > 0.4){
            var ang = Math.PI * 2 * Math.random();
            rTank.move.call(rTank, ang);
        }
    }, 1200);
    tanks[randomTank] = rTank;
    randomTank++;
}

 

  機器人是個麻煩的東西,這塊雖然不難,銷毀他們的時候費了不少力氣~~~主要是那么timer要跟着一起銷毀。

 

  ④ 構建對象說明

tanks[0] = new Tank({cx: 50, cy: 220, color:"red", bColor:"red"});
tanks[0].init('0', { keySet:debug_keySet[0] });

  這里需要說明一下,只要init后面加了第二個參數,就是調試模式,也就是說鍵盤是可以控制運行的。

  設置了一個全局變量

                //a   w   d  s   j      ←   ↑   →  ↓   p
debug_keySet = [[65, 87, 68, 83, 74], [37, 38, 39, 40, 80]];

 

3. socket這塊

  整個平台信息的交互就是以他為核心,socket這個東西還算比較新,所以學習的時候也沒找到太多的資料,只能對着w3c的一些文檔邊試邊做。

var socket;
function ws_init() {
    var host = "ws://192.168.86.1:1111/";
    // var host = "ws://202.114.20.79:1111/";
    try {
        socket = new WebSocket(host);
        logMsg('WebSocket - status '+socket.readyState);
        socket.onopen  = function(msg) { logMsg("Welcome - status "+this.readyState); send('display'); };
        socket.onclose  = function(msg) { logMsg("Disconnected - status "+this.readyState); };
        socket.onmessage = function(msg) { //.... };
    } catch(ex) {
        logMsg(ex);
    }
}
function send(msg) {
    try {
        socket.send(msg + '=');
    } catch(ex) {
        logMsg(ex);
    }
}

  socket在前端部分是非常簡單的,就是三個事件onopen, onclose, onmessage來驅動,重點還是后台操作,真心麻煩!

 

后台部分

后台用的是php,本來打算使用nodeJS,不是十分熟練,24個小時的賽制花太長時間去學習也不現實,所以就用了比較熟悉的php來建立socket連接,還算成功吧。

這個部分以后有時間說。先碎覺~~

 

最后,別忘了這個DEMO哦, http://qianduannotes.sinaapp.com/3dtank/html/index.html

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM