我的前端故事----欢乐大富翁( ̄︶ ̄)↗ (摇骰子+棋盘)

十一马上就要到了~~做为前端的小伙伴~活动页面必然是少不了了~那怎么吸引眼球呢?当然是玩游戏啦~这次就带来一个我为十一做的小游戏,作为活动页中的衬托~~

那我们要做个什么样的游戏呢?先上图~

由于实际的效果图因为是公司的活动,我就不贴出来了~这里用这个棋盘来大致说明一下效果咯~下面是游戏规则:

1,当用户看到棋盘的时候,棋子出现在上一次停留下来的位置;

2,当用户点击开始后,中间的骰子开始摇动,最后停止在服务器返回的数字前;

3,当骰子结束动画后,棋子还是移动,一步一步的向前移动,遇到四个顶点的时候自动转弯,并最终停留在骰子步数前进的位置前;

4,当棋子结束移动后,页面上显示用户最后剩下的游戏次数,并且如果移动到有礼物的位置时弹出遮罩告诉用户获奖;

5,在整个游戏期间,不允许用户继续点击开始按钮,并且当用户剩余次数用完之后开始按钮变色;

游戏规则都说明了,那么需求分析就到这里了,下面介绍页面布局:

HTML结构:

<div class="game">
    <div class="gameimg">
             <div id="pieces" class="p0-0">    <!-- 棋子 -->
                 <img src="images/pieces.png" />
             </div>
        <div class="play">
             <div class="dice">     <!-- 骰子 -->
                 <img id="dice" class="dicelo2" src="images/dice.png" />
             </div>
             <div class="playnum">
                 您今天还有<span id="pn">0</span>次游戏机会
               </div>
             <div id="playbtn">
                  <img src="images/btn_start_gray.png" />
             </div>
         </div>
    </div>
</div>

整体的结构就是一个大的div标签,它的背景是整个棋盘,然后棋子通过相对布局定位在背景图的18个位置上,然后骰子和开始按钮以及说明都居中显示在背景图的中心。

CSS样式:

对于css样式来说,主要用到的是相对定位,设置了18个位置的css样式,而且命名规则是按照 ’p0-0‘这样的方式来命名?为什么我要这样呢?这样可以用类名保存矩阵坐标的位置。棋盘上的位置1对应坐标的1-0、2对应2-0…..依此类推。最后就可以方便的设置棋子的位置了。同时,对于骰子的动画,是通过一整张png图片来进行定位。从骰子的1到6然后是动起来的3副图片,一共9张图片保存在一整张png中,然后依旧采用相对定位的方式来给用户展示。首先是骰子开始运动,我就循环显示最后3张动起来的图片,然后当动画结束后将位置停留在所要显示对应的数字前。

这样把部分图片贴出来就很明显的说明了我的意图~

javascrpt逻辑篇:

首先是进入页面的加载,流程就是首先通过jsonp请求服务器,获取该用户上次的棋子位置,和剩余次数等基础信息,然后渲染在页面中,我就不在这里展开了,这里注意想说的是负责棋子移动和骰子摇动的逻辑部分。

那么按照游戏规则,首先是骰子的摇动,当点击开始按钮后请求服务器结束后调用骰子执行函数,接着将服务器返回的骰子数字和到达的位置传递给复制骰子动画的函数。

/**
 * 操作骰子的执行函数
 *
 * @method play_dice
 *
 * @param  {ing}  dice_num  [骰子数字]
 * @param  {int}  next_step [到达位置]
 */
function play_dice (dice_num, next_step) {
    var _stop = dice_num,
        _pande = next_step;
    diceroll($(‘#dice‘), _stop, _pande);
}
/**
 * 摇动骰子的动画函数
 *
 * @method diceroll
 *
 * @param  {object} dice      [骰子对象]
 * @param  {int}    num       [摇动的结果]
 * @param  {int}    _pande    [棋子停下的位置]
 */
function diceroll(dice, num, _pande){
    var i = 0,
        b = 0,
        a = function(i) {
          b = setTimeout(function() {
              dice.removeClass().addClass(‘dicelo‘ + (i % 3 + 7));   // 清除上次动画后的点数
              i++;
              if (i > 5) {
                  // 这里的dicelo9是骰子最后一幅动画的类名,删除后依次添加dicelo7,dicelo8
                  dice.removeClass(‘dicelo9‘).addClass(‘dicelo‘+num);
                  var j = $(‘#pieces‘).attr(‘class‘).substr(1) || 1,
                      n = j + _pande;
                  var oldstep = _pande-num-1;
                  person.step = num;
                  run(person, true);//  1右,2下,3左,4上
                     clearTimeout(b);
                  i = 0;
              } else {
                  a(i);
              }
          }, 200);
        };
    a(i);
}

这里通过一个定时器,不断的循环骰子摇动的这个动画,然后在执行5次之后就让骰子停下来,同时清除定时器,然后在骰子停止摇动之后触发棋子移动的函数,在run函数中需要两个参数,如果第二个参数为true,就让棋子还是移动,否则的话则只是计算棋子的矩阵坐标。而person这个对象中保存着坐标位置start: [0, 0],所要前进的步数step,和当前前进的方向de,de的值我设定为1右,2下,3左,4上 。下面是棋子移动的函数。

/**
 * 控制棋子的移动和棋盘坐标的转换
 *
 * @method run
 *
 * @param  {object}  person [棋子移动的坐标]
 * @param  {Boolean} isAn   [棋子是否需要移动]
 *
 * @return {object}         [棋子移动的坐标]
 */
function run (person, isAn) {
    var _start = person.start,
        _step = person.step,
        _de = person.de;

    // 棋子移动过程的坐标集合
    gameList = new Array();
    for (var i = 1; i <= _step; i++) {
        if (_de == 1) {  // 棋子向右移动
            _start[0] += 1;
            if (_start[0] == 5) {
                _de = 2;
            }
        }else if (_de == 2) {  // 棋子向下移动
            _start[1] += 1;
            if (_start[1] == 4) {
                _de = 3;
            }
        }else if (_de == 3) {  // 棋子向左移动
            _start[0] += -1;
            if (_start[0] == 0) {
                _de = 4;
            }
        }else if (_de == 4) {  // 棋子向上移动
            _start[1] += -1;
            if (_start[1] == 0) {
                _de = 1;
            }
        }
        gameList.push([_start[0], _start[1]]);  // 将移动后的结果保存在集合中
    }

    // 当需要棋子移动时执行
    if (isAn) {
        var j = 0,
            d = 0,
            c = function(j) {
              d = setTimeout(function() {
                  $(‘#pieces‘).attr(‘class‘, null).addClass(‘p‘+gameList[0][0] + ‘-‘ +gameList[0][1]);
                  gameList.shift(0);
                  j++;
                  if (gameList.length == 0) { // 如果棋子移动结束后则弹出相应的结果
                          returndice(_start);
                      clearTimeout(d);
                  } else {
                      c(j);
                  }
              }, 500);
            };
        c(j);
    }
    person.start = _start;
    person.step = 0;
    person.de = _de;
    return person;
}

这里依旧是使用定时器来重复显示棋子的移动过程,由于定时器是异步执行的,所以我将函数产生的一个运动结果保存在数组中,然后在异步的定时器中一个个的遍历数组中的结果,每次取出数组中的第一个结果,执行移动之后便移除第一个结果,后面的结果顶上来,下次取出的第一个结果就是下一次需要移动的结果,最终在结束移动的时候及队列清空的情况下清除定时器,然后我在代码中执行了returndice函数来显示移动后的结果,如果中奖了则调出遮罩提示用户的获奖情况。

总结:

到这里,全部的逻辑基本都说明白了,其实整体来说就是3个函数的循环调用,为了保证在移动端上的性能,在每次定时器结束之后都需要及时的清除掉定时器,否则会出现定时器覆盖的情况,在我测试的时候如果没有及时清除定时器的话,在执行20000+的时候会出现移动的步数比实际的情况少一步的情况,最开始的时候我在最后写了校验函数来保证最终棋子停下来的位置与服务器返回的一致,本来以为是误差,结果后来再测试的时候发现校验的时候会出现棋子闪现的情况,这是很不好的用户体验,而且按照我棋子移动的逻辑来看,是不可能出现错位的,所以理论上是不需要校验函数的,所以再经过仔细查看代码后发现了第二次棋子移动的定时器在使用后并没有及时清除,在用户游戏次数较少的时候是很难出现bug的,但是自动测试的时候接近于无限的次数很容易出现错误的情况,所以还是很重要的bug,还好及时发现。。。o(︶︿︶)o 最后为了保证在一次游戏的过程中用户不能继续点击开始按钮,所以在开始摇骰子的时候将全局锁设置为false,并在最后棋子结束移动之后再打开全局锁。到此为止,所有的游戏规则都满足了~~

今天就到这里吧。。。下次带来一个页面跑马灯的效果~~

我的前端故事----欢乐大富翁( ̄︶ ̄) (摇骰子+棋盘)

时间: 2024-10-11 07:31:14

我的前端故事----欢乐大富翁( ̄︶ ̄)↗ (摇骰子+棋盘)的相关文章

我的前端故事----轮盘转起来(+﹏+)~

转眼间,马上又到了中秋了,忽然想到了有到了做活动的日子了~每逢佳节必活动的传统一直是我们前端的职责所在,去年我介绍了游戏机,大富翁,那今年的活动就来个轮盘开奖吧~其实这个东西在 pc 端上已经烂大街了,无数的 demo,插件可以帮助我们实现这个功能,所以我也就随大流的去找了个知名的 jQuery 插件去实现这个功能,可惜我做的是移动端的开发...平时基本都是原生 javaScript 做开发,顶多上一个 zepto,为了这个功能上一个 jQuery 总觉得不是那么地道,不过现在的jquery压缩

我的前端故事----优美的编辑器GitHub Atom

很多前端的同学都在用sublime text,我之前也在使用,但是后来接触到了Atom,就被它的高颜值深深的吸引了~~不愧是GitHub的工程师哦~审美就是高  Atom 作为一个跨平台的编辑软件,安装和使用都是十分的方便,刚刚接触的同学也很容易在上面找到sublime text的影子,这非常方便像我这样的人搬过来,那么最基础我就不介绍了,今天这篇就给刚刚接触Atom的同学带来一些常用的插件,你会发现,原来Atom可以变得更美丽~~ 插件篇 效果可在插件首页中查看 atom-beautify:这

数论之旅4---欧拉函数的证明及代码实现(我会证明都是骗人的╮( ̄▽ ̄)╭)

欧拉函数,用φ(n)表示 欧拉函数是求小于n的数中与n互质的数的数目 辣么,怎么求哩?~(-o ̄▽ ̄)-o 可以先在1到n-1中找到与n不互质的数,然后把他们减掉 比如φ(12) 把12质因数分解,12=2*2*3,其实就是得到了2和3两个质因数 然后把2的倍数和3的倍数都删掉 2的倍数:2,4,6,8,10,12 3的倍数:3,6,9,12 本来想直接用12 - 12/2 - 12/3 但是6和12重复减了 所以还要把即是2的倍数又是3的倍数的数加回来 (>﹏<) 所以这样写12 - 12/

( ̄▽ ̄&quot;) 没钱了

( ̄▽ ̄") 没钱了 TimeLimit: 1000ms  MenoryLimit:65536KB 64-bit integer IO format:%lld Problem Description 在忙碌的假期中, BOBO学长在考完驾驶证后,决定开车去旅游,然而,他不想经常的停下车,来给小车加油,他想尽快到达旅游点,在行驶的途中想要尽量少次数的给小车加油. 他行驶的道路是一条笔直的公路,在这条公路上,有 N (1 <= N <= 10,000) 个加油站,第i个加油站位于距离旅游

?( ̄(?) ̄)?

此页面为WP8"?( ̄(?) ̄)? "应用的发布页面. ?( ̄(?) ̄)? 是一款收集日本颜文字的WP8端应用. 此页面主要记录开发进度.APP发布等情况. -------------------相关进度--------------------- 目前进度:UI相关资源前期准备中,各相关开放平台的AppID申请中... ?( ̄(?) ̄)?,布布扣,bubuko.com

妈妈喜欢谁? (~ ̄▽ ̄)~

Linux 中有一个用于显示自身登录信息的特定命令结构,也就是登录用户信息的命令. who am i 或者是 who mom likes 没错看第三行!“妈妈喜欢谁” who mom likes   ,linux的命令真的是让人脑洞大开o( ̄▽ ̄)d

我的前端故事----来聊聊react-native应用的健康监控

监控什么 今天我们来聊聊如何监控你的应用程序,这里的监控说的不是让我们去监控用户,而是监控应用的健康状态,什么是健康状态呢?对于后端的同学来说,在微服务的架构下,每个子服务是否正常工作.返回的结果是否满足预期,这些就算是健康状态,再举个例子,你的台式机,对于操作系统来说,每个硬件是否能正常的工作.工作的稳定性,这些都是需要关注的健康状态. 既然我们关心健康状态,那么我们该如何衡量一个"设备"的健康状态呢?对于上面的例子,CPU运行的温度.硬盘读取的速度.子服务执行的效率,这些都可以作为

ACM数论之旅3---最大公约数gcd和最小公倍数lcm(苦海无边,回头是岸( ̄? ̄))

gcd(a, b),就是求a和b的最大公约数 lcm(a, b),就是求a和b的最小公倍数 然后有个公式 a*b = gcd * lcm     ( gcd就是gcd(a, b), ( •?∀•? ) 简写你懂吗) 解释(不想看就跳过){ 首先,求一个gcd,然后... a / gcd 和 b / gcd 这两个数互质了,也就是 gcd(   a / gcd ,b / gcd  )  =  1,然后... lcm = gcd *  (a / gcd) * (b / gcd) lcm = (a *

Java表单中关于JavaScript的非空必输验证,你的程序和大牛有多少差距╮( ̄▽ ̄&quot;)╭

var defaultEmptyOK = false; // スペース var whitespace = " \t\n\r "; function checkNull (theField, s, emptyOK) { if (checkNull.arguments.length == 2) emptyOK = defaultEmptyOK; if ((emptyOK == true) && (isEmpty(theField.value))) return true;