From 3c10a01c697e87f74def33855d15da1bc00c30e1 Mon Sep 17 00:00:00 2001 From: sjm <2431685932@qq.com> Date: Tue, 11 Jun 2024 15:11:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=93=A6=E7=89=87=E7=B1=BB=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=EF=BC=8CMap=E7=B1=BB=E5=9C=B0=E5=9B=BE=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=8A=A0=E8=BD=BD=EF=BC=8C=E5=9C=B0=E5=9B=BE=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TdGame/TdGame.vcxproj | 2 + TdGame/TdGame.vcxproj.filters | 6 ++ TdGame/config.json | 96 +++++++++++++++++++++++ TdGame/game_manager.h | 90 +++++++++++++++++++++ TdGame/level.json | 35 +++++++++ TdGame/main.cpp | 10 +-- TdGame/map.csv | 15 ++++ TdGame/map.h | 142 ++++++++++++++++++++++++++++++++++ TdGame/tile.h | 30 +++++++ 9 files changed, 420 insertions(+), 6 deletions(-) create mode 100644 TdGame/config.json create mode 100644 TdGame/level.json create mode 100644 TdGame/map.csv create mode 100644 TdGame/map.h create mode 100644 TdGame/tile.h diff --git a/TdGame/TdGame.vcxproj b/TdGame/TdGame.vcxproj index 72f4fcc..3b2d812 100644 --- a/TdGame/TdGame.vcxproj +++ b/TdGame/TdGame.vcxproj @@ -136,6 +136,8 @@ + + diff --git a/TdGame/TdGame.vcxproj.filters b/TdGame/TdGame.vcxproj.filters index a1dc21e..99fe9c8 100644 --- a/TdGame/TdGame.vcxproj.filters +++ b/TdGame/TdGame.vcxproj.filters @@ -29,5 +29,11 @@ 头文件\manager + + 头文件 + + + 头文件 + \ No newline at end of file diff --git a/TdGame/config.json b/TdGame/config.json new file mode 100644 index 0000000..a95a0f8 --- /dev/null +++ b/TdGame/config.json @@ -0,0 +1,96 @@ +{ + "basic": + { + "window_title": "村庄保卫战!", + "window_width": 1280, + "window_height": 720 + }, + "player": + { + "speed": 5, + "normal_attack_interval": 0.5, + "normal_attack_damage": 10, + "skill_interval": 10, + "skill_damage": 5 + }, + "tower": + { + "archer": + { + "interval": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + "damage": [5, 1, 1, 1, 10, 10, 10, 10, 10, 10], + "view_range": [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], + "cost": [10, 2, 2, 10, 10, 10, 10, 10, 10, 10], + "upgrade_cost": [10, 10, 10, 10, 10, 10, 10, 10, 10] + }, + "axeman": + { + "interval": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + "damage": [10, 10, 10, 10, 10, 10, 10, 10, 10, 10], + "view_range": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4], + "cost": [20, 20, 20, 20, 20, 20, 20, 20, 20, 20], + "upgrade_cost": [10, 10, 10, 10, 10, 10, 10, 10, 10] + }, + "gunner": + { + "interval": [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], + "damage": [20, 10, 10, 10, 10, 10, 10, 10, 10, 10], + "view_range": [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], + "cost": [30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "upgrade_cost": [10, 10, 10, 10, 10, 10, 10, 10, 10] + } + }, + "enemy": + { + "slim": + { + "hp": 20, + "speed": 1, + "damage": 1, + "reward_ratio": 0.8, + "recover_interval": 100, + "recover_range": -1, + "recover_intensity": 10 + }, + "king_slim": + { + "hp": 75, + "speed": 0.75, + "damage": 1, + "reward_ratio": 1, + "recover_interval": 100, + "recover_range": -1, + "recover_intensity": 10 + }, + "skeleton": + { + "hp": 40, + "speed": 1.5, + "damage": 1, + "reward_ratio": 1, + "recover_interval": 100, + "recover_range": -1, + "recover_intensity": 10 + }, + "goblin": + { + "hp": 50, + "speed": 1.5, + "damage": 1, + "reward_ratio": 1, + "recover_interval": 100, + "recover_range": -1, + "recover_intensity": 10 + }, + "goblin_priest": + { + "hp": 100, + "speed": 0.75, + "damage": 1, + "reward_ratio": 1, + "recover_interval": 10, + "recover_range": 5, + "recover_intensity": 10 + } + } +} \ No newline at end of file diff --git a/TdGame/game_manager.h b/TdGame/game_manager.h index 3591843..d9b2b8c 100644 --- a/TdGame/game_manager.h +++ b/TdGame/game_manager.h @@ -4,19 +4,109 @@ #include "manager.h" +#include +#include +#include +#include + + class GameManager : public Manager { friend class Manager; public: + int run(int argc,char** argv) + { + Uint64 last_counter = SDL_GetPerformanceCounter(); + const Uint64 counter_freq = SDL_GetPerformanceFrequency(); + + while (!is_quit) + { + while (SDL_PollEvent(&event)) + on_input(); + Uint64 current_counter = SDL_GetPerformanceCounter(); + double delta = (double)(current_counter - last_counter) / counter_freq; + last_counter = current_counter; + if (delta * 1000 < 1000.0 / 60) + SDL_Delay(Uint32(1000.0 / 60 - delta * 1000)); + + // + on_update(delta); + + //ƻ + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + on_render(); + + SDL_RenderPresent(renderer); + + } + + return 0; + } + protected: GameManager() { + init_assert(!SDL_Init(SDL_INIT_EVERYTHING),u8"SDL2 ʼʧܣ"); + init_assert(IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG), u8"SDL_image ʼʧܣ"); + init_assert(Mix_Init(MIX_INIT_MP3), u8"SDL_mixer ʼʧܣ"); + init_assert(!TTF_Init(), u8"SDL_ttf ʼʧܣ"); + + Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); + + SDL_SetHint(SDL_HINT_IME_SHOW_UI,"1"); + + window = SDL_CreateWindow(u8"ׯս", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_SHOWN); + init_assert(window, u8"Ϸʧܣ"); + + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); + init_assert(renderer, u8"Ⱦʧܣ"); + } ~GameManager() { + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + + TTF_Quit(); + Mix_Quit(); + IMG_Quit(); + SDL_Quit(); + } + +private: + SDL_Event event; + bool is_quit = false; + + SDL_Window* window = nullptr; + SDL_Renderer* renderer = nullptr; + +private: + void init_assert(bool flag, const char* err_msg) + { + if (flag) return; + + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, u8"Ϸʧܣ", err_msg, window); + exit(-1); + } + + void on_input() + { + + } + + void on_update(double delta) + { + + } + + void on_render() + { + } }; diff --git a/TdGame/level.json b/TdGame/level.json new file mode 100644 index 0000000..fe2be1e --- /dev/null +++ b/TdGame/level.json @@ -0,0 +1,35 @@ +[{ + "interval": 1, + "rewards": 100, + "spawn_list": [{ + "interval": 1, + "point": 1, + "enemy": "Slim" + }, { + "interval": 1, + "point": 2, + "enemy": "KingSlim" + }, { + "interval": 1, + "point": 1, + "enemy": "Goblin" + }, { + "interval": 1, + "point": 2, + "enemy": "GoblinPriest" + }, { + "interval": 1, + "point": 1, + "enemy": "Skeleton" + }] + }, { + "interval": 3, + "rewards": 100, + "spawn_list": [{ + "interval": 3, + "point": 2, + "enemy": "KingSlim" + }] + }] + + \ No newline at end of file diff --git a/TdGame/main.cpp b/TdGame/main.cpp index a647612..6b6e1ac 100644 --- a/TdGame/main.cpp +++ b/TdGame/main.cpp @@ -1,14 +1,12 @@ +#define SDL_MAIN_HANDLED #include -#include "manager.h" + #include "game_manager.h" -int main() +int main(int argc,char**argv) { - GameManager* instance = GameManager::instance(); - - std::cout << "Hello World!" << std::endl; - return 0; + return GameManager::instance()->run(argc, argv);; } \ No newline at end of file diff --git a/TdGame/map.csv b/TdGame/map.csv new file mode 100644 index 0000000..c65bf57 --- /dev/null +++ b/TdGame/map.csv @@ -0,0 +1,15 @@ +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,3\-1\4\1,3\-1\4\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\4\-1,3\-1\4\-1,3\-1\4\-1,3\-1\4\-1,3\-1\4\-1,3\-1\4\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,4\-1\2\-1,3\-1\3\-1,3\-1\3\-1,4\-1\3\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\54\0\-1,0\54\0\-1,0\29\0\-1,4\-1\2\-1,0\29\0\-1,0\54\0\-1,0\54\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\54\0\-1,4\128\0\-1,5\-1\0\-1,3\-1\2\-1,5\-1\0\-1,4\128\0\-1,0\54\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\53\0\-1,3\-1\0\-1,3\-1\0\-1,5\-1\0\0,3\-1\0\-1,3\-1\0\-1,0\53\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\53\0\-1,0\53\0\-1,5\-1\0\-1,4\-1\1\-1,5\-1\0\-1,0\53\0\-1,0\53\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\285\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,3\-1\3\-1,3\-1\3\-1,3\-1\3\-1,3\-1\3\-1,3\-1\3\-1,4\-1\3\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\2\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,26\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\4\-1,3\-1\4\-1,3\-1\4\-1,4\-1\1\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,27\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,4\-1\1\-1,3\-1\3\-1,3\-1\3\2,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 +0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1,0\-1\0\-1 \ No newline at end of file diff --git a/TdGame/map.h b/TdGame/map.h new file mode 100644 index 0000000..b30fe64 --- /dev/null +++ b/TdGame/map.h @@ -0,0 +1,142 @@ +#pragma once +#ifndef _MAP_H_ +#define _MAP_H_ + +#include "tile.h" + +#include +#include +#include +#include + +class Map +{ +public: + Map() = default; + ~Map() = default; + + bool load(const std::string& path) + { + std::ifstream file(path); + if (!file.good())return false; + + TileMap tile_map_temp; + + int idx_x = -1, idx_y = -1;//Ƭλ + + std::string str_line; + while (std::getline(file, str_line)) + { + str_line = trim_str(str_line); + if (str_line.empty()) + continue; + //ΪգһУidx_x-1 + idx_x = -1, idx_y++; + tile_map_temp.emplace_back();//ڶά + + std::string str_tile; + std::stringstream str_stream(str_line); + while (std::getline(str_stream, str_tile, ','))//ŷָƬ + { + idx_x++;//idx_x++ȥұһƬ + tile_map_temp[idx_y].emplace_back();//idx_yƬ + Tile& tile = tile_map_temp[idx_y].back();//ȡƬ Tile& tile = tile_map_temp[idx_y].back() Ա + + load_tile_from_string(tile,str_tile); + } + } + + file.close(); + + //ͼտ + if (tile_map_temp.empty() || tile_map_temp[0].empty()) + return false; + + tile_map = tile_map_temp; + + return true; + } + + size_t get_width() const //constڽ޸ + { + if (tile_map.empty()) + return 0; + + return tile_map[0].size();//һдСȣ + } + + size_t get_height() const + { + return tile_map.size();//߶ȣ + } + +private: + TileMap tile_map; + SDL_Point idx_home = { 0 }; + +private: + + //һȥַǰոƱĺ + std::string trim_str(const std::string& str) + { + size_t begin_idx = str.find_first_not_of(" \t"); + if (begin_idx == std::string::npos) + return ""; + size_t end_idx = str.find_last_not_of(" \t"); + size_t idx_range = end_idx - begin_idx + 1; + + return str.substr(begin_idx, idx_range); + } + + //Ԫַ + void load_tile_from_string(Tile& tile, const std::string& str) + { + std::string str_tidy = trim_str(str); + + std::string str_value; + std::vector values; + std::stringstream str_stream(str_tidy); + + while (std::getline(str_stream, str_value, '\\')) + { + int value; + try + { + value = std::stoi(str_value); //nƵַתΪʮ, ַ + } //磬stoi(str, 0, 2); ַ str 0 λֵ֮ 2 ,תΪʮ + catch (const std::invalid_argument&) + { + value = -1; + } + values.push_back(value); + } + + tile.terrian = (values.size() < 1 || values[0] < 0) ? 0 : values[0]; + tile.decoration = (values.size() < 2) ? -1 : values[1]; + tile.direction = (Tile::Direction)((values.size() < 3 || values[2] < 0) ? 0 : values[2]); + tile.special_flag = (values.size() <= 3) ? -1 : values[3]; + + } + + //ɵͼ + void generate_map_cache() + { + for (int y = 0; y < get_height(); y++) + { + for (int x = 0; x < get_width(); x++) + { + const Tile& tile = tile_map[y][x]; + if (tile.special_flag < 0) + continue; + + if (tile.special_flag == 0) + { + idx_home.x == x; + idx_home.y == y; + } + } + } + } +}; + +#endif \ No newline at end of file diff --git a/TdGame/tile.h b/TdGame/tile.h new file mode 100644 index 0000000..00087ca --- /dev/null +++ b/TdGame/tile.h @@ -0,0 +1,30 @@ +#pragma once +#ifndef _TILE_H_ +#define _TILE_H_ + +#include + +#define SIZE_TILE = 48 + +//ֻûзṹȽϺ +struct Tile +{ + enum class Direction + { + None = 0, + Up, + Down, + Left, + Right + }; + + int terrian = 0; + int decoration = -1; + int special_flag = -1; + bool has_tower = false; + Direction direction = Direction::None; +}; + +typedef std::vector> TileMap; + +#endif \ No newline at end of file