簡易語言

          數(shù)字溝通

           

          一個(gè)小游戲ChainReaction的設(shè)計(jì)(html5)

          本來一直覺得js是個(gè)讓人混亂不堪的語言,html5的出現(xiàn)改變了我對它的看法。到了html5的時(shí)代,各種犀利的設(shè)計(jì)就更明顯的需要js了。看了一些小游戲設(shè)計(jì),忽然來了興趣,于是寫了幾個(gè)小游戲,這是其中一個(gè)。已經(jīng)開源,歡迎下載https://github.com/yangyusong/ChainReaction。

           

          游戲叫連鎖反應(yīng),這個(gè)游戲是看到有人在ipad上面玩的游戲,覺得好玩,自己實(shí)現(xiàn)一遍。游戲是這樣的,一群小球在區(qū)域內(nèi)彈來彈去,玩家鼠標(biāo)點(diǎn)擊一個(gè)地方,在一個(gè)圓的范圍內(nèi),小球碰上就會爆炸,爆炸的過程中其他小球碰上也會發(fā)生爆炸,這就叫連鎖反應(yīng)。每一關(guān)爆破一定數(shù)量的小球就算勝利。

           

          我的設(shè)計(jì)中一個(gè)有20關(guān),數(shù)值增長比較平和,運(yùn)氣不是太差的話都能一次通關(guān)。在說有個(gè)再玩本級的功能,過一關(guān)的壓力是一點(diǎn)都沒有。這樣設(shè)計(jì)是為了給工作后的朋友緩解壓力。我們輕松的一點(diǎn)就爆炸一片。

           

          看看截圖


           

          大的那個(gè)灰色的(其實(shí)是半透明的)圓是鼠標(biāo)范圍。其他是彈來彈去的小球??梢钥吹剑∏蚴歉鞣N顏色的。

           

          我們看看小球的定義

          function Circle(x, y, xSpeed, ySpeed, radius, color, liveTime, state){

              //圓心坐標(biāo)

              this.x = x;

              this.y = y;

              //運(yùn)動速度

              this.xSpeed = xSpeed;

              this.ySpeed = ySpeed;

              //半徑

              this.radius = radius;

              //顏色

              this.color = color;

              //生存計(jì)數(shù)器

              this.liveTime = liveTime;

              //狀態(tài):

              this.state = state;

          }

           

          其中生存計(jì)數(shù)器是要和狀態(tài)結(jié)合使用的,狀態(tài)分為如下5個(gè)狀態(tài)

          //小球狀態(tài)

          var SMALL = 0;

          var BIG = 1;

          var EXPEND = 2;

          var END = 3;

          var DIS_VISIBLE = 4;

           

          當(dāng)處于EXPEND狀態(tài)的時(shí)候,就說明小球進(jìn)入爆炸狀態(tài),這時(shí)候生存計(jì)數(shù)器就用上了。計(jì)數(shù)器是個(gè)倒計(jì)時(shí),計(jì)時(shí)到零,小球進(jìn)入DIS_VISIBLE狀態(tài)。這時(shí)候小球就不再渲染出來。

           

          我們的小球有不同大小,不同顏色,看看小球的初始化就知道了,代碼在ObjectMgr.js

          for(i = 0; i < g_StepsArr[g_Steps].ballsNum; i++){

                      //_Util.dump_obj(_Color.color_str(new Color(Math.random(), Math.random(), Math.random())));

                      var raduis = _Util.random_range(SMALL_RADIUS1, SMALL_RADIUS2);

                      this.circles.push(new Circle(

                          _Util.random_range(raduis*2, this.canvasWidth-2*raduis),

                          _Util.random_range(raduis*2, this.canvasHeight-2*raduis),

                          _Util.random(SPEED_MIN, SPEED_MAX),

                          _Util.random(SPEED_MIN, SPEED_MAX),

                          raduis,

                          _Color.color_rgba_str(new Color1(Math.random(), Math.random(), Math.random(), 0.8)),

                          MID_LIVE_TIME,

                          SMALL

                          ));

                  }

           

          其中g_StepsArr負(fù)責(zé)我們關(guān)卡的管理,有這一關(guān)的小球數(shù),和通關(guān)需要爆破的小球數(shù)??傊?,這里按照本關(guān)需要的小球數(shù)初始化小球,可以看到里面有很多的隨機(jī)函數(shù)使用。小球的半徑處于如下兩個(gè)數(shù)之間

          var SMALL_RADIUS1 = 3;

          var SMALL_RADIUS2 = 10;

          通過random_range來進(jìn)行這個(gè)范圍隨機(jī)。我們看到速度也是隨機(jī)的,范圍是

          var SPEED_MIN = 10;

          var SPEED_MAX = 50;

          顏色中的color_rgba_str函數(shù)的第四個(gè)參數(shù)說明我們的每個(gè)小球的透明度是0.8,這樣我們就能在爆破的時(shí)候,或彈動的時(shí)候仍然看清其他小球。這段代碼就說到這。

           

          我們講講主要流程,其實(shí)其中的詳細(xì)注釋,我覺得已經(jīng)可以教會很多初學(xué)者。不過還是講講好。主要流程就在Main.js中。負(fù)責(zé)初始化,渲染和循環(huán)。開始我們設(shè)置了一堆全局變量。

          var g_ObjectMgr = null;

          var g_MouseEventDispatch = new MouseEventDispatch();

          var g_MouseMgr = null;//g_MouseMgrg_ObjectMgr初始化后才初始化

          //當(dāng)前關(guān)

          var g_Steps = 1;//todo 顯示出來

          //關(guān)卡數(shù)組

          var g_StepsArr = [];

          g_StepsArr = stepsInit();

          //爆炸開始標(biāo)識

          var _ExpendStart = false;

           

          if(DEBUG){

              _CircleLib.test();

          }

          var _Main = { 。。。

           

          包括關(guān)卡數(shù)組,當(dāng)前關(guān)數(shù),爆炸標(biāo)識等。居然還設(shè)置了一個(gè)是否調(diào)試的狀態(tài)量,其實(shí)我也不知道js調(diào)試怎樣才好,基本就按自己的方式調(diào)。 _Main是個(gè)很大的結(jié)構(gòu)。我更寧愿把它當(dāng)做單例來思考。主要是,它包括了渲染,這個(gè)渲染不具通用性,僅此一例就夠。其他地方用了且不是畫出什么就難說了。當(dāng)然已經(jīng)設(shè)計(jì)其實(shí)我會更多考慮通用性的設(shè)計(jì),盡量不設(shè)計(jì)成這種單例。

           

          這個(gè)_Main結(jié)構(gòu)中有我們的畫布canvas,我們的初始化函數(shù),每關(guān)調(diào)用一次,它來負(fù)責(zé)2d對象的初始化,游戲?qū)ο蟮某跏蓟J髽?biāo)監(jiān)聽初始化。然后就是進(jìn)入我們的循環(huán)。循環(huán)很簡單,就干四件事情

          /*

               * 循環(huán)繪圖

               * 1.清空畫面

               * 2.游戲?qū)ο箨P(guān)系處理

               * 3.渲染出來

               * 4.循環(huán)調(diào)用

               */

              step: function(){

                  this.clear();

                  g_ObjectMgr.step();

                  this.render();

                  _this = this;

                  this._st = setTimeout(function(){

                      _this.step();

                  }, 50);

              }

           

          看看我們的下一關(guān)都干些什么

          /*

               * 下一關(guān)

               */

              nextStep: function(){

                  clearTimeout(this._st);

                  if(this.canvas.getContext)

                  {

                      g_MouseEventDispatch.start();

                      this.initObjects();

                      this.step();

                  }

              }

          它就是清除計(jì)時(shí)器,重新分配事件,初始化對象。然后進(jìn)入循環(huán),為什么是這樣呢?清除計(jì)時(shí)器以使我們之前的循環(huán)停止。因?yàn)槲覀凂R上有新的循環(huán)了,其實(shí)事件可以看做有兩個(gè)狀態(tài),我們按下鼠標(biāo)的時(shí)候,這個(gè)事件就不可用了,下次使用必須初始化。小球數(shù)量變了,必須按照本關(guān)的需求來初始化。進(jìn)入循環(huán),新的循環(huán)開始。

          看看再玩一次(本級)按鈕的調(diào)用:

          /*

               * 再玩一次(本級)

               */

              again: function(){

                  this.nextStep()

              }

           

          為什么居然是調(diào)用下一關(guān)呢?只能說我設(shè)計(jì)的太懶惰,nextStep()本身根本不管關(guān)卡的變更。關(guān)卡的變更完全在爆炸檢查函數(shù)里,一旦發(fā)現(xiàn)小球爆炸,就會修改當(dāng)前關(guān)卡。而單純調(diào)用nextStep所使用的關(guān)卡是未改變過的,故而是在玩本級。

           

          我們再看一下ObjectMgr.js中的爆炸檢查函數(shù)

           

          expendCheck: function(){

                  if(_ExpendStart){

                      this.expendNum = _CircleLib.intersect(this.circles, g_MouseMgr.mouseCircle);

          //            _Util.dump_obj(g_StepsArr[g_Steps])

                      if(this.expendNum >= g_StepsArr[g_Steps].killNum){

                          var next = g_Steps + 1;

                          alert("成功爆破超過"+this.expendNum+"個(gè)小球,恭喜進(jìn)入第"+ next + "關(guān),\n\

          下一關(guān)需要爆破" +g_StepsArr[g_Steps + 1].killNum + "個(gè)小球");

                          g_Steps++;

                          _Main.init();

                      }

                  }

              }

           

          還記得_ExpendStart這個(gè)變量的意思么?就是說鼠標(biāo)是否按下了,按下的話我們就要檢查是否有小球撞上鼠標(biāo)范圍或撞上爆炸中的小球。其實(shí)這里的調(diào)用_CircleLib.intersect這個(gè)函數(shù)是有些小問題的。它是通過引用修改的當(dāng)前小球的狀態(tài),至于為什么有很少量的小球未修改狀態(tài),這個(gè)我還沒弄明白??傊?,這個(gè)函數(shù)檢查了爆炸小球的數(shù)量,一旦爆炸小球的數(shù)量符合本關(guān)的要求,那么就可以進(jìn)入下一關(guān),可以看到我們進(jìn)入下一關(guān)的提示是一個(gè)對話框,不是很友好,可以設(shè)計(jì)為一個(gè)圖片較好,可惜我沒時(shí)間找美術(shù)。

           

          點(diǎn)擊確定,我們玩下一關(guān)

           

          小球多了很多,找個(gè)好點(diǎn)的位置,能捕捉很多小球。

          看一下爆炸過程吧:


          這是第十八關(guān)的一個(gè)爆炸情形,更具體的內(nèi)容歡迎看具體代碼吧,要不還講好長時(shí)間。

           

          做完這個(gè)例子,發(fā)現(xiàn)其實(shí)非常多的小游戲很好設(shè)計(jì),可惜沒那么多時(shí)間,再說設(shè)計(jì)別人設(shè)計(jì)過的游戲也不是我的目標(biāo)。設(shè)計(jì)一些有趣的小游戲到手機(jī)里,這個(gè)倒是個(gè)不錯(cuò)的方向



          一種更好的態(tài)度,更好的學(xué)習(xí)、思維方式。它會是網(wǎng)絡(luò)極佳的生存方式,你喜歡就對。

          posted on 2011-12-18 23:03 yangyusong 閱讀(2141) 評論(2)  編輯  收藏

          評論

          # re: 一個(gè)小游戲ChainReaction的設(shè)計(jì)(html5) 2011-12-19 09:11 tb

          有好思維a   回復(fù)  更多評論   

          # re: 一個(gè)小游戲ChainReaction的設(shè)計(jì)(html5)[未登錄] 2011-12-22 17:15 tbw

          很有創(chuàng)意思維。  回復(fù)  更多評論   


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 海南省| 固始县| 镇原县| 贵阳市| 天水市| 安溪县| 郸城县| 栖霞市| 婺源县| 肃南| 类乌齐县| 临高县| 益阳市| 台南县| 安乡县| 咸阳市| 浦江县| 南宁市| 偏关县| 庐江县| 洛隆县| 买车| 安远县| 凤凰县| 安顺市| 华亭县| 股票| 额济纳旗| 威海市| 安福县| 开封市| 石台县| 昌邑市| 额济纳旗| 安远县| 康平县| 麻阳| 凤山县| 大石桥市| 毕节市| 砀山县|