ng2048源码阅读

Tutorial: http://www.ng-newsletter.com/posts/building-2048-in-angularjs.html

Github: https://github.com/fullstackio/ng2048.git

本地不部署项目一直卡在node-sass不成功的问题上,需要的css文件没办法生成,我的目的是弄清设计原理,学习ng的用法,所以直接用sass编译sass文件为css文件,丢到项目文件夹下跑起来。

sass编译css文件

  1. npm install node-sass -g
  2. sass D:\GitHub\ng2048\app\styles\main.scss D:\GitHub\ng2048\app\styles\main.css

启动项目

这个项目是grunt构建的, 使用--force忽略sass编译的错误继续执行

  1. grunt serve --force

这个列子有些小复杂,看看能学到啥

1. 数据传递,指令的使用,ng-if的使用

grid的使用,通过ng-model传递到指令内部的独立scope

  1. <!-- 显示格子 -->
  2. <div grid ng-model='ctrl.game' class="row"></div>

Grid中包含tile,tile指令也是通过ng-model传递到指令内部的独立scope,注意这里的ng-repeat迭代的对象的传递

  1. <div id="game-{{ ngModel.gameSize }}">
  2. <div class="grid-container">
  3. <div class="grid-cell" ng-repeat="cell in ngModel.grid track by $index"></div>
  4. </div>
  5. <div class="tile-container">
  6. <div tile
  7. ng-model='tile'
  8. ng-repeat='tile in ngModel.tiles track by $id(tile.id || $index)'></div>
  9. </div>
  10. </div>

tile的模板

  1. <div ng-if='ngModel' class="tile position-{{ ngModel.x }}-{{ ngModel.y }} tile-{{ ngModel.value }}"
  2. ng-class="{ 'tile-merged': ngModel.merged}">
  3. <div class="tile-inner">
  4. {{ ngModel.value }}
  5. </div>
  6. </div>

2. 通用的游戏键盘控制服务

服务init的时候这个keydown什么也不做,通过on订阅事件,将自己的处理程序加到服务的keyEventHandlers列表中完成事件的定制。这个服务就通用的了,你只需要写好自己的控制程序,然后通过on订阅就可以了。这也算是一种设计技巧了。

  1. 'use strict';
  2. angular.module('Keyboard', [])
  3. .service('KeyboardService', function($document) {
  4. var UP = 'up',
  5. RIGHT = 'right',
  6. DOWN = 'down',
  7. LEFT = 'left';
  8. var keyboardMap = {
  9. 37: LEFT,
  10. 38: UP,
  11. 39: RIGHT,
  12. 40: DOWN
  13. };
  14. this.init = function() {
  15. var self = this;
  16. this.keyEventHandlers = [];
  17. $document.bind('keydown', function(evt) {
  18. var key = keyboardMap[evt.which];
  19. if (key) {
  20. // An interesting key was pressed
  21. evt.preventDefault();
  22. self._handleKeyEvent(key, evt);
  23. }
  24. });
  25. };
  26. this.on = function(cb) {
  27. this.keyEventHandlers.push(cb);
  28. };
  29. this._handleKeyEvent = function(key, evt) {
  30. var callbacks = this.keyEventHandlers;
  31. if (!callbacks) {
  32. return;
  33. }
  34. evt.preventDefault();
  35. if (callbacks) {
  36. for (var x = 0; x < callbacks.length; x++) {
  37. var cb = callbacks[x];
  38. cb(key, evt);
  39. }
  40. }
  41. };
  42. });
  1. //初始化
  2. KeyboardService.init();
  3. //订阅事件
  4. KeyboardService.on(function(key) {
  5. self.game.move(key);
  6. });

3. 设计思路和实现思路

代码看完了,游戏的思路和我设想的差不多,但是在实现上跟我想的有些不一样,大致也就是两层循环挨个的处理格子,但是实现上感觉还是有些技巧的。

3.1 根据方向确定坐标的偏移量
  1. var vectors = {
  2. 'left': { x: -1, y: 0 },
  3. 'right': { x: 1, y: 0 },
  4. 'up': { x: 0, y: -1 },
  5. 'down': { x: 0, y: 1 }
  6. };
3.2 根据方向确定两层循环的索引序列,[0,1,2,3]还是[3,2,1,0]
  1. this.traversalDirections = function(key) {
  2. var vector = vectors[key];
  3. var positions = {x: [], y: []};
  4. for (var x = 0; x < this.size; x++) {
  5. positions.x.push(x);
  6. positions.y.push(x);
  7. }
  8. if (vector.x > 0) {
  9. positions.x = positions.x.reverse();
  10. }
  11. if (vector.y > 0) {
  12. positions.y = positions.y.reverse();
  13. }
  14. return positions;
  15. };
3.3 一次性拿到可以直接移动到的位置和紧跟的进行碰撞的位置
  1. this.calculateNextPosition = function(cell, key) {
  2. var vector = vectors[key];
  3. var previous;
  4. do {
  5. previous = cell;
  6. cell = {
  7. x: previous.x + vector.x,
  8. y: previous.y + vector.y
  9. };
  10. } while (this.withinGrid(cell) && this.cellAvailable(cell));
  11. //没有越界,并且cell是空的
  12. return {
  13. newPosition: previous,
  14. next: this.getCellAt(cell)
  15. };
  16. };

ng2048源码阅读的更多相关文章

  1. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  2. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  3. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  4. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  5. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  6. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  7. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  8. 【原】AFNetworking源码阅读(二)

    [原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...

  9. 【原】AFNetworking源码阅读(一)

    [原]AFNetworking源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 AFNetworking版本:3.0.4 由于我平常并没有经常使用AFNetw ...

随机推荐

  1. 如何创建独立的UE4服务端

    原文作者:@玄冬Wong 转载请注明原文出处:http://aigo.iteye.com/blog/2268777 这是论坛上对UE服务端功能的回答,意思是UE4提供了主流MMO网游服务端所具备的特性 ...

  2. 如何让eclipse进行智能提示?

    1.打开eclipse工具,点击window菜单,选择preferences选项 2.然后,选择Java->Editor->content assist 3.然后在Auto activat ...

  3. PHP_SELF、 SCRIPT_NAME、 REQUEST_URI区别

    $_SERVER[PHP_SELF], $_SERVER[SCRIPT_NAME], $_SERVER['REQUEST_URI'] 在用法上是非常相似的,他们返回的都是与当前正在使用的页面地址有关的 ...

  4. cookie的基本用法案例

    注:cookie必须在服务器环境下有效. 步骤讲解: 1,引入cookie文件: 2,设置过期时间: var date = new Date(); date.setTime(date.getTime( ...

  5. Odoo 报表中添加空格

    如果  不起作用,请用 代替.

  6. 线程处理模型 由于 SynchronizationContext 引起的死锁问题解决

    由于GUI 应用程序 不能使用线程池的线程更新UI,只能使用 GUI 线程更新,所以在 await 前后需要保证是同一个 GUI 线程 ASP.NET 程序 的线程处理客户端请求的时候,需要假定客户端 ...

  7. 关于PHP中<?php ?>的结束标签是否添加

    在纯PHP代码中“?>”结束标签最好不要添加 原因:容易导致输出多余的空白或者换行,以及由此产生的一些报错. 比如a.php文件中,在?>标签后面多出空格或者换行,而当b.php文件引入a ...

  8. Visual Studio 2015 如何将全英界面转成中文

    1 启动VS2015程序,在菜单栏中找到tools 2 在弹出的下拉窗口中选中options 3 此时弹出的对话框,选中Environment下的international setting 4 点击获 ...

  9. 一鼓作气 博客--第六篇 note6

    1.无论公司付给你多少,你的青春都是廉价的!! 2.通往财富自由之路 --得到APP 3.time 3.1 time.time() t = time.time() print(t) #--->1 ...

  10. error C2678

    自定义结构类型,为支持插入到stl set或者排序,一种方式是重载operator<运算符成员函数.如果忘记将函数标识为const,则在编译时会报 6>c:\program files ( ...