feat: enemy敌人基类实现

This commit is contained in:
sjm 2024-06-26 13:21:36 +08:00
parent 46a7b25970
commit 677a7d9a61
8 changed files with 338 additions and 7 deletions

View File

@ -138,12 +138,14 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="animation.h" /> <ClInclude Include="animation.h" />
<ClInclude Include="config_manager.h" /> <ClInclude Include="config_manager.h" />
<ClInclude Include="enemy.h" />
<ClInclude Include="enemy_type.h" /> <ClInclude Include="enemy_type.h" />
<ClInclude Include="game_manager.h" /> <ClInclude Include="game_manager.h" />
<ClInclude Include="manager.h" /> <ClInclude Include="manager.h" />
<ClInclude Include="map.h" /> <ClInclude Include="map.h" />
<ClInclude Include="resources_manager.h" /> <ClInclude Include="resources_manager.h" />
<ClInclude Include="route.h" /> <ClInclude Include="route.h" />
<ClInclude Include="slime_enemy.h" />
<ClInclude Include="tile.h" /> <ClInclude Include="tile.h" />
<ClInclude Include="timer.h" /> <ClInclude Include="timer.h" />
<ClInclude Include="vector2.h" /> <ClInclude Include="vector2.h" />

View File

@ -68,5 +68,11 @@
<ClInclude Include="vector2.h"> <ClInclude Include="vector2.h">
<Filter>头文件</Filter> <Filter>头文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="enemy.h">
<Filter>头文件\enemy</Filter>
</ClInclude>
<ClInclude Include="slime_enemy.h">
<Filter>头文件\enemy</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -12,7 +12,7 @@
class Animation class Animation
{ {
public: public:
//表示一个可以存储和调用无参数且无返回值的可调用对象类型。 //表示一个,可以存储和调用无参数且无返回值的,可调用对象类型。
typedef std::function<void()> PlayCallBack; typedef std::function<void()> PlayCallBack;
public: public:
Animation() Animation()

297
TdGame/TdGame/enemy.h Normal file
View File

@ -0,0 +1,297 @@
#pragma once
#ifndef _ENEMY_H_
#define _ENEMY_H_
#include "config_manager.h"
#include "vector2.h"
#include "timer.h"
#include "animation.h"
#include "route.h"
class Enemy
{
public:
typedef std::function<void(Enemy* enemy)> SkillCallback;
public:
Enemy()
{
//技能计时器
timer_skill.set_one_shot(false);
timer_skill.set_on_timeout([&]() {on_skill_released(this); });
//闪白计时器
timer_sketch.set_one_shot(true);
timer_sketch.set_wait_time(0.075);
timer_sketch.set_on_timeout([&]() {is_show_sketch = false; });
//速度恢复计时器
timer_restore_speed.set_one_shot(true);
timer_restore_speed.set_on_timeout([&]() {speed = max_speed;});
}
~Enemy() = default;
//帧更新
void on_update(double delta)
{
timer_skill.on_update(delta);
timer_sketch.on_update(delta);
timer_restore_speed.on_update(delta);
Vector2 move_distance = velocity * delta;
Vector2 target_distance = position_target - position;
position += move_distance < target_distance ? move_distance : target_distance;
//移动距离很小
if (target_distance.approx_zero())
{
idx_target++;
refresh_position_target();
direction = (position_target - position).normalize();
}
velocity.x = direction.x * speed * SIZE_TILE;
velocity.y = direction.y * speed * SIZE_TILE;
//是否展示水平动画
bool is_show_x_anim = (velocity.x) >= abs(velocity.y);
//1.是否展示剪影 2.是否展示水平动画
if (is_show_sketch)
{
if (is_show_x_anim)
anim_current = velocity.x > 0 ? &anim_right_sketch : &anim_left_sketch;
else
anim_current = velocity.y > 0 ? &anim_down_sketch : &anim_up_sketch;
}
else
{
if (is_show_x_anim)
anim_current = velocity.x > 0 ? &anim_right : &anim_left;
else
anim_current = velocity.y > 0 ? &anim_down : &anim_up;
}
anim_current->on_update(delta);
}
void on_render(SDL_Renderer* renderer)
{
//血条矩形(内容物、外边框,复用)
static SDL_Rect rect;
static SDL_Point point;
static const int offset_y = 2;
static Vector2 size_hp_bar = { 40,8 };
//血条外边框颜色
static const SDL_Color color_border = { 116,185,124,255 };
//血条内容物颜色
static const SDL_Color color_content = { 226,255,194,255 };
point.x = (int)(position.x - size.x / 2);
point.y = (int)(position.y - size.y / 2);
anim_current->on_render(renderer, point);
if (hp < max_hp)
{
//绘制血条
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.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);
//绘制血条外边框
rect.w = (int)size_hp_bar.x;
SDL_SetRenderDrawColor(renderer, color_border.r, color_border.g, color_border.b, color_border.a);
SDL_RenderDrawRect(renderer, &rect);
}
}
void set_on_skill_released(SkillCallback on_skill_released)
{
this->on_skill_released = on_skill_released;
}
void increase_hp(double val)
{
hp += val;
if (hp > max_hp)
hp = max_hp;
}
void decrease_hp(double val)
{
hp -= val;
if (hp < 0)
{
hp = 0;
is_valid = false;
}
is_show_sketch = true;
timer_sketch.restart();
}
void slow_down()
{
speed = max_speed - 0.5;
timer_restore_speed.set_wait_time(1);
timer_restore_speed.restart();
}
void set_position(const Vector2& position)
{
this->position = position;
}
void set_route(const Route* route)
{
this->route = route;
refresh_position_target();
}
void make_invalid()
{
is_valid = true;
}
double get_hp()const
{
return hp;
}
const Vector2& get_size()const
{
return size;
}
const Vector2& get_position()const
{
return position;
}
const Vector2& get_velocity()const
{
return velocity;
}
double get_damage()const
{
return damage;
}
double get_reward_ratio()const
{
return reward_ratio;
}
//获取恢复半径
double get_recover_radius()const
{
//转化世界坐标
return recover_range * SIZE_TILE;
}
double get_recover_intensity()const
{
return recover_intensity;
}
//是否可以移除enemy
bool can_move()
{
return !is_valid;
}
//获取enemy在路径上的进度
double get_route_process()const
{
if (route->get_idx_list().size() == 1)
return 1;
return (double)idx_target / route->get_idx_list().size() - 1;
}
protected:
Vector2 size;
Timer timer_skill;
Animation anim_up;
Animation anim_down;
Animation anim_left;
Animation anim_right;
Animation anim_up_sketch;
Animation anim_down_sketch;
Animation anim_left_sketch;
Animation anim_right_sketch;
double hp = 0;
double max_hp = 0;
//减速后速度
double speed = 0;
double max_speed = 0;
//对防守目标伤害
double damage = 0;
//爆金币概率
double reward_ratio = 0;
//恢复技能的间隔
double recover_interval = 0;
//恢复技能的范围
double recover_range = 0;
//恢复技能的强度
double recover_intensity = 0;
private:
//位置
Vector2 position;
//速度
Vector2 velocity;
//方向
Vector2 direction;
bool is_valid = true;
//闪白效果计时器和是否展示闪白
Timer timer_sketch;
bool is_show_sketch = false;
//当前动画帧
Animation* anim_current = nullptr;
SkillCallback on_skill_released;
//速度受损回复时间
Timer timer_restore_speed;
//行走路径
const Route* route = nullptr;
//当前和目标单元格
int idx_target = 0;
Vector2 position_target;
private:
void refresh_position_target()
{
const Route::IdxList& idx_list = route->get_idx_list();
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;
}
}
};
#endif // ! _ENEMY_H_

View File

@ -110,6 +110,7 @@ private:
//一个去除字符串前后空格和制表符的函数 //一个去除字符串前后空格和制表符的函数
std::string trim_str(const std::string& str) std::string trim_str(const std::string& str)
{ {
//找第一个不是空格和制表符的字母位置,找不到返回这个值->nops
size_t begin_idx = str.find_first_not_of(" \t"); size_t begin_idx = str.find_first_not_of(" \t");
if (begin_idx == std::string::npos) if (begin_idx == std::string::npos)
return ""; return "";

View File

@ -10,7 +10,7 @@
class Route class Route
{ {
public: public:
typedef std::vector<SDL_Point> Idxlist; typedef std::vector<SDL_Point> IdxList;
public: public:
Route() = default; Route() = default;
@ -63,13 +63,13 @@ public:
~Route() = default; ~Route() = default;
const Idxlist& get_idx_list() const const IdxList& get_idx_list() const
{ {
return idx_list; return idx_list;
} }
private: private:
Idxlist idx_list; IdxList idx_list;
private: private:
bool check_duplicate_idx(const SDL_Point& target_idx) bool check_duplicate_idx(const SDL_Point& target_idx)

View File

@ -0,0 +1,20 @@
#pragma once
#ifndef _SLIME_ENEMY_H_
#define _SLIME_ENEMY_H_
#include "enemy.h"
#include "config_manager.h"
#include "resources_manager.h"
class SlimeEnemy
{
public:
SlimeEnemy();
~SlimeEnemy();
private:
};
#endif // !_SLIME_ENEMY_H_

View File

@ -37,9 +37,14 @@ public:
x -= vec.x; y -= vec.y; x -= vec.x; y -= vec.y;
} }
Vector2 operator*(const Vector2& vec)const double operator*(const Vector2& vec) const
{ {
return Vector2(x * vec.x , y* vec.y); return x * vec.x + y * vec.y;
}
Vector2 operator*(double val)const
{
return Vector2(x * val , y* val);
} }
void operator*=(double val) void operator*=(double val)
@ -81,7 +86,7 @@ public:
bool approx_zero() const bool approx_zero() const
{ {
return length() < 0.00001; return length() < 0.0001;
} }
}; };