• js动画之弹球打砖块小游戏


    什么?你觉得方块碰撞问题太简单了。那就来一个复杂的,我们都熟悉的打砖块游戏。

    先看效果,熟悉吗?

    这个就是碰撞问题的升华。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>JS弹球打砖块小游戏</title>
        <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 { 15px;height: 15px;background: #b4ff0d;border-radius: 50%;position: absolute;top: 0;left: 0;box-shadow: 0 0 9px 9px #f3ff67;}
            #ward { 120px;height: 30px;z-index: 999;background-color: #336688;border-radius: 10px;box-shadow: 0 0 4px #333333;position: absolute;left: 0;}
            #score { 100px;height: 100px;font-size: 40px;position: absolute;right: 40px;top: 40px;color: #ff2541;}
            #wrap { 90%;height: 500px;position: relative;top: 100px;left: 0;right: 0;margin: auto;}
            #wrap div { 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; 300px;height: 200px;box-shadow: 0 0 4px #222222;background-color: #e1e1e1;display: none}
            #gameover p { 100%;height: 40px;text-align: center;font-size: 36px;color: #336688;margin-top: 50px;}
            #gameover span { 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>
    </head>
    <body>
        <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>
        <script type="text/javascript">
            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 () {      //点击开始游戏,小球运动 
                       console.log(This) 
                        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递归调用实现循环  
                        console.log("boll的位置");
                        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;
                    }
                    //挡板碰撞检测  
                    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();
                    }
                },
                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();
        </script>
    </body>
    </html>

    在我上两个博客中,我们知道小球碰撞到浏览器边框,速度的改变规律。

    那么在遇到砖块,小球的速度变化规律是什么呢?当然是水平方向的速度不变,垂直方向的速度取相反。

    就这么简单的思想,却玩出了不一样的精彩。

  • 相关阅读:
    android彻底结束进程的两种方法
    清理软件缓存
    android webview 设置
    创建和使用Android library工程
    如何使Android应用程序获得root权限
    自动安装mysql5.7shell脚本实现与ansible脚本实现
    老生常谈:Asp.net Mvc 3 加载cshtml文件创建自定义分页
    老生常谈: Asp.net Mvc3 加载cshtml文件自定义分页+ 查询
    Razor API翻译
    Asp.net MVC 3使用 Area 小结
  • 原文地址:https://www.cnblogs.com/duanhuarong/p/12197672.html
Copyright © 2020-2023  润新知