js实现红白球游戏
- 时间:2019年9月2号
- 类型:js练习
- 人员:魏欣怡
本案例素材联系魏欣怡或下载
效果图
案例说明
移动红球,不要碰到绿球,否则游戏结束,并且绿球是随机出来的
第一步:实现布局
<!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();
总结
- 这个游戏的主要思想是单对象编程,里面的this特别多,所以要注意this指向
- 其中又判断两个圆之前是否碰撞,它的公式是
- 绝大多数下,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下,当然在非严格模式下指向的是window,严格模式下是undefined
- 解决定时器this的方法
- 将当前对象的引用放在一个变量里,定时器内部的函数来访问这个变量,就可以得到当前的对象啦
- bind()方法是Function.prototype上的一个方法,当被绑定的函数执行时,bind方法会创建一个新函数,并将第一个参数作为新函数运行时的this
- 箭头函数,虽然这是es6里面的东西,不过可以提前了解一下,箭头函数内部的this是由外层函数的this所决定,一层一层往上找,找不到的情况下会指向window,bind(),call().apply(),也不会改变它的指向
评论区