error:错误版本,无法成成敌人

This commit is contained in:
sjm 2024-07-01 17:44:55 +08:00
parent b165dd9c9b
commit da08160625
19 changed files with 366 additions and 115 deletions

View File

@ -121,6 +121,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>..\ThirdParty\cJSON\include;..\ThirdParty\SDL2\include;..\ThirdParty\SDL2_gfx\include;..\ThirdParty\SDL2_image\include;..\ThirdParty\SDL2_mixer\include;..\ThirdParty\SDL2_ttf\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -137,6 +138,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="animation.h" />
<ClInclude Include="coin_manager.h" />
<ClInclude Include="config_manager.h" />
<ClInclude Include="enemy.h" />
<ClInclude Include="enemy_manager.h" />
@ -156,6 +158,7 @@
<ClInclude Include="timer.h" />
<ClInclude Include="vector2.h" />
<ClInclude Include="wave.h" />
<ClInclude Include="wave_manager.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -92,5 +92,11 @@
<ClInclude Include="home_manager.h">
<Filter>头文件\manager</Filter>
</ClInclude>
<ClInclude Include="wave_manager.h">
<Filter>头文件\manager</Filter>
</ClInclude>
<ClInclude Include="coin_manager.h">
<Filter>头文件\manager</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -8,7 +8,6 @@
#include <vector>
#include <functional>
class Animation
{
public:
@ -18,12 +17,14 @@ public:
Animation()
{
timer.set_one_shot(false);
timer.set_on_timeout
(
//[&]表示 lambda 表达式按引用捕获外部作用域的所有变量。这样,可以在 lambda 表达式中使用并修改这些变量。
[&]()
{
idx_frame++;
if (idx_frame >= rect_src_list.size())
{
idx_frame = is_loop ? 0 : rect_src_list.size() - 1;
@ -58,7 +59,8 @@ public:
rect_src.x = (idx % num_x) * width_frame;
rect_src.y = (idx / num_x) * height_frame;
rect_src.w = width_frame; rect_src.h = height_frame;
rect_src.w = width_frame;
rect_src.h = height_frame;
};
}
@ -81,16 +83,17 @@ public:
{
timer.on_update(delta);
}
//渲染器,渲染位置,角度(可能是旋转)
void on_render(SDL_Renderer* renderer, const SDL_Point& pos_dst, double angle = 0)const
void on_render(SDL_Renderer* renderer, const SDL_Point& pos_dst, double angle = 0) const
{
static SDL_Rect rect_dst;
rect_dst.x = pos_dst.x; rect_dst.y = pos_dst.y;
rect_dst.w = width_frame; rect_dst.h = height_frame;
//渲染器,纹理,裁剪矩形,目标矩形,角度,旋转中心点(默认1/2),翻转
SDL_RenderCopyEx(renderer, texture, &rect_src_list[idx_frame], &rect_dst, 0, nullptr, SDL_RendererFlip::SDL_FLIP_NONE);
//渲染器,纹理,裁剪矩形,目标矩形,角度,旋转中心点(默认1/2),翻转。 纹理绘制
SDL_RenderCopyEx(renderer, texture, &rect_src_list[idx_frame], &rect_dst, angle, nullptr, SDL_RendererFlip::SDL_FLIP_NONE);
}
private:
Timer timer;

View File

@ -0,0 +1,39 @@
#pragma once
#ifndef _COIN_MANAGER_H_
#define _COIN_MANAGER_H_
#include"manager.h"
class CoinManager:public Manager<CoinManager>
{
friend class Manager<CoinManager>;
public:
void increase_coin(double val)
{
num_coin += val;
}
void decrease_coin(double val)
{
num_coin -= val;
if (num_coin < 0)
num_coin = 0;
}
protected:
CoinManager()
{
num_coin = ConfigManager::instance()->num_initial_coin;
}
~CoinManager()
{
}
private:
double num_coin = 0;
};
#endif // _COINMANAGER_H_

View File

@ -1,7 +1,7 @@
{
"basic":
{
"window_title": "村庄保卫战",
"window_title": "村庄保卫战",
"window_width": 1280,
"window_height": 720
},

View File

@ -64,7 +64,7 @@ public:
int level_axeman = 0;//斧头兵等级
int level_gunner = 0;//枪兵等级
bool is_game_win =true;//游戏是否获胜
bool is_game_win =false;//游戏是否获胜
bool is_game_over = false;//游戏是否结束,和上面是两个不同层面的条件,需要分析
SDL_Rect rect_tile_map = { 0 };
@ -94,8 +94,8 @@ public:
if (!file.good())return false;
std::stringstream str_stream;
str_stream << file.rdbuf();//rdbuf()将一个流对象用另一个流对象输出
file.close();
//rdbuf()将一个流对象用另一个流对象输出
str_stream << file.rdbuf(); file.close();
cJSON* json_root = cJSON_Parse(str_stream.str().c_str());
if (!json_root) return false;//解析失败
@ -133,14 +133,17 @@ public:
continue;
wave.spawn_event_list.emplace_back();
Wave::SpawnEvent& spawn_event = wave.spawn_event_list.back();//填充内容,例:"interval" : 1,"point": 1,"enemy" : "Slim"
//填充内容,例:"interval" : 1,"point": 1,"enemy" : "Slime"
Wave::SpawnEvent& spawn_event = wave.spawn_event_list.back();
cJSON* json_spawn_event_interval = cJSON_GetObjectItem(json_spawn_event, "interval");
if (json_spawn_event_interval && json_spawn_event_interval->type == cJSON_Number)
spawn_event.interval = json_spawn_event_interval->valuedouble;
cJSON* json_spawn_event_spawn_point = cJSON_GetObjectItem(json_spawn_event,"point");
if (json_spawn_event_spawn_point && json_spawn_event_spawn_point->type == cJSON_Number)
spawn_event.spawn_point = json_spawn_event_spawn_point->valueint;
cJSON* json_spawn_event_enemy_type = cJSON_GetObjectItem(json_spawn_event, "enemy");
if (json_spawn_event_enemy_type && json_spawn_event_enemy_type->type == cJSON_String)
{
@ -157,7 +160,6 @@ public:
spawn_event.enemy_type = EnemyType::GoblinPriest;
}
}
if (wave.spawn_event_list.empty())
wave_list.pop_back();
}
@ -179,9 +181,7 @@ public:
if (!file.good()) return false;
std::stringstream str_stream;
str_stream << file.rdbuf();
file.close();
str_stream << file.rdbuf();file.close();
cJSON* json_root = cJSON_Parse(str_stream.str().c_str());
if (!json_root || json_root->type != cJSON_Object) return false;
@ -295,7 +295,8 @@ private:
void parse_enemy_template(EnemyTemplate& tpl, cJSON* json_root)
{
if (!json_root || json_root->type != cJSON_Object)return;
if (!json_root || json_root->type != cJSON_Object) return;
cJSON* json_hp = cJSON_GetObjectItem(json_root, "hp");
cJSON* json_speed = cJSON_GetObjectItem(json_root, "speed");
cJSON* json_damage = cJSON_GetObjectItem(json_root, "damage");

View File

@ -23,7 +23,7 @@ public:
//闪白计时器
timer_sketch.set_one_shot(true);
timer_sketch.set_wait_time(0.075);
timer_sketch.set_wait_time(0.001);
timer_sketch.set_on_timeout([&]() {is_show_sketch = false; });
//速度恢复计时器
@ -59,7 +59,7 @@ public:
//是否展示水平动画
bool is_show_x_anim = (velocity.x) >= abs(velocity.y);
//1.是否展示剪影 2.是否展示水平动画
//1.是否展示剪影 2.展示动画左右
if (is_show_sketch)
{
if (is_show_x_anim)
@ -102,7 +102,7 @@ public:
//绘制血条
rect.x = (int)(position.x - size_hp_bar.x / 2);
rect.y = (int)(position.y - size.y / 2 - size_hp_bar.y - offset_y);
rect.w = (int)size_hp_bar.x * (hp / max_hp);
rect.w = (int)(size_hp_bar.x * (hp / max_hp));
rect.h = (int)size_hp_bar.y;
SDL_SetRenderDrawColor(renderer, color_content.r, color_content.g, color_content.b, color_content.a);
SDL_RenderFillRect(renderer, &rect);
@ -159,7 +159,7 @@ public:
void make_invalid()
{
is_valid = true;
is_valid = false;
}
double get_hp()const
@ -216,7 +216,7 @@ public:
if (route->get_idx_list().size() == 1)
return 1;
return (double)idx_target / route->get_idx_list().size() - 1;
return (double)idx_target / (route->get_idx_list().size() - 1);
}
protected:
Vector2 size;
@ -285,8 +285,8 @@ private:
if (idx_target < idx_list.size())
{
const SDL_Point& point = idx_list[idx_target];
static const SDL_Rect& rect_tile_map = ConfigManager::instance()->rect_tile_map;
position.x = rect_tile_map.x + point.x * SIZE_TILE + SIZE_TILE / 2;
position.y = rect_tile_map.y + point.y * SIZE_TILE + SIZE_TILE / 2;
}

View File

@ -5,8 +5,12 @@
#include "enemy.h"
#include "manager.h"
#include "config_manager.h"
#include "Vector2.h"
#include "home_manager.h"
#include "slime_enemy.h"
#include "king_slime_enemy.h"
#include "skeleton_enemy.h"
#include "goblin_enemy.h"
#include "goblin_priest_enemy.h"
#include <vector>
#include <SDL.h>
@ -17,6 +21,7 @@ class EnemyManager: public Manager<EnemyManager>
friend class Manager<EnemyManager>;
public:
//类型:vector<Enemy*>
typedef std::vector<Enemy*> EnemyList;
public:
@ -38,8 +43,89 @@ public:
enemy->on_render(renderer);
}
/*
param2:
*/
void spawn_enemy(EnemyType type, int idx_spawn_point)
{
static Vector2 position;
static const SDL_Rect& rect_tile_map = ConfigManager::instance()->rect_tile_map;
//获取路径池
static const Map::SpawnerRoutePool& spawner_route_pool
= ConfigManager::instance()->map.get_idx_spawner_pool();
/*
*
*/
const auto& iter = spawner_route_pool.find(idx_spawn_point);
if(iter == spawner_route_pool.end())
return;
Enemy* enemy = nullptr;
switch (type)
{
case EnemyType::Slime:
enemy = new SlimeEnemy();
break;
case EnemyType::KingSlime:
enemy = new KingSlimeEnemy();
break;
case EnemyType::Skeleton:
enemy = new SkeletonEnemy();
break;
case EnemyType::Goblin:
enemy = new GoblinEnemy();
break;
case EnemyType::GoblinPriest:
enemy = new GoblinPriestEnemy();
break;
default:
enemy = new SlimeEnemy();
break;
}
//技能释放
enemy->set_on_skill_released
(
[&](Enemy* enemy_src)
{
double revocer_radius = enemy_src->get_recover_radius();
if (revocer_radius < 0) return;
const Vector2 pos_src = enemy_src->get_position();
for (Enemy* enemy_dst : enemy_list)
{
const Vector2& pos_dst = enemy_dst->get_position();
double distance = (pos_dst - pos_src).length();
if (distance <= revocer_radius)
enemy_dst->increase_hp(enemy_src->get_recover_intensity());
}
}
);
//寻路
const Route::IdxList& idx_list = iter->second.get_idx_list();
position.x = rect_tile_map.x + idx_list[0].x * SIZE_TILE + SIZE_TILE / 2;
position.y = rect_tile_map.y + idx_list[0].y * SIZE_TILE + SIZE_TILE / 2;
enemy->set_position(position);
enemy->set_route(&iter->second);
enemy_list.push_back(enemy);
}
bool check_cleared()
{
return enemy_list.empty();
}
protected:
EnemyManager() = default;
~EnemyManager()
{
for (Enemy* enemy : enemy_list)
@ -64,9 +150,10 @@ private:
for (Enemy* enemy : enemy_list)
{
if (enemy->can_remove())continue;
if (enemy->can_remove()) continue;
const Vector2& position = enemy->get_position();
if (position.x >= position_home_tile.x
&& position.y >= position_home_tile.y
&& position.x <= position_home_tile.x + SIZE_TILE
@ -75,7 +162,6 @@ private:
enemy->make_invalid();
HomeManager::instance()->decrease_hp(enemy->get_damage());
}
}
}
@ -91,7 +177,7 @@ private:
[](const Enemy* enemy)
{
bool deletable = enemy->can_remove();
if (deletable) delete(enemy);
if (deletable) delete enemy;
return deletable;
}), enemy_list.end());
}

View File

@ -5,6 +5,8 @@
#include "manager.h"
#include "config_manager.h"
#include "resources_manager.h"
#include "enemy_manager.h"
#include "wave_manager.h"
#include <SDL.h>
#include <SDL_ttf.h>
@ -33,7 +35,7 @@ public:
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));
SDL_Delay((Uint32)(1000.0 / 60 - delta * 1000));
//¸üÐÂÊý¾Ý
on_update(delta);
@ -119,7 +121,15 @@ private:
void on_update(double delta)
{
static ConfigManager* instance = ConfigManager::instance();
if (!instance->is_game_over)
{
WaveManager::instance()->on_update(delta);
EnemyManager::instance()->on_update(delta);
return;
}
}
void on_render()
@ -127,6 +137,8 @@ private:
static ConfigManager* instance = ConfigManager::instance();
static SDL_Rect& rect_dst = instance->rect_tile_map;
SDL_RenderCopy(renderer, tex_tile_map, nullptr, &rect_dst);
EnemyManager::instance()->on_render(renderer);
}
bool generate_tile_map_texture()
@ -145,7 +157,7 @@ private:
width_tex_tile_map = (int)map.get_width() * SIZE_TILE;
height_tex_tile_map = (int)map.get_height() * SIZE_TILE;
//第三个参数说明这张纹理可以被renderer绘制并且格式是第二个参数
//第三个参数说明这张纹理可以被renderer绘制并且格式是第二个参数,生成地图纹理
tex_tile_map = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ABGR8888,
SDL_TEXTUREACCESS_TARGET, width_tex_tile_map, height_tex_tile_map);
if (!tex_tile_map)return false;

View File

@ -20,40 +20,39 @@ public:
static ConfigManager::EnemyTemplate& goblin_template = ConfigManager::instance()->goblin_template;
static const std::vector<int> idx_list_up = { 6,7,8,9,10,11 };
static const std::vector<int> idx_list_down = { 0,1,2,3,4,5 };
static const std::vector<int> idx_list_left = { 18,19,20,21,22,23 };
static const std::vector<int> idx_list_right = { 12,13,14,15,16,17 };
static const std::vector<int> idx_list_up = { 5, 6, 7, 8, 9 };
static const std::vector<int> idx_list_down = { 0, 1, 2, 3, 4 };
static const std::vector<int> idx_list_left = { 15, 16, 17, 18, 19 };
static const std::vector<int> idx_list_right = { 10, 11, 12, 13, 14 };
anim_up.set_loop(true); anim_up.set_interval(0.1);
anim_up.set_frame_data(tex_goblin, 6, 4, idx_list_up);
anim_down.set_loop(true); anim_down.set_interval(0.1);
anim_down.set_frame_data(tex_goblin, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_goblin, 6, 4, idx_list_left);
anim_right.set_loop(true); anim_right.set_interval(0.1);
anim_right.set_frame_data(tex_goblin, 6, 4, idx_list_right);
anim_up.set_loop(true); anim_up.set_interval(0.15);
anim_up.set_frame_data(tex_goblin, 5, 4, idx_list_up);
anim_down.set_loop(true); anim_down.set_interval(0.15);
anim_down.set_frame_data(tex_goblin, 5, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.15);
anim_left.set_frame_data(tex_goblin, 5, 4, idx_list_left);
anim_right.set_loop(true); anim_right.set_interval(0.15);
anim_right.set_frame_data(tex_goblin, 5, 4, idx_list_right);
anim_up_sketch.set_loop(true); anim_up_sketch.set_interval(0.1);
anim_up_sketch.set_frame_data(tex_goblin_sketch, 6, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.1);
anim_down_sketch.set_frame_data(tex_goblin_sketch, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_goblin_sketch, 6, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.1);
anim_right_sketch.set_frame_data(tex_goblin_sketch, 6, 4, idx_list_right);
anim_up_sketch.set_loop(true); anim_up_sketch.set_interval(0.15);
anim_up_sketch.set_frame_data(tex_goblin_sketch, 5, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.15);
anim_down_sketch.set_frame_data(tex_goblin_sketch, 5, 4, idx_list_down);
anim_left_sketch.set_loop(true); anim_left_sketch.set_interval(0.15);
anim_left_sketch.set_frame_data(tex_goblin_sketch, 5, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.15);
anim_right_sketch.set_frame_data(tex_goblin_sketch, 5, 4, idx_list_right);
max_hp = king_slime_template.hp;
max_speed = king_slime_template.speed;
damage = king_slime_template.damage;
reward_ratio = king_slime_template.reward_ratio;
recover_interval = king_slime_template.recover_interval;
recover_range = king_slime_template.recover_range;
recover_intensity = king_slime_template.recover_intensity;
max_hp = goblin_template.hp;
max_speed = goblin_template.speed;
damage = goblin_template.damage;
reward_ratio = goblin_template.reward_ratio;
recover_interval = goblin_template.recover_interval;
recover_range = goblin_template.recover_range;
recover_intensity = goblin_template.recover_intensity;
size.x = 48, size.y = 48;
hp = max_hp;
speed = max_speed;
hp = max_hp,speed = max_speed;
}
~GoblinEnemy() = default;

View File

@ -21,28 +21,28 @@ public:
static ConfigManager::EnemyTemplate& goblin_priest_template = ConfigManager::instance()->goblin_priest_template;
static const std::vector<int> idx_list_up = { 6,7,8,9,10,11 };
static const std::vector<int> idx_list_down = { 0,1,2,3,4,5 };
static const std::vector<int> idx_list_left = { 18,19,20,21,22,23 };
static const std::vector<int> idx_list_right = { 12,13,14,15,16,17 };
static const std::vector<int> idx_list_up = { 5, 6, 7, 8, 9 };
static const std::vector<int> idx_list_down = { 0, 1, 2, 3, 4 };
static const std::vector<int> idx_list_left = { 15, 16, 17, 18, 19 };
static const std::vector<int> idx_list_right = { 10, 11, 12, 13, 14 };
anim_up.set_loop(true); anim_up.set_interval(0.1);
anim_up.set_frame_data(tex_goblin_priest, 6, 4, idx_list_up);
anim_down.set_loop(true); anim_down.set_interval(0.1);
anim_down.set_frame_data(tex_goblin_priest, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_goblin_priest, 6, 4, idx_list_left);
anim_right.set_loop(true); anim_right.set_interval(0.1);
anim_right.set_frame_data(tex_goblin_priest, 6, 4, idx_list_right);
anim_up.set_loop(true); anim_up.set_interval(0.15);
anim_up.set_frame_data(tex_goblin_priest, 5, 4, idx_list_up);
anim_down.set_loop(true); anim_down.set_interval(0.15);
anim_down.set_frame_data(tex_goblin_priest, 5, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.15);
anim_left.set_frame_data(tex_goblin_priest, 5, 4, idx_list_left);
anim_right.set_loop(true); anim_right.set_interval(0.15);
anim_right.set_frame_data(tex_goblin_priest, 5, 4, idx_list_right);
anim_up_sketch.set_loop(true); anim_up_sketch.set_interval(0.1);
anim_up_sketch.set_frame_data(tex_goblin_priest_sketch, 6, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.1);
anim_down_sketch.set_frame_data(tex_goblin_priest_sketch, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_goblin_priest_sketch, 6, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.1);
anim_right_sketch.set_frame_data(tex_goblin_priest_sketch, 6, 4, idx_list_right);
anim_up_sketch.set_loop(true); anim_up_sketch.set_interval(0.15);
anim_up_sketch.set_frame_data(tex_goblin_priest_sketch, 5, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.15);
anim_down_sketch.set_frame_data(tex_goblin_priest_sketch, 5, 4, idx_list_down);
anim_left_sketch.set_loop(true); anim_left_sketch.set_interval(0.15);
anim_left_sketch.set_frame_data(tex_goblin_priest_sketch, 5, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.15);
anim_right_sketch.set_frame_data(tex_goblin_priest_sketch, 5, 4, idx_list_right);
max_hp = goblin_priest_template.hp;
max_speed = goblin_priest_template.speed;
@ -53,8 +53,7 @@ public:
recover_intensity = goblin_priest_template.recover_intensity;
size.x = 48, size.y = 48;
hp = max_hp;
speed = max_speed;
hp = max_hp,speed = max_speed;
}
~GoblinPriestEnemy() = default;

View File

@ -20,10 +20,10 @@ public:
static ConfigManager::EnemyTemplate& king_slime_template = ConfigManager::instance()->king_slime_template;
static const std::vector<int> idx_list_up = { 6,7,8,9,10,11 };
static const std::vector<int> idx_list_down = { 0,1,2,3,4,5 };
static const std::vector<int> idx_list_left = { 18,19,20,21,22,23 };
static const std::vector<int> idx_list_right = { 12,13,14,15,16,17 };
static const std::vector<int> idx_list_up = { 18, 19, 20, 21, 22, 23 };
static const std::vector<int> idx_list_down = { 0, 1, 2, 3, 4, 5 };
static const std::vector<int> idx_list_left = { 6, 7, 8, 9, 10, 11 };
static const std::vector<int> idx_list_right = { 12, 13, 14, 15, 16, 17 };
anim_up.set_loop(true); anim_up.set_interval(0.1);
anim_up.set_frame_data(tex_king_slime, 6, 4, idx_list_up);
@ -38,8 +38,8 @@ public:
anim_up_sketch.set_frame_data(tex_king_slime_sketch, 6, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.1);
anim_down_sketch.set_frame_data(tex_king_slime_sketch, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_king_slime_sketch, 6, 4, idx_list_left);
anim_left_sketch.set_loop(true); anim_left_sketch.set_interval(0.1);
anim_left_sketch.set_frame_data(tex_king_slime_sketch, 6, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.1);
anim_right_sketch.set_frame_data(tex_king_slime_sketch, 6, 4, idx_list_right);
@ -52,8 +52,7 @@ public:
recover_intensity = king_slime_template.recover_intensity;
size.x = 48, size.y = 48;
hp = max_hp;
speed = max_speed;
hp = max_hp,speed = max_speed;
}
~KingSlimeEnemy() = default;

View File

@ -1,7 +1,6 @@
#define SDL_MAIN_HANDLED
#include<iostream>
#include "game_manager.h"

View File

@ -47,7 +47,7 @@ public:
tile_map_temp[idx_y].emplace_back();//在idx_y行中添加新瓦片
Tile& tile = tile_map_temp[idx_y].back();//获取对新增瓦片的引用,以便后续操作。
load_tile_from_string(tile,str_tile);
load_tile_from_string(tile, str_tile);
}
}
@ -64,8 +64,6 @@ public:
return true;
}
size_t get_width() const //const不会对类内进行修改
{
if (tile_map.empty())

View File

@ -20,28 +20,28 @@ public:
static ConfigManager::EnemyTemplate& skeleton_template = ConfigManager::instance()->skeleton_template;
//向上行动的动画帧索引根据resource中skeleton的资源图
static const std::vector<int> idx_list_up = { 6,7,8,9,10,11 };
static const std::vector<int> idx_list_down = { 0,1,2,3,4,5 };
static const std::vector<int> idx_list_left = { 18,19,20,21,22,23 };
static const std::vector<int> idx_list_right = { 12,13,14,15,16,17 };
static const std::vector<int> idx_list_up = { 5, 6, 7, 8, 9 };
static const std::vector<int> idx_list_down = { 0, 1, 2, 3, 4 };
static const std::vector<int> idx_list_left = { 15, 16, 17, 18, 19 };
static const std::vector<int> idx_list_right = { 10, 11, 12, 13, 14 };
anim_up.set_loop(true); anim_up.set_interval(0.1);
anim_up.set_loop(true); anim_up.set_interval(0.15);
anim_up.set_frame_data(tex_skeleton, 6, 4, idx_list_up);
anim_down.set_loop(true); anim_down.set_interval(0.1);
anim_down.set_loop(true); anim_down.set_interval(0.15);
anim_down.set_frame_data(tex_skeleton, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_loop(true); anim_left.set_interval(0.15);
anim_left.set_frame_data(tex_skeleton, 6, 4, idx_list_left);
anim_right.set_loop(true); anim_right.set_interval(0.1);
anim_right.set_loop(true); anim_right.set_interval(0.15);
anim_right.set_frame_data(tex_skeleton, 6, 4, idx_list_right);
anim_up_sketch.set_loop(true); anim_up_sketch.set_interval(0.1);
anim_up_sketch.set_frame_data(tex_skeleton_sketch, 6, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.1);
anim_down_sketch.set_frame_data(tex_skeleton_sketch, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_skeleton_sketch, 6, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.1);
anim_right_sketch.set_frame_data(tex_skeleton_sketch, 6, 4, idx_list_right);
anim_up_sketch.set_loop(true); anim_up_sketch.set_interval(0.15);
anim_up_sketch.set_frame_data(tex_skeleton_sketch, 5, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.15);
anim_down_sketch.set_frame_data(tex_skeleton_sketch, 5, 4, idx_list_down);
anim_left_sketch.set_loop(true); anim_left_sketch.set_interval(0.15);
anim_left_sketch.set_frame_data(tex_skeleton_sketch, 5, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.15);
anim_right_sketch.set_frame_data(tex_skeleton_sketch, 5, 4, idx_list_right);
max_hp = skeleton_template.hp;
max_speed = skeleton_template.speed;
@ -52,8 +52,7 @@ public:
recover_intensity = skeleton_template.recover_intensity;
size.x = 48, size.y = 48;
hp = max_hp;
speed = max_speed;
hp = max_hp,speed = max_speed;
}
~SkeletonEnemy() = default;

View File

@ -38,8 +38,8 @@ public:
anim_up_sketch.set_frame_data(tex_slime_sketch, 6, 4, idx_list_up);
anim_down_sketch.set_loop(true); anim_down_sketch.set_interval(0.1);
anim_down_sketch.set_frame_data(tex_slime_sketch, 6, 4, idx_list_down);
anim_left.set_loop(true); anim_left.set_interval(0.1);
anim_left.set_frame_data(tex_slime_sketch, 6, 4, idx_list_left);
anim_left_sketch.set_loop(true); anim_left_sketch.set_interval(0.1);
anim_left_sketch.set_frame_data(tex_slime_sketch, 6, 4, idx_list_left);
anim_right_sketch.set_loop(true); anim_right_sketch.set_interval(0.1);
anim_right_sketch.set_frame_data(tex_slime_sketch, 6, 4, idx_list_right);
@ -52,11 +52,9 @@ public:
recover_intensity = slime_template.recover_intensity;
size.x = 48, size.y = 48;
hp = max_hp;
speed = max_speed;
hp = max_hp, speed = max_speed;
}
~SlimeEnemy() = default;
};

View File

@ -45,6 +45,7 @@ public:
void on_update(double delta)
{
if (paused) return;
pass_time += delta;
if (pass_time >= wait_time)
{
@ -73,5 +74,4 @@ private:
std::function<void()> on_timeout;
};
#endif

View File

@ -13,7 +13,7 @@ struct Wave
{
double interval = 0;
int spawn_point = 1;
EnemyType enemy_type = EnemyType::Slime;//在level.json文件中见格式,波次序列配置文件
EnemyType enemy_type = EnemyType::Goblin;//在level.json文件中见格式,波次序列配置文件
};
double rewards = 0;

View File

@ -0,0 +1,110 @@
#ifndef _WAVE_MANAGER_H
#define _WAVE_MANAGER_H
#include"timer.h"
#include "manager.h"
#include "config_manager.h"
#include "enemy_manager.h"
#include "coin_manager.h"
class WaveManager : public Manager<WaveManager>
{
friend class Manager<WaveManager>;
public:
void on_update(double delta)
{
static ConfigManager* instance = ConfigManager::instance();
if (instance->is_game_over)
return;
if (!is_wave_started)
timer_start_wave.on_update(delta);
else
timer_spawn_enemy.on_update(delta);
//如果最后一个敌人已经生成&&敌人列表为空
if (is_spawned_last_enemy && EnemyManager::instance()->check_cleared())
{
CoinManager::instance()->increase_coin(instance->wave_list[idx_wave].rewards);
idx_wave++;
//如果最后一波
if (idx_wave >= instance->wave_list.size())
{
instance->is_game_win = true;
instance->is_game_over = true;
}
else
{
idx_spawn_event = 0;
is_wave_started = true;
is_spawned_last_enemy = false;
const Wave& wave = instance->wave_list[idx_wave];
timer_start_wave.set_wait_time(wave.interval);
timer_start_wave.restart();
}
}
}
protected:
WaveManager()
{
static const std::vector<Wave>& wave_list = ConfigManager::instance()->wave_list;
timer_start_wave.set_one_shot(true);
timer_start_wave.set_wait_time(wave_list[0].interval);
timer_start_wave.set_on_timeout(
[&]()
{
is_wave_started = true;
timer_spawn_enemy.set_wait_time(wave_list[idx_wave].spawn_event_list[0].interval);
timer_spawn_enemy.restart();
}
);
timer_spawn_enemy.set_one_shot(true);
timer_spawn_enemy.set_on_timeout(
[&]()
{
const std::vector<Wave::SpawnEvent>& spawn_event_list = wave_list[idx_wave].spawn_event_list;
const Wave::SpawnEvent& spawn_event = spawn_event_list[idx_spawn_event];
EnemyManager::instance()->spawn_enemy(spawn_event.enemy_type, spawn_event.spawn_point);
idx_spawn_event++;
if (idx_spawn_event >= spawn_event_list.size())
{
is_spawned_last_enemy = true;
return;
}
timer_spawn_enemy.set_wait_time(spawn_event_list[idx_spawn_event].interval);
timer_spawn_enemy.restart();
}
);
}
~WaveManager() = default;
private:
//波次
int idx_wave = 0;
//生成事件次,一波有很多次生成
int idx_spawn_event = 0;
//第一波开始计时器
Timer timer_start_wave;
//敌人生成计时器
Timer timer_spawn_enemy;
//是否开始
bool is_wave_started = false;
//是否生成最后一个敌人
bool is_spawned_last_enemy = false;
};
#endif