C++雷霆战机可视化小游戏 C++实现雷霆战机可视化小游戏
木笔# 人气:0用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 high, 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, 202, 131); } else { setlinecolor(RGB(255, 218, 185)); line(1501, 155, 23, 213); line(437, 600, 471, 493); line(1287, 616, 1034, 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, 255, 0)); line(1034, 640, 1188, 504); line(1034, 332, 985, 254); line(39, 697, 348, 315); setlinecolor(RGB(255, 0, 255)); line(1117, 259, 942, 593); line(942, 593, 1178, 666); line(985, 254, 1292, 105); } setlinecolor(RGB(255, 255, 255)); } void load_be_bk() //加载帮助界面背景 { loadimage(&be_bk01, L"image\\be_bk01.jpg", 1360, 760); putimage(0, 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, 30); roundrect(530, 130, 830, 630, 30, 30); LOGFONT f; set_textstyle(f, 30, 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, 810, 550); outtextxy(605, 570, _T("制作不易,请勿抄袭")); outtextxy(605, 600, _T(" ——木笔制作")); i++; EndBatchDraw(); Sleep(10); if (_kbhit()) { _getch(); break; } } } void home(int i) //初始界面 { BeginBatchDraw(); loadimage(&be_bk02, L"image\\be_bk02.jpg", 1360, 760); putimage(0, 0, &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, 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, 255 - j * 4, 217 - j * 5)); line(1120, 540 + j, 1290, 540 + j); } break; case 3: for (int j = 0; j < 30; j++) { setlinecolor(RGB(0 + j * 5, 255 - j * 4, 217 - j * 5)); line(1120, 605 + j, 1290, 605 + j); } break; case 4: for (int j = 0; j < 30; j++) { setlinecolor(RGB(0 + j * 5, 255 - j * 4, 217 - j * 5)); line(1120, 670 + j, 1290, 670 + j); } break; } setlinecolor(RGB(152, 245, 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, 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, L"image\\be_bk02.jpg", 1360, 760); putimage(0, 0, &be_bk02); LOGFONT f; set_textstyle(f, 50, 20); settextcolor(RGB(255, 255, 255)); outtextxy(390, 230, _T("是否要退出游戏?")); outtextxy(310, 320, _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, char*, 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, 254, 0); if (errcode) { wmcierror(errcode, buf, 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", 1360, 760); rotateimage(&plane01, &plane01, 3.1415926); } void Airplane::show_bg() //绘制背景图 { putimage(0, 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, 0, s, -1, NULL, 0); wchar_t* wide = new wchar_t[n]; MultiByteToWideChar(0, 0, s, -1, wide, n); wides = wide; } void show_score_level() //显示得分和关卡信息 { LOGFONT f; set_textstyle(f, 20, 5); //设置字体信息 wchar_t* wides1 = NULL; trans_int_ch(wides1, score); roundrect(1220, 20, 1320, 50, 20, 20); //绘制得分信息框 rectangle(1215, 15, 1325, 55); settextstyle(&f); outtextxy(1235, 27, _T("得分: ")); settextstyle(&f); outtextxy(1290, 27, wides1); wchar_t* wides2 = NULL; trans_int_ch(wides2, level); roundrect(1220, 70, 1320, 100, 20, 20); //绘制得分信息框 rectangle(1215, 65, 1325, 105); settextstyle(&f); outtextxy(1235, 77, _T("关卡: ")); settextstyle(&f); outtextxy(1290, 77, 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, 238, 0)); rectangle(15, 15, 165, 55); solidroundrect(20, 20, 160, 50, 8, 8); outtextxy(70, 22, ene); break; case 80: setfillcolor(RGB(192, 255, 62)); rectangle(15, 15, 165, 55); solidroundrect(20, 20, 132, 50, 8, 8); outtextxy(70, 22, ene); break; case 60: setfillcolor(RGB(255, 215, 0)); rectangle(15, 15, 165, 55); solidroundrect(20, 20, 104, 50, 8, 8); outtextxy(70, 22, ene); break; case 40: setfillcolor(RGB(238, 238, 0)); rectangle(15, 15, 165, 55); solidroundrect(20, 20, 76, 50, 8, 8); outtextxy(70, 22, ene); break; case 20: setfillcolor(RGB(255, 0, 0)); rectangle(15, 15, 165, 55); solidroundrect(20, 20, 48, 50, 8, 8); outtextxy(70, 22, ene); break; case 0: settextstyle(&f); outtextxy(70, 22, 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, 255)); outtextxy(300, 230, _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,40,10); settextstyle(&f); settextcolor(RGB(255, 255, 255)); outtextxy(530, 230, _T("是否返回初始界面")); outtextxy(490, 320, _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(); }
加载全部内容