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