游戲不僅能開(kāi)發(fā)人的智力,使人頭腦反應靈敏,還能滿(mǎn)足人的精神需求(如冒險、創(chuàng )造力、情感等),極具娛樂(lè )性和趣味性,深受人們的喜愛(ài)。隨著(zhù)消費類(lèi)電子產(chǎn)業(yè)的蓬勃發(fā)展,越來(lái)越多的嵌入式電子產(chǎn)品走進(jìn)了千家萬(wàn)戶(hù),催生出了諸如GBA(GameBoyAdvance)、PSP(Play-StationPortabk)以及最近才在我國上市的iPad等一大批專(zhuān)業(yè)的并且銷(xiāo)量驚人的明星級移動(dòng)娛樂(lè )游戲設備。 然而上述游戲平臺通常造價(jià)昂貴,且不具有開(kāi)放性。例如備受推崇的PSP,開(kāi)發(fā)授權問(wèn)題和昂貴的專(zhuān)用開(kāi)發(fā)套件(軟硬件)使得PSP游戲的開(kāi)發(fā)門(mén)檻很高。這在很大程度上限制了這些游戲平臺的普及。如果利用通用的處理器和常用的嵌入式操作系統(如WinCE、Linux等)構建一種基于以太網(wǎng)或者無(wú)線(xiàn)以太網(wǎng)的便攜式的游戲機。則可以吸引大量熟悉C/C++嵌入式編程的工程師或發(fā)燒友制作出各種精彩的游戲,這必將極大地推動(dòng)這種游戲平臺的普及。而且將平臺進(jìn)行功能裁剪和批量生產(chǎn)后成本較低,對于中低收入人群來(lái)說(shuō)將是極佳選擇,市場(chǎng)潛力無(wú)窮。 本文詳述了這種游戲平臺的硬件構建、互聯(lián)對戰游戲開(kāi)發(fā)框架和流程,以及從Win32到WinCE進(jìn)行代碼移植的整個(gè)開(kāi)發(fā)過(guò)程,并記錄了開(kāi)發(fā)過(guò)程中積累的經(jīng)驗,具有很高的借鑒價(jià)值。 1硬件平臺 硬件平臺架構如圖1所示。 ![]() S3C2410是Samsung公司推出的16/32位RISC處理器,為手持設備和一般類(lèi)型應用提供了低價(jià)格、低功耗、高性能小型微控制器的解決方案。 S3C2410采用了ARM920T內核,0.18μm工藝的CMOS標準宏單元和存儲器單元。它的低功耗、精簡(jiǎn)和出色的全靜態(tài)設計特別適用于對低成本和功耗敏感的應用。ARM920T實(shí)現了MMU,AMBABUS和Harvard高速緩沖體系結構。這一結構具有獨立的16kB的指令Cache和16kB數據Cache,每個(gè)都由8字長(cháng)的行構成。 2套接字編程 2.1WinSock基礎 WinSock是WindowsSockets的縮寫(xiě),是Windows環(huán)境下廣泛應用的、開(kāi)放的、支持多種協(xié)議的網(wǎng)絡(luò )編程接口規范。這里主要使用TCP/IP協(xié)議族實(shí)現通信。 基于TCP/IP的套接字有流式套接字(SOCK_STREAM)、數據報式套接字(SOCK_DGRAM)、原始式套接字(SOCK_RAW)3種類(lèi)型,如圖2所示。 ![]() TCP協(xié)議是面向連接的網(wǎng)絡(luò )協(xié)議,它的連接步驟較多,而且當檢測到數據包丟失或錯誤時(shí),會(huì )要求發(fā)送端重新發(fā)送,這樣一來(lái)就不可避免地引起了傳輸延時(shí)。 UDP協(xié)議面向無(wú)連接服務(wù),每個(gè)分組都攜帶有完整的目的地址,操作簡(jiǎn)單,且無(wú)傳輸延遲,比較適合要求不高的游戲通信。它的通信時(shí)序如圖3所示。 ![]() 2.2應用程序接口函數 1)加載套接字庫AfxSocketlnit() 布爾型,參數缺省值為NULL,在程序結束前自動(dòng)調用WSACleanup清除套接字。 2)創(chuàng )建套接字socket() 用于創(chuàng )建指定類(lèi)型的套接字,流式(TCP協(xié)議)SOCK_STREAM或數據報式(UDP協(xié)議)SOCK_DGRAM。 3)綁定本地地址bind() 將套接字地址(包括本地主機地址和本地端口地址)與所創(chuàng )建的套接字號聯(lián)系起來(lái),即將名字賦予套接字,以指定本地半相關(guān)。 4)接收recvfrom() 在套接字指定的已連接的數據報或流套接字上接收輸入數據。 5)發(fā)送sendto() 在套接字指定的已連接的數據報或流套接字上發(fā)送輸出數據。 3Win32下五子棋程序設計 3.1游戲設計思路 游戲開(kāi)始前有一系列引導步驟,讓用戶(hù)選擇游戲模式,并作相應的初始連接,如圖4所示。這些引導步驟可通過(guò)添加一系列對話(huà)框資源來(lái)實(shí)現。完成之后進(jìn)入選擇的游戲模式。 ![]() 對于單人五子棋游戲,即人機對戰,只需要一個(gè)應用程序。當用戶(hù)鼠標左擊棋盤(pán)時(shí),程序先在相應位置處畫(huà)棋子,然后執行電腦方策略,實(shí)現對戰。 對于雙人五子棋游戲,則需要先運行一個(gè)服務(wù)器端程序,然后兩個(gè)用戶(hù)分別運行一個(gè)客戶(hù)端程序,并與此服務(wù)器相連。游戲進(jìn)行過(guò)程中,由服務(wù)器執行游戲策略,客戶(hù)端程序只負責采集鼠標信息和顯示棋子。我們讓用戶(hù)A在游戲平臺A上運行服務(wù)器端程序,緊接著(zhù)運行客戶(hù)端程序,并與服務(wù)器建立Socket連接;然后告訴用戶(hù)B服務(wù)器的IP地址,讓其在平臺B上運行客戶(hù)端程序,并與服務(wù)器建立Socket連接;連接成功后就可以開(kāi)始游戲了。 3.2單人游戲 建立MFC工程,選擇創(chuàng )建單文檔類(lèi)型的應用程序。添加對話(huà)框資源用于選擇游戲模式,并在View類(lèi)構造函數中DoModal()。 進(jìn)入單人模式后的程序開(kāi)發(fā)流程如圖5所示。 ![]() 對于某些步驟需要作詳細說(shuō)明: ![]() 3)判斷游戲是否結束 在Doc類(lèi)中定義私有性質(zhì)的成員變量intstate[15][10];,用于記錄棋盤(pán)上每一格的狀態(tài):無(wú)棋(值為0)、用戶(hù)方棋(值為1)、電腦方棋(值為2),初始值是0。游戲過(guò)程中,某一方落棋后立即給state數組對應成員賦值,下標可由鼠標左鍵消息響應函數的CPointpoint參數轉換而來(lái)。 對于棋盤(pán)上每一個(gè)坐標點(diǎn)(i,j),沿東西、南北、東南西北、東北西南四個(gè)方向掃描五個(gè)沿途點(diǎn)的狀態(tài)值,若發(fā)現五個(gè)相同狀態(tài)相連,則該狀態(tài)(用戶(hù)方或電腦方)的棋手獲勝,游戲結束。 4)電腦方下棋策略 對于棋盤(pán)上每一個(gè)坐標點(diǎn)(i,j),掃描它的狀態(tài)值state[j],一經(jīng)發(fā)現不為0,就以此點(diǎn)為起點(diǎn),沿東、南、西、北、東南、西南、東北、西北8個(gè)方向搜索5個(gè)棋位。 事先定義針對每個(gè)點(diǎn)、每個(gè)方向的8個(gè)整型數組(初始值賦為0): ![]() 對于坐標點(diǎn)(i,j),搜索過(guò)程中若遇到具有相同狀態(tài)的點(diǎn)(m,n),則對應方向數組的[j]成員的值增加,遇到不同狀態(tài)點(diǎn)則減小。保存8個(gè)中絕對值最大的。 上述操作完后,比較所有點(diǎn)存的值,絕對值最大的說(shuō)明以該點(diǎn)起始的某個(gè)方向己方棋子相連較多,或者對方棋子相連較多,最適合落子。 3.3雙人游戲 從游戲開(kāi)始到結束,客戶(hù)端與服務(wù)器的交互過(guò)程如圖6所示。 ![]() 3.3.1服務(wù)器端程序 創(chuàng )建基于對話(huà)框的MFC工程。 在A(yíng)pp類(lèi)的BOOLInitInstance()中加載套接字庫:AfxSocketInit(); 在Dlg類(lèi)的BOOLOnInitDialog()中初始化套接字,包括新建和綁定套接字:socket()、bind(); 在對話(huà)框上畫(huà)兩個(gè)按鈕控件:“連接用戶(hù)”和“開(kāi)始游戲”。 開(kāi)發(fā)流程如圖7所示。 ![]() 對于某些步驟需要作詳細說(shuō)明: 1)開(kāi)辟線(xiàn)程 如果讓服務(wù)器一直recvfrom(),則主線(xiàn)程將一直執行此函數,造成消息擁堵,從而導致其他事件難以響應,因此選擇開(kāi)辟新線(xiàn)程在后臺接收客戶(hù)端信息,合理分配系統資源。 開(kāi)辟線(xiàn)程的過(guò)程如下: ①定義要傳送給線(xiàn)程的全局性質(zhì)的結構體RECVPARAM,成員為Dlg類(lèi)指針類(lèi)型變量。 ②定義RECVPARAM結構體變量pRecvParam,并把當前工程的Dlg類(lèi)指針賦給其成員;創(chuàng )建線(xiàn)程,把pRecvParam傳遞給線(xiàn)程;然后關(guān)閉線(xiàn)程。 ③在線(xiàn)程回調函數中接收傳遞來(lái)的變量pRecvParam,然后就可以調用Dlg類(lèi)的成員來(lái)實(shí)現功能。 2)信息格式 ①客戶(hù)端連接信息 格式隨意的字符串,目的是讓服務(wù)器端接收到數據,從而發(fā)現客戶(hù)端IP地址。我們發(fā)的是“0000”。 ②客戶(hù)端下棋信息 信息格式:用戶(hù)標識(1位)、落子橫坐標(2位)、落子縱坐標(2位)。 其中,用戶(hù)標識位1代表先手(白方),0代表后手(黑方)。 ③服務(wù)器端發(fā)送信息 指導客戶(hù)端畫(huà)棋子以及顯示狀態(tài)。 信息格式:用戶(hù)標識(1位)、落子橫坐標(2位)、落子縱坐標(2位)、游戲狀態(tài)(1位)。 其中,前5位與從客戶(hù)端接收的相同:游戲狀態(tài)位1表示游戲結束,0表示游戲未結束。 3.3.2客戶(hù)端程序 創(chuàng )建基于單文檔的MFC工程。 在A(yíng)pp類(lèi)的BOOLInitInstance()中加載套接字庫:AfxSocketInit(); 添加對話(huà)框資源CDlgMode,用于選擇游戲模式: 添加對話(huà)框資源CDlgLink,用于連接服務(wù)器;并在其上畫(huà)一個(gè)IP地址控件,用于填寫(xiě)服務(wù)器IP;在確定按鈕的響應函數中初始化套接字socket()、bind(),并向服務(wù)器發(fā)送連接請求sendto(); 在View類(lèi)構造函數中將模式選擇對話(huà)框DoModal(),選擇進(jìn)入雙人模式,之后的程序開(kāi)發(fā)流程如圖8所示。 ![]() 4代碼移植 4.1WindowsCE簡(jiǎn)介 WindowsCE是基于Win32API重新開(kāi)發(fā)的新型信息設備平臺,具有模塊化、結構化和基于Win32應用程序接口以及與處理器無(wú)關(guān)等特點(diǎn)。大量用戶(hù)對于Windows操作方式和編程的熟悉,是WindowsCE作為嵌入式操作系統迅速發(fā)展的最大的優(yōu)勢,也是選擇的原因。 4.2代碼移植 安裝WinCE5.0的標準SDK,在VS2008開(kāi)發(fā)環(huán)境下創(chuàng )建智能設備的MFC工程,選擇基于對話(huà)框或單文檔的應用程序,并選擇剛剛安裝的標準SDK平臺。工程創(chuàng )建完成后,將在Win32下開(kāi)發(fā)的代碼按同樣的方式轉移過(guò)來(lái),然后編譯,修改錯誤。 WinCE是Unicode環(huán)境,盡管WinCE支持ASCII功能來(lái)進(jìn)行文件交換,但是WinCE的本地文件格式是Unicode。所以,要將字符串轉換為UmcMe才能使用。另外就是代碼移植過(guò)程中丟三落四的粗心錯誤。以下列舉代碼移植過(guò)程中遇到的問(wèn)題及解決方法: 1)某些函數發(fā)生變化,不再識別ASCII碼字符或字符串,例如MessageBox,其字符串參數必須經(jīng)_T(“”)轉換成Unicode;另外Cstring類(lèi)不要輕易使用; 2)某些功能使用不同函數,例如整型轉字符串型,由函數itoa變?yōu)開(kāi)itoa_s; 3)智能設備項目中沒(méi)有IP地址控件,用編輯框代替,多了些字符串拼接、轉換的工作; 4)不要忘了使客戶(hù)端與服務(wù)器端的端口號保持一致。 5硬件調試及結果 5.1PC與ARM板連接 1)平臺連接 通過(guò)網(wǎng)線(xiàn)相連,然后指定網(wǎng)關(guān)地址和IP地址。指定方法如下:本地連接一>點(diǎn)右鍵看屬性—>雙擊“Internet協(xié)議(TCP/IP)”一>使用下面的IP地址,自己填寫(xiě)即可。特別注意,當兩臺機器直接用網(wǎng)線(xiàn)相連而不使用路由器時(shí),必須同一個(gè)網(wǎng)關(guān)才可實(shí)現數據交換?赏ㄟ^(guò)ping命令測試網(wǎng)絡(luò )是否連通。 2)運行游戲 利用同步軟件MicrosoftAcfiveSync將開(kāi)發(fā)的WinCE5.0下游戲程序傳到ARM平臺中,即可在上面運行。 5.2ARM板與ARM板連接 與上述過(guò)程類(lèi)同。 6結論 經(jīng)實(shí)際操作驗證,這種多人游戲開(kāi)發(fā)方式(多線(xiàn)程)使得資源占用率很低,S3C2410處理器完全可以勝任,整個(gè)游戲運行流暢。游戲平臺可以通過(guò)有線(xiàn)方式互聯(lián),也可以通過(guò)無(wú)線(xiàn)方式互聯(lián),操作簡(jiǎn)單,使用方便。而且這種游戲平臺具有很高的開(kāi)放性,利用上述的開(kāi)發(fā)框架可以輕易開(kāi)發(fā)出更多更好玩的游戲。 |