最近用unity3d引擎做了一個拼圖遊戲,會分幾次寫完,以此作為總結。本文基本尋找了網上能查到的所有資料作為參考。也算是大家節省了時間。
目前只完成了拼圖部分,leap motion手勢控制部分會在後續完成,不過說實話不太看好LM。
項目資源來自 棟篤神探 http://blog.csdn.net/cube454517408/article/details/7907247,不過玩法不同,玩法與小夭 http://game.ceeger.com/forum/read.php?tid=2852相同。我也重寫了前者的程式,部分實現思路不同,兩個遊戲的工程在本文完成後都會打包上傳。
首先是整個遊戲需要的模組。
一個拼圖遊戲大致需要如下幾個控制模組:片段顯示,片段隨機打亂,隨機排序後片段順序的合法性檢查,移動控制,拼圖是否完成的檢查。
一、片段顯示。
此部分可以有幾種選擇,第一個就是將每部分片段單獨做成圖片,比如這個
http://tieba.baidu.com/p/2053275362 好處是處理比較方便,可以使用GUI處理,缺點是每個圖片都需要前期處理,而且由於前期分區的份數固定,遊戲難度不能隨意調整,除非每個圖都準備很多不同難度的分割後的小圖。
第二是使用NGUI中的Atlas,對圖集中的sprite資訊進行重定義。具體參考小夭的程式。其中用到了UISprite類中的outer結構體,outer記錄了sprite在圖集中的位置資訊。但是在NGUI3.6版本中outer已經不是UISprite的成員變數,是否還能用文中的方法進行修改沒有嘗試,如果有人嘗試請留言告知,在此謝過。
第三是在材質球中設定紋理位移和縮放,具體做法參考上面篤棟神探的文章。本人也是用的此種方法。
第二和第三種實現方法的好處是可以隨意調整圖片分成的份數,因此可以很方便的調整遊戲難度。
Vector2 offset;\\記錄每一塊片段的位移offset.x = origin.x + piecesLength * j; offset.y = origin.y - piecesLength * i;temp.transform.localPosition = new Vector3 (offset.x*10f,offset.y*10f);texOffset[k].x = j*transform.localScale.x/row;\\計算紋理位移texOffset[k].y = (row-1-i)*transform.localScale.x/row;temp.renderer.material.mainTextureOffset = texOffset[k];\\設定紋理位移temp.renderer.material.mainTextureScale = new Vector2(transform.localScale.x/row,transform.localScale.x/row);\\設定紋理縮放
因為圖源為正方形所以,只考慮了將其分為N*N塊的分法,因此位移和縮放的計算較為簡單。
片段顯示部分就這麼多內容,下面是片段打亂演算法。
二、片段打亂演算法
這裡有兩種不同的思路,第一種是小夭採用的,將正確排列的片段隨機移動若干次,以達到打亂片段順序的目的,該方法的好處是,用這種方法產生的隨機序列一定可以還原,缺點是實現起來較為複雜。具體實現見小夭的文章。
第二種思路是採用洗牌演算法,使用一個數組儲存第N個片段的紋理位移,從第一個片段開始與隨機一個片段交換內容,直到數組結束。演算法實現起來比較簡單,但是並不一定保證可以正確還原。
void Shuffle(){Random.seed = System.Environment.TickCount;for (int i = 0; i < squence.Length - 1; i++) { int temp = squence[i]; int randomIndex = Random.Range(0, squence.Length-1); squence[i] = squence[randomIndex]; squence[randomIndex] = temp; } }
三、逆序和檢驗
通過洗牌演算法得到的隨機序列,並不一定可以還原成初始的順序,這是因為在洗牌時改變了數組的逆序和。參加百度百科(不可還原的拼圖)……http://baike.baidu.com/link?url=2ajCBRlh6Ox1I1SPK8gEayd-aAaCITNNQjVSA09qDHDLXZM9Ndrp-thdWdjg-Xt_sRk3PCABt-3LUPDKfTZDy_
lemene對此進行了證明,喜歡數學證明的同學請見 http://www.cppblog.com/lemene/archive/2007/10/04/33405.html
shaomn的講解比較容易明白,http://blog.sina.com.cn/s/blog_4ed8b87701011c6x.html
對於數組squence[],定義其逆序和為sum += (i - j) * (squence [i] - squence [j]) > 0 ? 0 : 1;對於初始序列其逆序和為0,左右移動片段時sum不變,上下移動時sum +2、-2或不變,但是無論怎樣移動,逆序和奇偶性是不變的。因此在洗牌演算法之後,檢驗數組逆序和是否為偶數即可。
bool Check(){int sum = 0;for (int i = 0; i < squence.Length; i++)for (int j = 0; j < i; j++)sum += (i - j) * (squence [i] - squence [j]) > 0 ? 0 : 1;return sum % 2 == 1;}
(待續……)