日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一套跨平臺五子棋網(wǎng)游的開發(fā)經(jīng)歷

閑來無事,因自己想要在服務(wù)器開發(fā)方面進(jìn)行更深入的學(xué)習(xí),積累更豐富的經(jīng)驗(yàn)。決定寫一套網(wǎng)絡(luò)游戲的c/s。

昌圖網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),昌圖網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為昌圖1000多家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站制作要多少錢,請找那個售后服務(wù)好的昌圖做網(wǎng)站的公司定做!

因?yàn)橹饕康氖欠?wù)器的開發(fā),因此游戲我選用規(guī)則較為簡單、畫面特效沒有要求的回合制游戲:五子棋。我曾經(jīng)在剛接觸編程的時(shí)候自己在控制臺 下做過這個游戲,當(dāng)時(shí)寫的ai特nb我自己根本下不贏他。確定是制作五子棋了, 但是還要滿足跨平臺的特性,畢竟移動互聯(lián)時(shí)代,得終端者得天下。游戲做成全平臺才能更好的將各種玩家聚集在一起??缙脚_?b/s是人們通常會第一個想到的 跨平臺方式,的確現(xiàn)在市面上有很多基于b/s的頁游,大部分使用的是flash作為游戲引擎。但手機(jī)上很少有人使用瀏覽器玩游戲。(其實(shí)根本不會 flash,html也爛得很,曾經(jīng)給別人用php做的數(shù)據(jù)管理網(wǎng)站根本就沒有像樣的界面)于是選擇了c++的跨平臺游戲引擎cocos2dx,這引擎簡 單好用,而且因?yàn)槭莄++作為游戲邏輯,移植特方便,以前也用過這個引擎(某比賽)。最終選用的版本是cocos2d-x 3.4。

既然是網(wǎng)絡(luò)游戲的服務(wù)器,那么就得高效,而且是在linux下,因此我選epoll模型進(jìn)行服務(wù)端的開發(fā),epoll的部分寫在這篇文章里:epoll模型的理解與封裝實(shí)現(xiàn),使用的linux系統(tǒng)為CENT OS 6.4,內(nèi)核為linux2.6。

關(guān)于游戲開發(fā)步驟的思考:

按照自己以前習(xí)慣的套路來說,通信方式與協(xié)議的設(shè)計(jì)應(yīng)該是放在首位的,然后是服務(wù)器、再到客戶端(沒有美工)。

而自己以前曾經(jīng)玩到很多的單機(jī)游戲,更新版本后,游戲便增加了網(wǎng)絡(luò)游戲功能。這似乎說明了很多游戲與網(wǎng)絡(luò)協(xié)議之間是相互獨(dú)立的。甚至網(wǎng)絡(luò)協(xié)議是根據(jù)實(shí)際的游戲邏輯設(shè)計(jì)的,而不是游戲根據(jù)協(xié)議來設(shè)計(jì)自身的邏輯。

最終決定先把單機(jī)的版本做出來。于是制定了如下的開發(fā)流程:

1、游戲的算法與數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)與實(shí)現(xiàn)

2、游戲交互設(shè)計(jì)與實(shí)現(xiàn)

3、單機(jī)游戲的實(shí)現(xiàn)

4、游戲通信協(xié)議設(shè)計(jì)

5、服務(wù)器實(shí)現(xiàn)(不可忽略掉的重點(diǎn),自己寫游戲的目的)

6、網(wǎng)絡(luò)游戲功能實(shí)現(xiàn)

7、平臺移植

1、游戲的算法與數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)與實(shí)現(xiàn):

五子棋這個游戲是一個二維平面上的游戲,我們將棋盤看做一個數(shù)組,每一個格子的狀態(tài)分為兩種:沒棋和有棋,有棋因不同玩家而區(qū)別(數(shù)量不限,可直接作為多人多子棋的游戲基類)

代碼:

 
 
  1. //Chess.h 
  2. #ifndef  _CHESS_H_ 
  3. #define  _CHESS_H_ 
  4. #include "cocos2d.h" 
  5. USING_NS_CC; 
  6.  
  7. //下棋坐標(biāo)狀態(tài)結(jié)構(gòu)體 
  8. struct Chesspos 
  9.     int x,y; 
  10.     int player;//該步數(shù)所屬玩家 
  11.     Chesspos(){}; 
  12.     Chesspos(int px,int py,int pp) 
  13.     { 
  14.         x=px; 
  15.         y=py; 
  16.         player=pp; 
  17.     } 
  18. }; 
  19.  
  20. class Chessway 
  21.     Chesspos *way;//路徑數(shù)組 
  22.     int totallen;//總長度 
  23.     int len;//當(dāng)前步數(shù) 
  24.  
  25. public: 
  26.     Chessway(int totalnum); 
  27.     ~Chessway(void); 
  28.     void setempty(); 
  29.     bool addway(int x,int y,int player);//添加步數(shù) 
  30.     int getstep(); 
  31.     Chesspos getnow(); 
  32. }; 
  33.  
  34. class Chess 
  35. public: 
  36.     Chess(int width,int heigh,int winlen=5,int playernum=2); 
  37.     ~Chess(void); 
  38.  
  39.     int **board; 
  40.     int w,h; 
  41.     int pnum; //palyer num 
  42.     int wlen; //how number can win 
  43.     Chessway *way; 
  44.     int playercnt;//player start at 1 
  45.     bool isgameend; 
  46.      
  47.     bool init(int width,int heigh,int winlen=5,int playernum=2); 
  48.     void exit(); 
  49.  
  50.     void restart(); 
  51.     bool nextstep(Chesspos np);//下棋,自動判斷玩家 
  52.     bool nextstep(int x,int y); 
  53.  
  54.     int getstatus(int x,int y);//獲取游戲狀態(tài) 
  55.  
  56.     bool checklen(int x,int y); 
  57.     int checkwin();//判斷游戲是否結(jié)束并返回勝利玩家 
  58. }; 
  59.  
  60.  
  61. #endif //_CHESS_H_ 

檢測勝利的邏輯很簡單:找到一個下有棋的位置,檢查這個位置下、右、左下、右下是否有連續(xù)相等的5個棋,即為游戲勝利。游戲一旦勝利是不可以繼續(xù)下棋的,所以只會有一個玩家勝利。下面給出判斷代碼:

 
 
  1. //Chess.cpp 
  2. //勝利檢測代碼 
  3. bool Chess::checklen(int x,int y) 
  4.     for(int i=1;i
  5.     { 
  6.         if(x+i>=w) 
  7.         { 
  8.             break; 
  9.         } 
  10.         if(board[x+i][y]!=board[x][y]) 
  11.         { 
  12.             break; 
  13.         } 
  14.         if(i==wlen-1) 
  15.         { 
  16.             return true; 
  17.         } 
  18.     } 
  19.  
  20.     for(int i=1;i
  21.     { 
  22.         if(y+i>=h) 
  23.         { 
  24.             break; 
  25.         } 
  26.         if(board[x][y+i]!=board[x][y]) 
  27.         { 
  28.             break; 
  29.         } 
  30.         if(i==wlen-1) 
  31.         { 
  32.             return true; 
  33.         } 
  34.     } 
  35.  
  36.     for(int i=1;i
  37.     { 
  38.         if(x+i>=w||y+i>=h) 
  39.         { 
  40.             break; 
  41.         } 
  42.         if(board[x+i][y+i]!=board[x][y]) 
  43.         { 
  44.             break; 
  45.         } 
  46.         if(i==wlen-1) 
  47.         { 
  48.             return true; 
  49.         } 
  50.     } 
  51.  
  52.     for(int i=1;i
  53.     { 
  54.         if(x-i<0||y+i>=h) 
  55.         { 
  56.             break; 
  57.         } 
  58.         if(board[x-i][y+i]!=board[x][y]) 
  59.         { 
  60.             break; 
  61.         } 
  62.         if(i==wlen-1) 
  63.         { 
  64.             return true; 
  65.         } 
  66.     } 
  67.     return false; 
  68. int Chess::checkwin() 
  69.     for(int i=0;i
  70.     { 
  71.         for(int j=0;j
  72.         { 
  73.             if(board[i][j]) 
  74.             { 
  75.                 if(checklen(i,j)) 
  76.                 { 
  77.                     isgameend=true; 
  78.                     return board[i][j]; 
  79.                 } 
  80.             } 
  81.         } 
  82.     } 
  83.     return 0; 

#p#

2、游戲交互設(shè)計(jì)與實(shí)現(xiàn)

涉及到游戲交互,這里就要使用到游戲引擎了。首先需要把游戲的一些圖片資源大致搞定,這里用畫圖這畫了幾個不堪入目的圖片資源:

別看這畫的丑,我可是用鼠標(biāo)和window自帶的畫圖畫出來的,到時(shí)候在游戲中看起來是毫無違和感的(筆者小學(xué)就會畫H漫了)。

這里就要用到cocos2dx的東西了。首先為每一個下棋的格子設(shè)計(jì)一個個塊狀的節(jié)點(diǎn),然后設(shè)計(jì)游戲主體布景層:

 
 
  1. class ChessNode:public Node
    class ChessMain:public Layer 

作為游戲棋盤,每一個格子的形態(tài)都是一樣的,我只需要將它們拼接成矩陣就成了一個完整的棋盤。因此在游戲布景層里,我開了一個Vector 的ChessNode,將其依次緊湊地排列在屏幕上。在游戲初始狀態(tài)時(shí),chess_1.png、chess_2.png是不會顯示的,如圖(截圖我直接 使用現(xiàn)成游戲的截圖):

這樣的棋盤看起來是不是很沒有違和感?

當(dāng)下棋后,就可以把對應(yīng)的棋圖顯示出來:

后面發(fā)現(xiàn)好像真正的下棋是下在十字交叉處的。。

這部分的注意事項(xiàng)主要就在于觸摸檢測與棋盤屏幕大小。觸摸的話計(jì)算相對棋盤布景層的坐標(biāo)可以得出下棋的位置。棋盤就以靜態(tài)值480px為標(biāo)準(zhǔn),在其他地方調(diào)用的時(shí)候縮放即可。

 
 
  1. #ifndef  _CHESSMAIN_H_ 
  2. #define  _CHESSMAIN_H_ 
  3. #include "cocos2d.h" 
  4. #include "Chess.h" 
  5. USING_NS_CC; 
  6.  
  7.  
  8. #define defaultwinsize 480.0 
  9. #define chesspicsize 50.0 
  10.  
  11.  
  12. static Point winsize; 
  13.  
  14. class ChessNode:public Node 
  15.     public: 
  16.     ChessNode(int playernum=2); 
  17.  
  18.     Vector chesspicarr; 
  19.     Sprite * basepic; 
  20. }; 
  21.  
  22. class ChessMain:public Layer 
  23. public: 
  24.  
  25.     Chess *chessdata; 
  26.  
  27.     Vector basenode; 
  28.  
  29.     virtual bool init(); 
  30.     //virtual void onEnter(); 
  31.  
  32.     void restart(); 
  33.     void updateone(int x,int y); 
  34.     void updateall(); 
  35.  
  36.     bool nextstep(int x,int y); 
  37.     int  checkwin(); 
  38.  
  39.  
  40.     CREATE_FUNC(ChessMain); 
  41. }; 
  42.  
  43. #endif //_CHESSMAIN_H_
 
 
  1. #include "ChessMain.h" 
  2.  
  3. ChessNode::ChessNode(int playernum) 
  4.     basepic=Sprite::create("chess_base_1.png"); 
  5.     basepic->setAnchorPoint(ccp(0,0)); 
  6.     this->addChild(basepic); 
  7.      
  8.     char addname[]="chess_1.png"; 
  9.     for(int i=0;i
  10.     { 
  11.         addname[6]='0'+i+1; 
  12.         auto newsprite=Sprite::create(addname); 
  13.         chesspicarr.pushBack(newsprite); 
  14.         chesspicarr.back()->setAnchorPoint(ccp(0,0)); 
  15.         this->addChild(chesspicarr.back()); 
  16.          
  17.     } 
  18.  
  19. bool ChessMain::init() 
  20.     winsize=Director::sharedDirector()->getWinSize(); 
  21.  
  22.     //默認(rèn)值棋盤 
  23.     chessdata=new Chess(15,15); 
  24.  
  25.     for(int i=0;iw;i++) 
  26.     { 
  27.         for(int j=0;jh;j++) 
  28.         { 
  29.             basenode.pushBack(new ChessNode()); 
  30.              
  31.             basenode.back()->setScale((defaultwinsize/chessdata->h)/chesspicsize); 
  32.             basenode.back()->setPosition( 
  33.                 ccp(defaultwinsize/chessdata->w*i,defaultwinsize/chessdata->h*j) 
  34.                 ); 
  35.             basenode.back()->setAnchorPoint(ccp(0,0)); 
  36.              
  37.             this->addChild(basenode.back()); 
  38.         } 
  39.     } 
  40.  
  41.     restart(); 
  42.  
  43.      
  44.  
  45.     return true; 
  46. /* 
  47. void ChessMain::onEnter() 
  48.     ; 
  49. */ 
  50. void ChessMain::restart() 
  51.     chessdata->restart(); 
  52.     updateall(); 
  53. void ChessMain::updateone(int x,int y) 
  54.     for(int i=0;ipnum;i++) 
  55.     { 
  56.         if(chessdata->getstatus(x,y)==i+1) 
  57.         { 
  58.             basenode.at(x*chessdata->w+y)-> 
  59.                 chesspicarr.at(i)->setVisible(true); 
  60.         } 
  61.         else 
  62.         { 
  63.             basenode.at(x*chessdata->w+y)-> 
  64.                 chesspicarr.at(i)->setVisible(false); 
  65.         } 
  66.     } 
  67. void ChessMain::updateall() 
  68.     for(int i=0;iw;i++) 
  69.     { 
  70.         for(int j=0;jh;j++) 
  71.         { 
  72.             updateone(i,j); 
  73.         } 
  74.     } 
  75.  
  76. bool ChessMain::nextstep(int x,int y) 
  77.     if(chessdata->isgameend) 
  78.     { 
  79.         return false; 
  80.     } 
  81.     if(!chessdata->nextstep(x,y)) 
  82.     { 
  83.         return false; 
  84.     } 
  85.     updateone(x,y); 
  86.     checkwin(); 
  87.  
  88.     return true; 
  89.  
  90. int ChessMain::checkwin() 
  91.     return chessdata->checkwin(); 
  92.  
  93. /* 
  94. bool ChessMain::onTouchBegan(Touch *touch, Event *unused_event) 
  95.     Point pos=convertTouchToNodeSpace(touch); 
  96.  
  97.     if(pos.x>defaultwinsize||pos.y>defaultwinsize) 
  98.     { 
  99.         return false; 
  100.     } 
  101.     int x=chessdata->w*(pos.x/defaultwinsize); 
  102.     int y=chessdata->h*(pos.y/defaultwinsize); 
  103.  
  104.     return nextstep(x,y); 
  105. */ 

這里的觸摸函數(shù)會由以后ChessMain的子類重寫。

#p#

3、單機(jī)游戲的實(shí)現(xiàn)

單機(jī)游戲,只需寫好對手的AI邏輯即可。幸好是五子棋不是圍棋,AI很好寫,能很快計(jì)算出必勝態(tài)。由于自己主要目的是寫網(wǎng)絡(luò)端。因此我把單機(jī)功能實(shí)現(xiàn)后并沒有寫AI,把接口留著的,只接了一個隨機(jī)函數(shù),等以后有閑情把AI邏輯加上。

總的來說這部分就是加上了進(jìn)入游戲前的菜單以及單機(jī)游戲的選項(xiàng)和游戲結(jié)束的對話框:

 
 
  1. #include "ChessMain.h" 
  2.  
  3. ChessNode::ChessNode(int playernum) 
  4.     basepic=Sprite::create("chess_base_1.png"); 
  5.     basepic->setAnchorPoint(ccp(0,0)); 
  6.     this->addChild(basepic); 
  7.      
  8.     char addname[]="chess_1.png"; 
  9.     for(int i=0;i
  10.     { 
  11.         addname[6]='0'+i+1; 
  12.         auto newsprite=Sprite::create(addname); 
  13.         chesspicarr.pushBack(newsprite); 
  14.         chesspicarr.back()->setAnchorPoint(ccp(0,0)); 
  15.         this->addChild(chesspicarr.back()); 
  16.          
  17.     } 
  18.  
  19. bool ChessMain::init() 
  20.     winsize=Director::sharedDirector()->getWinSize(); 
  21.  
  22.     //默認(rèn)值棋盤 
  23.     chessdata=new Chess(15,15); 
  24.  
  25.     for(int i=0;iw;i++) 
  26.     { 
  27.         for(int j=0;jh;j++) 
  28.         { 
  29.             basenode.pushBack(new ChessNode()); 
  30.              
  31.             basenode.back()->setScale((defaultwinsize/chessdata->h)/chesspicsize); 
  32.             basenode.back()->setPosition( 
  33.                 ccp(defaultwinsize/chessdata->w*i,defaultwinsize/chessdata->h*j) 
  34.                 ); 
  35.             basenode.back()->setAnchorPoint(ccp(0,0)); 
  36.              
  37.             this->addChild(basenode.back()); 
  38.         } 
  39.     } 
  40.  
  41.     restart(); 
  42.  
  43.      
  44.  
  45.     return true; 
  46. /* 
  47. void ChessMain::onEnter() 
  48.     ; 
  49. */ 
  50. void ChessMain::restart() 
  51.     chessdata->restart(); 
  52.     updateall(); 
  53. void ChessMain::updateone(int x,int y) 
  54.     for(int i=0;ipnum;i++) 
  55.     { 
  56.         if(chessdata->getstatus(x,y)==i+1) 
  57.         { 
  58.             basenode.at(x*chessdata->w+y)-> 
  59.                 chesspicarr.at(i)->setVisible(true); 
  60.         } 
  61.         else 
  62.         { 
  63.             basenode.at(x*chessdata->w+y)-> 
  64.                 chesspicarr.at(i)->setVisible(false); 
  65.         } 
  66.     } 
  67. void ChessMain::updateall() 
  68.     for(int i=0;iw;i++) 
  69.     { 
  70.         for(int j=0;jh;j++) 
  71.         { 
  72.             updateone(i,j); 
  73.         } 
  74.     } 
  75.  
  76. bool ChessMain::nextstep(int x,int y) 
  77.     if(chessdata->isgameend) 
  78.     { 
  79.         return false; 
  80.     } 
  81.     if(!chessdata->nextstep(x,y)) 
  82.     { 
  83.         return false; 
  84.     } 
  85.     updateone(x,y); 
  86.     checkwin(); 
  87.  
  88.     return true; 
  89.  
  90. int ChessMain::checkwin() 
  91.     return chessdata->checkwin(); 
  92.  
  93. /* 
  94. bool ChessMain::onTouchBegan(Touch *touch, Event *unused_event) 
  95.     Point pos=convertTouchToNodeSpace(touch); 
  96.  
  97.     if(pos.x>defaultwinsize||pos.y>defaultwinsize) 
  98.     { 
  99.         return false; 
  100.     } 
  101.     int x=chessdata->w*(pos.x/defaultwinsize); 
  102.     int y=chessdata->h*(pos.y/defaultwinsize); 
  103.  
  104.     return nextstep(x,y); 
  105. */

現(xiàn)在一個能玩的游戲已經(jīng)完成,接下來是重點(diǎn)的網(wǎng)絡(luò)部分。

#p#

4、游戲通信協(xié)議設(shè)計(jì)

因?yàn)槭荘C、手機(jī)都能玩的游戲,考慮到糟糕的手機(jī)網(wǎng)絡(luò)環(huán)境,通信采用客戶端單方發(fā)起請求,服務(wù)器回復(fù)的方式,使服務(wù)器不用考慮確保手機(jī)信號不好或IP變更的情況,類似于web方式。

游戲沒有設(shè)計(jì)固定的用戶,采用的是游戲每次向服務(wù)器申請一個游戲ID,使用這個游戲ID在互聯(lián)網(wǎng)上和其他用戶對戰(zhàn)。于是協(xié)議報(bào)文設(shè)計(jì)了兩種:普通請求/回復(fù)報(bào)文gamequest、游戲數(shù)據(jù)報(bào)文nextquest。

 
 
  1. #include  
  2. #include  
  3. #include  
  4.  
  5.  
  6. #define NEWID       (char)1 
  7. #define NEWGAME     (char)3 
  8. #define NEXTSTEP    (char)5 
  9. #define GETNEXTSTEP (char)6 
  10. #define GAMEEND     (char)10 
  11.  
  12. #define NEWID_FAIL       0 
  13. #define NEWID_SECC       1 
  14.  
  15. #define NEWGAME_FAIL     0 
  16. #define NEWGAME_ISFIRST  1 
  17. #define NEWGAME_ISSEC    2 
  18.  
  19. #define NEXTSTEP_FAIL    1 
  20. #define NEXTSTEP_SEC     1 
  21.  
  22. struct gamequest 
  23.     unsigned int id; 
  24.     char type; 
  25.     unsigned int data; 
  26. }; 
  27.  
  28. struct nextstephead 
  29.     unsigned int id; 
  30.     char type; 
  31.     char x; 
  32.     char y; 
  33.     char mac;//游戲數(shù)據(jù)校驗(yàn) 
  34.     short stepno; 
  35. }; 

NEWID:申請一個新的游戲ID的請求與回復(fù)

NEWGAME:申請開始游戲的請求與回復(fù)

NEXTSTEP:更新游戲?qū)謹(jǐn)?shù)據(jù)的請求與回復(fù)

GETNEXSTEP:獲取游戲?qū)謹(jǐn)?shù)據(jù)的請求與回復(fù)

GAMEEND:終止或結(jié)束游戲的請求

關(guān)于游戲請求與游戲?qū)謺r(shí)的通信,因?yàn)椴捎玫氖钦埱蠹踊貜?fù)的方式,服務(wù)器不能主動通知客戶端有新的游戲開始或是對手已經(jīng)喜下了下一步棋,因 此需要客戶端主動向服務(wù)器獲取相應(yīng)的信息。于是這部分被設(shè)計(jì)為客戶端定時(shí)向服務(wù)器發(fā)送更新數(shù)據(jù)的請求,服務(wù)器一旦接收到請求,就把通過該請求的TCP連接 發(fā)回去。這樣雖然增加了網(wǎng)絡(luò)的流量,但為了數(shù)據(jù)的穩(wěn)定性必須做出犧牲。好的是該協(xié)議報(bào)文很小,而且因?yàn)槭菍钟螒?,就算有幾萬人同時(shí)在玩,實(shí)際單位時(shí)間的 數(shù)據(jù)量也不會太多,最重要的是在處理并發(fā)數(shù)據(jù)的情況。

#p#

5、服務(wù)器實(shí)現(xiàn):

這是最重要最核心的部分。一個高效、穩(wěn)定的游戲服務(wù)器程序直接決定了游戲的體驗(yàn)。在實(shí)際的游戲服務(wù)器開 發(fā)中,游戲邏輯與網(wǎng)絡(luò)通信邏輯可能分工由不同的人員開發(fā)。因此,游戲邏輯與網(wǎng)絡(luò)通信邏輯應(yīng)在保證效率的情況下盡可能地實(shí)現(xiàn)低耦合。我這里雖然是獨(dú)立開發(fā) 的,是因?yàn)橛螒虻倪壿嫼芎唵?,但如果比如去開發(fā)一個像GTAOL這樣的游戲服務(wù)器,本來做網(wǎng)絡(luò)通信的人想要做出GTA的游戲邏輯那就相當(dāng)?shù)乩щy,需要寫處 理世界、物體、角色,還要和游戲端的邏輯一致,累成狗狗。

所以說游戲的邏輯與網(wǎng)絡(luò)的通信需要盡可能地獨(dú)立,就這個五子棋服務(wù)器而言,網(wǎng)絡(luò)通信端使用PPC、select、epoll都和游戲邏輯無 關(guān),只要能接收分類并交給游戲邏輯處理,并將游戲邏輯處理好的數(shù)據(jù)發(fā)出即可。該服務(wù)器選用的epoll實(shí)現(xiàn)的,因篇幅原因,網(wǎng)絡(luò)通信部分已經(jīng)在這篇文章中 說明清楚:epoll模型的理解封裝與應(yīng)用。

關(guān)于服務(wù)器的游戲邏輯,首先看看我們的服務(wù)器要做哪些事情:

1、用戶游戲ID的申請與管理

2、對局?jǐn)?shù)據(jù)的處理與管理

大致就以上這兩種事情。但是因?yàn)橛螒虻目蛻舳藬?shù)量很多,不同的客戶端之間進(jìn)行對局,必須要清晰地處理與管理這些數(shù)據(jù)。我這里建立了一個idpool,用于id的儲存于申請,以防發(fā)生錯誤給用戶分配無效或是重復(fù)的id。

對局?jǐn)?shù)據(jù)的處理與管理:

在兩個用戶都有id的情況下,雙方都能申請進(jìn)行游戲。這是服務(wù)端要做的就是匹配好這些用戶并通知這些用戶開始游戲。為方便說明,我先把代碼粘上來:

 
 
  1. #ifndef  _GAME_H_ 
  2. #define  _GAME_H_ 
  3.  
  4. #include 
  5. #include 
  6. #include 
  7. #include 
  8. #include 
  9. #include 
  10.  
  11. #include "ssock.h" 
  12. #include "gameprotocol.h" 
  13.  
  14. using namespace std; 
  15.  
  16. #define idpoollength 1000 
  17. #define datapoollength 50 
  18.  
  19. //鏈?zhǔn)絀Dpool 
  20. class idpool 
  21.     list ids; 
  22. public: 
  23.     idpool() 
  24.     { 
  25.         for(int i=1;i
  26.         { 
  27.             ids.push_back(i); 
  28.         } 
  29.     } 
  30.     unsigned getid() 
  31.     { 
  32.         if(ids.empty()) 
  33.         { 
  34.             return 0; 
  35.         } 
  36.         unsigned re=ids.front(); 
  37.         ids.pop_front(); 
  38.         return re; 
  39.     } 
  40.     void freeid(unsigned int x) 
  41.     { 
  42.         ids.push_front(x); 
  43.     } 
  44.  
  45. }; 
  46.  
  47. //對局匹配類 
  48. class p2p 
  49.     unsigned int with[idpoollength]; 
  50.     unsigned int info[idpoollength]; 
  51. public: 
  52.     p2p() 
  53.     { 
  54.         for(int i=0;i
  55.         { 
  56.             with[i]=i; 
  57.         } 
  58.     } 
  59.     bool ispair(unsigned int x1) 
  60.     { 
  61.         return with[x1]!=x1&&with[x1]!=0; 
  62.     } 
  63.     //設(shè)置為該id等待匹配 
  64.     void setwait(unsigned int x1) 
  65.     { 
  66.         with[x1]=0; 
  67.     } 
  68.     //自動匹配函數(shù) 
  69.     bool makepair(unsigned int x1) 
  70.     { 
  71.         for(int i=1;i
  72.         { 
  73.             if(with[i]==0&&x1!=i) 
  74.             { 
  75.                 setp2p(x1,i); 
  76.                 return true; 
  77.             } 
  78.         } 
  79.         return false; 
  80.     } 
  81.     //設(shè)置兩id匹配 
  82.     void setp2p(unsigned int x1,unsigned x2) 
  83.     { 
  84.         with[x1]=x2; 
  85.         with[x2]=x1; 
  86.         info[x1]=1; 
  87.         info[x2]=2; 
  88.     } 
  89.     //釋放匹配(單方向) 
  90.     void freep2p(unsigned int x1) 
  91.     { 
  92.         //with[with[x1]]=with[x1]; 
  93.         with[x1]=x1; 
  94.     } 
  95.     unsigned int getotherid(unsigned int x1) 
  96.     { 
  97.         return with[x1]; 
  98.     } 
  99.     unsigned int getp2pinfo(unsigned int x1) 
  100.     { 
  101.         return info[x1]; 
  102.     } 
  103. }; 
  104.  
  105. struct step 
  106.     unsigned short x; 
  107.     unsigned short y; 
  108.     short stepno; 
  109. }; 
  110. //對于下棋狀態(tài)類 
  111. class 網(wǎng)站名稱:一套跨平臺五子棋網(wǎng)游的開發(fā)經(jīng)歷
    文章出自:http://www.dlmjj.cn/article/codespe.html