黃近秋,黃惠洪
目前,在中國乃至世界,游戲產(chǎn)業(yè)[1]已經(jīng)逐漸成為微控制器領(lǐng)域的一個相當龐大以及重要的分支,而關(guān)于這方面的高級人才仍甚是缺乏,很多初學單片機的朋友都會對其龐大而復雜的機制感到困惑。本文以經(jīng)典的推箱子游戲規(guī)則為基礎(chǔ),趣味而有序地對這個游戲從需求分析到整體方案進行了全新的設計。
首先運行游戲并載入相應的地圖數(shù)據(jù),屏幕上出現(xiàn)一個推箱子工人,其周圍是預制好的地圖、圍墻、人可以行走的通道、幾個可以移動的箱子和游戲勝利結(jié)束時安放這些箱子的目標位置。如圖1所示。
玩家先通過功能按鍵選擇希望到達的關(guān)卡,再通過鍵盤操縱推箱子工人的位置。當工人靠近箱子并朝箱子位置移動的時候,箱子在其移動方向沒有被其他物件(箱子或者墻)
所阻礙的情況下可以被移動,并實時記錄游戲的步數(shù)與所用的時間,當所有箱子被移到指定的安放位置后,則勝利通關(guān)并進入下一關(guān)的游戲。在游戲過程中,若遇到死局,可以按
返回鍵回到本次游戲的最初界面,但是所走的步數(shù)與時間均會累加。當玩家希望選擇另一關(guān)的時候,可以按重選關(guān)鍵退出選擇另一關(guān)游戲,不管系統(tǒng)處于何種狀態(tài)下,均可實現(xiàn)關(guān)機動作,關(guān)機后也可開機繼續(xù)游戲。
圖1 第8關(guān)游戲界面
該游戲的系統(tǒng)硬件設計原理框圖如圖2所示。
系統(tǒng)硬件電路[主要由電源、AT89C55單片機、單片機復位電路、時鐘電路、鍵盤和液晶顯示模塊等部分組成。系統(tǒng)要顯示的信息通過P2口送到LCD液晶顯示器;復位電路使單片機的片內(nèi)電路初始化,使單片機從一種確定的狀態(tài)開始運行;時鐘電路用于提供單片機內(nèi)各種微操作的時間基準;電源電路為各個電路提供穩(wěn)定的+5V電源。
圖2 系統(tǒng)硬件設計原理框圖
電源電路如圖3所示:
圖3 電源電路
三端穩(wěn)壓芯片7805把9V輸入電壓穩(wěn)壓成5伏直流電源提供給單片機系統(tǒng)使用,右邊兩個電容是5伏電源的濾波及去耦電容,電阻和綠色的LED組成5伏電源的工作指示電路,只要電源部分正常,綠色的 LED(D4)就會點亮,用戶可以根據(jù)這個 LED來判斷整個電源部分是否工作正常。
鍵盤在單片機應用系統(tǒng)中,實現(xiàn)輸入數(shù)據(jù)、傳送命令的功能,是人工干預系統(tǒng)的主要手段。本文的鍵盤電路包括兩個相對獨立的鍵盤,直觀地根據(jù)有無控制線的結(jié)構(gòu)分為有線鍵盤和無線鍵盤。有線鍵盤即通常說的獨立式鍵盤。如圖4所示:
圖4 獨立式鍵盤
本游戲還可使用無線鍵盤進行操作,其原理跟獨立式鍵盤原理一樣,都是要使得單片機相應的引腳產(chǎn)生預期的高電平或低電平,從而達到無線遙控控制[6]。
液晶顯示模塊與單片機的連接如圖5示:
圖5 液晶顯示模塊
本文選用TS160128液晶顯示模塊,它不僅可以顯示字符、數(shù)字,還可以顯示各種圖形、曲線及漢字,并且可以實現(xiàn)屏幕上下左右滾動、動畫、閃爍、文本特征顯示等功能。本液晶模塊內(nèi)有T6963C液晶驅(qū)動控制器。根據(jù)模塊硬件的要求,必須在復位端接一阻值為5K的上拉電阻,VEE端接一阻值為 20K的下拉電阻,并且分壓到 Vadj(CON)端用于屏幕亮度的調(diào)節(jié)。
定義核心數(shù)據(jù)結(jié)構(gòu),定義一個二維數(shù)組 map_define來進行地圖定義,定義map來存放各關(guān)的地圖,用于記錄屏幕上各點的狀態(tài),其中,“0”表示空地,即什么都沒有;“1”表示推箱子工人;“2”表示墻壁;“3”表示箱子;“4”表示目的地;“5”表示箱子被放在目的地上,即合成物。
對整個軟件進行功能模塊的劃分:①初始化——主要是液晶屏幕的初始化跟中斷設置;②選項——選擇進入游戲、關(guān)于或者是關(guān)機;③游戲地圖初始化,并根據(jù)各關(guān)的要求在屏幕上輸出空地、墻、箱子、目的地、合成物和人,及其他信息;④進入游戲循環(huán)——這個游戲主循環(huán)時等待按鍵,當接收到上下左右鍵時執(zhí)行相關(guān)的操作,接收到關(guān)機時退出游戲,接收到返回時返回到本關(guān)開頭,接收到重選關(guān)時退出游戲進入關(guān)卡選擇,接收到無效按鍵時做忽略處理;⑤判斷是否過關(guān)——箱子的數(shù)目和目的地的數(shù)目是一樣的,所以函數(shù)每執(zhí)行一次操作就判斷是否所有箱子都已經(jīng)安放好,即都移到了目的地上,檢測地圖中是否還有“目的地”這一狀態(tài)值的區(qū)域,如果有,則還沒有完全放置好所有的箱子,否則,勝利結(jié)束游戲。
3.1.1 系統(tǒng)的主流程圖
圖6 系統(tǒng)的主流程圖圖
系統(tǒng)的主流程圖如圖6所示,其中power=0為待機;gamemode=1為游戲模式;rechoice=1表重選關(guān);e2為選擇入口變量。
3.1.2 中斷服務程序
中斷服務程序用于處理鍵盤被按下后系統(tǒng)的動作,其實現(xiàn)的流程圖如圖7所示。
圖7 中斷服務程序流程
在完成了整體框架的搭建后,接下來將對整個游戲的核心進行實現(xiàn)了。首先,可以先設計出游戲的核心數(shù)據(jù)結(jié)構(gòu)(包括這些數(shù)據(jù)的存取方式),接著再根據(jù)游戲的特性設計出實現(xiàn)算法,最后就要將算法融入到與用戶交互的各個環(huán)節(jié)中去。
3.2.1 地圖與內(nèi)部數(shù)據(jù)結(jié)構(gòu)的設計
目前為止,已經(jīng)完成所有動作數(shù)據(jù)的運算和處理,剩下的工作就是將這些數(shù)據(jù)圖像展現(xiàn)在屏幕上,并實現(xiàn)交互。地圖即游戲區(qū)域,對于整個游戲區(qū)域的繪制,采用分塊繪制的方法,將整個游戲區(qū)域分成若干個很小的塊狀區(qū)域,然后根據(jù)該區(qū)域在地圖中對應存儲位置的狀態(tài)值繪制地圖。它是由多個縱向和橫向分布的小方塊組成,例如圖8中的小方塊A和B。本游戲的行列個數(shù)分別為12和14。
而在游戲的某一瞬間,整個游戲區(qū)域的圖像總是由這些小方塊根據(jù)不同的狀態(tài)分別顯示后構(gòu)成的。需要顯示的狀態(tài)有可行走的空地、不可通過的墻壁、箱子、工人、目的地,合成物。
我們首先要定義一張空白的游戲地圖,如圖8所示:
圖8 地圖區(qū)域示意
idata uchar map_define[12] [14] =//定義地圖
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, };
定義了這樣一張空白地圖之后,我們可以很方便地使得各關(guān)的游戲地圖得到編輯和更新改變,可以用文件的方式進行各關(guān)卡游戲地圖的存儲。這里將函數(shù)名稱定義為map[] [14] [12] ,其數(shù)據(jù)的具體存儲方式如下所示(圖9為其對應的游戲地圖的顯示效果):
unsigned char code map[] [14] [12] = //g=0,第 1 關(guān)
圖9 第一關(guān)游戲
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,4,2,0,0,0,0,0,0,0,0,0,2,0,2,2,2,2,0,0,0,0,2,2,2,3,1,3,4,2,0,0,0,0,2,4,0,3,0,2,2,2,0,0,0,0,2,2,2,2,3,2,0,0,0,0,0,0,0,0,0,2,4,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, };
從以上數(shù)據(jù)我們看到,一個文件里面可以包含若干個地圖的數(shù)據(jù),而每個地圖的開始我們可以定義“[g] ”這樣的字段來標識開始,其中的g表示地圖的序號,接著就是地圖的數(shù)據(jù)內(nèi)容實體,設計好數(shù)據(jù)的存儲格式后,剩下的工作就是將這些數(shù)據(jù)圖像展現(xiàn)在屏幕上,并實現(xiàn)交互,對于整個游戲區(qū)域的繪制,這里仍采用分塊繪制的方法,將整個游戲區(qū)域分成若干個很小的塊狀區(qū)域(如以上介紹),然后根據(jù)該區(qū)域在地圖中對應存儲位置的狀態(tài)值繪制其圖像,最后將這些方塊組合就構(gòu)成了整個游戲區(qū)域,圖10所示為該函數(shù)的流程圖實現(xiàn)。
圖10 地圖構(gòu)建流程
對于游戲區(qū)域的每個方塊,函數(shù)體都根據(jù)其所對應位置的狀態(tài)值調(diào)用相應的函數(shù)進行繪制,并在繪制直線時先計算出該方塊區(qū)域所在游戲區(qū)域的位置(左上角的坐標位置)。
3.2.2 物體移動的算法設計
大多數(shù)的游戲都是通過與用戶的交互并根據(jù)具體情況來做相應的運算處理的,在整個推箱子的游戲過程中,用戶總是通過鍵盤操作界面的顯示來實現(xiàn)交互。下面就從不同的角度來分析這個游戲的特性。
假設:游戲過程中的某一瞬間,工人在某個區(qū)域,此時游戲接收到用戶的按鍵動作指示并按照游戲規(guī)則判斷出該動作應該做出的響應。該響應是在沒有違反游戲規(guī)則的情況下使工人執(zhí)行用戶指示的運動,對違反游戲規(guī)則的指示則不予以響應。分析了工人將會遇到的所有情況,以便歸納出動作的算法。圖11:
圖11 工人移動狀態(tài)分析示意圖
圖中的符號含義如下所示。
假設移動趨勢方向向右,其他方位移動趨勢的情況也可以通過變化坐標方向,轉(zhuǎn)為上面向右的情況。上圖列出工人可能遇到的所有情況,在前面3種情況中,只要根據(jù)前言的物件就可以判斷出工人是否可以移動了(按照指示方向移動),移動后的位置狀態(tài)數(shù)據(jù)只改變兩個區(qū)域;而第4種情況是工人的前方為箱子,需要深入判斷箱子前方的狀態(tài)才能判斷出工人是否可以移動。所以要完全判斷出操作指示是否可執(zhí)行,需要 2個工人前方的位置狀態(tài)值,移動后的位置狀態(tài)數(shù)據(jù)改變了三個區(qū)域。而要判斷位置狀態(tài)得出執(zhí)行動作,
則需要按照前面分析工人遇到的所有情況去處理,接下來就可以實現(xiàn)這些子模塊了。包括以下兩個方面:
(1) 鍵盤操作指示采集(用戶交互),見中斷服務程序。
(2) 人和箱子的移動判斷
函數(shù)體對方向按鍵的處理部分,處理函數(shù)首先要根據(jù)移動的趨勢計算出工人當前位置的前兩個區(qū)域的位置。其具體實現(xiàn)流程如圖12:
圖12 人和箱子的移動判斷流程
本文以經(jīng)典的推箱子游戲規(guī)則為基礎(chǔ),構(gòu)建了相應的硬件平臺,并通過若干子地圖構(gòu)建整個游戲區(qū)域,根據(jù)操作規(guī)律設計了靈活的控制算法,通過TS160128點陣式液晶為載體顯示數(shù)據(jù),最后采用 C語言進行軟件設計。測試結(jié)果表明,本設計達到了具有人性化的操作和美觀的頁面效果。
[1] 樊永顯,許永,張向文,潘明,黃冬梅.基于STC89C54RC/RD+單片機的游戲系統(tǒng)設計[J] .湖南工業(yè)大學學報,2007,(05):66-69.
[2] 饒慶和.MCS-51單片機實用技術(shù)[M] .電子工業(yè)出版社,2003.4.
[3] 樓然苗等.51系列單片機設計實例[M] .北京航天航空大學出版社,2003.3.
[4] 李群芳等.單片微型計算機與接口技術(shù)(第 2版) [M] .電子工業(yè)出版社,2005.1.
[5] 郭勇等.Protel 99 SE印制電路板設計教程.機械工業(yè)出版社[M] ,2004.6.
[6] 張昊曄.基于無線傳輸?shù)挠螒驒C操縱系統(tǒng)設計[J] .信息技術(shù),2008,(07):159-161.
[7] 羅偉堅.Visual C++經(jīng)典游戲程序設計[M] .人民郵電出版社,2006.2.``