大致介绍

看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了,但是自己实现起来会遇到各种问题。比如,在最后判断游戏是否结束的时候,我写的语句语法是对的,但就是不执行。最后通过对视频源码的分析对比,发现原作者写的一个setTimeout定时器有额外的意思,本来我以为它就是简单的一个延时动画,其实他是在等待另外一个函数执行完毕。-_-||。最后还是很高兴能写出来,也改进了一些源代码的不足。

这篇博客并不是详细的讲解,只是大致介绍函数的作用,其中实现的细节注释中有解释,网上的这个源码有点乱,如果想看比较整齐的源码或者视频的可以QQ联系我(免费)(找共同学习的伙伴)

思路

这个小游戏可以抽象化分为3层(我觉得这样能更好理解)

◆最底下的一层是基本的样式(可见的)

◆中间的层是最主要的,是一个4x4的二维数组,游戏中我们都是对这个二维数组进行操作(不可见的)

◆最上面的一层也是一个4x4的二维数组,它只是根据第二层数组的每个数显示样式(可见的)

我们通过最底下的一层显示最基本的16个小方格,通过键盘的按键或者手指在屏幕的滑动来操作中间层的数组,最后在通过最上面的一层显示出数字

基本结构与样式

基本的结构和样式都挺简单,直接看代码

结构:

2048

开始新的游戏

分数:0

样式:

*{

margin: 0;

padding: 0;

}

#test2048{

font-family: Arial;

margin: 0 auto;

text-align: center;

}

#header{

margin: 20px;

}

#header a{

font-family: Arial;

text-decoration: none;

display: block;

color: white;

margin: 20px auto;

width: 125px;

height: 35px;

text-align: center;

line-height: 40px;

background-color: #8f7a66;

border-radius: 10px;

font-size: 15px;

}

#header p{

font-family: Arial;

font-size: 20px;

}

#container{

width: 460px;

height: 460px;

background-color: #bbada0;

margin: 0 auto;

border-radius: 10px;

position: relative;

padding: 20px;

}

.cell{

width: 100px;

height: 100px;

border-radius: 6px;

background-color: #ccc0b3;

position: absolute;

}

从CSS样式可以看出,我们并没有对每个格子的位置进行设置,因为如果用CSS给每个格子设置样式代码量太大,而且他们的位置有一定的规律,所以我们可以用js循环来完成每个格子样式的设置

代码:

// 初始化棋盘格

function initialize(){

for(var i=0;i<4;i++){

for(var j=0;j<4;j++){

// 设置棋盘格的位置

var everyCell = $('#cell-'+ i +'-'+ j);

everyCell.css({top:getPos(i),left:getPos(j)});

}

}

}

// 获取位置

function getPos(num){

return 20 + num*120;

}

这样我们的第一层就好了

效果:

现在构造第二层,即构建一个4x4的值全部为0的数组,由于在构造第二层时,有两层循环,所以我们可以在构造第一层时也能构造第二层

第三层是用js生成16个格子,它和第一层的16个格子一一对应

代码:

// 数字格

function numFormat(){

for(var i=0;i<4;i++){

for(var j=0;j<4;j++){

$('#container').append('

// 设置数字格的位置,样式

var everyNumber = $('#number-'+ i +'-'+ j);

if(checkerboard[i][j] == 0){

everyNumber.css({

width:'0px',

height:'opx',

top:getPos(i) + 50,

left:getPos(j) + 50

})

}else{

everyNumber.css({

width:'100px',

height:'100px',

top:getPos(i),

left:getPos(j),

backgroundColor:getBackgroundColor(checkerboard[i][j]),

color:getColor(checkerboard[i][j])

});

everyNumber.text(checkerboard[i][j]);

}

}

}

}

// 获取相应数字的背景颜色

function getBackgroundColor(number){

switch (number) {

case 2:return "#eee4da";break;

case 4:return "#ede0c8";break;

case 8:return "#f2b179";break;

case 16:return "#f59563";break;

case 32:return "#f67c5f";break;

case 64:return "#f65e3b";break;

case 128:return "#edcf72";break;

case 256:return "#edcc61";break;

case 512:return "#9c0";break;

case 1024:return "#33b5e5";break;

case 2048:return "#09c";break;

case 4096:return "#a6c";break;

case 8192:return "#93c";break;

}

}

// 设置相应数字的文字颜色

function getColor(number){

if (number <= 4) {

return "#776e65"

}

return "white";

}

初始化

在每次游戏重新开始时,都会在随机的位置出现两个随机的数字,我们写一个在随机位置出现一个随机数的函数,只要调用两次就可以实现了

代码:

// 随机的在一个位置上产生一个数字

function randomNum(){

// 随机产生一个坐标值

var randomX = Math.floor(Math.random() * 4);

var randomY = Math.floor(Math.random() * 4);

// 随机产生一个数字(2或4)

var randomValue = Math.random() > 0.5 ? 2 : 4;

// 在数字格不为0的地方生成一个随机数字

while(true){

if(checkerboard[randomX][randomY] == 0){

break;

}else{

var randomX = Math.floor(Math.random() * 4);

var randomY = Math.floor(Math.random() * 4);

}

}

// 将随机产生的数字显示在随机的位置上

checkerboard[randomX][randomY] = randomValue;

// 动画

randomNumAnimate(randomX,randomY,randomValue);

}

// 随机产生数字的动画

function randomNumAnimate(randomX,randomY,randomValue){

var randomnum = $('#number-'+ randomX +'-'+ randomY);

randomnum.css({

backgroundColor:getBackgroundColor(randomValue),

color:getColor(randomValue),

})

.text(randomValue)

.animate({

width:'100px',

height:'100px',

top:getPos(randomX),

left:getPos(randomY)

},50);

}

基本操作

我们通过switch循环,来根据用户不同的输入进行不同的操作

代码:

// 获取键盘事件,检测不同的按键进行不同的操作

$(document).keydown(function(event){

switch(event.keyCode){

case 37://左

if(canMoveLeft(checkerboard)){

// 如果可以向左移动

MoveLeft();

// 向左移动

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

case 38://上

if(canMoveUp(checkerboard)){

// 如果可以向上移动

MoveUp();

// 向上移动

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

case 39://右

if(canMoveRight(checkerboard)){

// 如果可以向右移动

MoveRight();

// 向右移动

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

case 40://下

if(canMoveDown(checkerboard)){

// 如果可以向下移动

MoveDown();

// 向下移动

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

default:

break;

}

});

由于数字格的移动只有左、上、右、下四种方式,并且他们都是大同小异的,所以就拿向左移动为例,

向左移动,我们首先需要判断它是否能向左移动,能向左移动有两种情况

第一种:当前格子的左边的格子是空的即值为0

第二种:当前格子的值和左边格子的值相同

由于向左移动,所以第一列的格子不可能向左移动,所以不需要判断

代码:

// 判断是否可以向左移动

function canMoveLeft(checkerboard){

for(var i=0;i<4;i++){

for(var j=1;j<4;j++){

if(checkerboard[i][j] != 0){

// 如果这个数字格它左边的数字格为空或者左边的数字格和它相等,则可以向左移动

if(checkerboard[i][j-1] == 0 || checkerboard[i][j] == checkerboard[i][j-1]){

return true;

}

}

}

}

return false;

}

判断能否向左移动后,我们就要对可以移动的格子进行移动,这里需要特别注意,向哪个方向移动就要先从哪个方向开始判断

代码:

// 向左移动

function MoveLeft(){

for(var i=0;i<4;i++){

for(var j=1;j<4;j++){

if(checkerboard[i][j] != 0){

for(var k=0;k

if(checkerboard[i][k] == 0 && noMiddleNumRow(i,k,j,checkerboard)){

moveAnimation(i,j,i,k);

checkerboard[i][k] = checkerboard[i][j];

checkerboard[i][j] = 0;

}else if(checkerboard[i][k] == checkerboard[i][j] && noMiddleNumRow(i,k,j,checkerboard) && !hasConflicted[i][k]){

moveAnimation(i,j,i,k);

checkerboard[i][k] += checkerboard[i][j];

checkerboard[i][j] = 0;

}

}

}

}

}

// 设置刷新的时间是为了让运动的动画走完在进行更新数字格,否则数字格运动的动画将会被打断

setTimeout(function(){

numFormat();

},200);

}

// 判断中间的数字格是否为0(行)

function noMiddleNumRow(row,col1,col2,checkerboard){

for(var i=col1+1;i

if(checkerboard[row][i] != 0){

return false;

}

}

return true;

}

将上、右、下四个方向写完以后,游戏基本的操作就已经完成了。

游戏分数和判断游戏结束

游戏的分数是每个相加的数的和,所以我们在每个数相加的时候更新分数就可以了

代码:

// 更新分数

score += checkerboard[k][j];

updateScore(score);

// 设置分数

function updateScore(num){

$('#score').text(num);

}

判断游戏是否结束很简单,用我们之前定义的方法就可以实现

代码:

// 判断游戏是否结束

function wheGameOver(checkerboard){

if(!canMoveLeft(checkerboard) && !canMoveUp(checkerboard) && !canMoveRight(checkerboard) && !canMoveDown(checkerboard) ){

showGameOver();

}

}

// 显示游戏结束

function showGameOver(){

$('#container').append("

最终得分

"+ score +"重新开始游戏

")

}

// 重新开始游戏

function resert(){

$('#gameover').remove();

newgame();

}

最后优化

1、游戏中会出现一次移动,一个数会被累加很多次

在原游戏中,每个数在每次操作中只能累加一次,所以我们在定义一个4x4的值为false的数组,与中间层的数组一一对应,专门用来防止一个数的多次累加,如果是false则可以累加,并将值改为false,否则不可以累加

2、结束死循环

由于在设置随机数的时候用到了一个死循环,但是在游戏结束后,该循环还在,所以我们在死循环中在添加一个条件,如果游戏结束就跳出循环

3、最后的结束游戏提示不执行

case 37://左

if(canMoveLeft(checkerboard)){

// 如果可以向左移动

MoveLeft();

// 向左移动

setTimeout(function(){

wheGameOver(checkerboard)

},300);

// 判断游戏是否结束,这里设置延时是因为要等到随机产生数字后再进行判断,如果不加

// 延时,则最后一次的判断因为canMoveLeft(checkerboard)为false就不会再执行了

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

从代码中可以看出,判断游戏是否结束是在随机产生一个数字前执行的,所以在判断游戏结束时,总是有一个空的格子,所以代码执行后认为游戏没有结束,但是当这个随机数字产生后,所有的格子不能移动,当我们按键时,if条件不通过,判断游戏是否结束的函数不能执行。所以我们要给判断游戏结束的函数设置定时器,让他在随机产生一个数字后再进行判断

4、在移动端可以执行

由于原作者没有写有关移动端的操作,所以我在网上找的判断移动端触屏手机滑动位置的代码,加入了游戏的事件就可以执行了

//返回角度

function GetSlideAngle(dx, dy) {

return Math.atan2(dy, dx) * 180 / Math.PI;

}

//根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动

function GetSlideDirection(startX, startY, endX, endY) {

var dy = startY - endY;

var dx = endX - startX;

varresult = 0;

//如果滑动距离太短

if(Math.abs(dx) < 2 && Math.abs(dy) < 2) {

returnresult;

}

var angle = GetSlideAngle(dx, dy);

if(angle >= -45 && angle < 45) {

result = 4;

}else if (angle >= 45 && angle < 135) {

result = 1;

}else if (angle >= -135 && angle < -45) {

result = 2;

}

else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {

result = 3;

}

return result;

}

//滑动处理

var startX, startY;

document.addEventListener('touchstart',function (ev) {

startX = ev.touches[0].pageX;

startY = ev.touches[0].pageY;

}, false);

document.addEventListener('touchend',function (ev) {

var endX, endY;

endX = ev.changedTouches[0].pageX;

endY = ev.changedTouches[0].pageY;

var direction = GetSlideDirection(startX, startY, endX, endY);

switch(direction) {

case 0:

//没滑动

break;

case 1:

if(canMoveUp(checkerboard)){

// 如果可以向上移动

MoveUp();

// 向上移动

setTimeout(function(){

wheGameOver(checkerboard)

},300);

// 判断游戏是否结束

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

case 2:

if(canMoveDown(checkerboard)){

// 如果可以向下移动

MoveDown();

// 向下移动

setTimeout(function(){

wheGameOver(checkerboard)

},300);

// 判断游戏是否结束

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

case 3:

if(canMoveLeft(checkerboard)){

// 如果可以向左移动

MoveLeft();

// 向左移动

setTimeout(function(){

wheGameOver(checkerboard)

},300);

// 判断游戏是否结束,这里设置延时是因为要等到随机产生数字后再进行判断,如果不加

// 延时,则最后一次的判断因为canMoveLeft(checkerboard)为false就不会再执行了

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

case 4:

if(canMoveRight(checkerboard)){

// 如果可以向右移动

MoveRight();

// 向右移动

setTimeout(function(){

wheGameOver(checkerboard)

},300);

// 判断游戏是否结束

setTimeout(function(){

randomNum();

},200);

// 随机产生一个数字

}

break;

default:

}

}, false);

总结

总体来说这个游戏实现起来并不是太难,就是许多小的操作集合起来

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!

2048网页版html项目报告,jQuery编写网页版2048小游戏相关推荐

  1. 使用jQuery编写一个打飞机小游戏

    正文: 1.闪烁 我们需要让背景闪烁,为此我们先要在css中定义背景色,我定义为黑色,然后用Jquery的animate函数实现渐隐渐现的动画. 代码示例: $(document).ready(fun ...

  2. Python编写人机对战小游戏(抓狐狸)(2)

    封面图片:<中学生可以这样学Python>,董付国.应根球著,清华大学出版社 =========== 很久很久以前,在公众号里推送过一个抓狐狸游戏,详见Python编写人机对战小游戏(抓小 ...

  3. unity编写一个简单的小游戏

    unity编写一个简单的小游戏 简易fly bird的制作 关于flybird 场景的搭建和素材的导入 使用素材搭建game和scene 制作柱体 bird的script column的sprite ...

  4. Python编写微信打飞机小游戏(三)

    如果觉得这篇文章对您有所启发,欢迎关注我的公众号,我会尽可能积极和大家交流,谢谢. Python编写微信打飞机小游戏(一) Python编写微信打飞机小游戏(二) Python编写微信打飞机小游戏(三 ...

  5. Python编写微信打飞机小游戏(八)

    如果觉得这篇文章对您有所启发,欢迎关注我的公众号,我会尽可能积极和大家交流,谢谢. Python编写微信打飞机小游戏(一) Python编写微信打飞机小游戏(二) Python编写微信打飞机小游戏(三 ...

  6. Python编写微信打飞机小游戏(十一)

    如果觉得这篇文章对您有所启发,欢迎关注我的公众号,我会尽可能积极和大家交流,谢谢. Python编写微信打飞机小游戏(一) Python编写微信打飞机小游戏(二) Python编写微信打飞机小游戏(三 ...

  7. 单机版斗地主游戏源代码,纯JS编写的斗地主单机版小游戏源代码

    单机版斗地主游戏源代码,纯JS编写的斗地主单机版小游戏源代码,下载游戏后,直接运行index.html即可. 完整代码下载地址:单机版斗地主游戏源代码 index.html <!DOCTYPE ...

  8. Python编写微信打飞机小游戏(七)

    如果觉得这篇文章对您有所启发,欢迎关注我的公众号,我会尽可能积极和大家交流,谢谢. Python编写微信打飞机小游戏(一) Python编写微信打飞机小游戏(二) Python编写微信打飞机小游戏(三 ...

  9. Python编写微信打飞机小游戏(十)

    如果觉得这篇文章对您有所启发,欢迎关注我的公众号,我会尽可能积极和大家交流,谢谢. Python编写微信打飞机小游戏(一) Python编写微信打飞机小游戏(二) Python编写微信打飞机小游戏(三 ...

最新文章

  1. python人脸识别门禁系统毕设_树莓派人脸识别门禁系统代码以及代码分析——opencv拍照调用FACE++处理...
  2. 23.C++类对象的指针为空时,调用成员函数不会挂掉
  3. 修改Oracle数据库字符集
  4. C++/Java线程之分
  5. (4)JavaScript之alert语句
  6. sqlsever 导入大数据sql文件
  7. yii2 controller 接收get形式传输过来的参数
  8. GNU Radio 之 rtl-sdr
  9. 企业架构TOGAF认证培训
  10. 你该知道的杂志分区和影响因子及最新表格下载
  11. 弘辽科技:天猫国际预测2022六大进口消费趋势
  12. iis无法启动万维网发布服务W3SVC
  13. office2003注册序列号CAB文件丢失…
  14. arcpy批量合并融合矢量数据
  15. OSChina 周三乱弹 —— 你们的女神宣布结婚了
  16. 安装Oracle XE 18c
  17. PHP 进阶:代码整洁之道
  18. ubuntu下添加日语输入法
  19. iphone 打开safari调试
  20. 算符优先算法c语言,c语言实现算符优先语法分析

热门文章

  1. 学习Python的心得体会——阜阳师范大学 21级大数据管理与应用1班的同学不要抄哦
  2. 字符串、列表、字典、元组的基本操作
  3. 台湾榜首iPhone游戏创作者谈开发成败
  4. 【上海交大oj】畅畅的牙签袋(状态压缩dp)
  5. Spring @Value读取配置文件
  6. 量化交易之vn.py篇 - 同步持仓发单逻辑(非净头寸 净头寸)
  7. 使用qq邮箱进行服务器邮件代发
  8. S7-1200PLC求数组里数据最大值最小值FB块
  9. python quit函数作用_初识Python之基础知识
  10. 将excel中的一个工作表按照某列拆分成多个sheet工作表