C++實現雷霆戰機視覺化小遊戲
阿新 • • 發佈:2020-11-25
用C++和easyx實現簡單的雷霆戰機小遊戲
之前在網上看了許多關於c++或者是其他語言實現雷霆戰機的帖子,大多不完整,或者是要付費才能閱讀,現將原始碼展示如下,僅作學習交流之用。
基本原理
基本思路
程式碼如下
注意:執行程式碼所需環境為c++11或更高,程式碼中所涉及的圖片、背景音樂等素材均需自行蒐集並修改程式碼中的檔案路徑。
程式碼如有任何問題請在評論區指正,謝謝!
覺得幫到您了的話,可以考慮一下打賞博主呦,您的支援是我創作的最大動力!!!
/*seeting.h*/ #pragma once void set_textstyle(LOGFONT& f,int high,int wei); //設定輸出文字形式 void load_be_bk(); //載入初始背景 void help(); //幫助介面 void decorete(int x); //初始介面裝飾 void home(int i); //初始介面 bool exit(); //退出遊戲 /*seeting.cpp*/ #include <graphics.h> #include <conio.h> #include <ctime> #include <string.h> #include "setting.h" IMAGE be_bk01,be_bk02; static int i = 0; //裝飾時計數 void set_textstyle(LOGFONT& f,int wei) { gettextstyle(&f); // 獲取當前字型設定 f.lfHeight = high; // 設定字型高度為 48 f.lfWeight = wei; _tcscpy_s(f.lfFaceName,_T("宋體")); // 設定字型 f.lfQuality = ANTIALIASED_QUALITY; // 設定輸出效果為抗鋸齒 } void decorate(int x) //裝飾 { if ((x/10) % 2 == 0) { setlinecolor(RGB(255,250,250)); line(202,662,71,549); line(1157,403,1117,259); setlinecolor(RGB(0,238,0)); line(1004,413,1157,403); line(1188,504,1020,534); line(228,388,202,131); setlinecolor(RGB(255,69,0)); line(202,131,404,261); line(471,493,228,388); line(1020,534,1307,563); setlinecolor(RGB(0,245,255)); line(1303,291,1034,332); line(66,373,437,600); setlinecolor(RGB(191,62,255)); line(1178,666,1287,616); line(404,261,131); } else { setlinecolor(RGB(255,218,185)); line(1501,155,23,213); line(437,600,471,493); line(1287,616,644); setlinecolor(RGB(84,255,159)); line(348,315,103,263); line(269,606,39,697); line(1094,462,1004,413); setlinecolor(RGB(30,144,255)); line(71,549,269,606); line(103,263,66,373); line(1307,563,1303,291); setlinecolor(RGB(255,0)); line(1034,640,1188,504); line(1034,332,985,254); line(39,697,348,315); setlinecolor(RGB(255,255)); line(1117,259,942,593); line(942,593,1178,666); line(985,254,1292,105); } setlinecolor(RGB(255,255)); } void load_be_bk() //載入幫助介面背景 { loadimage(&be_bk01,L"image\\be_bk01.jpg",1360,760); putimage(0,&be_bk01); } void help() //幫助介面 { while (1) { BeginBatchDraw(); load_be_bk(); decorate(i); roundrect(526,126,834,634,30,30); roundrect(528,128,832,632,30); roundrect(530,130,830,630,30); LOGFONT f; set_textstyle(f,5); settextstyle(&f); // 設定字型樣式 outtextxy(595,170,_T("遊 戲 須 知")); line(550,220,810,220); set_textstyle(f,20,3); settextstyle(&f); outtextxy(555,240,_T("① 按下 w a s d 移動飛機。")); outtextxy(555,280,_T("② 按下 空格 發射子彈。")); outtextxy(555,320,_T("③ 遊戲中按 ESC 暫停。")); outtextxy(555,360,_T("④ 每撞機一次,生命值減少20,")); outtextxy(555,400,_T(" 通過本關,生命值恢復。")); set_textstyle(f,15,2); settextstyle(&f); outtextxy(625,525,_T("按任意鍵返回")); line(550,550,550); outtextxy(605,570,_T("製作不易,請勿抄襲")); outtextxy(605,_T(" ——木筆製作")); i++; EndBatchDraw(); Sleep(10); if (_kbhit()) { _getch(); break; } } } void home(int i) //初始介面 { BeginBatchDraw(); loadimage(&be_bk02,L"image\\be_bk02.jpg",&be_bk02); int m = 465,n = 515; //輸出框上下邊界 for (int t = 0; t < 4; t++) { for (int j = 0; j < 4; j++) { roundrect(1110 + j,m + j,1300 - j,n - j,30); } m += 65; n += 65; } switch (i) { case 1: for (int j = 0; j < 30; j++) { setlinecolor(RGB(0+j*5,255 - j * 4,217 - j * 5)); line(1120,475 + j,1290,475 + j); } break; case 2: for (int j = 0; j < 30; j++) { setlinecolor(RGB(0 + j * 5,540 + j,540 + j); } break; case 3: for (int j = 0; j < 30; j++) { setlinecolor(RGB(0 + j * 5,605 + j,605 + j); } break; case 4: for (int j = 0; j < 30; j++) { setlinecolor(RGB(0 + j * 5,670 + j,670 + j); } break; } setlinecolor(RGB(152,255)); LOGFONT f; gettextstyle(&f); f.lfHeight = 30; f.lfWeight = 7; _tcscpy_s(f.lfFaceName,_T("隸書")); f.lfQuality = ANTIALIASED_QUALITY; settextstyle(&f); setbkmode(TRANSPARENT); //透明字型背景 settextcolor(RGB(255,0)); outtextxy(1125,475,_T("簡單模式(1)")); outtextxy(1125,540,_T("困難模式(2)")); outtextxy(1125,605,_T(" 幫 助 (3) ")); outtextxy(1125,670,_T(" 退 出 (4) ")); f.lfHeight = 70; f.lfWeight = 30; _tcscpy_s(f.lfFaceName,_T("方正舒體")); settextstyle(&f); for (int j = 0; j < 5; j++) roundrect(950+j,280+j,1300-j,410-j,50,50); settextcolor(RGB(255,165,0)); outtextxy(960,300,_T("外星人入侵")); EndBatchDraw(); } bool exit() //退出遊戲 { loadimage(&be_bk02,&be_bk02); LOGFONT f; set_textstyle(f,20); settextcolor(RGB(255,255)); outtextxy(390,230,_T("是否要退出遊戲?")); outtextxy(310,_T("是(回車)否(任意鍵)")); FlushBatchDraw(); char hit = _getch(); if (hit == 13) return 1; else return 0; }
/*music.h*/ #pragma once #include <wtypes.h> #include <string> typedef int(__stdcall* w32mci)(const char*,char*,int,int); typedef int(__stdcall* w32mcierror)(int,int); using namespace std; class Mci { private: HINSTANCE hins; w32mci wmci; w32mcierror wmcierror; public: Mci(); ~Mci(); char buf[256]; bool send(string command); }; class AudioClip { private: Mci mci; std::string filename; std::string alias; int length_ms; public: AudioClip(); ~AudioClip(); bool load(const std::string& _filename); bool play(int start_ms = 0,int end_ms = -1); bool stop(); bool pause(); bool unpause(); int milliseconds(); }; /*music.cpp*/ #include "music.h" #include<iostream> #include <string> #include <cstring> #include<random> #include<time.h> Mci::Mci() { HINSTANCE hins = LoadLibraryA("winmm.dll"); wmci = (w32mci)GetProcAddress(hins,"mciSendStringA"); wmcierror = (w32mcierror)GetProcAddress(hins,"mciGetErrorStringA"); } Mci::~Mci() { FreeLibrary(hins); } bool Mci::send(std::string command) { int errcode = wmci(command.c_str(),buf,0); if (errcode) { wmcierror(errcode,254); return false; } return true; } AudioClip::AudioClip() { //do nothing } AudioClip::~AudioClip() { std::string cmd; cmd = "close " + alias; mci.send(cmd); } bool AudioClip::load(const std::string& _filename) { filename = _filename; for (unsigned int i = 0; i < filename.length(); i++) { if (filename[i] == '/') filename[i] = '\\'; } alias = "mp3_"; srand(time(NULL)); char randstr[6]; _itoa_s(rand() % 65536,randstr,10); alias.append(randstr); std::string cmd; cmd = "open " + filename + " alias " + alias; if (mci.send(cmd) == false) return false; cmd = "set " + alias + " time format milliseconds"; if (mci.send(cmd) == false) return false; cmd = "status " + alias + " length"; if (mci.send(cmd) == false) return false; length_ms = atoi(mci.buf); return true; } bool AudioClip::play(int start_ms,int end_ms) { if (end_ms == -1) end_ms = length_ms; std::string cmd; char start_str[16],end_str[16]; _itoa_s(start_ms,start_str,10); _itoa_s(end_ms,end_str,10); cmd = "play " + alias + " from "; cmd.append(start_str); cmd.append(" to "); cmd.append(end_str); return mci.send(cmd); } bool AudioClip::stop() { std::string cmd; cmd = "stop " + alias; if (mci.send(cmd) == false) return false; cmd = "seek " + alias + " to start"; if (mci.send(cmd) == false) return false; return true; } bool AudioClip::pause() { std::string cmd; cmd = "pause " + alias; if (mci.send(cmd) == false) return false; return true; } bool AudioClip::unpause() { std::string cmd; cmd = "resume " + alias; if (mci.send(cmd) == false) return false; return true; } int AudioClip::milliseconds() { return length_ms; }
/*alien.h*/ #pragma once #include <graphics.h> class Alien { public: int alien_x = 0,alien_y = -40; //外星人座標 IMAGE alien01; //外星人圖片 void load_alien(); //載入外星人圖片 void show_alien(); //繪製外星人 Alien(); }; /*alien.cpp*/ #include <deque> #include "alien.h" #include <graphics.h> void Alien::load_alien() { loadimage(&alien01,L"image\\alien.jpg",40,40); } void Alien::show_alien() { putimage(alien_x,alien_y,&alien01); } Alien::Alien() { load_alien(); }
/*airplane.h*/ #pragma once class Airplane { public: int airplane_x = 650,airplane_y = 720; //飛機初始座標 IMAGE plane01; //飛機圖片 IMAGE background; //背景圖 char key_hit; //接受按鍵 int airplane_speed = 10; //飛船移動速度 Airplane(); //建構函式 void load_image();//載入飛機圖片 void show_plane();//繪製飛機圖片 void show_bg(); //繪製背景圖片 void key_Down(char hit); //按鍵響應 }; /*airplane.cpp*/ #include <graphics.h> #include <conio.h> #include <Windows.h> #include "Airplane.h" void Airplane::load_image() //載入飛機圖片和背景圖 { loadimage(&plane01,L"image\\plane01.jpg",60,40); loadimage(&background,L"image\\background01.jpg",760); rotateimage(&plane01,&plane01,3.1415926); } void Airplane::show_bg() //繪製背景圖 { putimage(0,&background); } void Airplane::show_plane() //繪製飛機圖片 { putimage(airplane_x,airplane_y,&plane01); } void Airplane::key_Down(char hit) //按鍵響應 { key_hit = hit; switch (key_hit) { case 'w': case 'W': if(airplane_y > 500) airplane_y-=airplane_speed; break; case 's': case 'S': if (airplane_y < 720) airplane_y+= airplane_speed; break; case 'a': case 'A': if (airplane_x > 0) airplane_x-= airplane_speed; break; case 'd': case 'D': if (airplane_x < 1300) airplane_x+= airplane_speed; break; default: break; } } Airplane::Airplane() { load_image(); }
/*bullet.h*/ #pragma once class Bullet { public: int bullet_x = 0,bullet_y = 0; //子彈座標 IMAGE bullet01; //子彈圖片 int bullet_speed = 15; //子彈速度 void load_bullet(); //載入子彈圖片 void show_bullet(); //繪製子彈圖片 Bullet(); }; /*bullet.cpp*/ #include <graphics.h> #include "bullet.h" void Bullet::load_bullet() { loadimage(&bullet01,L"image\\bullet.jpg",10,30); } void Bullet::show_bullet() { putimage(bullet_x,bullet_y,&bullet01); } Bullet::Bullet() { load_bullet(); }
/*launch.h*/ #pragma once bool choose_all(char key,int &i); //初始選擇介面按鍵處理 void load_music01(); //載入初始介面音樂 /*launch.cpp*/ #include <iostream> #include <Windows.h> #include <graphics.h> #include <conio.h> #include<cstdlib> #include <deque> #include <vector> #include <ctime> #include <string> #include <tchar.h> #include "airplane.h" #include "bullet.h" #include "alien.h" #include "music.h" #include "setting.h" using namespace std; static int score = 0; //得分 int tx = 0; //儲存上次得分資訊 static int level = 1; //關卡 int player_eneygy = 100; //玩家血量 static int alien_speed = 1; //外星人移動速度 int alien_num = 5; //初始外星人數量 AudioClip mu_be01,choose,level13,level46,level710,bulbul,gameov,levelup; //音樂 void load_music01() //載入初始介面音樂 { mu_be01.load("music\\be_bg01.mp3"); mu_be01.play(); } void trans_int_ch(wchar_t*& wides,int num) //將數字轉換為能夠被outtextxy輸出的wchar_t型 { string temp = to_string(num); char s[100]; int i; for (i = 0; i < temp.length(); i++) s[i] = temp[i]; s[i] = '\0'; int n = MultiByteToWideChar(0,s,-1,NULL,0); wchar_t* wide = new wchar_t[n]; MultiByteToWideChar(0,wide,n); wides = wide; } void show_score_level() //顯示得分和關卡資訊 { LOGFONT f; set_textstyle(f,5); //設定字型資訊 wchar_t* wides1 = NULL; trans_int_ch(wides1,score); roundrect(1220,1320,20); //繪製得分資訊框 rectangle(1215,1325,55); settextstyle(&f); outtextxy(1235,27,_T("得分: ")); settextstyle(&f); outtextxy(1290,wides1); wchar_t* wides2 = NULL; trans_int_ch(wides2,level); roundrect(1220,70,100,65,105); settextstyle(&f); outtextxy(1235,77,_T("關卡: ")); settextstyle(&f); outtextxy(1290,wides2); } void show_energy() //顯示玩家血量 { LOGFONT f; set_textstyle(f,25,5); settextstyle(&f); setbkmode(TRANSPARENT); //透明字型背景 wchar_t* ene = NULL; trans_int_ch(ene,player_eneygy); switch (player_eneygy) { case 100: setfillcolor(RGB(0,0)); rectangle(15,55); solidroundrect(20,160,8,8); outtextxy(70,22,ene); break; case 80: setfillcolor(RGB(192,62)); rectangle(15,132,ene); break; case 60: setfillcolor(RGB(255,215,104,ene); break; case 40: setfillcolor(RGB(238,76,ene); break; case 20: setfillcolor(RGB(255,48,ene); break; case 0: settextstyle(&f); outtextxy(70,ene); break; default: break; } } void get_Cours(Bullet &b) //獲取滑鼠資訊 { HWND hwnd = GetHWnd(); //獲取視窗控制代碼 POINT point; //滑鼠位置 GetCursorPos(&point); // 獲取滑鼠指標位置(螢幕座標) ScreenToClient(hwnd,&point); // 將滑鼠指標位置轉換為視窗座標 if (point.x >= 0 && point.x <= 1360 && point.y >= 500 && point.y <= 760) { b.bullet_x = point.x; b.bullet_y = point.y; } } void add_alien(deque<Alien>& a) //新增外星人 { Alien ali; int x = 0; //作為隨機數 while (1) { int i = 0; x = rand() % 1320; for (int k = 0; k < a.size(); k++) { if (x >= a[k].alien_x && x <= a[k].alien_x + 40) i++; } if (i == 0) break; else i = 0; } ali.alien_x = x; a.push_back(ali); } void update_level(deque<Alien>& a) //更新等級和外星人數量資訊 { if (score > tx) if (score >= 10 && score % 10 == 0) { level++; levelup.load("music\\levelup.mp3"); levelup.play(); player_eneygy = 100; alien_speed *= 1.5; add_alien(a); tx = score; } } void update_energy(Airplane pl,deque<Alien> &a) //更新血量 { int i = 0,t = 0; for ( ; i < a.size(); i++) { if ((pl.airplane_x <= a[i].alien_x + 40 && pl.airplane_x + 60 >= a[i].alien_x && pl.airplane_y == a[i].alien_y + 30)|| (pl.airplane_y <= a[i].alien_y + 40 && pl.airplane_y + 40 >= a[i].alien_y && pl.airplane_x <= a[i].alien_x + 40 && pl.airplane_x + 60 >= a[i].alien_x)) { player_eneygy -= 20; t++; break; } } if (t != 0) { a.erase(a.begin() + i); add_alien(a); } } void draw_bu_al(deque<Alien>& a,deque<Bullet>& b) //更新並繪製外星人和子彈 { vector<int> as; vector<int> bs; for (int i = 0; i < a.size(); i++) //判斷子彈和外星人相撞 { for (int j = 0; j < b.size(); j++) { if (a[i].alien_x <= b[j].bullet_x + 10 && a[i].alien_x + 40 >= b[j].bullet_x && a[i].alien_y+40 >= b[j].bullet_y) { bulbul.load("music\\bullet.mp3"); bulbul.play(); as.push_back(i); bs.push_back(j); score++; } } } if (!as.empty()) for (int i = a.size() - 1; i >= 0; i--) //刪除碰撞後的外星人 { int k = as.size() - 1; if (i == as[k]) { a.erase(a.begin() + i); k--; add_alien(a); //每次刪除都新增一個外星人 } } if (!bs.empty()) for (int i = b.size() - 1; i >= 0; i--) //刪除碰撞後的子彈 { int k = bs.size() - 1; if (i == bs[k]) { b.erase(b.begin() + i); k--; } } if(!a.empty()) //刪除飛出螢幕的外星人 if (a[0].alien_y > 720) { a.pop_front(); add_alien(a); //每次刪除都新增一個外星人 } if (!b.empty()) //刪除飛出螢幕的子彈 if (b[0].bullet_y < -20) b.pop_front(); for (int i = 0; i < a.size(); i++) //繪製外星人 { a[i].show_alien(); a[i].alien_y += alien_speed; } for (int i = 0; i < b.size(); i++) //繪製子彈 { if (b[i].bullet_x > 0 && b[i].bullet_x < 1350 && b[i].bullet_y > -29 && b[i].bullet_y < 730) b[i].show_bullet(); b[i].bullet_y -= b[i].bullet_speed; } } bool launch(int a) //遊戲執行 { Airplane plane; Bullet bul; Alien ali; if (a == 1) { alien_speed = 3; alien_num = 5; plane.airplane_speed = 10; level13.load("music\\level01.mp3"); level13.play(); } if (a == 2) { alien_speed = 6; alien_num = 7; plane.airplane_speed = 20; level46.load("music\\level03.mp3"); level46.play(); } deque<Alien> aliens; deque<Bullet> bullets; ali.alien_x = rand() % 1320; aliens.push_back(ali); //放入頭,便於後續操作 for (int i = 0; i < alien_num - 1; i++) add_alien(aliens); char hit; //記錄按鍵 plane.show_bg(); plane.show_plane(); while (1) { BeginBatchDraw(); srand((unsigned)time(NULL)); //隨機數種子 plane.show_bg(); update_energy(plane,aliens); show_energy(); if (player_eneygy == 0) { gameov.load("music\\gameover.mp3"); gameov.play(); LOGFONT f; set_textstyle(f,150,10); settextstyle(&f); settextcolor(RGB(255,255)); outtextxy(300,_T("GAME OVER")); FlushBatchDraw(); Sleep(1000); return 1; } update_level(aliens); show_score_level(); get_Cours(bul); if (_kbhit()) { hit = _getch(); if (hit == ' ') //判斷是否往佇列裡新增子彈 { bul.bullet_x = plane.airplane_x + 25; bul.bullet_y = plane.airplane_y ; bullets.push_back(bul); } else if (hit == 27) { LOGFONT f; set_textstyle(f,255)); outtextxy(530,_T("是否返回初始介面")); outtextxy(490,_T("是(回車)否(任意鍵)")); FlushBatchDraw(); hit = _getch(); if (hit == 13) return 1; } else plane.key_Down(hit); } draw_bu_al(aliens,bullets); FlushBatchDraw(); plane.show_plane(); EndBatchDraw(); //cleardevice(); //Sleep(100); system("cls"); } level13.stop(); level46.stop(); } bool choose_all(char key,int &i) //初始選擇介面按鍵處理 { switch (key) { case 72: if (i >= 2) { choose.load("music\\choose.mp3"); choose.play(); i--; home(i); } return 0; break; case 80: if (i <= 3) { choose.load("music\\choose.mp3"); choose.play(); i++; home(i); } return 0; break; case 13: choose.play(); switch (i) { case 1: mu_be01.stop(); launch(1); return 0; break; case 2: mu_be01.stop(); launch(2); return 0; break; case 3: help(); return 0; break; case 4: if (exit()) return 1; break; } break; default: return 0; break; } }
/*main.cpp*/ #include <iostream> #include <graphics.h> #include <conio.h> #include<windows.h> #include<Mmsystem.h> #include "launch.h" #include "setting.h" #pragma comment(lib,"winmm.lib") using namespace std; int main() { int i = 1; char be_key; //初始介面按鍵輸入 load_music01(); initgraph(1360,760); home(1); while (1) { home(i); be_key = _getch(); if (choose_all(be_key,i)) return 0; } closegraph(); }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。