C++ 开发【梦幻西游】500多行代码实现
文章目錄
- 一、項目展示
- 二、準(zhǔn)備
- 1、開發(fā)環(huán)境
- 2、圖片素材
- 三、整個流程
- 四、函數(shù)構(gòu)建
- 五、Hero 和 Boss 邏輯
- 六、Hero Boss 技能繪制
- 七、判斷死亡
- 八、信息欄顯示
- 九、奉上源碼
一、項目展示
二、準(zhǔn)備
1、開發(fā)環(huán)境
在使用VS 的時候通過 win32 項目創(chuàng)建,這里一定不要選錯,如下圖
選中空項目,去掉安全開發(fā)聲明周期
2、圖片素材
三、整個流程
整個流程是很重要的,這里一定要懂
首先看看主函數(shù)的參數(shù)
由于這是 Win32 項目創(chuàng)建,所以和我們平時看的控制臺 main 函數(shù)是不一樣的
參數(shù)只要知道第一個就行了,和最后一個就行了,因為剩下兩個也沒有用到
HINSTANCE hInstance :表示該程序當(dāng)前運行的實例句柄,是一個數(shù)值標(biāo)識。當(dāng)程序在Windows下運行時,它唯一標(biāo)識運行中的實例
int nShowCmd :指定程序的窗口應(yīng)該如何顯示,例如最大化、最小化、隱藏等。這個參數(shù)的值由該程序的調(diào)用者所指定,應(yīng)用程序通常不需要去理會這個參數(shù)的值。
然后我們在主函數(shù)中先定義一些東西,這些是必須要有的
另外也可以設(shè)置窗口的樣式,以及鼠標(biāo)等等,當(dāng)然該項目沒有用到
然后對窗口進行 注冊,創(chuàng)建,更新
接下來是對窗口進行初始化
需要做這些東西,具體啥含義需要深究Win32,就不探討了
然后把英雄,Boss,技能圖標(biāo)加載進來
首先需要定義
另外對 Boss 和 英雄的屬性初始值也可以在初始化函數(shù)中賦值
當(dāng)然也得定義
//初始英雄化數(shù)據(jù) Hero.Agility = 20; Hero.Intell = 10; Hero.level = 6; Hero.strength = 10; Hero.MaxHp = 1000; Hero.NowHp = 1000; Hero.MaxMp = 60; Hero.NowMp = 60; //初始化Boss數(shù)據(jù) Boss.Agility = 10; Boss.Intell = 10; Boss.level = 10; Boss.strength = 10; Boss.MaxHp = 2000; Boss.NowHp = 2000;初始化完成之后
下面就是一個循環(huán)了
TranslateMessage 把消息轉(zhuǎn)換為字符串,在下一次調(diào)度 PeekMessage 是被讀出
DispatchMessage 調(diào)度一個消息給窗口程序
下面是 GamePaint 函數(shù)中的調(diào)用,為什么會在窗口中有背景,技能,這種視覺性畫面,其實就是GamePaint 函數(shù)在繪制
四、函數(shù)構(gòu)建
繪制函數(shù)的主邏輯
//繪制函數(shù) VOID GamePaint(HWND hwnd){//貼出背景圖片和戰(zhàn)斗信息PutBackInformation();//如果Boss氣血不為0,貼出圖片和生命值if (Boss.NowHp > 0){ PutImageBoss();PutLife(false);}//如果Hero氣血不為0,則貼圖片和生命值if (Hero.NowHp > 0){PutImageHero();PutLife(true);}//如果游戲結(jié)束if (g_bGameOver){if (Hero.NowHp <= 0){IsGameOver(TRUE);}else{IsGameOver(FALSE);}g_bCanAttack = false;}//如果可以攻擊if (g_bCanAttack){g_frame++;//消息循環(huán),每一次循環(huán)就是一幀if (g_frame >= 5 && g_frame <= 10){if (g_frame == 5){//根據(jù)不同的技能,貼上對應(yīng)的技能圖HeroAction_Logic();DieCheck(Boss.NowHp, false);}HeroActionPaint();//hero的技能圖片}else if (g_frame == 15){BossAction_Logic();//怪物邏輯}else if (g_frame >= 16 && g_frame < 30){BossActionPaint();//顯示怪物的攻擊圖片}//第三十幀,回合結(jié)束else if (g_frame == 30){g_frame = 0;int MpRecover = 2 * rand() % Hero.Intell + 6; Hero.NowMp += MpRecover;if (Hero.NowMp >= Hero.MaxMp){Hero.NowMp = Hero.MaxMp;}}}//需要把 g_memdc 中的寫入到g_hdc中BitBlt(g_hdc, 0, 0, 800, 600, g_memdc, 0, 0, SRCCOPY); }五、Hero 和 Boss 邏輯
Hero 的邏輯模塊
//這個邏輯是由程序猿自定以的,如果你想游戲簡單點,就可以在這里進行設(shè)定 //如果你想讓游戲復(fù)雜,在這里也可以讓游戲變得復(fù)雜,所以這里是玩家邏輯模塊VOID HeroAction_Logic(){int damage = 0;switch (HeroAction) //根據(jù) HeroAction不同的值觸發(fā)不同的技能{case NORMAL: //普通攻擊有一定機會觸發(fā)暴擊//模擬隨機暴擊幾率 25%if (rand() % 4 == 1){HeroAction = CRITICAL;damage = 4 * (3 * (rand() % Hero.Agility) + Hero.level*Hero.strength + 20);//這里可以自定以設(shè)置Boss.NowHp -= damage;}else{//普通攻擊damage = 3 * (rand() % Hero.Agility) + Hero.level*Hero.strength + 20;//80~107Boss.NowHp -= damage;}break;case MAGIC://消耗30藍if (Hero.NowMp >= 30){damage = 5 * (2 * (rand() % Hero.Agility) + Hero.level*Hero.Intell);Boss.NowHp -= damage;Hero.NowMp -= 30;}else{HeroAction = MISS;}break;case RECOVER://消耗40藍if (Hero.NowMp >= 40){Hero.NowMp -= 40;int HpRecover = 3 * (rand() % Hero.Intell) + 13; //0-27Hero.NowHp += HpRecover;if (Hero.NowHp >= Hero.MaxHp){Hero.NowHp = Hero.MaxHp;}}else{HeroAction = MISS;}break;} }Boss 的邏輯
這里如果你想讓Boss變得厲害,也可以在這里設(shè)置
如果你想讓它變得很菜,也是在這里設(shè)置
VOID BossAction_Logic(){srand((unsigned int)time(NULL));//血量充足的時候if (Boss.NowHp >= (Boss.MaxHp / 2)){switch (rand() % 3){case 0:BossAction = NORMAL;break;case 1:BossAction = CRITICAL;break;case 2:BossAction = MAGIC;break;default:break;}}else{ //血量比較低的時候,進入狂暴狀態(tài)switch (rand() % 3){case 0:BossAction = CRITICAL;break;case 1:BossAction = MAGIC;break;case 2:BossAction = RECOVER;break;default:break;}} }六、Hero Boss 技能繪制
Hero 技能圖片繪制
VOID HeroActionPaint(){switch (HeroAction){case NORMAL:SelectObject(g_bufdc, g_heroskill1);TransparentBlt(g_memdc, 50, 150, 364, 140, g_bufdc, 0, 0, 364, 140, RGB(0, 0, 0));break;case CRITICAL:SelectObject(g_bufdc, g_heroskill2);TransparentBlt(g_memdc, 50, 60, 574, 306, g_bufdc, 0, 0, 574, 306, RGB(0, 0, 0));break;case MAGIC:SelectObject(g_bufdc, g_heroskill3);TransparentBlt(g_memdc, 50, 60, 100, 77, g_bufdc, 0, 0, 100, 77, RGB(0, 0, 0));break;case RECOVER:SelectObject(g_bufdc, g_recover);TransparentBlt(g_memdc, 380, 340, 150, 150, g_bufdc, 0, 0, 150, 150, RGB(0, 0, 0));break;default:break;} }Boss 技能的繪制 + 邏輯運算
VOID BossActionPaint(){int damage = 0;int recover = 0;wchar_t str[100];switch (BossAction){case NORMAL:SelectObject(g_bufdc, g_bossskill1);TransparentBlt(g_memdc, 360, 390, 150, 120, g_bufdc, 0, 0, 150, 120, RGB(0, 0, 0));if (g_frame == 30){damage = rand() % Boss.Agility + (Boss.level*Boss.strength);Hero.NowHp -= damage;DieCheck(Hero.NowHp, true);}break;case CRITICAL:SelectObject(g_bufdc, g_bossskill2);TransparentBlt(g_memdc, 360, 390, 249, 231, g_bufdc, 0, 0, 249, 231, RGB(0, 0, 0));if (g_frame == 30){damage = 2 * (rand() % Boss.Agility + (Boss.level*Boss.strength));Hero.NowHp -= damage;DieCheck(Hero.NowHp, true);}break;case MAGIC:SelectObject(g_bufdc, g_bossskill3);TransparentBlt(g_memdc, 50, 60, 574, 306, g_bufdc, 0, 0, 574, 306, RGB(0, 0, 0));if (g_frame == 30){damage = 2 * (2 * (rand() % Boss.Agility) + Boss.strength*Boss.Intell);Hero.NowHp -= damage;recover = (int)((double)damage*0.2);Boss.NowHp += recover;DieCheck(Hero.NowHp, true);}break;case RECOVER:SelectObject(g_bufdc, g_recover);TransparentBlt(g_memdc, 150, 150, 150, 150, g_bufdc, 0, 0, 150, 150, RGB(0, 0, 0));if (g_frame == 30){recover = 2 * Boss.Intell * Boss.Intell;Hero.NowHp += recover;if (Boss.NowHp > Boss.MaxHp){Boss.NowHp = Boss.MaxHp;}}break;default:break;} }七、判斷死亡
每次Hero 和 Boss 減少氣血的時候調(diào)用一次
//判斷死亡,第一個參數(shù)可以是 Boss 的,也可以是Hero的 VOID DieCheck(int nowhp, bool ishero){if (nowhp <= 0){g_bGameOver = true;//播放音樂if (ishero){ PlaySound(L"./res/failure.wav", NULL, SND_FILENAME | SND_ASYNC);}else{PlaySound(L"./res/victory.wav", NULL, SND_FILENAME | SND_ASYNC);}} }八、信息欄顯示
就是我藍色框框的東西,該怎么實現(xiàn)?
第一步:在初始化函數(shù)中
第二步:定義 Message_Insert 插入信息欄函數(shù)
第三步:在繪制函數(shù)中
第四步:在每一次的攻擊或者回復(fù)氣血之后,都調(diào)用一次
例如
其他函數(shù)的實現(xiàn)
//貼Hero 和 Boss VOID PutImageHero(){SelectObject(g_bufdc, g_hero);//BitBlt(g_memdc, 350, 250, 250, 250, g_bufdc, 0, 0, SRCCOPY);TransparentBlt(g_memdc, 350, 250, 250, 250, g_bufdc, g_heronum * 250, 0, 250, 250, RGB(0, 0, 0));//去掉黑背景,透明繪圖if (g_heronum++ >= 13){g_heronum = 0;} }VOID PutImageBoss(){SelectObject(g_bufdc, g_boss);TransparentBlt(g_memdc, 100, 120, 250, 250, g_bufdc, g_bossnum * 250, 0, 250, 250, RGB(0, 0, 0));//去掉黑背景,透明繪圖if (g_bossnum++ >= 15){g_bossnum = 0;}}//顯示血量 VOID PutLife(BOOL hero){wchar_t str[100]; //保存血量if (!hero){swprintf_s(str, L"%d/%d", Boss.NowHp, Boss.MaxHp);SetTextColor(g_memdc, RGB(255, 0, 0));TextOut(g_memdc, 180, 310, str, wcslen(str));}else{//顯示血量swprintf_s(str, L"%d/%d", Hero.NowHp, Hero.MaxHp);SetTextColor(g_memdc, RGB(255, 0, 0));TextOut(g_memdc, 450, 465, str, wcslen(str));//顯示藍swprintf_s(str, L"%d/%d", Hero.NowMp, Hero.MaxMp);SetTextColor(g_memdc, RGB(0, 0, 255));TextOut(g_memdc, 465, 480, str, wcslen(str));} }//貼背景,戰(zhàn)斗信息,技能圖標(biāo) VOID PutBackInformation(){//貼背景圖片SelectObject(g_bufdc, g_backbmp); //把圖片選入 memdcBitBlt(g_memdc, //目標(biāo)設(shè)備0, 0, 800, 600, //目標(biāo)設(shè)備的范圍g_bufdc, //源設(shè)備0, 0, //源設(shè)備的起始值SRCCOPY); //拷貝 //顯示戰(zhàn)斗信息SetTextColor(g_memdc, RGB(255, 0, 0));for (int i = 0; i < g_iTextNum; ++i){TextOut(g_memdc, 20, 20 + i * 20, text[i], wcslen(text[i]));}//貼技能圖標(biāo)SelectObject(g_bufdc, g_skillbutton1);BitBlt(g_memdc, 600, 200, 40, 40, g_bufdc, 0, 0, SRCCOPY);SelectObject(g_bufdc, g_skillbutton2);BitBlt(g_memdc, 600, 250, 40, 40, g_bufdc, 0, 0, SRCCOPY);SelectObject(g_bufdc, g_skillbutton3);BitBlt(g_memdc, 600, 300, 40, 40, g_bufdc, 0, 0, SRCCOPY);SelectObject(g_bufdc, g_skillbutton4);BitBlt(g_memdc, 600, 350, 40, 40, g_bufdc, 0, 0, SRCCOPY); }VOID IsGameOver(BOOL isGameOver){if (isGameOver){//英雄敗,SelectObject(g_bufdc, g_hGameOver);BitBlt(g_memdc, 120, 150, 543, 396, g_bufdc, 543, 0, SRCAND);BitBlt(g_memdc, 120, 150, 543, 396, g_bufdc, 0, 0, SRCPAINT);}else{SelectObject(g_bufdc, g_hVictor);TransparentBlt(g_memdc, 240, 195, 294, 147, g_bufdc, 0, 0, 294, 147, RGB(0, 0, 0));} }九、奉上源碼
Github 地址
記得點個 star
總結(jié)
以上是生活随笔為你收集整理的C++ 开发【梦幻西游】500多行代码实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 墨西哥萨卡特卡斯将举行GNOME GUA
- 下一篇: CC00003.LBCHAC——|LBC