From 897abcf0686ce01b836596ead4eb503822f0ee53 Mon Sep 17 00:00:00 2001 From: flykhan Date: Sun, 3 May 2026 11:29:39 +0800 Subject: [PATCH] fix: SDL2 Linux port - fix black screen by setting CWD to binary path --- CMakeLists.txt | 47 +- tank_battles_on_the_scrap_paper.sln | 31 - tank_battles_on_the_scrap_paper/data_config.h | 73 +- tank_battles_on_the_scrap_paper/main.cpp | 1231 +++++++++-------- tank_battles_on_the_scrap_paper/resource.h | 16 - tank_battles_on_the_scrap_paper/resource.rc | Bin 3018 -> 0 bytes .../tank_battles_on_the_scrap_paper.vcxproj | 147 -- ...battles_on_the_scrap_paper.vcxproj.filters | 46 - 8 files changed, 670 insertions(+), 921 deletions(-) delete mode 100644 tank_battles_on_the_scrap_paper.sln delete mode 100644 tank_battles_on_the_scrap_paper/resource.h delete mode 100644 tank_battles_on_the_scrap_paper/resource.rc delete mode 100644 tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj delete mode 100644 tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj.filters diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c1470a..186acd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,12 @@ project(tank_battles_on_the_scrap_paper set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +# ── SDL2 依赖 ── +find_package(SDL2 REQUIRED) +find_package(SDL2_image REQUIRED) +find_package(SDL2_mixer REQUIRED) +find_package(SDL2_ttf REQUIRED) + # ── 源文件 ── set(SOURCES tank_battles_on_the_scrap_paper/main.cpp @@ -18,45 +24,18 @@ set(HEADERS tank_battles_on_the_scrap_paper/tank.h tank_battles_on_the_scrap_paper/map.h tank_battles_on_the_scrap_paper/data_config.h - tank_battles_on_the_scrap_paper/resource.h ) # ── 可执行文件 ── -add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS} - tank_battles_on_the_scrap_paper/resource.rc +add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE + SDL2::SDL2 + SDL2_image::SDL2_image + SDL2_mixer::SDL2_mixer + SDL2_ttf::SDL2_ttf ) -# ── Windows 特定配置 ── -if(WIN32) - # EasyX 图形库 - target_include_directories(${PROJECT_NAME} PRIVATE - ${EASYX_INCLUDE_DIR} - ) - - # Windows 多媒体库 - target_link_libraries(${PROJECT_NAME} PRIVATE - winmm.lib - gdi32.lib - ) - - # 控制台子系统 - set_target_properties(${PROJECT_NAME} PROPERTIES - WIN32_EXECUTABLE FALSE - ) - - target_compile_definitions(${PROJECT_NAME} PRIVATE - _CONSOLE - _UNICODE - UNICODE - ) -else() - # 非 Windows 平台给出提示 - message(WARNING - "${PROJECT_NAME} 依赖 EasyX (Windows-only 图形库)," - "当前平台不支持编译。仅生成项目结构参考。" - ) -endif() - # ── 复制资源文件到构建目录 ── file(COPY tank_battles_on_the_scrap_paper/images/ diff --git a/tank_battles_on_the_scrap_paper.sln b/tank_battles_on_the_scrap_paper.sln deleted file mode 100644 index aa28c4a..0000000 --- a/tank_battles_on_the_scrap_paper.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.33530.505 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tank_battles_on_the_scrap_paper", "tank_battles_on_the_scrap_paper\tank_battles_on_the_scrap_paper.vcxproj", "{AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Debug|x64.ActiveCfg = Debug|x64 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Debug|x64.Build.0 = Debug|x64 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Debug|x86.ActiveCfg = Debug|Win32 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Debug|x86.Build.0 = Debug|Win32 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Release|x64.ActiveCfg = Release|x64 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Release|x64.Build.0 = Release|x64 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Release|x86.ActiveCfg = Release|Win32 - {AC8C4A04-1650-473C-8E9A-3B7CDE2AD5CC}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4E9B74CF-EE0B-430C-8380-34BE94639065} - EndGlobalSection -EndGlobal diff --git a/tank_battles_on_the_scrap_paper/data_config.h b/tank_battles_on_the_scrap_paper/data_config.h index 60ee9ec..e170b05 100644 --- a/tank_battles_on_the_scrap_paper/data_config.h +++ b/tank_battles_on_the_scrap_paper/data_config.h @@ -1,52 +1,51 @@ -// ö +// �������ö��� #ifndef DATA_CONFIG_H #define DATA_CONFIG_H -// tank bullet ͷļ +// ���� tank �� bullet ����ͷ�ļ� #include "tank.h" #include "bullet.h" -// -const int CELL_SIZE = 30; // ÿԪ̹ˡǽյصȣĴС磺أ -const int MAP_CELL_NUM = 20; // ͼСΪMAP_CELL_NUM^2 -const int ENEMIES_NUM = 10; // ͼĵ -const int BULLET_NUM = 20; // ͼӵ -const int SINGLE_BULLET = 3; // ÿ̹ͬʱڵӵ -const int White = 0; // Ҷͼ- -const int Black = 1; // Ҷͼ- +// �������� +const int CELL_SIZE = 30; // ÿ����Ԫ��̹�ˡ�ǽ���յصȣ��Ĵ�С�����磺���أ� +const int MAP_CELL_NUM = 20; // ��ͼ��СΪMAP_CELL_NUM^2 +const int ENEMIES_NUM = 10; // ��ͼ�����ĵ������� +const int BULLET_NUM = 20; // ��ͼ�������ӵ����� +const int SINGLE_BULLET = 3; // ÿ��̹��ͬʱ���ڵ�����ӵ����� +const int White = 0; // �Ҷ�ͼ-�� +const int Black = 1; // �Ҷ�ͼ-�� -#define PIEXL1 30 //س +#define PIEXL1 30 //���س��� #define PIEXL2 4 -#define X_OFFSET 50 //ϵһǽΪ׼ƫ -#define Y_OFFSET 45 //ϵһǽΪ׼ƫ +#define X_OFFSET 50 //�����ϵ�һ��ǽΪ��׼��ƫ���� +#define Y_OFFSET 45 //�����ϵ�һ��ǽΪ��׼��ƫ���� /* - ͼ - ʹ洢ͼϢ - map[x][y] 洢ǰ̹Ϣ - BLANK յ - RED_TANK 췽̹ - RED_DEAD_TANK 췽̹ - BLUE_TANK, ̹ - BLUE_DEAD_TANK ̹ + ��ͼ�� + ʹ������洢��ͼ��Ϣ + map[x][y] �洢��ǰ̹����Ϣ + BLANK �յ� + RED_TANK �췽̹�� + RED_DEAD_TANK �췽����̹�� + BLUE_TANK, ����̹�� + BLUE_DEAD_TANK ��������̹�� WALL ǽ - BULLET ӵ + BULLET �ӵ� */ enum CELL_Type { - BLANK, // յ - RED_TANK, // 췽̹ - RED_DEAD_TANK, // 췽̹ - BLUE_TANK, // ̹ - BLUE_DEAD_TANK, // ̹ + BLANK, // �յ� + RED_TANK, // �췽̹�� + RED_DEAD_TANK, // �췽����̹�� + BLUE_TANK, // ����̹�� + BLUE_DEAD_TANK, // ��������̹�� WALL, // ǽ - BULLET, // ӵ + BULLET, // �ӵ� }; -int map[MAP_CELL_NUM][MAP_CELL_NUM]; //map.hԤ - -int kill = 5; //ɱ -tank player; // -tank enemies[ENEMIES_NUM]; // -bullet E_bullets[BULLET_NUM * ENEMIES_NUM]; //з̹ӵ -bullet P_bullets[BULLET_NUM]; //ӵ - -tank enemy; // ڸĵ˵ԣѶõ +// 全局变量声明(extern),定义在 main.cpp 中 +extern int map[MAP_CELL_NUM][MAP_CELL_NUM]; +extern int kill; +extern tank player; +extern tank enemies[ENEMIES_NUM]; +extern bullet E_bullets[BULLET_NUM * ENEMIES_NUM]; +extern bullet P_bullets[BULLET_NUM]; +extern tank enemy; #endif // !DATA_CONFIG_H \ No newline at end of file diff --git a/tank_battles_on_the_scrap_paper/main.cpp b/tank_battles_on_the_scrap_paper/main.cpp index 864fd83..631d17c 100644 --- a/tank_battles_on_the_scrap_paper/main.cpp +++ b/tank_battles_on_the_scrap_paper/main.cpp @@ -1,24 +1,138 @@ -// Ŀֽϵ̹˴ս -#include -#include -#include -#include -#include +// 项目:纸牌上的坦克大战 - SDL2 Linux Port +#include +#include #include #include -// data_config ͷļ -#include "data_config.h" -// #include "map.h" // Ԥͼͷļ -// #include "main.h" // 뺯ͷļ +#include +#include +#include +#include +#include +#include -// -------- Ч -------- -#include"resource.h"//Դ֮һresource.hͷļ ǵü -#include -#include -#pragma comment(lib,"winmm.lib") +// 引入 data_config 等头文件 +#include "data_config.h" +// #include "map.h" // 引入预设地图头文件 +// #include "main.h" // 引入函数声明头文件 using namespace std; +// -------- 全局变量定义 --------- +int map[MAP_CELL_NUM][MAP_CELL_NUM]; //用map.h预置 +int kill = 5; //玩家击杀数 +tank player; //玩家 +tank enemies[ENEMIES_NUM]; //敌人 +bullet E_bullets[BULLET_NUM * ENEMIES_NUM]; //敌方坦克子弹数量 +bullet P_bullets[BULLET_NUM]; //玩家子弹数量 +tank enemy; // 用于修改敌人的属性,难度设置时用到 + +// -------- SDL2 全局变量 -------- +SDL_Window* g_window = NULL; +SDL_Renderer* g_renderer = NULL; +TTF_Font* g_font = NULL; +Mix_Music* g_bgm = NULL; + +// -------- 辅助函数 -------- + +// 加载纹理(带缩放) +SDL_Texture* load_texture(const char* path) { + static unordered_map tex_cache; + string key(path); + auto it = tex_cache.find(key); + if (it != tex_cache.end()) { + return it->second; + } + SDL_Surface* surf = IMG_Load(path); + if (!surf) { + fprintf(stderr, "IMG_Load error: %s - %s\n", path, IMG_GetError()); + return NULL; + } + SDL_Texture* tex = SDL_CreateTextureFromSurface(g_renderer, surf); + SDL_FreeSurface(surf); + if (tex) { + SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND); + } else { + fprintf(stderr, "CreateTexture error: %s - %s\n", path, SDL_GetError()); + } + tex_cache[key] = tex; + return tex; +} + +// 渲染纹理到指定位置和大小 +void render_texture(SDL_Texture* tex, int x, int y, int w, int h) { + if (!tex) return; + SDL_Rect dst = {x, y, w, h}; + SDL_RenderCopy(g_renderer, tex, NULL, &dst); +} + +// 渲染纹理到指定位置(不缩放,使用纹理原始大小) +void render_texture_raw(SDL_Texture* tex, int x, int y) { + if (!tex) return; + int w, h; + SDL_QueryTexture(tex, NULL, NULL, &w, &h); + SDL_Rect dst = {x, y, w, h}; + SDL_RenderCopy(g_renderer, tex, NULL, &dst); +} + +// 带缩放加载并渲染纹理(一次性操作) +void draw_image(const char* path, int x, int y, int w, int h) { + SDL_Texture* tex = load_texture(path); + render_texture(tex, x, y, w, h); +} + +// 渲染文本 +void render_text(const char* text, int x, int y, SDL_Color color) { + if (!g_font || !text) return; + SDL_Surface* surf = TTF_RenderUTF8_Blended(g_font, text, color); + if (!surf) return; + SDL_Texture* tex = SDL_CreateTextureFromSurface(g_renderer, surf); + if (tex) { + SDL_Rect dst = {x, y, surf->w, surf->h}; + SDL_RenderCopy(g_renderer, tex, NULL, &dst); + SDL_DestroyTexture(tex); + } + SDL_FreeSurface(surf); +} + +// 渲染int数值为文本 +void render_int(int value, int x, int y, SDL_Color color) { + string s = to_string(value); + render_text(s.c_str(), x, y, color); +} + +// 清屏 +void clear_screen() { + SDL_SetRenderDrawColor(g_renderer, 0, 0, 0, 255); + SDL_RenderClear(g_renderer); +} + +// 更新画面 +void present_screen() { + SDL_RenderPresent(g_renderer); +} + +// 事件处理辅助:等待并处理键盘和鼠标事件,返回是否退出 / 转到菜单 +// 返回: 0=继续循环, -1=退出/返回菜单 +int handle_menu_events(bool& goto_menu) { + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + exit(0); + } + if (e.type == SDL_KEYDOWN) { + if (e.key.keysym.sym == SDLK_ESCAPE) { + goto_menu = true; + return -1; + } + } + if (e.type == SDL_MOUSEBUTTONDOWN) { + return 1; // 鼠标点击发生,调用者需检查坐标 + } + } + return 0; +} + +// -------- 原函数声明(保持不变) -------- void EnemyBulletMove(); void PlayerBulletMove(); int BulletMoveCheck(int dir, bullet bul); @@ -45,106 +159,123 @@ void PlayerShoot(); int TankMoveCheck(int dir, tank tank); void Update(); -// git - +// git 提交 /* - ˵棺 - չʾϷѶȣ˳ѡ - ûͨwsѡӦİťس + 菜单界面: + 展示开始游戏,难度设置,退出等选项 + 用户通过w/s来选择对应的按钮,回车进行选择 - Ϸ - ѡϷͼʼͼ̹ + 开始游戏: + 当选中开始游戏时,跳转游戏主函数,直接进入游戏。 - Ѷȣ - öӦѶȽϷ + 难度设置: + 当选中难度设置时,跳转难度选择函数,进行对敌方坦克血量以及攻击力进行变化等操作。 + 调整完毕之后需要esc返回菜单然后才可以进入游戏。 - ڿԱ - ҵҳ棬չʾԱ + 退出游戏: + 当选中退出时,直接退出程序。 - ˳Ϸ - ѡ˳Ϸ + 关于开发人员 + 跳转相关信息页面,展示开发人员信息 - Ϸ - չʾͼ̹ˣҶ̹ԶƶͿ - wsadҷƶ - ¿ոԼǰڵ - УѪ - һ̹ˣϷ,ص˵ + // 游戏进行中的开始页面 - ͣ - չʾϷ˳ϷťͬʱϷͣ +游戏过程 + 展示地图和坦克,玩家控制己方坦克进行自动移动和开火 + 操作wsad控制己方坦克进行上下左右移动 + 按下空格控制己方向前发射子弹 + 撞到墙,掉血 + 当杀死所有敌方坦克时,游戏胜利,返回主菜单 + + 暂停界面 + 展示继续游戏、退出游戏按钮,同时游戏暂停 */ /* - - 1˵ - 2˵Ϸ - 3Ϸͣ - 4ͣò˵ + 功能模块 + 1.菜单界面 + 2.菜单界面转到游戏界面 + 3.游戏界面转到暂停界面 + 4.暂停界面转到菜单界面 */ //-----------------view------------------------ /* - ˣ - ܣչʾϷѶȣ˳ѡ, - Ϸ - ѡϷʱϷ溯ֱӽϷ - Ѷȣ - ѡѶʱҳ溯з̹ѪԼ仯ĺݡ - ֮Ҫesc˵ȻɽϷ - ˳Ϸ - ѡ˳ʱ˳ֱӽϷ - ǣ - չʾŶϢ - // Ϸеʼҳ + 功能描述: + 功能:展示开始游戏,难度设置,退出等选项, 关于我们 + 开始游戏: + 当选中开始游戏时,跳转游戏主函数,直接进入游戏。 + 难度设置: + 当选中难度设置时,跳转难度选择函数,进行对敌方坦克血量以及攻击力进行变化等操作。 + 调整完毕之后需要esc返回菜单然后才可以进入游戏。 + 退出游戏: + 当选中退出时,直接退出程序。 + 关于我们: + 展示团队信息 + // 游戏进行中的开始页面 */ void MenuView(); /* -* Ϸ - ˣunder a bushel - ܣ +* 游戏界面 + 功能描述: */ -// ÿһΣͼͼÿһ״̬ -// һµͼϽӣ̹˺ӵ꣺λúͷ -void GameView() //Ϸͼ +// 每一帧,地图和坦克每一帧状态渲染 +// 在一个新的地图上进行操作,包括坦克和子弹的坐标:位置和方向 +void GameView() //游戏主界面视图 { - InitMap(); //ʼͼ - // InitMap(map1); //ʼͼ - EnemyInit(); //ʼз̹˵λ - PlayerInit(); //ʼ̹˵λ + InitMap(); //初始化地图 + // InitMap(map1); //初始化地图 + EnemyInit(); //初始化敌方坦克的位置 + PlayerInit(); //初始化己方坦克的位置 - GameView_ShowMap(); //ʾͼ - GameView_ShowTank(); //ʾ̹ + // 初始渲染 + clear_screen(); + GameView_ShowMap(); //显示地图 + GameView_ShowTank(); //显示坦克 + present_screen(); - while (!IsWin()) // Ϸûʤ + while (!IsWin()) // 游戏循环没有胜利 { - if (player.hp <= 0) //жҵֵǷСڻ 0 + if (player.hp <= 0) //判断玩家的生命值是否小于或等于 0 { - GameView_ShowLose(); // failView ʾʧͼ - /*MenuView();*/ //ص˵ + GameView_ShowLose(); //调用 failView 函数显示失败视图 + /*MenuView();*/ //返回主菜单界面 break; } - if (GetAsyncKeyState(VK_ESCAPE)) //ûļ¼ǷΪ ESC - { - MenuView(); // menuView ص˵ + // 处理ESC和窗口事件 + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + exit(0); + } + if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { + MenuView(); //调用菜单 menuView 函数返回主菜单界面 + } } - Move(); // MoveShoot Update ЩҪʵ̹˺ӵƶ״̬¡ - // - if(GetAsyncKeyState(VK_SPACE)) + Move(); // 调用 Move、Shoot 和 Update 函数:这些函数需要实现坦克和子弹的移动、射击和状态更新。 + //射击 + const Uint8* keys = SDL_GetKeyboardState(NULL); + if (keys[SDL_SCANCODE_SPACE]) PlayerShoot(); EnemyShoot(); // Update(); Update(); - GameView_ShowMap(); //ʾͼ״̬ - GameView_ShowBullet(); //ʾӵ״̬ - GameView_ShowTank(); //ʾ̹˵״̬ + + // 渲染帧 + clear_screen(); + GameView_ShowMap(); //显示地图的最新状态 + GameView_ShowBullet(); //再进行子弹显示更新状态 + GameView_ShowTank(); //显示坦克的最新状态 + present_screen(); + + SDL_Delay(16); // ~60 FPS,控制帧率 } - if (IsWin()) //Ϸʤ winView ʾʤͼص˵档 + if (IsWin()) //如果游戏胜利,调用 winView 函数显示胜利界面,并返回主菜单界面。 { GameView_ShowWIN(); /*MenuView();*/ @@ -152,10 +283,10 @@ void GameView() // } /* - :Ӻˮ - - жӵǷﵽޣ0-3ֱӱ0-3ҵһis_live == false,break - ģӵʼ + 创建者:桃仁和毛血旺 + 功能 + 用来判断玩家子弹是否到达上限,0-3跳过直接返回0-3并找到第一个is_live == false,break + 射击模块:子弹初始化发射 */ void PlayerShoot() { @@ -167,7 +298,7 @@ void PlayerShoot() { if (P_bullets[i].is_live == false) { - //ʼӵ + //初始化子弹 P_bullets[i].x = player.x; P_bullets[i].y = player.y; P_bullets[i].dir = player.dir; @@ -179,11 +310,11 @@ void PlayerShoot() } /* - :Ӻˮ - 룺˽ṹ - ˷ӵԶ,̹ - жǷҪ䣬%2,01 - if Ҫ ӵ + 创建者:桃仁和毛血旺 + 输入:敌人结构体数组 + 敌人发射子弹自动射击,由敌方坦克 + 先通过随机数判断是否要发射,随机数%2,返回0或1 + if 要发射 则循环子弹数组 */ void EnemyShoot() { @@ -191,12 +322,12 @@ void EnemyShoot() if ((clock() - start) < 3000) return; start = clock(); - for (int i = 0; i < ENEMIES_NUM; i++) //е̹ + for (int i = 0; i < ENEMIES_NUM; i++) //遍历所有敌方坦克 { if (enemies[i].hp > 0) { for (auto& j : E_bullets) { - if (j.is_live == false) //ֻҪһӵڣ䣬ŶѾڣ򲻷ӵ + if (j.is_live == false) //只要一个子弹不存活,发射,否则若都已经存在,则不发射子弹 { j.x = enemies[i].x; j.y = enemies[i].y; @@ -211,81 +342,70 @@ void EnemyShoot() } /* - :Ӻˮ - ܣ - ƶӵƶӵĿĴײ + 创建者:桃仁和毛血旺 + 功能: + 调用移动函数,子弹移动函数和碰撞检测等 */ void Move() { bool move = false; - if (GetAsyncKeyState('W') || GetAsyncKeyState(VK_UP)) + const Uint8* keys = SDL_GetKeyboardState(NULL); + if (keys[SDL_SCANCODE_W] || keys[SDL_SCANCODE_UP]) { player.dir = UP; move = true; } - else if (GetAsyncKeyState('S') || GetAsyncKeyState(VK_DOWN)) + else if (keys[SDL_SCANCODE_S] || keys[SDL_SCANCODE_DOWN]) { player.dir = DOWN; move = true; } - else if (GetAsyncKeyState('A') || GetAsyncKeyState(VK_LEFT)) + else if (keys[SDL_SCANCODE_A] || keys[SDL_SCANCODE_LEFT]) { player.dir = LEFT; move = true; } - else if (GetAsyncKeyState('D') || GetAsyncKeyState(VK_RIGHT)) + else if (keys[SDL_SCANCODE_D] || keys[SDL_SCANCODE_RIGHT]) { player.dir = RIGHT; move = true; - };//ķ + };//设置方向 if (move) { - PlayerMove(); //player.dir ȫֱô + PlayerMove(); //player.dir 是全局变量所以能调用 } - EnemiesMove(); //ƶ + EnemiesMove(); //敌人移动函数 PlayerBulletMove(); EnemyBulletMove(); } ///* -//* ҷǰһǿյ +//* 判断我方坦克前方是否为空地 //*/ //bool PlayerCollision(); /* - ˣС yang - ܣ - mapɵͼ + 创建者:小 yang + 功能: + 根据map数组生成地图 */ -void GameView_ShowMap() // ̹ȫֵģҪ +void GameView_ShowMap() // 坦克是全局的,不需要传参 //void GameView_ShowMap(tank player) { - // ˫ - setbkmode(TRANSPARENT); // ñ͸ - BeginBatchDraw(); // ʼͼ + //绘制背景 + draw_image("images/游戏主界面背景.jpg", 0, 0, 700, 700); - //ȡͼƬ - //·ȷȷΨһ ------ - IMAGE image_WALL, image_back, image_RED_HP; - // IMAGE image_WALL, image_back, image_RED_HP, image_BLUE_HP; - loadimage(&image_WALL, ".//images//wall.jpg", CELL_SIZE, CELL_SIZE); - loadimage(&image_back, ".//images//Ϸ汳.jpg", 700, 700); - loadimage(&image_RED_HP, ".//images//red_hp_bar.jpg", CELL_SIZE, CELL_SIZE); - // loadimage(&image_BLUE_HP, ".//images//blue_hp.jpg", 30, 30); // version1汾ĿǰзѪ - - //Ⱦ - putimage(0, 0, &image_back); - - //췽̹HPȾ + //红色方HP渲染 + SDL_Texture* hp_tex = load_texture("images/red_hp_bar.jpg"); for (int i = 0; i < player.hp; i++) { - putimage(100 + i * 30 , 10, &image_RED_HP); + render_texture(hp_tex, 100 + i * 30, 10, CELL_SIZE, CELL_SIZE); } - ////̹HPȾ + ////蓝色方HP渲染 //for (int j = 0; j < player.hp; j++) //{ // putimage(570 - j * 30, 120, &image_RED_HP); @@ -295,25 +415,27 @@ void GameView_ShowMap() // ̹ for (auto& i : enemies) { if (i.hp <= 0) dieNum++; } - //ʾʵʱȾ - settextcolor((157, 157, 157)); - settextstyle(30, 0, ""); - outtextxy(110, 660, "ܣ"); - outtextxy(185, 660, to_string(dieNum).data()); - outtextxy(210, 660, "/"); - outtextxy(225, 660, "10"); + + //文本渲染杀敌数 + SDL_Color text_color = {157, 157, 157, 255}; + render_text("杀敌:", 110, 660, text_color); + render_int(dieNum, 185, 660, text_color); + render_text("/", 210, 660, text_color); + render_text("10", 225, 660, text_color); - outtextxy(325, 660, string("" + to_string(player.attack)).data()); + //当前攻击力 + string atk_str = "当前攻击力" + to_string(player.attack); + render_text(atk_str.c_str(), 325, 660, text_color); - - //ǽȾ + //墙壁纹理渲染 + SDL_Texture* wall_tex = load_texture("images/wall.jpg"); for (int i = 0; i < MAP_CELL_NUM; i++) { for (int j = 0; j < MAP_CELL_NUM; j++) { if (map[i][j] == WALL) { - putimage(j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, &image_WALL); + render_texture(wall_tex, j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); } } } @@ -321,110 +443,63 @@ void GameView_ShowMap() // ̹ /* - ˣ - ܣڵͼ + 创建者: + 功能:渲染子弹到地图 */ // void GameView_ShowBullet(); // void GameView_ShowBullet(bullet b); /* - ˣС yang - ܣ̹ͼ + 创建者:小 yang + 功能:渲染坦克到地图 */ void GameView_ShowTank() // void GameView_ShowTank(tank player, tank enemies[]) { - // ˫ - setbkmode(TRANSPARENT); // ñ͸ - BeginBatchDraw(); // ʼͼ + //我方坦克纹理 + SDL_Texture* red_up = load_texture("images/red_up_b.png"); + SDL_Texture* red_down = load_texture("images/red_down_b.png"); + SDL_Texture* red_left = load_texture("images/red_left_b.png"); + SDL_Texture* red_right = load_texture("images/red_right_b.png"); - //̹ͼƬ - IMAGE image_REDtank_UP[2], image_REDtank_DOWN[2], image_REDtank_LEFT[2], image_REDtank_RIGHT[2], + //敌方坦克纹理 + SDL_Texture* blue_up = load_texture("images/blue_up_b.png"); + SDL_Texture* blue_down = load_texture("images/blue_down_b.png"); + SDL_Texture* blue_left = load_texture("images/blue_left_b.png"); + SDL_Texture* blue_right = load_texture("images/blue_right_b.png"); - image_BLUEtank_UP[2], image_BLUEtank_DOWN[2], image_BLUEtank_LEFT[2], image_BLUEtank_RIGHT[2], + //死亡坦克纹理 + SDL_Texture* dead_tank = load_texture("images/dead_tank_b.png"); - image_BLUE_DEADtank[2]; - - //صͼ - //·ȷȷΨһ ------ - - loadimage(&image_REDtank_DOWN[White], ".//images//red_down_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_REDtank_DOWN[Black], ".//images//red_down_b.png", CELL_SIZE, CELL_SIZE); - - loadimage(&image_REDtank_UP[White], ".//images//red_up_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_REDtank_UP[Black], ".//images//red_up_b.png", CELL_SIZE, CELL_SIZE); - - loadimage(&image_REDtank_LEFT[White], ".//images//red_left_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_REDtank_LEFT[Black], ".//images//red_left_b.png", CELL_SIZE, CELL_SIZE); - - loadimage(&image_REDtank_RIGHT[White], ".//images//red_right_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_REDtank_RIGHT[Black], ".//images//red_right_b.png", CELL_SIZE, CELL_SIZE); - - - loadimage(&image_BLUEtank_UP[White], ".//images//blue_up_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_BLUEtank_UP[Black], ".//images//blue_up_b.png", CELL_SIZE, CELL_SIZE); - - loadimage(&image_BLUEtank_DOWN[White], ".//images//blue_down_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_BLUEtank_DOWN[Black], ".//images//blue_down_b.png", CELL_SIZE, CELL_SIZE); - - loadimage(&image_BLUEtank_LEFT[White], ".//images//blue_left_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_BLUEtank_LEFT[Black], ".//images//blue_left_b.png", CELL_SIZE, CELL_SIZE); - - loadimage(&image_BLUEtank_RIGHT[White], ".//images//blue_right_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_BLUEtank_RIGHT[Black], ".//images//blue_right_b.png", CELL_SIZE, CELL_SIZE); - - // loadimage(&image_RED_DEADtank, "./̹.png", CELL_SIZE, CELL_SIZE); // ̹˱ϺζϷֱӵϷʧҳ棬˲ҪʾԼı״̬ - loadimage(&image_BLUE_DEADtank[White], ".//images//dead_tank_w.png", CELL_SIZE, CELL_SIZE); - loadimage(&image_BLUE_DEADtank[Black], ".//images//dead_tank_b.png", CELL_SIZE, CELL_SIZE); - //loadimage(&image_BLANK, ".//images//blank.jpg", CELL_SIZE, CELL_SIZE); - - - - - //ȾͼԪ + //渲染地图元素 for (int i = 0; i < MAP_CELL_NUM; i++) { for (int j = 0; j < MAP_CELL_NUM; j++) { - //if (map[i][j] == BLANK) - //{ - // putimage(j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, &image_BLANK); // ͼ - //} - - if ((map[i][j] == RED_TANK && player.dir == LEFT)) + if (map[i][j] == RED_TANK && player.dir == LEFT) { - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_LEFT[White], SRCAND); - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_LEFT[Black], SRCPAINT); + render_texture(red_left, player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); } if (map[i][j] == RED_TANK && player.dir == RIGHT) { - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_RIGHT[White], SRCAND); - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_RIGHT[Black], SRCPAINT); + render_texture(red_right, player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); } if (map[i][j] == RED_TANK && player.dir == DOWN) { - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_DOWN[White], SRCAND); - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_DOWN[Black], SRCPAINT); + render_texture(red_down, player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); } if (map[i][j] == RED_TANK && player.dir == UP) { - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_UP[White], SRCAND); - putimage(player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, &image_REDtank_UP[Black], SRCPAINT); + render_texture(red_up, player.x * CELL_SIZE + X_OFFSET, player.y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); } - - //if (map[i][j] == RED_DEAD_TANK) - //{ - - // putimage(j * CELL_SIZE + X_OFFSET, i * CELL_SIZE + Y_OFFSET, &image_RED_DEADtank); - //} } } - //Ⱦ̹ + //渲染敌方坦克 for (int i = 0; i < ENEMIES_NUM; i++) { if (enemies[i].is_taken) @@ -433,213 +508,134 @@ void GameView_ShowTank() switch (enemies[i].dir) { case UP: - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_UP[White], SRCAND); - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_UP[Black], SRCPAINT); + render_texture(blue_up, enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); break; case DOWN: - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_DOWN[White], SRCAND); - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_DOWN[Black], SRCPAINT); + render_texture(blue_down, enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); break; case LEFT: - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_LEFT[White], SRCAND); - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_LEFT[Black], SRCPAINT); + render_texture(blue_left, enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); break; case RIGHT: - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_RIGHT[White], SRCAND); - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUEtank_RIGHT[Black], SRCPAINT); + render_texture(blue_right, enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); break; default: break; } } else { - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUE_DEADtank[White], SRCAND); - putimage(enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, &image_BLUE_DEADtank[Black], SRCPAINT); + render_texture(dead_tank, enemies[i].x * CELL_SIZE + X_OFFSET, enemies[i].y * CELL_SIZE + Y_OFFSET, CELL_SIZE, CELL_SIZE); } } - - // ͼʾͼ - EndBatchDraw(); // ͼ } - -IMAGE image_BULLET[4][2]; +// 子弹纹理缓存(仅加载一次) +SDL_Texture* g_bullet_tex[4] = {NULL, NULL, NULL, NULL}; void GameView_ShowBullet() { - bool b = true; - if (b) { - b = false; - loadimage(&image_BULLET[UP][White], ".//images//B_UP_w.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2); - loadimage(&image_BULLET[UP][Black], ".//images//B_UP_b.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2); - loadimage(&image_BULLET[DOWN][White], ".//images//B_DOWN_w.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2); - loadimage(&image_BULLET[DOWN][Black], ".//images//B_DOWN_b.png", CELL_SIZE / 2 / 2, CELL_SIZE / 2); - loadimage(&image_BULLET[LEFT][White], ".//images//B_LEFT_w.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2); - loadimage(&image_BULLET[LEFT][Black], ".//images//B_LEFT_b.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2); - loadimage(&image_BULLET[RIGHT][White], ".//images//B_RIGHT_w.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2); - loadimage(&image_BULLET[RIGHT][Black], ".//images//B_RIGHT_b.png", CELL_SIZE / 2, CELL_SIZE / 2 / 2); + // 首次使用时加载子弹纹理 + if (!g_bullet_tex[UP]) { + g_bullet_tex[UP] = load_texture("images/B_UP_b.png"); + g_bullet_tex[DOWN] = load_texture("images/B_DOWN_b.png"); + g_bullet_tex[LEFT] = load_texture("images/B_LEFT_b.png"); + g_bullet_tex[RIGHT] = load_texture("images/B_RIGHT_b.png"); } - for (int i = 0; i < BULLET_NUM; i++) { //ӵ + + for (int i = 0; i < BULLET_NUM; i++) { //遍历玩家子弹 if (P_bullets[i].is_live) { int x = P_bullets[i].x * CELL_SIZE + X_OFFSET; int y = P_bullets[i].y * CELL_SIZE + Y_OFFSET; - putimage((P_bullets[i].dir > DOWN ? x : x + 10.5), (P_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[P_bullets[i].dir][White], SRCAND); - putimage((P_bullets[i].dir > DOWN ? x : x + 10.5), (P_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[P_bullets[i].dir][Black], SRCPAINT); + int tex_x = (P_bullets[i].dir > DOWN ? x : x + 10); + int tex_y = (P_bullets[i].dir > DOWN ? y + 10 : y); + int bw = (P_bullets[i].dir > DOWN ? CELL_SIZE / 2 : CELL_SIZE / 2 / 2); + int bh = (P_bullets[i].dir > DOWN ? CELL_SIZE / 2 / 2 : CELL_SIZE / 2); + render_texture(g_bullet_tex[P_bullets[i].dir], tex_x, tex_y, bw, bh); } } - for (int i = 0; i < BULLET_NUM * ENEMIES_NUM; i++) { //Ƶзӵ + for (int i = 0; i < BULLET_NUM * ENEMIES_NUM; i++) { //绘制敌方子弹 if (E_bullets[i].is_live) { int x = E_bullets[i].x * CELL_SIZE + X_OFFSET; int y = E_bullets[i].y * CELL_SIZE + Y_OFFSET; - putimage((E_bullets[i].dir > DOWN ? x : x + 10.5), (E_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[E_bullets[i].dir][White], SRCAND); - putimage((E_bullets[i].dir > DOWN ? x : x + 10.5), (E_bullets[i].dir > DOWN ? y + 10.5 : y), &image_BULLET[E_bullets[i].dir][Black], SRCPAINT); + int tex_x = (E_bullets[i].dir > DOWN ? x : x + 10); + int tex_y = (E_bullets[i].dir > DOWN ? y + 10 : y); + int bw = (E_bullets[i].dir > DOWN ? CELL_SIZE / 2 : CELL_SIZE / 2 / 2); + int bh = (E_bullets[i].dir > DOWN ? CELL_SIZE / 2 / 2 : CELL_SIZE / 2); + render_texture(g_bullet_tex[E_bullets[i].dir], tex_x, tex_y, bw, bh); } } - - /*for (int i = 0; i < 50; i++) - { - for (int j = 0; j < 50; j++) - { - if (map[i][j] == BULLET && bullets[i].dir == UP) - { - putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_UP); - } - if (map[i][j] == BULLET && BULLET.dir == DOWN) - { - putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_DOWN); - } - if (map[i][j] == BULLET && BULLET.dir == RIGHT) - { - putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_RIGHT); - } - if (map[i][j] == BULLET && BULLET.dir == LEFT) - { - putimage(j * PIEXL1 + X + (PIEXL1 - PIEXL2) / 2, i * PIEXL1 + (PIEXL1 - PIEXL2) / 2, &image_BULLET_LEFT); - } - } - }*/ } /* - ˣ - ܣʤ + 创建者:凌零 + 功能:显示胜利界面 */ void GameView_ShowWIN() { - cleardevice(); - setbkmode(TRANSPARENT); - IMAGE img; - loadimage(&img, ".//images//ʤ.png", 700, 700); - putimage(0, 0, &img); - IMAGE img_back; - loadimage(&img_back, ".//images//ذť.jpg", 150, 50); - putimage(30, 550, &img_back); - // - ExMessage msg; + clear_screen(); + draw_image("images/胜利.png", 0, 0, 700, 700); + draw_image("images/返回按钮.jpg", 30, 550, 150, 50); + present_screen(); + + bool goto_menu = false; while (true) { - //̲ - if (_kbhit()) - { - char key = _getch();//һֱ - //printf("%d,%c\n", key, key); - switch (key) - { - case 27://ϼ - //ز˵ - MenuView(); - //printf("ز˵/n"); - return; - break; - } + int ev = handle_menu_events(goto_menu); + if (goto_menu) { + MenuView(); + return; } - - // - if (peekmessage(&msg, WH_MOUSE)) - { - switch (msg.message) - { - case WM_LBUTTONDOWN: - - //ص˵ - if (msg.x >= 30 && msg.x <= 180 && msg.y >= 550 && msg.y <= 600) + if (ev == 1) { + //鼠标点击 - 判断返回按钮区域 + // 用SDL_GetMouseState获取点击坐标 + int mx, my; + Uint32 buttons = SDL_GetMouseState(&mx, &my); + if (buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) { + if (mx >= 30 && mx <= 180 && my >= 550 && my <= 600) { MenuView(); return; - //printf("ص˵\n"); - //תѶȽ } - break; - default: - break; } } + SDL_Delay(16); } - //char s[] = "˵"; - //outtextxy(250, 400, s); - //_getch(); } /* - ˣ - ܣʧܽ + 创建者:凌零 + 功能:显示失败界面 */ void GameView_ShowLose() { - cleardevice(); - setbkmode(TRANSPARENT); - IMAGE img; - loadimage(&img, ".//images//ʧ.png", 700, 700); - putimage(0, 0, &img); - IMAGE img_back; - loadimage(&img_back, ".//images//ذť.jpg", 150, 50); - putimage(30, 550, &img_back); - // - ExMessage msg; + clear_screen(); + draw_image("images/失败.png", 0, 0, 700, 700); + draw_image("images/返回按钮.jpg", 30, 550, 150, 50); + present_screen(); + + bool goto_menu = false; while (true) { - //̲ - if (_kbhit()) - { - char key = _getch();//һֱ - //printf("%d,%c\n", key, key); - switch (key) - { - case 27://ϼ - //ز˵ - MenuView(); - //printf("ز˵/n"); - return; - break; - } + int ev = handle_menu_events(goto_menu); + if (goto_menu) { + MenuView(); + return; } - - // - if (peekmessage(&msg, WH_MOUSE)) - { - switch (msg.message) - { - case WM_LBUTTONDOWN: - - //ص˵ - if (msg.x >= 30 && msg.x <= 180 && msg.y >= 550 && msg.y <= 600) + if (ev == 1) { + int mx, my; + Uint32 buttons = SDL_GetMouseState(&mx, &my); + if (buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) { + if (mx >= 30 && mx <= 180 && my >= 550 && my <= 600) { MenuView(); return; - //printf("ص˵\n"); - //תѶȽ } - break; - default: - break; } } + SDL_Delay(16); } - //char s[] = "˵"; - //outtextxy(250, 400, s); - //_getch(); } //------------------view------------------- @@ -647,13 +643,13 @@ void GameView_ShowLose() //-------------------service--------------- /* -* ˢµͼ +* 刷新地图 */ void Update() { - InitMap(); //ԭеĵͼݸһmap + InitMap(); //把原有的地图数据再赋值一次map - map[player.x][player.y] = RED_TANK; //ҡˡӵ飬λϢд뵽ͼ + map[player.x][player.y] = RED_TANK; //把玩家、敌人、子弹数组,将位置信息写入到地图 for (int i = 0; i < ENEMIES_NUM; i++) { if (enemies[i].hp > 0) { @@ -664,13 +660,13 @@ void GameView_ShowLose() } } - //for (int j = 0; j < BULLET_NUM; j++) { //ӵ + //for (int j = 0; j < BULLET_NUM; j++) { //玩家子弹 // if (P_bullets[j].is_live == true) { // map[enemies[j].x][enemies[j].y] = BULLET; // } //} - //for (int k = 0; k < BULLET_NUM * ENEMIES_NUM; k++) { //зӵ + //for (int k = 0; k < BULLET_NUM * ENEMIES_NUM; k++) { //敌方子弹 // if (E_bullets[k].is_live == true) { // map[enemies[k].x][enemies[k].y] = BULLET; // } @@ -678,19 +674,19 @@ void GameView_ShowLose() } /* - ˣ - ܣʼΪǽĿհ׵ͼ + 创建者:凌零 + 功能:初始化为周围是墙壁的空白地图 */ void InitMap() { - // ʼͼ + // 初始化地图 for (int i = 0; i < MAP_CELL_NUM; i++) { for (int j = 0; j < MAP_CELL_NUM; j++) { - // ܵλã趨Ϊ WALL + // 如果是边缘的位置,设定为 WALL if (i == 0 || i == MAP_CELL_NUM - 1 || j == 0 || j == MAP_CELL_NUM - 1) { map[i][j] = WALL; } - // λ趨Ϊ BLANK + // 其他位置设定为 BLANK else { map[i][j] = BLANK; } @@ -699,8 +695,8 @@ void InitMap() } /* - ˣ - ܣչĵͼʼmap.hļͼ + 创建者:凌零 + 功能:扩展功能的地图初始化(根据map.h文件预设地图数据) */ //void InitMap(const int preset_map[MAP_CELL_NUM][MAP_CELL_NUM]) { // for (int i = 0; i < MAP_CELL_NUM; i++) { @@ -711,10 +707,10 @@ void InitMap() //} /* - ˣɥɥ - ܣ - շж̹ƶĿ - ʵ̹ƶ + 创建者:丧丧的咸鱼 + 功能: + 根据传入的方向参数判断坦克移动的可行性 + 实现坦克移动 */ void PlayerMove() { static clock_t start = clock() - 100; @@ -722,14 +718,14 @@ void PlayerMove() { return; start = clock(); if (player.dir == UP) { - switch (TankMoveCheck(player.dir, player)) { //յ,з̹,ӵ,з̹,ǽ + switch (TankMoveCheck(player.dir, player)) { //空地,敌方坦克,子弹,敌方死亡坦克,墙 case BLANK: player.y--; break; case BULLET: player.y--; player.hp--; - for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //ҳĿӵ䱨 + for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //找出并干掉那颗子弹报销 if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) { E_bullets[i].is_live = false; } @@ -739,8 +735,8 @@ void PlayerMove() { player.y--; player.attack++; if(player.hp < 5) player.hp++; - for (int i = 0; i < ENEMIES_NUM; i++) { //ѭ̹ - if (player.x == enemies[i].x && player.y == enemies[i].y) //Ҹλ̹ + for (int i = 0; i < ENEMIES_NUM; i++) { //循环敌人坦克数组 + if (player.x == enemies[i].x && player.y == enemies[i].y) //找个位置下无敌坦克 enemies[i].is_taken = true; } break; @@ -751,14 +747,14 @@ void PlayerMove() { } else if (player.dir == DOWN) { - switch (TankMoveCheck(player.dir, player)) { //յ,з̹,ӵ,з̹,ǽ + switch (TankMoveCheck(player.dir, player)) { //空地,敌方坦克,子弹,敌方死亡坦克,墙 case BLANK: player.y++; break; case BULLET: player.y++; player.hp--; - for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //ҳĿӵ䱨 + for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //找出并干掉那颗子弹报销 if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) { E_bullets[i].is_live = false; } @@ -768,8 +764,8 @@ void PlayerMove() { player.y++; player.attack++; if (player.hp < 5) player.hp++; - for (int i = 0; i < ENEMIES_NUM; i++) { //ѭ̹ - if (player.x == enemies[i].x && player.y == enemies[i].y) //Ҹλ̹ + for (int i = 0; i < ENEMIES_NUM; i++) { //循环敌人坦克数组 + if (player.x == enemies[i].x && player.y == enemies[i].y) //找个位置下无敌坦克 enemies[i].is_taken = true; } break; @@ -778,14 +774,14 @@ void PlayerMove() { } } else if (player.dir == LEFT) { - switch (TankMoveCheck(player.dir, player)) { //յ,з̹,ӵ,з̹,ǽ + switch (TankMoveCheck(player.dir, player)) { //空地,敌方坦克,子弹,敌方死亡坦克,墙 case BLANK: player.x--; break; case BULLET: player.x--; player.hp--; - for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //ҳĿӵ䱨 + for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //找出并干掉那颗子弹报销 if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) { E_bullets[i].is_live = false; } @@ -795,8 +791,8 @@ void PlayerMove() { player.x--; player.attack++; if (player.hp < 5) player.hp++; - for (int i = 0; i < ENEMIES_NUM; i++) { //ѭ̹ - if (player.x == enemies[i].x && player.y == enemies[i].y) //Ҹλ̹ + for (int i = 0; i < ENEMIES_NUM; i++) { //循环敌人坦克数组 + if (player.x == enemies[i].x && player.y == enemies[i].y) //找个位置下无敌坦克 enemies[i].is_taken = true; } break; @@ -805,14 +801,14 @@ void PlayerMove() { } } else if (player.dir == RIGHT) { - switch (TankMoveCheck(player.dir, player)) { //յ,з̹,ӵ,з̹,ǽ + switch (TankMoveCheck(player.dir, player)) { //空地,敌方坦克,子弹,敌方死亡坦克,墙 case BLANK: player.x++; break; case BULLET: player.x++; player.hp--; - for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //ҳĿӵ䱨 + for (int i = 0; i <= BULLET_NUM * ENEMIES_NUM; i++) { //找出并干掉那颗子弹报销 if (E_bullets[i].x == player.x && E_bullets[i].y == player.y) { E_bullets[i].is_live = false; } @@ -822,8 +818,8 @@ void PlayerMove() { player.x++; player.attack++; if (player.hp < 5) player.hp++; - for (int i = 0; i < ENEMIES_NUM; i++) { //ѭ̹ - if (player.x == enemies[i].x && player.y == enemies[i].y) //Ҹλ̹ + for (int i = 0; i < ENEMIES_NUM; i++) { //循环敌人坦克数组 + if (player.x == enemies[i].x && player.y == enemies[i].y) //找个位置下无敌坦克 enemies[i].is_taken = true; } break; @@ -831,17 +827,17 @@ void PlayerMove() { break; } } -}//ײǽ͵з̹̹˲ƶ޸ +}//撞墙和敌方坦克坦克不移动将不会修改 /* - ˣɥɥ - ܣ̹ײ⣺Ƿǽз̹ˡз̹ˡյ - ԲͬвͬĴ - 0->յء1->ʾǽ2->̹ˡ3->̹ˡ4->̹ - һλõ꣨player.dir㣩ʲô + 创建者:丧丧的咸鱼 + 功能:坦克碰撞检测:检测是否为墙壁、敌方死亡坦克、敌方坦克、空地 + 对不同类型进行不同的处理 + 0->空地、1->表示墙、2->己方坦克、3->敌方坦克、4->死亡坦克 + 返回值为下一个位置的坐标(根据player.dir计算),并返回该位置存储的枚举值 */ -int TankMoveCheck(int dir, tank tank) { //̹ܷƶ,ؼλô洢öֵ - int ret = 0; // ĬϷֵΪ 0 +int TankMoveCheck(int dir, tank tank) { //坦克能否移动检查,返回检测位置存储的枚举值 + int ret = 0; // 默认返回值为 0 switch (dir) { case UP: return map[tank.x][tank.y - 1]; @@ -855,25 +851,25 @@ int TankMoveCheck(int dir, tank tank) { //̹ case RIGHT: return map[tank.x + 1][tank.y]; break; - default: // ĬϷ֧ + default: // 添加默认分支 break; } return ret; } /* - ˣ - ܣӵ飬ÿһӵд - ȿ϶üĩ״̬λã12-1512131415 - ӵײ⣺Ƿǽз̹ˡз̹ˡӵзӵյء̹ˡ + 创建者:凌零 + 功能:遍历子弹数组,对每一个子弹进行处理 + 首先肯定要用个外循环遍历所有子弹,分1,2,......1,5. 12,13,14,15,16... + 子弹碰撞检测:检测是否为墙壁、敌方死亡坦克、敌方坦克、玩家子弹、敌方子弹、空地、己方坦克。 */ /* - ˣ + 创建者:凌零 */ -int BulletMoveCheck(int dir, bullet bul) //صǰĿmapֵ +int BulletMoveCheck(int dir, bullet bul) //返回当前目标位置的map枚举值 { - int ret = 0; // ĬϷֵΪ 0 + int ret = 0; // 默认返回值为 0 switch (dir) { case UP: return map[bul.x][bul.y - 1]; @@ -887,37 +883,37 @@ int BulletMoveCheck(int dir, bullet bul) // case RIGHT: return map[bul.x + 1][bul.y]; break; - default: // ĬϷ֧ + default: // 添加默认分支 return ret; break; } } /* - ˣɥɥ - ܣ - ƶwasd4ȡģ0123 - ֮-жһλõ״̬ȻӦ - ʱƶı䷽жϵƶĿʵֵƶ + 创建者:丧丧的咸鱼 + 功能: + 通过随机移动(wasd)和方向取余4取模0123 + 生成方向之后-调用检查判断下一个位置的状态然后再进行相应的操作 + 同时移动时改变方向判断下一步移动的可行性实现随机移动 */ -void EnemiesMove() { //ؿ +void EnemiesMove() { //敌人控制函数 static clock_t start = clock() - 1000; if((clock() - start) < 1000) return; start = clock(); - for (int i = 0; i < ENEMIES_NUM; ++i) { //nз̹ƶ + for (int i = 0; i < ENEMIES_NUM; ++i) { //n个敌方坦克移动 if (enemies[i].hp <= 0) continue; - int dir = rand() % 4; //ɵз̹˵ƶ - if (dir == UP) { //0 - enemies[i].dir = UP; // ǰ enemies[i] ķ - switch (TankMoveCheck(dir, enemies[i])) { //յ,з̹,ӵ,ǽ + int dir = rand() % 4; //随机生成敌方坦克的移动方向 + if (dir == UP) { //0向上 + enemies[i].dir = UP; // 更新当前 enemies[i] 的方向为向上 + switch (TankMoveCheck(dir, enemies[i])) { //空地,敌方坦克,子弹,墙 case BLANK: enemies[i].y--; break; case BULLET: enemies[i].y--; - for (int i = 0; i < BULLET_NUM; i++) { //ӵ + for (int i = 0; i < BULLET_NUM; i++) { //遍历玩家子弹数组 if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) { P_bullets[i].is_live = false; enemies[i].hp--; @@ -926,15 +922,15 @@ void EnemiesMove() { // break; } } - else if (dir == DOWN) { //1 + else if (dir == DOWN) { //1向下 enemies[i].dir = DOWN; - switch (TankMoveCheck(dir, enemies[i])) { //յ,з̹,ӵ,ǽ + switch (TankMoveCheck(dir, enemies[i])) { //空地,敌方坦克,子弹,墙 case BLANK: enemies[i].y++; break; case BULLET: enemies[i].y++; - for (int i = 0; i < BULLET_NUM; i++) { //ӵ + for (int i = 0; i < BULLET_NUM; i++) { //遍历玩家子弹数组 if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) { P_bullets[i].is_live = false; enemies[i].hp--; @@ -943,15 +939,15 @@ void EnemiesMove() { // break; } } - else if (dir == LEFT) { //2 + else if (dir == LEFT) { //2向左 enemies[i].dir = LEFT; - switch (TankMoveCheck(dir, enemies[i])) { //յ,з̹,ӵǽ + switch (TankMoveCheck(dir, enemies[i])) { //空地,敌方坦克,子弹,墙 case BLANK: enemies[i].x--; break; case BULLET: enemies[i].x--; - for (int i = 0; i < BULLET_NUM; i++) { //ӵ + for (int i = 0; i < BULLET_NUM; i++) { //遍历玩家子弹数组 if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) { P_bullets[i].is_live = false; enemies[i].hp--; @@ -960,15 +956,15 @@ void EnemiesMove() { // break; } } - else if (dir == RIGHT) { //3 + else if (dir == RIGHT) { //3向右 enemies[i].dir = RIGHT; - switch (TankMoveCheck(dir, enemies[i])) { //յ,з̹,ӵ,ǽ + switch (TankMoveCheck(dir, enemies[i])) { //空地,敌方坦克,子弹,墙 case BLANK: enemies[i].x++; break; case BULLET: enemies[i].x++; - for (int i = 0; i < BULLET_NUM; i++) { //ӵ + for (int i = 0; i < BULLET_NUM; i++) { //遍历玩家子弹数组 if (P_bullets[i].x == enemies[i].x && P_bullets[i].y == enemies[i].y) { P_bullets[i].is_live = false; enemies[i].hp--; @@ -981,11 +977,11 @@ void EnemiesMove() { // } /* - ˣ - ܣ - շBulletMoveCheck() -ķֵжӵƶ - ʵӵƶ + 创建者:凌零 + 功能: + 根据传入的方向参数调用BulletMoveCheck() + 返回的枚举值判断子弹移动结果 + 实现子弹移动 */ void PlayerBulletMove() { @@ -1000,7 +996,7 @@ void PlayerBulletMove() { {-1, 0}, {1, 0}, }; - for (int i = 0; i < BULLET_NUM; i++) // ӵ + for (int i = 0; i < BULLET_NUM; i++) // 遍历子弹 { if (P_bullets[i].is_live == false) { @@ -1008,10 +1004,10 @@ void PlayerBulletMove() { } else { - // ӵײ⣺Ƿյءǽ̹ˡз̹ˡз̹ˡӵзӵ - // 0->յء1->ʾǽ2->̹ˡ3->̹ˡ4->̹ˡ5->ҷӵ6->зӵ - // 0 յ 1 ǽ 3 з̹ 6 зӵ - int type = BulletMoveCheck(P_bullets[i].dir, P_bullets[i]); + // 子弹碰撞检测:检测是否碰到空地、墙壁、己方坦克、敌方坦克、敌方死亡坦克、玩家子弹、敌方子弹 + // 0->空地、1->表示墙、2->己方坦克、3->敌方坦克、4->死亡坦克、5->我方子弹、6->敌方子弹 + // 0 空地 1 墙 3 敌方坦克 6 敌方子弹 + int type = BulletMoveCheck(P_bullets[i].dir, P_bullets[i]); if (type == BLANK) { P_bullets[i].x += arr[P_bullets[i].dir][0]; @@ -1021,37 +1017,37 @@ void PlayerBulletMove() { { P_bullets[i].is_live = false; } - else if (type == BLUE_TANK) //з̹ + else if (type == BLUE_TANK) //敌方坦克 { - P_bullets[i].is_live = false; //ӵ - for (int k = 0; k < ENEMIES_NUM; k++) //̹˱ + P_bullets[i].is_live = false; //子弹消失 + for (int k = 0; k < ENEMIES_NUM; k++) //坦克爆炸 { switch (P_bullets[i].dir) { case UP: - if (enemies[k].x == P_bullets[i].x && enemies[k].y == P_bullets[i].y - 1) //Ϸз̹ + if (enemies[k].x == P_bullets[i].x && enemies[k].y == P_bullets[i].y - 1) //位于子弹上方敌方坦克受到伤害 { enemies[k].hp -= P_bullets[i].damage; } break; case DOWN: - if (enemies[k].x == P_bullets[i].x && enemies[k].y == P_bullets[i].y + 1) //Ϸз̹ + if (enemies[k].x == P_bullets[i].x && enemies[k].y == P_bullets[i].y + 1) //位于子弹下方敌方坦克受到伤害 { enemies[k].hp -= P_bullets[i].damage; } break; case LEFT: - if (enemies[k].x == P_bullets[i].x - 1 && enemies[k].y == P_bullets[i].y) //Ϸз̹ + if (enemies[k].x == P_bullets[i].x - 1 && enemies[k].y == P_bullets[i].y) //位于子弹左方敌方坦克受到伤害 { enemies[k].hp -= P_bullets[i].damage; } break; case RIGHT: - if (enemies[k].x == P_bullets[i].x + 1 && enemies[k].y == P_bullets[i].y) //Ϸз̹ + if (enemies[k].x == P_bullets[i].x + 1 && enemies[k].y == P_bullets[i].y) //位于子弹右方敌方坦克受到伤害 { enemies[k].hp -= P_bullets[i].damage; } break; - default: // ĬϷ֧ + default: // 添加默认分支 break; } @@ -1152,54 +1148,54 @@ void EnemyBulletMove() { } } /* - ˣ - ܣ̹ + 创建者:凌零 + 功能:初始化玩家坦克 */ void PlayerInit() { - player.x = MAP_CELL_NUM / 2; // ʼ + player.x = MAP_CELL_NUM / 2; // 玩家初始位置 player.y = MAP_CELL_NUM / 2; - player.hp = 5; // Ѫʼ - player.dir = UP; // ʼҷ - player.attack = 5; // ʼҹΪ 5 - kill = 0; // ҳʼɱΪ 0 - map[player.x][player.y] = RED_TANK; // ڵͼϱ̹˵λ + player.hp = 5; // 玩家血量初始化 + player.dir = UP; // 初始化玩家方向 + player.attack = 5; // 初始化玩家攻击力为 5 + kill = 0; // 玩家击杀数初始化为 0 + map[player.x][player.y] = RED_TANK; // 在地图上标记坦克的位置 } /* - ˣ - ܣɵз̹ + 创建者:凌零 + 功能:生成敌方坦克 */ void EnemyInit() { - srand((unsigned int)time(NULL)); // - // ʹ ⴴ + srand((unsigned int)time(NULL)); //初始化随机数种子 + // 使用 库创建随机数生成器 //default_random_engine generator; - //uniform_int_distribution distribution(0, 49); // һȷֲɵΧ1-48 + //uniform_int_distribution distribution(0, 49); // 创建一个均匀分布,生成的随机数范围在1-48 - // ʼ̹ + // 初始化敌方坦克 for (int i = 0; i < ENEMIES_NUM; i++) { - enemies[i].x = rand() % (MAP_CELL_NUM - 2) + 1 ; // ʹ + enemies[i].x = rand() % (MAP_CELL_NUM - 2) + 1 ; // 使用随机数生成器生成坐标 enemies[i].y = rand() % (MAP_CELL_NUM - 2) + 1; - // ɵλѾ̹˻ǽô + // 如果随机到的位置已经被坦克或者墙壁占据,那么重新生成 while (map[enemies[i].x][enemies[i].y] != BLANK) { enemies[i].x = rand() % (MAP_CELL_NUM - 2) + 1; enemies[i].y = rand() % (MAP_CELL_NUM - 2) + 1; } - enemies[i].hp = enemy.hp; // ˳ʼѪΪ5 - enemies[i].attack = enemy.attack; // ˳ʼΪ1 - enemies[i].dir = LEFT; // ˳ʼ泯 - map[enemies[i].x][enemies[i].y] = BLUE_TANK; // ڵͼϱǵλ + enemies[i].hp = enemy.hp; // 设置敌人初始血量为5 + enemies[i].attack = enemy.attack; // 设置敌人初始攻击力为1 + enemies[i].dir = LEFT; // 设置敌人初始面朝左 + map[enemies[i].x][enemies[i].y] = BLUE_TANK; // 在地图上标记敌人位置 } } /* - ˣ - ܣ - ֵΪ:˵ʧܣ̹hp<=0߻û棺̹hp>0,з̹>0 - ֵΪ棺˵Ӯ ̹hp==0,з̹==0 + 创建者:凌零 + 功能: + 返回值为假:说明失败,己方坦克hp<=0,或者还没有胜利条件:己方坦克hp>0,敌方坦克数量>0 + 返回值为真:说明赢了 己方坦克hp==0,敌方坦克数量==0 */ bool IsWin() { bool all_die = true; @@ -1208,250 +1204,265 @@ bool IsWin() { all_die = false; } if (player.hp > 0 && all_die) { - return true; // ʤ + return true; // 胜利 } - else return false; // ûʤʧܡ ϷС + else return false; // 没胜利或失败。 还在游戏进行中。 } -// +// 难度选择 void Level() { - cleardevice(); - IMAGE img_memberview; - loadimage(&img_memberview, ".//images//Ϸ汳.jpg", 700, 700); - putimage(0, 0, &img_memberview); + clear_screen(); + draw_image("images/游戏主界面背景.jpg", 0, 0, 700, 700); - IMAGE img_easy; - loadimage(&img_easy, ".//images//Ѷ.jpg", 150, 100); - putimage(275, 150, &img_easy); + draw_image("images/简单难度.jpg", 275, 150, 150, 100); + draw_image("images/中等难度.jpg", 275, 300, 150, 100); + draw_image("images/困难难度.jpg", 275, 450, 150, 100); + present_screen(); - IMAGE img_middle; - loadimage(&img_middle, ".//images//еѶ.jpg", 150, 100); - putimage(275, 300, &img_middle); - - IMAGE img_difficult; - loadimage(&img_difficult, ".//images//Ѷ.jpg", 150, 100); - putimage(275, 450, &img_difficult); - - //̲ - ExMessage msg; while (true) { - //̲ - if (_kbhit()) - { - char key = _getch();//һֱ - //printf("%d,%c\n", key, key); - switch (key) - { - case 27://ϼ - //ز˵ + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) exit(0); + if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { MenuView(); - //printf("ز˵/n"); return; - break; } - } + if (e.type == SDL_MOUSEBUTTONDOWN) { + int mx = e.button.x; + int my = e.button.y; - // - if (peekmessage(&msg, WH_MOUSE)) - { - switch (msg.message) - { - case WM_LBUTTONDOWN: - - //ѡѶ - if (msg.x >= 275 && msg.x <= 425 && msg.y >= 150 && msg.y <= 250) + //选择简单难度 + if (mx >= 275 && mx <= 425 && my >= 150 && my <= 250) { enemy.hp = 5; enemy.attack = 1; - //printf("Ѷ\n"); MenuView(); - //printf("ز˵/n"); return; } - //ѡеѶ - if (msg.x >= 275 && msg.x <= 425 && msg.y >= 300 && msg.y <= 400) + //选择中等难度 + if (mx >= 275 && mx <= 425 && my >= 300 && my <= 400) { enemy.hp = 10; enemy.attack = 2; - //printf("еѶ\n"); MenuView(); - //printf("ز˵/n"); return; } - //ѡѶ - if (msg.x >= 275 && msg.x <= 425 && msg.y >= 450 && msg.y <= 550) + //选择困难难度 + if (mx >= 275 && mx <= 425 && my >= 450 && my <= 550) { enemy.hp = 15; enemy.attack = 3; - //printf("Ѷ\n"); MenuView(); - //printf("ز˵/n"); return; } - break; - default: - break; } } + SDL_Delay(16); } } -// +// 开发人员 void MemberView() { - cleardevice(); - IMAGE img_memberview; - loadimage(&img_memberview, ".//images//Ա.jpg", 700, 700); - putimage(0, 0, &img_memberview); + clear_screen(); + draw_image("images/开发人员界面.jpg", 0, 0, 700, 700); + draw_image("images/返回按钮.jpg", 30, 550, 150, 50); + present_screen(); - IMAGE img_back; - loadimage(&img_back, ".//images//ذť.jpg", 150, 50); - putimage(30, 550, &img_back); - // - ExMessage msg; while (true) { - //̲ - if (_kbhit()) - { - char key = _getch();//һֱ - //printf("%d,%c\n", key, key); - switch (key) - { - case 27://ϼ - //ز˵ + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) exit(0); + if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) { MenuView(); - //printf("ز˵/n"); return; - break; } - } + if (e.type == SDL_MOUSEBUTTONDOWN) { + int mx = e.button.x; + int my = e.button.y; - // - if (peekmessage(&msg, WH_MOUSE)) - { - switch (msg.message) - { - case WM_LBUTTONDOWN: - - //ص˵ - if (msg.x >= 30 && msg.x <= 180 && msg.y >= 550 && msg.y <= 600) + //返回主菜单界面 + if (mx >= 30 && mx <= 180 && my >= 550 && my <= 600) { MenuView(); return; - //printf("ص˵\n"); - //תѶȽ } - break; - default: - break; } } + SDL_Delay(16); } } -// +// 菜单 void MenuView() { InitMap(); - cleardevice(); - //ͼƬ - setbkmode(TRANSPARENT); - IMAGE img_menuview; - loadimage(&img_menuview, ".//images//˵.jpg", 700, 700); - putimage(0, 0, &img_menuview); + clear_screen(); + draw_image("images/菜单界面.jpg", 0, 0, 700, 700); + draw_image("images/开始游戏按键.jpg", 50, 250, 150, 50); + draw_image("images/难度设置按键.jpg", 50, 330, 150, 50); + draw_image("images/相关人员按键.jpg", 50, 410, 150, 50); + draw_image("images/退出游戏按键.jpg", 50, 490, 150, 50); + present_screen(); - IMAGE img_start; - loadimage(&img_start, ".//images//ʼϷ.jpg", 150, 50); - putimage(50, 250, &img_start); - - IMAGE img_level; - loadimage(&img_level, ".//images//Ѷð.jpg", 150, 50); - putimage(50, 330, &img_level); - - IMAGE img_member; - loadimage(&img_member, ".//images//Ա.jpg", 150, 50); - putimage(50, 410, &img_member); - - IMAGE img_quit; - loadimage(&img_quit, ".//images//˳Ϸ.jpg", 150, 50); - putimage(50, 490, &img_quit); - // - ExMessage msg; while (true) { + SDL_Event e; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) exit(0); + if (e.type == SDL_MOUSEBUTTONDOWN) { + int mx = e.button.x; + int my = e.button.y; - // - if (peekmessage(&msg, WH_MOUSE)) - { - switch (msg.message) - { - case WM_LBUTTONDOWN: - - //תϷ - if (msg.x >= 50 && msg.x <= 200 && msg.y >= 250 && msg.y <= 300) + //跳转游戏主页面 + if (mx >= 50 && mx <= 200 && my >= 250 && my <= 300) { GameView(); - //printf("ʼϷ\n"); } - //תѶȽ - if (msg.x >= 50 && msg.x <= 200 && msg.y >= 330 && msg.y <= 380) + //跳转至游戏难度选择 + if (mx >= 50 && mx <= 200 && my >= 330 && my <= 380) { Level(); return; - //printf("Ѷ\n"); } - //תԱ - if (msg.x >= 50 && msg.x <= 200 && msg.y >= 410 && msg.y <= 460) + //跳转至开发人员界面 + if (mx >= 50 && mx <= 200 && my >= 410 && my <= 460) { MemberView(); return; - //printf("Ա\n"); } - //Ϸ - if (msg.x >= 50 && msg.x <= 200 && msg.y >= 490 && msg.y <= 540) + //退出游戏 + if (mx >= 50 && mx <= 200 && my >= 490 && my <= 540) { exit(0); } - break; - default: - break; } } + SDL_Delay(16); } } void change() { - //ȡھ - HWND hnd = GetHWnd(); - //ôڱ - SetWindowText(hnd, "ֽ̹"); + SDL_SetWindowTitle(g_window, "纸牌坦克"); } //-------------------service--------------- /* - ˣɥɥ + 创建者:丧丧的咸鱼 */ int main() { - // bgm - //PlaySound(LPWSTR(IDR_WAVE1), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC | SND_LOOP); - PlaySound(MAKEINTRESOURCE(IDR_WAVE1), GetModuleHandle(NULL), SND_RESOURCE | SND_ASYNC | SND_LOOP); + // 将工作目录设置为可执行文件所在目录,确保相对路径资源(images/、music/)能正确加载 + char* base_path = SDL_GetBasePath(); + if (base_path) { + chdir(base_path); + SDL_free(base_path); + } - // ---------------------- - // - initgraph(700, 700); + // 初始化SDL + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + fprintf(stderr, "SDL初始化失败: %s\n", SDL_GetError()); + return -1; + } + + // 初始化SDL_image + int img_flags = IMG_INIT_PNG | IMG_INIT_JPG; + if (!(IMG_Init(img_flags) & img_flags)) { + fprintf(stderr, "SDL_image初始化失败: %s\n", IMG_GetError()); + SDL_Quit(); + return -1; + } + + // 初始化SDL_mixer + if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) { + fprintf(stderr, "SDL_mixer初始化失败: %s\n", Mix_GetError()); + IMG_Quit(); + SDL_Quit(); + return -1; + } + + // 初始化SDL_ttf + if (TTF_Init() < 0) { + fprintf(stderr, "SDL_ttf初始化失败: %s\n", TTF_GetError()); + Mix_CloseAudio(); + IMG_Quit(); + SDL_Quit(); + return -1; + } + + // 创建窗口和渲染器 + g_window = SDL_CreateWindow("纸牌坦克", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700, 700, SDL_WINDOW_SHOWN); + if (!g_window) { + fprintf(stderr, "窗口创建失败: %s\n", SDL_GetError()); + TTF_Quit(); + Mix_CloseAudio(); + IMG_Quit(); + SDL_Quit(); + return -1; + } + + g_renderer = SDL_CreateRenderer(g_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + if (!g_renderer) { + fprintf(stderr, "渲染器创建失败: %s\n", SDL_GetError()); + SDL_DestroyWindow(g_window); + TTF_Quit(); + Mix_CloseAudio(); + IMG_Quit(); + SDL_Quit(); + return -1; + } + + // 加载字体(尝试多个常用中文字体路径) + const char* font_paths[] = { + "/usr/share/fonts/wqy-microhei-fonts/wqy-microhei.ttc", + "/usr/share/fonts/wqy-zenhei-fonts/wqy-zenhei.ttc", + "/usr/share/fonts/google-noto-sans-cjk-vf-fonts/NotoSansCJK-VF.ttc", + "/usr/share/fonts/google-noto-serif-cjk-vf-fonts/NotoSerifCJK-VF.ttc", + NULL + }; + for (int i = 0; font_paths[i] != NULL; i++) { + g_font = TTF_OpenFont(font_paths[i], 30); + if (g_font) { + printf("已加载字体: %s\n", font_paths[i]); + break; + } + } + if (!g_font) { + fprintf(stderr, "警告: 未找到中文字体,文本将无法显示。请安装 wqy-microhei 或 noto-cjk 字体。\n"); + // 尝试使用任何可用TTF字体 + } + + // 加载BGM + g_bgm = Mix_LoadMUS("music/bgm.wav"); + if (!g_bgm) { + fprintf(stderr, "BGM加载失败: %s,将静音运行\n", Mix_GetError()); + } else { + Mix_PlayMusic(g_bgm, -1); // 循环播放 + } + + // 设置窗口标题 change(); + // 进入主菜单 MenuView(); - getchar(); - //رմ - closegraph(); + // 清理资源 + if (g_bgm) { + Mix_HaltMusic(); + Mix_FreeMusic(g_bgm); + } + if (g_font) TTF_CloseFont(g_font); + SDL_DestroyRenderer(g_renderer); + SDL_DestroyWindow(g_window); + Mix_CloseAudio(); + TTF_Quit(); + IMG_Quit(); + SDL_Quit(); return 0; -} \ No newline at end of file +} diff --git a/tank_battles_on_the_scrap_paper/resource.h b/tank_battles_on_the_scrap_paper/resource.h deleted file mode 100644 index 6964a71..0000000 --- a/tank_battles_on_the_scrap_paper/resource.h +++ /dev/null @@ -1,16 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ ɵİļ -// resource.rc ʹ -// -#define IDR_WAVE1 101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/tank_battles_on_the_scrap_paper/resource.rc b/tank_battles_on_the_scrap_paper/resource.rc deleted file mode 100644 index ada8777c13963ed67efd20ba6a2b4d485d8bf88e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3018 zcmd6p+iuf95QhJ21n*#yn^w?sOhbkoiY#jvfZZojLe}P=pLuk9Ie8gv3id5#K~4N`iJ_Yijy|Ys*{VIp6&fY zC+exMftreRtg*TZ;Wn9f)YdyVJ>EyE!)Y`3=bH`X8{Rrk1GT_q6XO_^E_K2Em!M-f z^ttt0-VwKMa8JV{g#V0Z(<6WO!Ii@|(ObvAe296AlIU20l|@p_y?2WZkG$WvT+~|^ z=%DlcY){{=d&l>04mv-E`#GLor1EC!FnPF^KNIbN(n}&I$(tTIG9ZH*#Lk!qYBOx# zuZ*Bjv(Fw~;&hDOD>7`~o!W-mfjfYuFJD`*oxCJO#s|8er>n?%s0M!M=jqkzZ{` zdU9KFLy)_}*=oryXXI7+in2APq7k)fL_r60~s+s z&|_TCHC)kQd|B%Q?5~*Tk-x8tKU+5H()*Qbo{lNA?0v!Af7plx&5C8xG diff --git a/tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj b/tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj deleted file mode 100644 index 4157d31..0000000 --- a/tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj +++ /dev/null @@ -1,147 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {ac8c4a04-1650-473c-8e9a-3b7cde2ad5cc} - tankbattlesonthescrappaper - 10.0 - - - - Application - true - v143 - Unicode - - - Application - false - v143 - true - Unicode - - - Application - true - v143 - MultiByte - - - Application - false - v143 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj.filters b/tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj.filters deleted file mode 100644 index 97a5b30..0000000 --- a/tank_battles_on_the_scrap_paper/tank_battles_on_the_scrap_paper.vcxproj.filters +++ /dev/null @@ -1,46 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - 源文件 - - - - - 头文件 - - - 头文件 - - - 头文件 - - - 头文件 - - - - - 资源文件 - - - - - 资源文件 - - - \ No newline at end of file