作者:channingbreeze

日期:2016-12-11

2048作为前段时间十分火爆的小游戏,以其简单的操作,有趣的玩法,一下子从小游戏的角逐中脱颖而出。本教程通过phaser来实现了一个标准版的2048,可以在桌面和移动端运行,一起来看看其中的关键代码吧。

效果就不在这里截图了,给一个地址,大家自己体验一下先。http://game.webxinxin.com/2048。

本教程主要介绍一些思路,技术关键点以及实现过程中遇到的一些坑!

开始界面呀,结束界面呀,这些就不介绍了,非常简单,如果还不会的话,可以看前面的入门教程和一些实例。本案例比较难的就是游戏的逻辑以及数据结构的组织方式。

第一个技术点是上面的两个计分的框,由于本案例的图片资源比较少,很多东西都是由js去画出来的,两个计分框也不例外。其实每个计分框可以看成一个大的sprite,这个大的sprite由几部分组成,框子、标题和分数,分别用graphic和两个text就能实现,把这些都放到sprite里面,就组成了一个计分框。

//score

var scoreSprite = game.add.sprite(10, 10);

var scoreGraphics = game.add.graphics(0, 0);

scoreGraphics.lineStyle(5, 0xA1C5C5);

scoreGraphics.beginFill(0x308C8C);

scoreGraphics.drawRoundedRect(0, 0, 70, 50, 10);

scoreGraphics.endFill();

scoreSprite.addChild(scoreGraphics);

var scoreTitle = game.add.text(0, 5, "SCORE", titleStyle);

scoreTitle.setTextBounds(0, 0, 70, 50);

scoreSprite.addChild(scoreTitle);

this.scoreText = game.add.text(0, 20, this.score, scoreStyle);

this.scoreText.setTextBounds(0, 0, 70, 50);

scoreSprite.addChild(this.scoreText);

其实有了计分框的实现思路,不难想象,2048游戏中的方块也是这种方式,一个框加上一个分数,组成一个sprite,也就是一个方块。但是方块仅仅实现了显示的需求,逻辑需求要怎么实现呢?所以其实我们需要一个4x4的数组,然后根据上下左右的滑动来做不同的遍历,决定怎么合并和移动方块。而每一个方块对象,除了有一个sprite属性外,还有一些标识去记录一些状态,表示逻辑的处理结果。

在滑动逻辑的处理中,我们总是从前面开始,从后往前遍历,如果碰到一个非零的方块,就检查是否能够合并,能够合并就进行合并,交换方块的位置及sprite等属性,并且直接开始执行动画(这种方式比记录下来动画再在最后全部执行来得简单)。如果不能合并,就需要移动当前方块了,这时候判断遍历的终点是否是空的,来决定移动的距离。

其实计算出最终的结果是很简单的,难的是计算出每一个方块的动画,每一个方块,可能会移动,可能会合并。具体的逻辑还需要大家自己细细琢磨。

// swipe的公共逻辑抽出

this.swipeCommon = function(i, j, arrNode, posJson, condition, nextArrNode, nextPosJson) {

var that = this;

var duration = 100;

// 遇到了可以合并的

if(!arrNode.newNode && arrNode.value == this.array[i][j].value) {

arrNode.value = arrNode.value * 2;

arrNode.newNode = true;

this.array[i][j].value = 0;

this.score = this.score + arrNode.value;

this.scoreText.text = this.score;

if(this.score > this.best) {

this.best = this.score;

this.bestText.text = this.best;

}

// 渐渐透明后被kill掉

var t1 = game.add.tween(arrNode.sprite).to({alpha: 0}, duration, Phaser.Easing.Linear.None, true);

t1.onComplete.add(function() {

this.sprite.kill();

that.placeSquare(this.x, this.y, this.value);

if(!that.canSwipe) {

that.canSwipe = true;

that.generateSquare();

}

}, arrNode);

var t2 = game.add.tween(this.array[i][j].sprite).to({alpha: 0}, duration, Phaser.Easing.Linear.None, true);

t2.onComplete.add(function() {

this.kill();

if(!that.canSwipe) {

that.canSwipe = true;

that.generateSquare();

}

}, this.array[i][j].sprite);

game.add.tween(this.array[i][j].sprite).to(posJson, duration, Phaser.Easing.Linear.None, true);

arrNode.sprite = this.array[i][j].sprite;

this.array[i][j].sprite = undefined;

} else if(arrNode.value == 0) {

arrNode.value = this.array[i][j].value;

this.array[i][j].value = 0;

var t = game.add.tween(this.array[i][j].sprite).to(posJson, duration, Phaser.Easing.Linear.None, true);

t.onComplete.add(function() {

if(!that.canSwipe) {

that.canSwipe = true;

that.generateSquare();

}

});

arrNode.sprite = this.array[i][j].sprite;

this.array[i][j].sprite = undefined;

} else if(condition) {

nextArrNode.value = this.array[i][j].value;

this.array[i][j].value = 0;

var t = game.add.tween(this.array[i][j].sprite).to(nextPosJson, duration, Phaser.Easing.Linear.None, true);

t.onComplete.add(function() {

if(!that.canSwipe) {

that.canSwipe = true;

that.generateSquare();

}

});

nextArrNode.sprite = this.array[i][j].sprite;

this.array[i][j].sprite = undefined;

}

};

其实在做滑动逻辑的时候,最好是先分别做完上下左右的逻辑,然后,再将公共的逻辑抽出,变成一个函数,这样会稍微简单一些。

另一个需要解决的问题,就是如何判断手势,也就是怎么判断上滑,下滑,左滑和右滑。这里我找到了网上的一个插件,使用起来还是很方便的。但是假如不用插件,我们其实也能做,无非就是判断一下按下和抬起的时候,点的相对位置而已。大家可以去看看插件的源码,也是这么做的,但是插件原来对滑动的判断并不敏感,我对参数做了一些改动,想省事的同学可以直接拿去用。关键代码就是:

// add swipe check

this.swipe = new Swipe(this.game, this.swipeCheck);

// swipe检测

this.swipeCheck = {

up: this.swipeUp.bind(this),

down: this.swipeDown.bind(this),

left: this.swipeLeft.bind(this),

right: this.swipeRight.bind(this)

};

其实把滑动检测和滑动逻辑做完之后,游戏基本就可以了。但是我还在方块的生成动画这里跌了一下,我希望方块生成的时候,从中心开始往外缩放。但是一开始设置了anchor竟然无效。一开始还以为无法实现,但是其实只是自己的几个精灵的组织关系没有写好,调整之后,很轻松就实现了。

// 在x,y位置放置一个值为value的方块

this.placeSquare = function(x, y, value) {

var squareStyle = { font: "bold 20px Arial", fill: "#FFFFFF", boundsAlignH: "center", boundsAlignV: "middle" };

var square = game.add.sprite();

square.reset(this.transX(x), this.transY(y));

var squareBackground = game.add.graphics(-45/2, -45/2);

squareBackground.beginFill(this.colors[value]);

squareBackground.drawRoundedRect(0, 0, 45, 45, 5);

squareBackground.endFill();

square.addChild(squareBackground);

var squareText = game.add.text(-45/2, -45/2, value, squareStyle);

squareText.setTextBounds(0, 0, 45, 45);

square.addChild(squareText);

this.array[x][y].value = value;

this.array[x][y].sprite = square;

square.anchor.setTo(0.5, 0.5);

square.scale.setTo(0.0, 0.0);

var tween = game.add.tween(square.scale).to({x:1.0, y:1.0}, 100, Phaser.Easing.Sinusoidal.InOut, true);

tween.onComplete.add(function() {

if(this.checkGameover()) {

this.gameOver();

}

}, this);

};

好了,2048的讲解到这里就结束了,期待下一个小游戏!

转载请注明出处:http://www.phaser-china.com/tutorial-detail-6.html

2048php,Phaser实现2048相关推荐

  1. 使用Phaser开发你的第一个H5游戏(一)

    本文来自网易云社区 作者:王鸽 不知你是否还记得当年风靡一时的2048这个游戏,一个简单而又不简单的游戏,总会让你在空闲时间玩上一会儿. 在这篇文章里,我们将使用开源的H5框架--Phaser来重现这 ...

  2. 是男人就下100层【第五层】——2048游戏从源代码到公布市场

    上一篇<是男人就下100层[第五层]--换肤版2048游戏>中阳光小强对2048游戏用自己的方式进行了实现,并分享了核心源码,这一篇阳光小强打算将该项目的全部源码公开并结合这个实例在这篇文 ...

  3. f-fdisk做磁盘分区,起始扇区从2048块开始

    文章目录 First Sector 起始扇区 fdisk工具加分区 fdisk删除分区 First Sector 起始扇区 默认从第2048块扇区开始是因为,由于EFI的兴起,要给EFI 代码留磁盘最 ...

  4. Flex报错Error #2048: 安全沙箱冲突

    Flex+JPA架构,JPA程序迁移,从A服务器到B.其他一切没变,唯一变的就是IP. 前端Flex也就是swf报错Error #2048: 安全沙箱冲突:http://xxx.swf 不能从 xxx ...

  5. phaser.min.js_如何使用Phaser 3,Express和Socket.IO构建多人纸牌游戏

    phaser.min.js I'm a tabletop game developer, and am continually looking for ways to digitize game ex ...

  6. 使用javascript开发2048

    嗯,团队队友开发了一个简单的2048...哈哈,没办法,这游戏那么疯狂,必须搞搞啦,大家能够直接粘贴代码到一个html文件,直接执行就可以 依赖文件:jquery,假设乜有,大家能够自己下载一份 &l ...

  7. 【ACM】杭电OJ 2048 2049

    两题均是错排公式与阶乘的运用 2048算的是一个比例,2049计算的是一个事情发生的总数 一个用double 来存放数据,一个用long  long来存放数据 2048 #include <io ...

  8. 你玩《2048》能拿多少分?AI的最高分纪录:401912

    来源|量子位 如果让AI来玩<2048>这样的游戏,那会是怎样一种画面? 现在,有人用强化学习方法实践了起来. 于是,插上DQN的翅膀,AI从零起步,自己琢磨出了<2048>的 ...

  9. 基于 react, redux 最佳实践构建的 2048

    前段时间 React license 的问题闹的沸沸扬扬,搞得 React 社区人心惶惶,好在最终 React 团队听取了社区意见把 license 换成了 MIT.不管 React license ...

  10. python游戏代码五子棋_用20行Python代码实现2048小游戏,你会吗?

    前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...

最新文章

  1. 诺康得NKD完成500万天使轮融资,专注于糖化学细胞治疗...
  2. Windows Server 2003 备份和恢复的最佳做法
  3. Java中的低级错误
  4. 索引节点(inode)爆满问题处理
  5. Xml,XPath,XSLTxue 学习方法
  6. koa-static使用时报Unexpected token function
  7. Linux命令工具基础02 文件及目录管理
  8. 苹果ppt_你的PPT太low了,学学苹果吧
  9. Vue优化策略_项目发布_01
  10. RHEL 5服务篇—LAMP平台的部署及应用
  11. Mysql type字段值1改为2,2改为1
  12. eagle php,使用EaglePHP打造自己的网站(非PHP程序员的菜鸟使用手册)
  13. 【老生谈算法】matlab实现自适应滤波器源码——自适应滤波器
  14. 电脑ping,怎么ping网速,详细教您ping网络的方法
  15. uniapp 安卓快捷方式插件(桌面长按app图标) Ba-Shortcut
  16. 使用chrome设置代理,果然还是linux 方便呢。想安装一个chrome的插件,通过命令设置代理。
  17. 当代大学生的生活痛点
  18. Java分页查询详解
  19. [洛谷]P1010 [NOIP1998 普及组] 幂次方
  20. 【空格】前后是非多,它能导致大故障,请看

热门文章

  1. oracle中的各种命令(关于表的增删改查)
  2. 这世上倒底有没有神仙——说“Excel不是数据库,是不是犯了白马非马论的错误??...
  3. BERT tokenization 处理英文句子 Wordpiece之后的处理技巧
  4. paperwhite3翻页_Kindle vs. Paperwhite vs. Voyage vs. Oasis:您应该购买哪种Kindle?
  5. 在mysql中,涉及到金钱的数据类型一般是什么?
  6. EUI学习之自定义皮肤
  7. 易语言5.8袖珍绿色免安装
  8. 工业蒸汽_到底什么是蒸汽机,我想要一个吗?
  9. 【SIGIR2017满分论文】IRGAN:大一统信息检索模型的博弈竞争
  10. 【巴马火麻茶】调节三高、治疗失眠、排毒减肥,轻松get长寿的秘密!