目 录CONTENT

文章目录

js红白球游戏

Administrator
2020-07-24 / 0 评论 / 0 点赞 / 8550 阅读 / 8367 字

js实现红白球游戏

  • 时间:2019年9月2号
  • 类型:js练习
  • 人员:魏欣怡

本案例素材联系魏欣怡或下载

效果图

image.png

案例说明

移动红球,不要碰到绿球,否则游戏结束,并且绿球是随机出来的

第一步:实现布局

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>game</title>
    <link rel="stylesheet" href="css/index.css">
</head>
<body>
      <span id="timer">马上开始</span>
      <div id="outer">
          <div id="move"></div>
      </div>  
      <p>游戏规则:移动红球,坚持至少30秒</p>  
      <script src="js/index.js"></script>
</body>
</html>

第二步:css样式

*{
    margin: 0;
    padding: 0;
}
body{
    background: #326b86;
    text-align: center;
    padding: 30px;
    color: #ffffff;
}
#outer{
    position: relative;
    width: 450px;
    height: 450px;
    background: #222;
    margin: 30px auto;
}
#move{
    position: absolute;
    width: 60px;
    height: 60px;
    background: red;
    border-radius: 50%;
    opacity: 0.6;
    cursor: move;
    left: 195px;
    top: 195px;
}
.green{
    position: absolute;
    width: 50px;
    height: 50px;
    background: green;
    border-radius: 50%;
    opacity: 0.6;
    left: 0;
    top: 0; 
}

第三步:实现js功能

/**
 * 单对象的编程
 */

var game = {
    redBall: document.getElementById('move'),//获取红色的求
    timeNode: document.getElementById('timer'),
    creatTimer:null,
    timer:null,
    num:0,
    movePlus: {
        outer: document.getElementById('outer'),
        iWidth: document.getElementById('outer').offsetWidth,//外面盒子的宽度
        iHeight: document.getElementById('outer').offsetHeight,//高度
        speedX: 10,
        speedY: 10
    },
    //入口函数,因为定义的函数太多,可以放在入口函数当中,这样调用的时候,这调用它就可以了
    init: function () {
        this.creatBoll(this.movePlus);//创建小球函数
        this.dragBall(this.movePlus);//创建小红球拖拽
        this.timerRun();//时间计时

    },
    timerRun:function(){
        var that = this;
        //setInterval中的this已经指向了window,所以保存外部的this
        this.timer = setInterval(function(){
            that.num ++ ;
            that.timeNode.innerHTML = '已经坚持' + that.num + '秒';
        },1000)


    },
    creatBoll: function (obj) {
        var movePlus = obj;
        //创建一个小绿色球的类
        function Green(movePlus) {//创建一个小球的工厂
            this.ball = document.createElement('div');
            this.ball.className = 'green';
            this.iWCurrent = Math.floor(Math.random() * (movePlus.iWidth - 50));
            this.ball.style.left = this.iWCurrent + 'px';
            //让outer这个盒子装进ball.他的left(outer的宽度-ball的宽度 范围之内)
            //小球的速度speedx speedy
            movePlus.outer.appendChild(this.ball);
            this.speedX = Math.floor(Math.random() * movePlus.speedX);
            this.speedY = Math.floor(Math.random() * movePlus.speedY);
            this.iWidth = movePlus.iWidth;
            this.iHeight = movePlus.iHeight;
        }

        var newBall = new Green(movePlus);
        this.moveBall(newBall, this.redBall);
        //创建第一个小球
        var that = this;
        this.creatTimer = setInterval(function(){
            var newBall = new Green(movePlus);
            that.moveBall(newBall, that.redBall);
        },2000)
        //计时器生成小球
    },
    moveBall: function (obj, redBall) {
        var that = this;
        obj.ball.goTimer = setInterval(function () {
            that.crashCheck(obj, redBall)//检测碰撞函数
            var newLeft = obj.speedX + obj.ball.offsetLeft;
            var newTop = obj.speedY + obj.ball.offsetTop;
            //回弹运动
            if (newLeft < 0) {//判断左壁
                obj.speedX *= -1;
            }
            if (newLeft > obj.iWidth - obj.ball.offsetWidth) {//判断右壁
                obj.speedX *= -1;
            }
            if (newTop < 0) {//判断上壁
                obj.speedY *= -1;
            }
            if (newTop > obj.iHeight - obj.ball.offsetHeight) {//判断下壁
                obj.speedY *= -1;
            }

            obj.ball.style.left = newLeft + 'px';
            obj.ball.style.top = newTop + 'px';

        }, 50)
    },
    dragBall: function (obj) {
        var that = this;
        this.redBall.onmousedown = function (e) {
            var e = e || event;
            var on_x = e.pageX;
            var on_y = e.pageY;

            document.onmousemove = function (e) {
                var cha_x = e.pageX - on_x;
                var cha_y = e.pageY - on_y;
                that.redBall.style.left = that.redBall.offsetLeft + cha_x + 'px';
                that.redBall.style.top = that.redBall.offsetTop + cha_y + 'px';
                on_x = e.pageX;
                on_y = e.pageY;
                //检测拖拽边界
                if (that.redBall.offsetWidth + that.redBall.offsetLeft > obj.iWidth) {
                    that.clearTimer();
                    window.location.reload();
                    alert('游戏结束!已经坚持' + that.num + '秒');
                    //右
                }
                if (that.redBall.offsetLeft < 0) {
                    that.clearTimer();
                    window.location.reload();
                    alert('游戏结束!已经坚持' + that.num + '秒');
                    //左
                }
                if (that.redBall.offsetHeight + that.redBall.offsetTop > obj.iHeight) {
                    that.clearTimer();
                    window.location.reload();
                    alert('游戏结束!已经坚持' + that.num + '秒');
                    //上
                }
                if (that.redBall.offsetTop < 0) {
                    that.clearTimer();
                    window.location.reload();
                    alert('游戏结束!已经坚持' + that.num + '秒');
                    //下
                }

            }

            this.onmouseup = function (e) {
                document.onmousemove = null;
            }
        }


    },
    //检查两个球是否碰撞
    crashCheck: function (obj, redBall) {
        var greenX1 = obj.ball.offsetLeft + Math.floor(obj.ball.offsetWidth / 2);
        var greenY1 = obj.ball.offsetTop + Math.floor(obj.ball.offsetWidth / 2);

        var redX2 = redBall.offsetLeft + Math.floor(redBall.offsetWidth / 2);
        var redY2 = redBall.offsetTop + Math.floor(redBall.offsetWidth / 2);

        var dx = Math.abs(greenX1 - redX2);
        var dy = Math.abs(greenY1 - redY2);
        //两个圆之间的距离计算
        var dis = Math.floor(Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)));
        // console.log(dis);
        var R = redBall.offsetWidth / 2 + obj.ball.offsetWidth / 2;
        // console.log(R)
        if (dis < R) {
            
            this.clearTimer();
            alert('游戏结束!已经坚持' + this.num + '秒');
            window.location.reload();

        }
    },
    clearTimer: function () {
        clearInterval(this.creatTimer);
        clearInterval(this.timer);
        var outer = this.movePlus.outer;//找到所有小球清除定时器
        var allballs = outer.getElementsByClassName('green');
        for (var i = 0; i < allballs.length; i++) {
            clearInterval(allballs[i].goTimer);
        }

    }

}
game.init();

总结

  1. 这个游戏的主要思想是单对象编程,里面的this特别多,所以要注意this指向
  2. 其中又判断两个圆之前是否碰撞,它的公式是1567435054474
  3. 绝大多数下,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下,当然在非严格模式下指向的是window,严格模式下是undefined
  4. 解决定时器this的方法
    • 将当前对象的引用放在一个变量里,定时器内部的函数来访问这个变量,就可以得到当前的对象啦
    • bind()方法是Function.prototype上的一个方法,当被绑定的函数执行时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this
    • 箭头函数,虽然这是es6里面的东西,不过可以提前了解一下,箭头函数内部的this是由外层函数的this所决定,一层一层往上找,找不到的情况下会指向window,bind(),call().apply(),也不会改变它的指向

0

评论区