内容简介:今天给大家带来一个小游戏
今天给大家带来一个小游戏
要求:熟悉JavaScript继承的概念
游戏预览
玩法:开局一个球 两块板子。其中最上方是电脑板子,会跟着球跑。球达到板子上回弹回来。打到你的板子上也是回弹出去。如果达到了上下边界。游戏结束
控制你的板子就用方向左右键
接到一个球+10分
基础布局部分(HTML+CSS)
游戏部分,我们按照以下图示尺寸设定
html:
<div class="game"> //游戏本体
<div class="board b1"> //电脑的板子(上板子)
</div>
<div class="board b2"> //你的板子(下板子)
</div>
<div class="ball"></div> //球体
<div class="info">
<h2 class="infoText">开始游戏</h2>
<button class="start">点击这里</button>
</div>
<div class="grade">0</div> //左上角分数卡
</div>复制代码
CSS :
.game {
width: 500px;
height: 500px;
position: relative;
border: 5px solid #fff;
background-color: #222;
}
.board {
background-color: #FF644E;
}
.ball {
background-color: #fff;
}
.info {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
color: white;
background-color: #222;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.grade {
padding: 10px;
}复制代码
逻辑部分(JavaScript)
我们采用JavaScript继承的方式来写这个游戏。首先先定义一个GameObject
let GameObject = function (position,size,selector){
this.$el = $(selector) //选择器
this.position = position //游戏物体位置
this.size = size //游戏物体大小
this.$el.css("position","absolute") //设置其Css为绝对定位
this.updateCss()
}
GameObject.prototype.updateCss = function(){
this.$el.css("left",this.position.x+"px")
this.$el.css("top",this.position.y+"px")
this.$el.css("width",this.size.width+"px")
this.$el.css("height",this.size.height+"px")
}复制代码
首先
$el为选择器。代表jQuery的元素选择器
position为元素定位的位置
size为元素大小
设置在原型链上的 updateCss方法为元素位置,大小更新方法。按照当前对象的属性数值更新
那我们先创建一个球(Ball)对象。继承GameObject
let Ball = function () {
this.size = {width: 15, height: 15}; //球的大小
this.position = {x: 250, y: 250}; //球的位置
this.velocity = {x: 5, y: 5}; //球的速度
GameObject.call(this,this.position,{width: 15, height: 15},".ball") //继承GameObject。并将参数和自身传入
};
Ball.prototype = Object.create(GameObject.prototype); //将Ball的原型链连接GameObjecr的原型链
Ball.prototype.constructor = Ball.constructor //因为连接,所以需要重新指向构造函数。将原型链的构造函数指向自己的构造函数复制代码
因为球只有一个,所以参数我们写死在对象里面
我们实例化一个球对象
let ball = new Ball();复制代码
接着屏幕中央就会有一个球
接下来开始绘制两个可移动的板子
let Board = function (position, sel) {
this.size = { //锁定板子大小
width: 100,
height: 15
};
GameObject.call(this, position, this.size, sel); //对接父对象
};
Board.prototype = Object.create(GameObject.prototype); //对接父对象原型链
Board.prototype.constructor = Board.constructor; //更改原型链上的构造为自己的构造复制代码
然后new 两块板子
let board1 = new Board({x: 0, y: 30}, '.b1');
let board2 = new Board({x: 0, y: 455}, '.b2');复制代码
然后,我们让球动起来
我们在Ball的原型链上定义一个update方法。来移动小球
Ball.prototype.update = function () {
this.position.x += this.velocity.x; //x轴按速度移动
this.position.y += this.velocity.y; //Y轴按速度移动
this.updateCss(); //调用父对象的updateCss方法更新界面
if (this.position.x < 0 || this.position.x > 500) { //如果撞到了左右墙壁
this.velocity.x = -this.velocity.x; // 回弹
}
if (this.position.y < 0 || this.position.y > 500) { //如果撞到了上下墙壁
this.velocity.y = -this.velocity.y; // 回弹
}
};复制代码
如果球的 横向边界 小于0或者大于500,说明球碰到了左右墙壁
如果球的 纵向边界 小于0或者大于500,说明球碰到了上下墙壁
然后我们每隔30ms 调用一下小球的update函数。使其位置更新
setInterval(function () {
ball.update();
}, 30)复制代码
如图 :
这样 小球就有了碰到障碍物反弹的能力了
接着我们删掉这个定时器的代码
然后,我们定义一个Game对象。这个对象不会继承任何父对象。因为他只负责控制其他物体对象
let Game = function () {
this.timer = null; //唯一timer 负责开始游戏结束游戏的timer
this.grade = 0; //分数
this.initControl(); //键盘监听事件
this.control = {}; //这个放置各个键盘按键情况的对象
};
复制代码
因为我们有键盘要控制板子的移动,所以我们要加监听事件
Game.prototype.initControl = function () {
let _this = this; //防止this作用域混淆
$(window).keydown(function (evt) { //按键按下
_this.control[evt.key] = true; //设置当前的key value为true
});
$(window).keyup(function (evt) { //按键抬起
_this.control[evt.key] = false; //设置当前的key value为false
})
};复制代码
根据我们的游戏规则,小球碰到上下墙壁要判别输赢。碰到上下板子要回弹
所以我们在GameObject的原型链上定义一个碰撞方法collide
GameObject.prototype.collide = function (otherObject) {
let inRangeX = otherObject.position.x > this.position.x &&
otherObject.position.x < this.position.x + this.size.width;
let inRangeY = otherObject.position.y > this.position.y &&
otherObject.position.y < this.position.y + this.size.height;
return inRangeX && inRangeY;
};复制代码
其参数是另一个物体对象。
inRangeX 的判别式:当另一个物体的X值大于你的X值 且 另个物体X值小于你的X值+你宽度的时候,返回true。否则false
inRangeY 的判别式:当另一个物体的Y值大于你的 Y 值 且 另个物体 Y 值小于你的 Y 值+你高度的时候,返回true。否则false
然后返回两个判别式的情况
如果都为true,说明两个物体相撞了
这样我们在Game对象定义一个startGameMain方法。代表是我们游戏控制器主体
Game.prototype.startGameMain = function () {
let _this = this; //作用域!!!
this.timer = setInterval(function () { //唯一定时器
if (board1.collide(ball)) { //如果一号板子撞到了球
console.log("碰到了1号板子");
ball.velocity.y = -ball.velocity.y; //Y反向运动
}
if (board2.collide(ball)) { //如果二号板子撞到了球
console.log("碰到了2号板子");
_this.grade += 10; //自己的分数+10
ball.velocity.y = -ball.velocity.y;
}
ball.update(); //球体更新方法
$(".grade").text(this.grade); //jQuery更新分数
}, 30) //每隔30ms走一次
};复制代码
然后
let game = new Game(); game.startGameMain();复制代码
看一看效果
接着在 startGameMain 函数内,继续编写
如果球碰到上板子。说明上板子输了 如果碰到下板子,下板子输了
if (ball.position.y < 0) {
console.log("第一个板子输了");
_this.endGame("你赢了"); //后面的结束游戏方法
}
if (ball.position.y > 500) {
console.log("第二个板子输了");
_this.endGame("你输了");
}复制代码
接着我们让上板子跟着球跑
我们现在板子Board对象内定义一个update方法。更新板子的坐标和UI
Board.prototype.update = function () {
this.updateCss();
};复制代码
然后继续在startGameMain 函数内 写板子跟球跑的逻辑
board1.position.x += ball.position.x > board1.position.x + board1.size.width / 2 ? 12 : 0; board1.position.x += ball.position.x < board1.position.x + board1.size.width / 2 ? -12 : 0; board1.update();复制代码
如果球的X坐标 > 板子X坐标+板子宽度/2,那么板子X +12。向右跑
如果球的X坐标 < 板子X坐标+板子宽度/2,那么板子X -12 。 向左跑
如图
但是细心的朋友可能会发现,板子超出边界了。
所以我们就限制板子最小x为0,最大x为 容器width-板子width
于是我们重写一下Board的update方法
Board.prototype.update = function () {
if (this.position.x < 0) {
this.position.x = 0;
}
if (this.position.x + this.size.width > 500) {
this.position.x = 500 - this.size.width;
}
this.updateCss();
};复制代码
这样再看看~~
接着写我方板子 键盘控制事件
还是在startGameMain函数内
if (_this.control["ArrowLeft"]) { //如果左键
board2.position.x -= 8; //二号板子左移8
}
if (_this.control["ArrowRight"]) { //如果右键
board2.position.x += 8; //二号板子右移8
}
复制代码
board2.update(); 复制代码
这样我们的键盘也可以操控了。球也能正常回弹
我们继续写endGame函数
Game.prototype.endGame = function (res) {
clearInterval(this.timer); //清除定时器
$(".infoText").html(res + '<br>分数:' + this.grade); //展示分数
$(".info").show(); //展示信息
};复制代码
然后我们在加一个startGame的函数
Game.prototype.startGame = function () {
let time = 3; //倒计时3秒
let _this = this;
this.grade = 0; //初始化分数0
ball.init(); //稍后用到
let timer = setInterval(function () {
$(".infoText").text(time);
time--;
if (time < 0) { //如果时间<0
clearInterval(timer); //清除定时器
$(".info").hide(); //隐藏信息
_this.startGameMain(); //开始主要的游戏函数
}
}, 1000)
};复制代码
我们在HTML里面新增info信息的元素
<div class="game">
<div class="board b1">
</div>
<div class="board b2">
</div>
<div class="ball"></div>
<div class="info"> //新增的地方
<h2 class="infoText">开始游戏</h2>
<button class="start">点击这里</button>
</div>
<div class="grade">0</div>
</div>复制代码
最下面我们调用一下startGame
let game = new Game();
$(".start").click(function () {
game.startGame();
})复制代码
这样一个比较完整的游戏完成了
但是这看起来有点傻。因为他每次只向一个方向去发车
我们可以使用JavaScript中的三角函数,解决这个问题
首先我们找到Ball对象。把里面的速度参数,抽出为一个函数。取名叫init
Ball.prototype.init = function () {
this.position = {x: 250, y: 250};
let randomDeg = Math.random() * 2 * Math.PI;
this.velocity = {
x: Math.cos(randomDeg) * 8,
y: Math.sin(randomDeg) * 8
}
};复制代码
然后 Ball对象内只剩下
let Ball = function () {
this.size = {width: 15, height: 15};
this.init();
GameObject.call(this, this.position, this.size, '.ball');
};复制代码
我们来仔细讲一下这个init函数
首先我们先锁定速度为10,这个是首要条件。所以我们先产生一个随机角度:
let randomDeg = Math.random() * 2 * Math.PI;复制代码
1PI 为180度 2PI为360度
然后我们再随机一个小数。可以得到一个360度以内的任意角
接着,我们可以根据三角函数,cos和sin
sin是斜边 / 对边,cos是斜边 / 邻边。我们如果知道了角度和长度,就可以知道XY的速度分别是多少
X长度 = 斜边长 * Cos(角度)
Y长度 = 斜边长 * Sin(角度)如图
这也就是数学中 向量 的概念
然后我们再看看我们的游戏:
显然比之前合理多了。
写完这篇文章已经 凌晨3点钟了。睡觉~~~~
谢谢各位
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Chinese Authoritarianism in the Information Age
Routledge / 2018-2-13 / GBP 115.00
This book examines information and public opinion control by the authoritarian state in response to popular access to information and upgraded political communication channels among the citizens in co......一起来看看 《Chinese Authoritarianism in the Information Age》 这本书的介绍吧!