1. 程式人生 > >原生javascript面向對象開發兒時經典打磚塊小遊戲

原生javascript面向對象開發兒時經典打磚塊小遊戲

javascript 經典 打磚塊 遊戲 面向對象

技術分享圖片

知識點: js面向對象,js運動碰撞檢測,js隨機顏色,動態生成動態監測實現原理,運動實現原理,模塊化編程思想, 事件監聽封裝, 頁面刷新事件 ,call與bind改變this指向等。

html代碼:

<div id="wrap"></div>
<div id="ball"></div>
<div id="ward"></div>
<div id="score">0分</div>
<div id="gameover">
    <p>總分:74</p>
    <span>確定</span>
</div>

css代碼:

    <style type="text/css">
        * { margin: 0; padding: 0; cursor: none; }

        a { text-decoration: none; }

        ul, li { list-style: none; }

        body { font-size: 14px; font-family: "微軟雅黑"; background: url("images/bg.jpg") top/cover; }

        #ball { width: 15px; height: 15px; background: #b4ff0d; border-radius: 50%; position: absolute; top: 0; left: 0; box-shadow: 0 0 9px 9px #f3ff67; }

        #ward { width: 120px; height: 30px; z-index: 999; background-color: #336688; border-radius: 10px; box-shadow: 0 0 4px #333333; position: absolute; left: 0; }

        #score { width: 100px; height: 100px; font-size: 40px; position: absolute; right: 40px; top: 40px; color: #ff2541; }

        #wrap { width: 90%; height: 500px; position: relative; top: 100px; left: 0; right: 0; margin: auto; }

        #wrap div { width: 45px; height: 15px; border: 1px solid #ff645b; position: absolute; background: rgb(255, 99, 89); box-shadow: 0 0 9px 1px rgb(255, 187, 136) inset; top: 0; left: 0; transform-origin: top center }

        #gameover { position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin: auto; width: 300px; height: 200px; box-shadow: 0 0 4px #222222; background-color: #e1e1e1; display: none }

        #gameover p { width: 100%; height: 40px; text-align: center; font-size: 36px; color: #336688; margin-top: 50px; }

        #gameover span { width: 60%; height: 40px; display: block; margin: 38px auto 0; text-align: center; font-size: 20px; background: #336688; color: #ffffff; border-radius: 10px; line-height: 40px; }
    </style>

javascript代碼:

<script type="text/javascript">
    /*  javascript中嚴格區分大小寫 a!==A;
             1.需要哪些元素
                 小球 擋板 磚塊區域 初始x位置 初始y位置
             2.要有那些行為
                初始化init
                     init用來存放初始化方法
                     如果實例化對象調用所有方法很麻煩,所以一次性解決
             創建磚塊creatBrick
             for循環生成磚塊
             計算每一個磚塊初始化top和left
             計算金字塔中線位置
             初始化小球
             初始化小球x方向移動向量
             初始化小球y方向移動向量
             初始化小球寬度和高度
             初始化小球開始運動事件
             初始化小球位置 x,y
             初始化擋板
             初始化擋板位置 x,y
             初始化鼠標監聽事件
             擋板的移動
             擋板中央跟隨鼠標x方向移動
             擋板運動邊界 左 右
             小球的移動
             小球移動方法 requestAnimationFrame
             小球x y 向量自增
             碰撞檢測{
             1:小球和瀏覽器邊框的碰撞
             反彈 x||y
             2:小球和擋板的碰撞
             反彈 y
             3.小球和磚塊的碰撞
             反彈 y && 移除磚塊
             }
     */
    var oBall = document.querySelector("#ball");  //球
    var oWard = document.querySelector("#ward");  //擋板
    var oScore = document.querySelector(‘#score‘);//計分板
    var oWrap = document.querySelector(‘#wrap‘);  //磚塊區域
    var over = document.querySelector(‘#gameover‘); //結束

    function Breakout(ball, ward, score, wrap, over) {   //打磚塊小遊戲對象 構造函數
        this.ball = ball;
        this.ward = ward;
        this.scores = score;
        this.wrap = wrap;
        this.over = over;
        this.x = 0;
        this.y = 0;
        this.score = 0;
    }
    Breakout.prototype = {    //原型方法
        init: function () {  //初始化系統
            this.ballstar();    //初始化小球
            this.creatBrick();  //創建磚塊
            this.wardMove();    //擋板移動

        },
        creatBrick: function () {    //磚塊初始化
            var x = document.documentElement.offsetWidth / 2 - document.documentElement.offsetWidth * .05, //設置居中位置
                w = 45 * 2, //設置橫向間距基準值
                h = 15 * 2; //設置縱向間距基準值
            for (var i = 1; i <= 8; i++) {  //循環生成div 8層
                for (var j = 0; j < i * 2 - 1; j++) {    //每一層的磚塊個數為 層數*2-1
                    var brick = document.createElement("div");
                    brick.style.top = (i - 1) * h + ‘px‘;
                    brick.style.left = x - (i * w) + (j * w) + ‘px‘;
                    this.wrap.appendChild(brick);
                }
            }
        },
        wardMove: function () {     //擋板初始化
            this.ward.style.top = window.innerHeight - 180 + ‘px‘;  //初始化擋板的top位置
            this.ward.style.left = this.x - 60 + ‘px‘;              //初始化擋板的left位置居中
            this.addEvent(document, ‘mousemove‘, this.mouseMove.bind(this)); //監聽鼠標移動
        },
        ballstar: function () {    //小球初始化
            var This = this;
            this.y = window.innerHeight - 200;    //初始化坐標X的位置 窗口底部上移200px
            this.x = window.innerWidth / 2;       //初始化坐標Y的位置 窗口中間部位
            this.ball.style.top = this.y + ‘px‘;  //初始化小球的top值為y
            this.ball.style.left = this.x + ‘px‘; //初始化小球的left值為x
            this.ball.speed = 10;                 //初始化小球的速度
            this.ball.width = 15;                   //初始化小球的寬度
            this.ball.height = 15;                  //初始化小球的高度
            document.onclick = function () {      //點擊開始遊戲,小球運動
                This.ballMove();                  //小球移動
            }

        },
        //擋板移動
        mouseMove: function (e) {                               //鼠標移動,擋板跟隨鼠標運動
            e = e || window.event;                              //事件對象兼容性處理
            var _left = e.pageX - this.ward.offsetWidth / 2;    //保證鼠標移動,擋板中間位置同步鼠標位置
            _left = Math.min(window.innerWidth - this.ward.offsetWidth, _left); //擋板向右移動不能超過屏幕右邊界
            _left = Math.max(0, _left);                                         //擋板向左移動不能超過屏幕左邊界
            this.ward.style.left = _left + ‘px‘;                                //通過設置擋板left值實現擋板移動
        },
        ballMove: function () {                 //小球開始運動
            document.onclick = null;            //先清除document的點擊事件防止一直重置運動
            this.ball.xspeed = this.ball.speed; //初始化小球x運動速度和方向 +為往左 -為往右
            this.ball.yspeed = -this.ball.speed;//初始化小球y運動速度和方向 +為往上 -為往下
            function auto() {                   //運動函數 auto 通過requestAnimationFrame遞歸調用實現循環
                this.x += this.ball.xspeed;     //x代表當前橫向位置 += 橫向移動速度 10 每一次都在自己原先的位置基礎上+10
                this.y += this.ball.yspeed;     //y代表當前橫向位置 += 橫向移動速度 10 每一次都在自己原先的位置基礎上+10
                this.crash();                   //碰撞檢測
                this.ball.style.left = this.x + ‘px‘;   //小球運動賦值 x軸運動
                this.ball.style.top = this.y + ‘px‘;    //小球運動賦值 y軸運動
                requestAnimationFrame(auto.bind(this)); //原生js動畫 根據cpu運算速度來實現更新
            }

            auto.call(this);
        },
        crash: function () {
            var maxWidth = window.innerWidth - this.ball.offsetWidth;        //瀏覽器左邊界=瀏覽器寬度-球的寬度
            var maxHeight = window.innerHeight - this.ball.offsetHeight;     //瀏覽器右邊界=瀏覽器高度-球的高度
            if (this.y >= maxHeight) {                                       //小球掉下去之後,遊戲結束
                this.gameOver();
            }
            if (this.x >= maxWidth) {
                this.ball.xspeed *= -1;                                     //小球碰到右邊墻壁後 橫向移動速度取反 往返方向移動
                this.x = maxWidth;                                          //重置小球位置
            }
            if (this.x < 0) {                                               //碰到左邊墻 重置橫向移動速度 並且重置橫向位置 為0
                this.ball.xspeed = this.ball.speed;
                this.x = 0;
            }
            if (this.y < 0) {                                               //碰到上邊墻壁之後 重置縱向移動速度 以及縱向位置 為0
                this.ball.yspeed = this.ball.speed;
                this.y = 0;
            }
            //擋板碰撞檢測 xweizhi
            if (Math.abs(this.x - (this.ward.offsetLeft + (this.ward.clientWidth / 2))) < 60 && Math.abs(this.y - this.ward.offsetTop - 30) < 45) {
                var color = this.ranColor();
                this.ward.style.background = color;
                this.ball.yspeed *= -1;
                this.y = this.ward.offsetTop - 40;
            }

            for (var i = this.wrap.children.length - 1; i >= 0; i--) {
                var ballMx = this.ball.offsetLeft + (this.ball.width / 2);
                var ballMy = this.ball.offsetTop + (this.ball.height / 2);
                var brickMx = (this.wrap.children[i].offsetLeft + this.wrap.offsetLeft) + (45 / 2);
                var brickMy = (this.wrap.children[i].offsetTop + this.wrap.offsetTop) + (15 / 2);
                if (Math.abs(ballMx - brickMx) <= 45 && Math.abs(ballMy - brickMy) <= 15) {
                    this.ball.yspeed *= -1;
                    this.y = brickMy;
                    this.wrap.removeChild(this.wrap.children[i]);
                    if (this.wrap.children.length == 0) {
                        this.gameOver();
                    }
                    this.scoreChange();
                }
            }
        },
        scoreChange: function () {
            this.score++;
            this.scores.innerHTML = this.score + ‘分‘;
        },
        gameOver: function () {
            this.over.style.display = ‘block‘;
            this.over.children[0].innerHTML = ‘總分:‘ + this.score;
            var all = document.querySelectorAll(‘*‘);
            for (var i = 0; i < all.length; i++) {
                all[i].style.cursor = ‘auto‘
            }
            this.ward.style.display = ‘none‘;
            this.ball.style.display = ‘none‘;
            this.over.children[1].onclick = function () {
                window.location.reload();
            }
        },
        /*    getStyle: function (ele, curr) {  //獲取屬性值
         return ele.currentStyle ? parseInt(ele.currentStyle[curr]) : parseInt(getComputedStyle(ele, null)[curr]);
         },*/
        addEvent: function (element, e, fn) {//事件監聽
            return element.attachEvent ? element.attachEvent(‘on‘ + e, fn) : element.addEventListener(e, fn, false);
        },
        ranColor: function () { //隨機顏色
            var color = ‘#‘;
            for (var i = 0; i < 6; i++) {
                color += ‘0123456789abcdef‘[Math.floor(Math.random() * 16)]
            }
            return color;
        },
    }
    var breakout = new Breakout(oBall, oWard, oScore, oWrap, over);
    breakout.init();
    //湊個200行玩玩....
    //湊個200行玩玩...
</script>

有興趣想學習web前端的可以來web前端qun“189394454”可以免費獲取2018最新web前端學習資料。

原生javascript面向對象開發兒時經典打磚塊小遊戲