一、前言

2048是之前火过一段时间的休闲数字消除类游戏,它的玩法很简单,上手很容易,可是想到要得到高分却很难,看似简单的游戏却有着很多得分的技巧,想当初这个游戏也曾是陪伴我大学课堂的游戏之一。虽然在得分上有着很多的技巧,但对于开发来说,这其实是一件相当容易的事情,仔细分析之后就可能大概理清楚这种消除游戏的逻辑。

二、游戏分析

这款游戏仔细想想就差不多清楚它的大致的思路,游戏中只有方块这一个我们操作的对象,这个对象包含了所在行,所在列,以及方块显示的数字三个属性,这三个属性足以表达游戏中的所有效果。除了方块,其他的就是游戏中必不可少的背景图层,开始及结束场景等。由于游戏中需要将4x4的方块们整齐排列,因此还需要一个四行四列的表格,来呈现我们的游戏效果。

三、滑动逻辑

游戏中最主要的操作就是通过手指触摸屏幕进行滑屏操作,带动场景中的方块整体移动,并且遇到相同数字的方块进行合并。滑动的逻辑就是遍历场景中所有的方块,每一个方块在滑动方向进行移动,如果前方没有方块,方块就一直滑动,如果前方有方块,判断自己的数字与这个方块的数字是否相同,相同进行合并操作,不相同则停在当前位置。

四、游戏实现

在对游戏逻辑进行了分析之后,就可以用代码进行实现了,编码,其实就是一个将游戏逻辑转换为机器语言的过程而已。

1.方块类

首先,我们需要一个类来存储方块的长度和宽度,代码如下:

  1. // 保存方块长度方块
  2. var tile = {
  3. width: 0,
  4. height: 0
  5. };

方块类是对场景中可操的方块的封装,包括所在行,所在列,显示数字三个属性,代码如下:

  1. var Tiled = cc.Node.extend({
  2. num: 0,
  3. col: 0,
  4. row: 0,
  5. ctor: function (num) {
  6. this._super();
  7. return true;
  8. }
  9. }

当然仅仅有以上三个属性是不够的,我们还需要在方块的构造函数中绘制方块的背景、绘制方块显示的数字、以及随机设定方块的行列坐标。

  1. var Tiled = cc.Node.extend({
  2. num: 0,
  3. col: 0,
  4. row: 0,
  5. ctor: function (num) {
  6. this._super();
  7. this.num = num;
  8. var count = 0;
  9. while (true) {
  10. count++;
  11. this.row = Math.floor(Math.random() * 4);
  12. this.col = Math.floor(Math.random() * 4);
  13. if (tiles[this.row][this.col] == null) {
  14. tiles[this.row][this.col] = this;
  15. break;
  16. }
  17. if (count >= 16) {// 格子满了
  18. return true;
  19. }
  20. }
  21. // 绘制背景
  22. var bg = new cc.DrawNode();
  23. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(255, 209, 145, 255), 1, cc.color(255, 209, 145, 255));
  24. this.addChild(bg);
  25. bg.setTag(2);
  26. // 绘制数字
  27. var labelNum = new cc.LabelTTF();
  28. labelNum.setString("" + this.num);
  29. labelNum.setFontSize(60);
  30. // 字体描边效果
  31. // labelNum.enableStroke(cc.color.BLACK, 0);
  32. this.addChild(labelNum);
  33. labelNum.setTag(1);
  34. // 设定字体和坐标
  35. labelNum.setPosition(tile.width / 2, tile.height / 2);
  36. // 移动块
  37. this.newTile(this.row, this.col);
  38. return true;
  39. }
  40. }

除此之外,每个方块应该还要包含一个newTile方法、moveTo方法和updateNum方法,分别封装随机创建方块、移动方块和更新方块数字三个功能。

在updateNum方法中,我们主要做两件事,更新方块显示数字和更新方块背景颜色(在方块的背景色上,我还专门上网搜了几种颜色搭配,恩,感觉很有艺术美,哈哈),代码如下:

  1. updateNum: function () {
  2. this.getChildByTag(1).setString("" + this.num);
  3. var bg = this.getChildByTag(2);
  4. switch (this.num) {
  5. case 2:
  6. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(235, 245, 223, 255), 1, cc.color(235, 245, 223, 255));
  7. break;
  8. case 4:
  9. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(186, 212, 170, 255), 1, cc.color(186, 212, 170, 255));
  10. break;
  11. case 8:
  12. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(212, 212, 170, 255), 1, cc.color(212, 212, 170, 255));
  13. break;
  14. case 16:
  15. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(193, 160, 117, 255), 1, cc.color(193, 160, 117, 255));
  16. break;
  17. case 32:
  18. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(124, 99, 84, 255), 1, cc.color(124, 99, 84, 255));
  19. break;
  20. case 64:
  21. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(218, 227, 224, 255), 1, cc.color(218, 227, 224, 255));
  22. break;
  23. case 128:
  24. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(64, 125, 148, 255), 1, cc.color(64, 125, 148, 255));
  25. break;
  26. case 256:
  27. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(123, 118, 135, 255), 1, cc.color(123, 118, 135, 255));
  28. break;
  29. case 512:
  30. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(172, 173, 172, 255), 1, cc.color(172, 173, 172, 255));
  31. break;
  32. case 1024:
  33. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(204, 196, 194, 255), 1, cc.color(204, 196, 194, 255));
  34. break;
  35. case 2048:
  36. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(199, 225, 240, 255), 1, cc.color(199, 225, 240, 255));
  37. break;
  38. case 4096:
  39. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(150, 196, 230, 255), 1, cc.color(150, 196, 230, 255));
  40. break;
  41. case 8192:
  42. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(25, 77, 91, 255), 1, cc.color(25, 77, 91, 255));
  43. break;
  44. case 16384:
  45. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(229, 96, 205, 255), 1, cc.color(229, 96, 205, 255));
  46. break;
  47. case 32768:
  48. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(250, 174, 78, 255), 1, cc.color(250, 174, 78, 255));
  49. break;
  50. case 65536:
  51. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(255, 241, 222, 255), 1, cc.color(255, 241, 222, 255));
  52. break;
  53. default:
  54. bg.drawRect(cc.p(5, 5), cc.p(tile.width - 5, tile.height - 5), cc.color(255, 209, 145, 255), 1, cc.color(255, 209, 145, 255));
  55. break;
  56. }
  57. }

方块的移动方法和创建方法,我在这里先写成一样,因为还没有对方块的创建和移动做区别,如果要做优化,可以在移动时加入移动的动画,在创建加入创建的动画,代码如下:

  1. moveTo: function (row, col) {
  2. this.row = row;
  3. this.col = col;
  4. this.setPositionX((cc.winSize.width - tile.width * 4) / 2 + tile.width * this.col);
  5. this.setPositionY((cc.winSize.height - tile.height * 4) / 2 + tile.height * this.row);
  6. },
  7. newTile: function (row, col) {
  8. this.row = row;
  9. this.col = col;
  10. this.setPositionX((cc.winSize.width - tile.width * 4) / 2 + tile.width * this.col);
  11. this.setPositionY((cc.winSize.height - tile.height * 4) / 2 + tile.height * this.row);
  12. }

2.游戏场景类

所有的游戏操作及操作反馈都在游戏场景类中进行,游戏场景类将封装好的方块类放到游戏逻辑中,通过玩家操作给予一定的操作反馈。游戏场景类中主要接受玩家的滑动操作,并在接收到滑动操作后将所有的方块类进行移动或合并。

游戏场景类中需要isMove,startX,startY,以及tiles四个属性:第一个是控制玩家触摸操作的标识变量,避免重复调用移动方法;中间两个为记录玩家手指滑动的距离,当距离查过一定的长度之后,才判断玩家进行了滑动操作;最后一个变量是一个数组,用于存储在4x4的表格中的方块的信息。

有了以上四个属性之后,就可以在构造函数中进行初始化了,代码如下:

  1. var tiles = null;// 存储方块信息
  2. var GameLayer = cc.Layer.extend({
  3. isMove: false,
  4. startX: 0,
  5. startY: 0,
  6. ctor: function () {
  7. this._super();
  8. this.isMove = false;
  9. this.startX = 0;
  10. this.startY = 0;
  11. //设置块的宽高
  12. if (cc.winSize.width < cc.winSize.height) {
  13. // 竖屏
  14. tile.width = cc.winSize.width / 5;
  15. tile.height = cc.winSize.width / 5;
  16. } else {
  17. // 横屏
  18. tile.width = cc.winSize.height / 5;
  19. tile.height = cc.winSize.height / 5;
  20. }
  21. // 初始化数组
  22. tiles = [
  23. [null, null, null, null],
  24. [null, null, null, null],
  25. [null, null, null, null],
  26. [null, null, null, null]
  27. ];
  28. return true;
  29. }
  30. }

在初始化完之后,我们就可以在场景的onEnter方法中绘制场景了,绘制的内容包括游戏背景以及随机初始化两个方块,代码如下:

  1. onEnter: function () {
  2. this._super();
  3. // 绘制背景
  4. this.drawBg();
  5. // 绘制块
  6. var tile1 = new Tiled(2);
  7. var tile2 = new Tiled(2);
  8. this.addChild(tile1);
  9. this.addChild(tile2);
  10. //处理事件
  11. cc.eventManager.addListener({
  12. event: cc.EventListener.TOUCH_ONE_BY_ONE,
  13. swallowTouches: true,
  14. onTouchBegan: this.touchbegan,
  15. onTouchMoved: this.touchmoved
  16. }, this);
  17. return true;
  18. }

其中drawBg方法中,绘制了五条垂直直线以及五条水平直线,来作为方块所在的4x4的表格,代码如下:

  1. drawBg: function () {
  2. //绘制背景
  3. var bgRect = new cc.DrawNode();
  4. bgRect.drawRect(cc.p(0, 0), cc.p(cc.winSize.width, cc.winSize.height), cc.color(173, 140, 61, 255), 1, cc.color(173, 140, 61, 255));
  5. this.addChild(bgRect);
  6. var bg = new cc.DrawNode();
  7. for (var n = 0; n < 5; n++) {
  8. bg.drawSegment(cc.p((cc.winSize.width - tile.width * 4) / 2, (cc.winSize.height - tile.height * 4) / 2 + n * tile.width), cc.p(cc.winSize.width / 2 + tile.width * 2, (cc.winSize.height - tile.height * 4) / 2 + n * tile.width), 5,
  9. cc.color(55, 62, 64, 255));
  10. bg.drawSegment(cc.p((cc.winSize.width - tile.width * 4) / 2 + n * tile.width, (cc.winSize.height - tile.height * 4) / 2), cc.p((cc.winSize.width - tile.width * 4) / 2 + n * tile.width, (cc.winSize.height - tile.height * 4) / 2 + tile.width * 4), 5,
  11. cc.color(55, 62, 64, 255));
  12. }
  13. this.addChild(bg);
  14. }

可以看到,在onEnter中,注册了触摸事件,这个触摸事件就用于接受玩家的操作,在TouchBegan事件中记录触摸开始时的点,在TouchMoved中记录当前移动到的点,当触摸距离超过一定长度时,判定玩家进行了滑动操作,并通过触摸点来判断玩家滑动的举例,代码如下:

  1. touchbegan: function (touch, event) {
  2. this.isMove = true;
  3. this.startX = touch.getLocationX();
  4. this.startY = touch.getLocationY();
  5. return true;
  6. },
  7. touchmoved: function (touch, event) {
  8. if (!this.isMove) {
  9. return;
  10. }
  11. var endX = touch.getLocation().x;
  12. var endY = touch.getLocation().y;
  13. if (Math.abs(endX - this.startX) > 20 ||
  14. Math.abs(endY - this.startY) > 20) {
  15. var dir = "";
  16. if (Math.abs(endX - this.startX) > Math.abs(endY - this.startY)) {//左右
  17. if (endX > this.startX) {
  18. dir = "right";
  19. } else {
  20. dir = "left";
  21. }
  22. } else {
  23. //上下
  24. if (endY > this.startY) {
  25. dir = "up";
  26. } else {
  27. dir = "down";
  28. }
  29. }
  30. this.isMove = false;
  31. event.getCurrentTarget().moveAllTiled(dir);
  32. }
  33. return true;
  34. },
  35. moveAllTiled: function (dir) {
  36. var isMoved = false;
  37. switch (dir) {
  38. case "up":
  39. isMoved = this.moveUp();
  40. break;
  41. case "down":
  42. isMoved = this.moveDown();
  43. break;
  44. case "left":
  45. isMoved = this.moveLeft();
  46. break;
  47. case "right":
  48. isMoved = this.moveRight();
  49. break;
  50. }
  51. if (isMoved) {
  52. //每次移动产生一个新块
  53. this.newTiled();
  54. }
  55. }

触动滑动操作后,开始执行滑动逻辑,每次滑动之后,会随机创建一个新的方块,在newTiled方法中,除了创建新方块之外,还需要判断游戏是否结束,代码如下:

  1. newTiled: function () {
  2. var tile = new Tiled(2);
  3. this.addChild(tile);
  4. // 判断游戏是否结束
  5. var isOver = true;
  6. // 判断是否有空余位置
  7. for (var row = 0; row < 4; row++) {
  8. for (var col = 0; col < 4; col++) {
  9. if (tiles[row][col] == null) {
  10. isOver = false;
  11. }
  12. }
  13. }
  14. if (isOver) {
  15. // 判断四周是否有数字相同方块
  16. for (var row = 0; row < 4; row++) {
  17. for (var col = 0; col < 4; col++) {
  18. if (row < 3 && tiles[row + 1][col].num == tiles[row][col].num) {
  19. isOver = false;
  20. }
  21. if (row > 0 && tiles[row - 1][col].num == tiles[row][col].num) {
  22. isOver = false;
  23. }
  24. if (col < 3 && tiles[row][col + 1].num == tiles[row][col].num) {
  25. isOver = false;
  26. }
  27. if (col > 0 && tiles[row][col - 1].num == tiles[row][col].num) {
  28. isOver = false;
  29. }
  30. }
  31. }
  32. }
  33. if (isOver) {
  34. cc.director.runScene(new cc.TransitionFade(1, new OverScene()));
  35. }
  36. }

方块的滑动,就是2048这款游戏最主要的逻辑了,我们在滑动的时候,需要遍历tiles数组所有不是null的元素,并将这个元素按照滑动方向进行移动,一直遍历到数组的最大长度,也就是将滑动到表格的边缘,如果中途遇到了方块,并且数字与自己相同,就进行合并,合并是将自己删除,将遇到的方块数字乘以2,如果中途遇到的方块的数字与自己不同,此方块的滑动就停止,使其停在当前的位置,滑动分为上下左右四个逻辑,代码分别如下:

  1. moveUp: function () {
  2. var isMoved = false;
  3. for (var col = 0; col < 4; col++) {
  4. for (var row = 3; row >= 0; row--) {
  5. if (tiles[row][col] != null) {// 有方块
  6. for (var row1 = row; row1 < 3; row1++) {
  7. if (tiles[row1 + 1][col] == null)//如果没有向上移动
  8. {
  9. tiles[row1 + 1][col] = tiles[row1][col];
  10. tiles[row1][col] = null;
  11. tiles[row1 + 1][col].moveTo(row1 + 1, col);
  12. isMoved = true;
  13. } else if (tiles[row1 + 1][col].num == tiles[row1][col].num) {// 合并
  14. tiles[row1 + 1][col].num = parseInt(tiles[row1][col].num) * 2;
  15. tiles[row1 + 1][col].updateNum();
  16. tiles[row1][col].removeFromParent();
  17. tiles[row1][col] = null;
  18. isMoved = true;
  19. break;
  20. }
  21. }
  22. }
  23. }
  24. }
  25. return isMoved;
  26. },
  27. moveDown: function () {
  28. var isMoved = false;
  29. for (var col = 0; col < 4; col++) {
  30. for (var row = 0; row < 4; row++) {
  31. if (tiles[row][col] != null) {// 有方块
  32. for (var row1 = row; row1 > 0; row1--) {
  33. if (tiles[row1 - 1][col] == null)//如果没有向下移动
  34. {
  35. tiles[row1 - 1][col] = tiles[row1][col];
  36. tiles[row1][col] = null;
  37. tiles[row1 - 1][col].moveTo(row1 - 1, col);
  38. isMoved = true;
  39. } else if (tiles[row1 - 1][col].num == tiles[row1][col].num) {// 合并
  40. tiles[row1 - 1][col].num = parseInt(tiles[row1][col].num) * 2;
  41. tiles[row1 - 1][col].updateNum();
  42. tiles[row1][col].removeFromParent();
  43. tiles[row1][col] = null;
  44. isMoved = true;
  45. break;
  46. }
  47. }
  48. }
  49. }
  50. }
  51. return isMoved;
  52. },
  53. moveLeft: function () {
  54. var isMoved = false;
  55. for (var row = 0; row < 4; row++) {
  56. for (var col = 0; col < 4; col++) {
  57. if (tiles[row][col] != null) {
  58. for (var col1 = col; col1 > 0; col1--) {
  59. if (tiles[row][col1 - 1] == null) {
  60. tiles[row][col1 - 1] = tiles[row][col1];
  61. tiles[row][col1] = null;
  62. tiles[row][col1 - 1].moveTo(row, col1 - 1);
  63. isMoved = true;
  64. } else if (tiles[row][col1 - 1].num == tiles[row][col1].num) {// 合并
  65. tiles[row][col1 - 1].num = parseInt(tiles[row][col1].num) * 2;
  66. tiles[row][col1 - 1].updateNum();
  67. tiles[row][col1].removeFromParent();
  68. tiles[row][col1] = null;
  69. isMoved = true;
  70. break;
  71. }
  72. }
  73. }
  74. }
  75. }
  76. return isMoved;
  77. },
  78. moveRight: function () {
  79. var isMoved = false;
  80. for (var row = 0; row < 4; row++) {
  81. for (var col = 3; col >= 0; col--) {
  82. if (tiles[row][col] != null) {
  83. for (var col1 = col; col1 < 3; col1++) {
  84. if (tiles[row][col1 + 1] == null) {
  85. tiles[row][col1 + 1] = tiles[row][col1];
  86. tiles[row][col1] = null;
  87. tiles[row][col1 + 1].moveTo(row, col1 + 1);
  88. isMoved = true;
  89. } else if (tiles[row][col1 + 1].num == tiles[row][col1].num) {// 合并
  90. tiles[row][col1 + 1].num = parseInt(tiles[row][col1].num) * 2;
  91. tiles[row][col1 + 1].updateNum();
  92. tiles[row][col1].removeFromParent();
  93. tiles[row][col1] = null;
  94. isMoved = true;
  95. break;
  96. }
  97. }
  98. }
  99. }
  100. }
  101. return isMoved;
  102. }

至此,我们就基本实现了2048游戏的主要逻辑。

3.开始/结束场景类

为了游戏框架的完整,我们还是创建一个开始场景类和结束场景类,代码分别如下:

开始场景类

  1. var HelloWorldLayer = cc.Layer.extend({
  2. sprite:null,
  3. ctor:function () {
  4. //////////////////////////////
  5. // 1. super init first
  6. this._super();
  7. /////////////////////////////
  8. // 2. add a menu item with "X" image, which is clicked to quit the program
  9. // you may modify it.
  10. // ask the window size
  11. var size = cc.winSize;
  12. /////////////////////////////
  13. // 3. add your codes below...
  14. // add a label shows "Hello World"
  15. // create and initialize a label
  16. var helloLabel = new cc.LabelTTF("2048", "Arial", 38);
  17. // position the label on the center of the screen
  18. helloLabel.x = size.width / 2;
  19. helloLabel.y = size.height / 2 + 200;
  20. // add the label as a child to this layer
  21. this.addChild(helloLabel, 5);
  22. // add "HelloWorld" splash screen"
  23. // this.sprite = new cc.Sprite(res.HelloWorld_png);
  24. // this.sprite.attr({
  25. // x: size.width / 2,
  26. // y: size.height / 2
  27. // });
  28. // this.addChild(this.sprite, 0);
  29. var start = new cc.MenuItemFont("开始游戏",function(){
  30. cc.director.runScene(new cc.TransitionFade(1,new GameScene()));
  31. });
  32. var menu = new cc.Menu(start);
  33. this.addChild(menu);
  34. return true;
  35. }
  36. });
  37. var HelloWorldScene = cc.Scene.extend({
  38. onEnter:function () {
  39. this._super();
  40. var layer = new HelloWorldLayer();
  41. this.addChild(layer);
  42. }
  43. });

结束场景类

  1. /**
  2. * Created by Henry on 16/6/19.
  3. */
  4. var OverLayer = cc.Layer.extend({
  5. ctor: function () {
  6. this._super();
  7. var overText = new cc.LabelTTF("Game Over", "", 50);
  8. overText.setPosition(cc.winSize.width / 2, cc.winSize.height / 2);
  9. var back = new cc.MenuItemFont("再来一次", function () {
  10. cc.director.runScene(new cc.TransitionFade(1, new HelloWorldScene()));
  11. }, this);
  12. var menu = new cc.Menu(back);
  13. this.addChild(menu);
  14. return true;
  15. }
  16. });
  17. var OverScene = cc.Scene.extend({
  18. ctor: function () {
  19. this._super();
  20. var layer = new OverLayer();
  21. this.addChild(layer);
  22. return true;
  23. }
  24. });

五、运行效果

最后的运行效果如下



通过CVP平台的项目托管可看到实际运行效果,地址如下:

http://www.cocoscvp.com/usercode/ea72822aeed0546b537b4226954a11be87a7f152/

六、源代码

所有源代码均上传到github,欢迎交流学习,地址:

https://github.com/hjcenry/2048

Cocos2d-JS实现的2048的更多相关文章

  1. cocos2d js jsb XMLHttpRequest 中文乱码

    1.首先讲下怎样使用XMLHttpRequest 下面所说的是在cocos2d-x 2.2.2 或者 2.3 版本号中. 首先要明确cocos2d js事实上分两个版本号,一个是html5的版本号,另 ...

  2. cocos2d js的一些tip

    cocos2d-js-v3.2-rc0 cc.director.end();//退出app cc.Application.getInstance().openURL("http://www. ...

  3. cocos2d js ClippingNode 制作标题闪亮特效

    1.效果图: 之前在<Android 高仿 IOS7 IPhone 解锁 Slide To Unlock>中制作了文字上闪亮移动的效果,这次我们来看下怎样在cocos2d js 中做出类似 ...

  4. cocos2d.js

    1.节点是Cocos2d最基础的东西 2.坐标与普通数学坐标一致 3.children属性表示节点的孩子,父节点位置变化,它包含的子节点也会跟着变化,以整体的形势移动 4.层(layer), 新建层: ...

  5. cocos2d JS 源生js实现each方法

    javascript笔记——源生js实现each方法   出处:http://www.lovejavascript.com/#!zone/blog/content.html?id=48 jquery里 ...

  6. cocos2d JS 错误异常抛出捕获和崩溃拦截

    Error对象 一旦代码解析或运行时发生错误,JavaScript引擎就会自动产生并抛出一个Error对象的实例,然后整个程序就中断在发生错误的地方. Error对象的实例有三个最基本的属性: nam ...

  7. cocos2d JS 在 JavaScript 中,怎样把一个对象转化成 JSON 字符串?

    为什么今天要做这样子的操作,原因很简单,因为cocos JS 的本地缓存储存不了对象,所以当我通过本地缓存的 key和value来取值的时候就取不出来来,json的消息数据是一个对象来的,然而在做牌局 ...

  8. cocos2d JS 本地缓存存储登陆记住账号密码->相当于C++中的UserDefault

    在cocos-js 3.0以上的版本中,当我们用到本地存储的时候,发现以前用到的UserDefault在JS中并没有导出,而是换成了LocalStorage. 在LocalStorage.h文件中我们 ...

  9. 纯JS写的2048游戏,分享之

    这几天玩儿着2048这个游戏,突然心血来潮想练习下敲代码的思路.于是乎就模仿做了一个,到眼下位置还没有实现动态移动,不是非常好看,只是玩儿着自己模仿的小游戏还是蛮爽的,哈哈 假设没有玩儿过这个游戏,最 ...

  10. html5 cocos2d js Access-Control-Allow-Origin

    1.No 'Access-Control-Allow-Origin' header is present on the requested 近期在接html5的渠道,遇到了跨域的问题,使用 js 的 ...

随机推荐

  1. 【java】java设计模式(5):原型模式(Prototype)

    原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.本小结会通过对象的复制,进行讲解.在Java中 ...

  2. 【jersey】 spring 整合jersey 实现RESTful webservice

         Jersey是一个RESTFUL请求服务JAVA框架,与常规的JAVA编程使用的struts框架类似,它主要用于处理业务逻辑层.与Struts类似,它同样可以和hibernate,sprin ...

  3. mongodb启动时报错ERROR: child process failed, exited with error number 1

    不多说,直接上干货! 前期博客 Ubuntu14.04下Mongodb安装部署步骤(图文详解) Ubuntu16.04下Mongodb安装部署步骤(图文详解) root@zhouls-virtual- ...

  4. mybatis由浅入深day02_2一对一查询_2.3方法二:resultMap_resultType和resultMap实现一对一查询小结

    2.3 方法二:resultMap 使用resultMap,定义专门的resultMap用于映射一对一查询结果. 2.3.1 sql语句 同resultType实现的sql SELECT orders ...

  5. day24<多线程>

    多线程(多线程的引入) 多线程(多线程并行和并发的区别) 多线程(Java程序运行原理和JVM的启动是多线程的吗) 多线程(多线程程序实现的方式1) 多线程(多线程程序实现的方式2) 多线程(实现Ru ...

  6. Windows上Tomcat启动,服务中没有Tomcat

    首先需要查看Tomcat的bin目录下是否有service.bat,如果没有需要去下载一版bin目录下有service.bat的Tomcat,只有Windows版本的Tomcat的bin目录下才有se ...

  7. /var/log/cron

    /var/log/cron 用来记录任务计划的运行日志,如下,分别表示: 任务运行的日期与时间 .在哪台主机上运行 .运行任务的程序[进程号] .任务运行的具体信息 [root@localhost ~ ...

  8. 高性能LAMP程序设计

    高性能LAMP程序设计 原文地址: http://www.infoq.com/cn/presentations/fcq-high-performance-lamp-programming 演讲稿: h ...

  9. php学习十四:抽象,接口和多态

    多态为面向对象编程的精华所在,js等面向过程的语言虽然可以模拟面向对象,但是毕竟模仿的永远比不上真的,所以了解而且会使用面向对象的多态是必不可少的 在了解多态之前,我们必须要了解接口,但是接口又是在抽 ...

  10. 关于线上js报错问题的思考

    1.有没有可能对线上报错进行实时监控,只要线上报错出现就会以邮件的形式发出来. 2.有没有可能将每个模块和开发者联系起来,只要报错就直接报给开发者