【Visual C++】遊戲開發筆記十六 講解一個完整的回合制遊戲demo

本系列文章由zhmxy555編寫,轉載請註明出處。 文章鏈接

http://qianmo.blog.51cto.com/5127279/875550

作者:毛星雲 郵箱: [email protected] 歡迎郵件交流編程心得 

這節筆記的主要內容是介紹一個完整的回合制遊戲demo,而這個demo裏面主要突出了遊戲裏AI的各種思考與行爲的方式.這樣的通過計算機角色本身的判斷思考,然後產生對應行爲的AI稱作行爲型遊戲AI。

如果對AI基礎不太瞭解的朋友,請移步:

【Visual C++】遊戲開發筆記十五 遊戲人工智能(一) 運動型遊戲AI

首先,我們來了解這種行爲型AI的設計方法。

遊戲程序中計算機角色的思考與行爲,實際上是對各種不同事件進行分析思考,然後根據不同的情況作出相應的反應。但如何對發生的條件進行判斷,並作出相應的反應呢?

對,我們可以利用“if-else”條件句以及“switch-case”語句這類的判斷式來完成。

通常情況下,設計此類AI,會涉及到連串的條件判斷句,簡單數學運算,及一些數據結構的知識。

下面我們就來具體講解這個demo涉及到的一些知識點:

一、AI怪物***與思考方式設計

例如今天我們要展示的這個回合制遊戲demo裏的AI,就有如下幾種行爲

(1)利爪***

(2)閃電鏈***

(3)致命一擊

(4)使用梅肯斯姆回覆生命值

(5)逃跑

那麼我們可以根據以上設計的怪物行爲,設計以下一段算法,用來模擬怪物對戰時的思考與行爲的方式:

  1. if(monster.nHp > 20)     //生命值大於20  
  2. {  
  3. if(rand()%5!= 1)             
  4.  //進行利爪***概率4/5  
  5. else 
  6.        //進行閃電鏈***概率1/5  
  7. }  
  8. else     //生命值小於20  
  9. {  
  10. switch(rand()%5)  
  11. {  
  12. case 0:  //利爪***  
  13. break;  
  14. case 1:  //釋放閃電鏈  
  15. break;  
  16. case 2:  //致命一擊  
  17. break;  
  18. case 3:  //使用梅肯斯姆回覆  ;  
  19. break;  
  20. case 4:  //逃跑  
  21. if(1== rand()%3 )     //逃跑成功機率1/3  
  22. //逃跑成功  
  23. else 
  24. //逃跑失敗  
  25. break;  
  26. }  

這段代碼中,利用if-else判斷式判斷怪物生命值,然後怪物有4/5的機率釋放普通的利爪***,有1/5的機率釋放閃電鏈魔法***,當怪物重傷生命值小於20點時,也有一定的機率逃跑。

以上的利用“if-else”、“switch”語句,使計算機角色進行事件情況判斷,然後寫出相應的動作實現代碼,這就是行爲型遊戲AI

設計的核心精神。

 

  1. if (4==rand()%5)                   // 20%機率觸發幻影刺客的大招,恩賜解脫,4倍暴擊傷害  
  2. {  
  3. damage = 4*(rand()%10 + player.lv*player.w);  
  4. monster.nHp -= (int)damage;  
  5. sprintf(str,"恩賜解脫觸發,這下牛逼了,4倍暴擊...對怪物照成了%d點傷害",damage);  
  6. }   
  7. else 
  8. {  
  9. damage = rand()%10 + player.lv*player.w;  
  10. monster.nHp -= (int)damage;  
  11. sprintf(str,"玩家使用了無敵斬,傷害一般般...對怪物照成了%d點傷害",damage);  

三、完整的回合制遊戲源代碼

基礎部分就講解完了,下面就貼出註釋詳細的,完整的回合制遊戲demo的代碼吧:

  1. #include "stdafx.h" 
  2. #include <stdio.h>  
  3.  
  4. //定義一個結構體  
  5. struct chr  
  6. {  
  7.     int     nHp;  
  8.     int     fHp;  
  9.     int     lv;  
  10.     int     w;  
  11.     int     kind;  
  12. };  
  13.  
  14. //全局變量聲明  
  15. HINSTANCE hInst;  
  16. HBITMAP bg,sheep,girl,skill,skillult,slash,magic,recover,game;  
  17. HDC     hdc,mdc,bufdc;  
  18. HWND    hWnd;  
  19. DWORD   tPre,tNow;  
  20. int     pNum,f,txtNum;  
  21. bool    attack,over;  
  22. chr     player,monster;  
  23. char    text[5][100];  
  24.  
  25.  
  26.  
  27.  
  28. //全局函數聲明  
  29. ATOM                MyRegisterClass(HINSTANCE hInstance);  
  30. BOOL                InitInstance(HINSTANCE, int);  
  31. LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);  
  32. void                MyPaint(HDC hdc);  
  33. void                MsgInsert(char*);  
  34. void                CheckDie(int hp,bool player);  
  35.  
  36. //****WinMain函數,程序入口點函數**************************************  
  37. int APIENTRY WinMain(HINSTANCE hInstance,  
  38.                      HINSTANCE hPrevInstance,  
  39.                      LPSTR     lpCmdLine,  
  40.                      int       nCmdShow)  
  41. {  
  42.     MSG msg;  
  43.  
  44.     MyRegisterClass(hInstance);  
  45.  
  46.     //初始化    
  47.     if (!InitInstance (hInstance, nCmdShow))   
  48.     {  
  49.         return FALSE;  
  50.     }  
  51.  
  52.     //消息循環  
  53.     GetMessage(&msg,NULL,NULL,NULL);            //初始化msg      
  54.     while( msg.message!=WM_QUIT )  
  55.     {  
  56.         if( PeekMessage( &msg, NULL, 0,0 ,PM_REMOVE) )  
  57.         {  
  58.             TranslateMessage( &msg );  
  59.             DispatchMessage( &msg );  
  60.         }  
  61.         else 
  62.         {  
  63.             tNow = GetTickCount();  
  64.             if(tNow-tPre >= 40)  
  65.                 MyPaint(hdc);  
  66.         }  
  67.     }  
  68.  
  69.     return msg.wParam;  
  70. }  
  71.  
  72. //***設計一個窗口類,類似填空題,使用窗口結構體*************************  
  73. ATOM MyRegisterClass(HINSTANCE hInstance)  
  74. {  
  75.     WNDCLASSEX wcex;  
  76.  
  77.     wcex.cbSize = sizeof(WNDCLASSEX);   
  78.     wcex.style          = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;  
  79.     wcex.lpfnWndProc    = (WNDPROC)WndProc;  
  80.     wcex.cbClsExtra     = 0;  
  81.     wcex.cbWndExtra     = 0;  
  82.     wcex.hInstance      = hInstance;  
  83.     wcex.hIcon          = NULL;  
  84.     wcex.hCursor        = NULL;  
  85.     wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);  
  86.     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  
  87.     wcex.lpszMenuName   = NULL;  
  88.     wcex.lpszClassName  = "canvas";  
  89.     wcex.hIconSm        = NULL;  
  90.  
  91.     return RegisterClassEx(&wcex);  
  92. }  
  93.  
  94. //****初始化函數************************************  
  95. //加載位圖並設定各種初始值   
  96. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)  
  97. {  
  98.     HBITMAP bmp;  
  99.     hInst = hInstance;  
  100.  
  101.     hWnd = CreateWindow("canvas""淺墨的繪圖窗口" , WS_OVERLAPPEDWINDOW,  
  102.         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULLNULL, hInstance, NULL);  
  103.  
  104.     if (!hWnd)  
  105.     {  
  106.         return FALSE;  
  107.     }  
  108.  
  109.     MoveWindow(hWnd,10,10,640,510,true);  
  110.     ShowWindow(hWnd, nCmdShow);  
  111.     UpdateWindow(hWnd);  
  112.  
  113.     hdc = GetDC(hWnd);  
  114.     mdc = CreateCompatibleDC(hdc);  
  115.     bufdc = CreateCompatibleDC(hdc);  
  116.  
  117.     bmp = CreateCompatibleBitmap(hdc,640,510);  
  118.     SelectObject(mdc,bmp);  
  119.  
  120.     bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,640,510,LR_LOADFROMFILE);  
  121.     sheep = (HBITMAP)LoadImage(NULL,"sheep.bmp",IMAGE_BITMAP,133,220,LR_LOADFROMFILE);  
  122.     girl = (HBITMAP)LoadImage(NULL,"girl.bmp",IMAGE_BITMAP,480,148,LR_LOADFROMFILE);  
  123.     skill = (HBITMAP)LoadImage(NULL,"skill.bmp",IMAGE_BITMAP,50,50,LR_LOADFROMFILE);  
  124.     skillult = (HBITMAP)LoadImage(NULL,"skillult.bmp",IMAGE_BITMAP,50,50,LR_LOADFROMFILE);  
  125.     slash = (HBITMAP)LoadImage(NULL,"slash.bmp",IMAGE_BITMAP,196,162,LR_LOADFROMFILE);  
  126.     magic = (HBITMAP)LoadImage(NULL,"magic.bmp",IMAGE_BITMAP,200,100,LR_LOADFROMFILE);  
  127.     recover = (HBITMAP)LoadImage(NULL,"recover.bmp",IMAGE_BITMAP,300,150,LR_LOADFROMFILE);  
  128.     game = (HBITMAP)LoadImage(NULL,"over.bmp",IMAGE_BITMAP,289,74,LR_LOADFROMFILE);  
  129.  
  130.     player.nHp = player.fHp = 50;   //設定玩家角色聲明值及上限  
  131.     player.lv = 2;                  //設定玩家角色等級  
  132.     player.w  = 4;                  //設定***傷害加權值  
  133.  
  134.     monster.nHp = monster.fHp = 120;    //設定怪物角色生命值及上限  
  135.     monster.lv = 1;                     //設定怪物角色等級  
  136.     monster.w = 1;                      //設定***傷害加權值  
  137.  
  138.     txtNum = 0;     //顯示消息數目  
  139.  
  140.     SetBkMode(mdc, TRANSPARENT);    //設置TextOut背景透明  
  141.  
  142.       
  143.  
  144.  
  145.     MyPaint(hdc);  
  146.  
  147.     return TRUE;  
  148. }  
  149.  
  150. //****自定義繪圖函數*********************************  
  151. // 1.畫面貼圖與對戰消息顯示  
  152. // 2.怪物行爲判斷及各項數據處理與計算  
  153. void MyPaint(HDC hdc)  
  154. {  
  155.     char str[100];  
  156.     int i,damage;  
  157.  
  158.     //貼上背景圖  
  159.     SelectObject(bufdc,bg);  
  160.     BitBlt(mdc,0,0,640,510,bufdc,0,0,SRCCOPY);  
  161.  
  162.     //顯示對戰消息  
  163.       
  164.       
  165.           
  166.     for(i=0;i<txtNum;i++)  
  167.         TextOut(mdc,0,360+i*18,text[i],strlen(text[i]));  
  168.  
  169.     //貼上怪物圖  
  170.     if(monster.nHp>0)  
  171.     {  
  172.         SelectObject(bufdc,sheep);  
  173.         BitBlt(mdc,70,180,133,110,bufdc,0,110,SRCAND);  
  174.         BitBlt(mdc,70,180,133,110,bufdc,0,0,SRCPAINT);  
  175.         sprintf(str,"%d / %d",monster.nHp,monster.fHp);  
  176.         TextOut(mdc,100,320,str,strlen(str));  
  177.     }  
  178.  
  179.     //貼上玩家圖  
  180.     if(player.nHp>0)  
  181.     {  
  182.         SelectObject(bufdc,girl);  
  183.         BitBlt(mdc,500,200,60,74,bufdc,pNum*60,74,SRCAND);  
  184.         BitBlt(mdc,500,200,60,74,bufdc,pNum*60,0,SRCPAINT);  
  185.         sprintf(str,"%d / %d",player.nHp,player.fHp);  
  186.         TextOut(mdc,510,320,str,strlen(str));  
  187.     }  
  188.  
  189.     if(over)                //貼上游戲結束圖畫  
  190.     {  
  191.         SelectObject(bufdc,game);  
  192.         BitBlt(mdc,200,200,289,37,bufdc,0,37,SRCAND);  
  193.         BitBlt(mdc,200,200,289,37,bufdc,0,0,SRCPAINT);  
  194.     }  
  195.     else if(!attack)        //貼上***命令圖畫  
  196.     {  
  197.         SelectObject(bufdc,skill);  
  198.         BitBlt(mdc,500,350,50,50,bufdc,0,0,SRCCOPY);  
  199.         SelectObject(bufdc,skillult);  
  200.         BitBlt(mdc,430,350,50,50,bufdc,0,0,SRCCOPY);  
  201.         //BitBlt(mdc,500,350,74,30,bufdc,0,30,SRCAND);  
  202.         //BitBlt(mdc,500,350,74,30,bufdc,0,0,SRCPAINT);  
  203.     }     
  204.     else 
  205.     {  
  206.         f++;  
  207.  
  208.         //第5~10個畫面時顯示玩家***圖標  
  209.         if(f>=5 && f<=10)  
  210.         {  
  211.             SelectObject(bufdc,slash);  
  212.               
  213.             BitBlt(mdc,100,160,98,162,bufdc,98,0,SRCAND);  
  214.             BitBlt(mdc,100,160,98,162,bufdc,0,0,SRCPAINT);  
  215.  
  216.             //第10個畫面時計算怪物受傷害程度並加入顯示消息  
  217.             if(f == 10)  
  218.             {  
  219.  
  220.                 if (4==rand()%5)                   // 20%機率觸發幻影刺客的大招,恩賜解脫,4倍暴擊傷害  
  221.                 {  
  222.                     damage = 4*(rand()%10 + player.lv*player.w);  
  223.                     monster.nHp -= (int)damage;  
  224.  
  225.                     sprintf(str,"恩賜解脫觸發,這下牛逼了,4倍暴擊...對怪物照成了%d點傷害",damage);  
  226.                 }   
  227.                 else 
  228.                 {  
  229.                     damage = rand()%10 + player.lv*player.w;  
  230.                     monster.nHp -= (int)damage;  
  231.  
  232.                     sprintf(str,"玩家使用了無敵斬,傷害一般般...對怪物照成了%d點傷害",damage);  
  233.                 }  
  234.  
  235.  
  236.                   
  237.                 MsgInsert(str);  
  238.  
  239.                 CheckDie(monster.nHp,false);  
  240.             }  
  241.         }  
  242.  
  243.         srand(tPre);  
  244.  
  245.         //第15個畫面時判斷怪物進行哪項動作  
  246.         if(f == 15)  
  247.         {  
  248.             if(monster.nHp > 20)                //生命值大於20  
  249.             {  
  250.                 if(rand()%5 != 1)          //進行利爪***概率4/5  
  251.                     monster.kind = 0;  
  252.                 else                       //進行閃電鏈***概率1/5  
  253.                     monster.kind = 1;      
  254.             }  
  255.             else                                //生命值小於20  
  256.             {  
  257.                 switch(rand()%5)  
  258.                 {  
  259.                     case 0:                     //利爪***  
  260.                         monster.kind = 0;  
  261.                         break;  
  262.                     case 1:                     //釋放閃電鏈  
  263.                         monster.kind = 1;  
  264.                         break;  
  265.                     case 2:                     //致命一擊  
  266.                         monster.kind = 2;  
  267.                         break;  
  268.                     case 3:                     //使用梅肯斯姆回覆  
  269.                         monster.kind = 3;  
  270.                         break;  
  271.                     case 4:                     //逃跑  
  272.                         monster.kind = 4;  
  273.                         break;  
  274.                 }  
  275.             }  
  276.         }  
  277.  
  278.         //第26~30個畫面時顯示玩家***圖標  
  279.         if(f>=26  && f<=30)  
  280.         {  
  281.             switch(monster.kind)  
  282.             {  
  283.                 case 0:                         //利爪***  
  284.                     SelectObject(bufdc,slash);  
  285.                     BitBlt(mdc,480,150,98,162,bufdc,98,0,SRCAND);  
  286.                     BitBlt(mdc,480,150,98,162,bufdc,0,0,SRCPAINT);  
  287.  
  288.                     //第30個畫面時計算玩家受傷害程度並加入顯示消息  
  289.                     if(f == 30)  
  290.                     {  
  291.                         damage = rand()%10 + monster.lv*monster.w;  
  292.                         player.nHp -= (int)damage;  
  293.                           
  294.                         sprintf(str,"怪物利爪***...對玩家照成 %d 點傷害",damage);  
  295.                         MsgInsert(str);  
  296.  
  297.                         CheckDie(player.nHp,true);  
  298.                     }  
  299.                     break;  
  300.                 case 1:                         //釋放閃電鏈  
  301.                     SelectObject(bufdc,magic);  
  302.                     BitBlt(mdc,480,190,100,100,bufdc,100,0,SRCAND);  
  303.                     BitBlt(mdc,480,190,100,100,bufdc,0,0,SRCPAINT);  
  304.  
  305.                     //第30個畫面時計算玩家受傷害程度並加入顯示消息  
  306.                     if(f == 30)  
  307.                     {  
  308.                         damage = rand()%10 + 3*monster.w;  
  309.                         player.nHp -= (int)damage;    
  310.                           
  311.                         sprintf(str,"怪物釋放閃電鏈...對玩家照成 %d 點傷害",damage);  
  312.                         MsgInsert(str);  
  313.  
  314.                         CheckDie(player.nHp,true);  
  315.                     }  
  316.                     break;  
  317.                 case 2:                         //致命一擊  
  318.                     SelectObject(bufdc,slash);  
  319.                     BitBlt(mdc,480,150,98,162,bufdc,98,0,SRCAND);  
  320.                     BitBlt(mdc,480,150,98,162,bufdc,0,0,SRCPAINT);  
  321.  
  322.                     //第30個畫面時計算玩家受傷害程度並加入顯示消息  
  323.                     if(f == 30)  
  324.                     {  
  325.                         damage = rand()%10 + monster.lv*monster.w*5;  
  326.                         player.nHp -= (int)damage;  
  327.                           
  328.                         sprintf(str,"怪物致命一擊...對玩家照成 %d 點傷害.",damage);  
  329.                         MsgInsert(str);  
  330.  
  331.                         CheckDie(player.nHp,true);  
  332.                     }  
  333.                     break;  
  334.                 case 3:                         //使用梅肯斯姆補血  
  335.                     SelectObject(bufdc,recover);  
  336.                     BitBlt(mdc,60,160,150,150,bufdc,150,0,SRCAND);  
  337.                     BitBlt(mdc,60,160,150,150,bufdc,0,0,SRCPAINT);  
  338.  
  339.                     //第30個畫面時怪物回覆生命值並加入顯示消息  
  340.                     if(f == 30)  
  341.                     {  
  342.                         monster.nHp += 30;  
  343.                           
  344.                         sprintf(str,"怪物使用梅肯斯姆...恢復了30點生命值",damage);  
  345.                         MsgInsert(str);  
  346.                     }  
  347.                     break;  
  348.                 case 4:  
  349.                     //在第30個畫面時判斷怪物是否逃跑成功  
  350.                     if(f == 30)  
  351.                     {  
  352.                         if(1== rand()%3 )   //逃跑機率1/3  
  353.                         {  
  354.                             over = true;  
  355.                             monster.nHp = 0;  
  356.  
  357.                             sprintf(str,"怪物逃跑中...逃跑成功");  
  358.                             MsgInsert(str);  
  359.                         }  
  360.                         else 
  361.                         {  
  362.                             sprintf(str,"怪物逃跑中...逃跑失敗");  
  363.                             MsgInsert(str);  
  364.                         }  
  365.                     }  
  366.                     break;  
  367.             }  
  368.         }  
  369.  
  370.         if(f == 30)         //回合結束  
  371.         {  
  372.             attack = false;  
  373.             f = 0;  
  374.         }  
  375.     }  
  376.  
  377.     BitBlt(hdc,0,0,640,510,mdc,0,0,SRCCOPY);  
  378.  
  379.     tPre = GetTickCount();  
  380.  
  381.     pNum++;  
  382.     if(pNum == 8)  
  383.         pNum = 0;  
  384. }  
  385.  
  386. //****新增的對戰消息函數********************************  
  387. void MsgInsert(char* str)  
  388. {  
  389.     if(txtNum < 5)  
  390.     {  
  391.         sprintf(text[txtNum],str);  
  392.         txtNum++;  
  393.     }  
  394.     else 
  395.     {  
  396.         for(int i=0;i<txtNum;i++)  
  397.             sprintf(text[i],text[i+1]);  
  398.  
  399.         sprintf(text[4],str);  
  400.     }  
  401. }  
  402.  
  403. //****生命值判斷函數*************************  
  404. void CheckDie(int hp,bool player)  
  405. {  
  406.     char str[100];  
  407.  
  408.     if(hp <= 0)  
  409.     {  
  410.         over = true;  
  411.         if(player)  
  412.         {  
  413.             sprintf(str,"勝敗乃兵家常事,大俠請重新來過......");  
  414.             MsgInsert(str);  
  415.         }  
  416.         else 
  417.         {  
  418.             sprintf(str,"少年,你贏了,有兩下子啊~~~~~!!!!");  
  419.             MsgInsert(str);  
  420.         }  
  421.     }  
  422. }  
  423.  
  424. //****消息處理函數***********************************  
  425. //   
  426. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  
  427. {  
  428.     int x,y;  
  429.  
  430.     switch (message)  
  431.     {  
  432.         case WM_KEYDOWN:                //鍵盤消息  
  433.             if(wParam==VK_ESCAPE)       //按下Esc鍵  
  434.                 PostQuitMessage(0);  
  435.             break;  
  436.         case WM_LBUTTONDOWN:            //鼠標左鍵消息  
  437.             if(!attack)  
  438.             {  
  439.                 x = LOWORD(lParam);     //X座標  
  440.                 y = HIWORD(lParam);     //Y座標  
  441.               
  442.                 if(x >= 500 && x <= 550 && y >= 350 && y <= 400)  
  443.                     attack = true;  
  444.             }  
  445.             break;  
  446.         case WM_DESTROY:                //窗口結束消息  
  447.             DeleteDC(mdc);  
  448.             DeleteDC(bufdc);  
  449.             DeleteObject(bg);  
  450.             DeleteObject(sheep);  
  451.             DeleteObject(girl);  
  452.             DeleteObject(skill);  
  453.             DeleteObject(skillult);  
  454.             DeleteObject(slash);  
  455.             DeleteObject(magic);  
  456.             DeleteObject(recover);  
  457.             DeleteObject(game);  
  458.  
  459.             ReleaseDC(hWnd,hdc);  
  460.  
  461.             PostQuitMessage(0);  
  462.             break;  
  463.         default:                        //默認消息  
  464.             return DefWindowProc(hWnd, message, wParam, lParam);  
  465.    }  
  466.    return 0;  

每一回合開始的時候,我們點擊畫面上“無敵斬”的技能圖標,就可以進行***,對怪物造成傷害,人品好的話,還可以觸發強力被動技能“恩賜解脫”,對怪物造成4倍暴擊傷害,這裏我們設定的暴擊概率爲20%

淺墨在截圖的時候,人品挺好的,恩賜解脫的暴擊概率爲20%,但是淺墨的4次***裏,有3次都打出了“恩賜解脫”的暴擊效果,直接果斷地把這隻小綿羊帶走了,呵呵。

下面就是遊戲運行的截圖:
遊戲開始

 

第一刀就出暴擊了,48點傷害

 

運氣不錯,又一刀暴擊,68點傷害

 

最後一刀又出了暴擊,小綿羊被“秒殺”,遊戲結束

我們還可以調節怪物等級,怪物***加權值,怪物血量上限以及玩家角色等級,玩家角色***加權值,玩家角色血量上限來讓遊戲更具挑戰性。

當然,我們也可以增加更多的代碼,來使怪物的思考與行動方式更具真實性和多樣性,來使玩家的技能更加豐富。

這個回合制遊戲demo可以說是目前市場上回合制遊戲的本體,《仙劍奇俠傳》(三代以前的,三代及以後的仙劍都是進度條模式了),《夢幻西遊》《問道》等經典的回合制遊戲,無非就是在這種風格的demo基礎上,寫更多的代碼,豐富內容而已,或爲遊戲引擎的核心代碼。

最後淺墨再提一點,以結束這篇筆記,其實就是爲了給大家提供一些實現思路:

可以在這個demo的基礎上,增加劇情,世界觀,遊戲地圖,等級系統,經驗值系統,寵物系統,道具系統,符文系統,五行相剋系

統,天氣系統等,讓這個回合制遊戲更加有趣更加吸引人。

而這些系統,我在以後的筆記裏面會盡量全部涵蓋進行講解的,希望大家繼續關注我的博客。

本節筆記到這裏就結束了。

本節筆記的源代碼請點擊這裏下載: 【Visual C++】Note_Code_16

感謝一直支持【Visual C++】遊戲開發筆記系列專欄的朋友們,也請大家繼續關注我的專欄,我一有時間就會把自己的學習心得,覺得比較好的知識點寫出來和大家一起分享。

精通遊戲開發的路還很長很長,非常希望能和大家一起交流,共同學習,共同進步。

大家看過後覺得值得一看的話,可以頂一下這篇文章,你們的支持是我繼續寫下去的動力~

如果文章中有什麼疏漏的地方,也請大家指正。也希望大家可以多留言來和我探討編程相關的問題。

最後,謝謝你們一直的支持~~~

二,玩家角色***方式設計

然後我們再來設計一下玩家的***技能。

今天放出的這個demo裏我給人物設定了兩個技能,一個主動的普通***技能“無敵斬”,傷害計算公式爲damage = rand()%10 + player.lv*player.w(player.lv爲角色等級,player.w爲***係數)。

而被動技能爲可以有一定機率打出4倍暴擊傷害的“恩賜解脫”,這個技能是Dota裏面幻影刺客的大招(呵呵,淺墨玩dota時可是超級幻刺控~~)。

其實暴擊的實現方式很簡單,就是用if條件句進行概率的判斷(淺墨在這裏利用4==rand( )%5來設定暴擊概率爲20%),如果判斷成功就將“倍率x普通***”作爲damage的值。

(哈哈,淺墨專門找到了Dota裏面這兩個技能的圖標以及用到了這個demo裏面,具體效果圖在下面)

下面貼出實現人物技能的代碼:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章