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>
<ClInclude Include="animation.h" />
<ClInclude Include="config_manager.h" />
<ClInclude Include="enemy.h" />
<ClInclude Include="enemy_type.h" />
<ClInclude Include="game_manager.h" />
<ClInclude Include="manager.h" />
<ClInclude Include="map.h" />
<ClInclude Include="resources_manager.h" />
<ClInclude Include="route.h" />
<ClInclude Include="slime_enemy.h" />
<ClInclude Include="tile.h" />
<ClInclude Include="timer.h" />
<ClInclude Include="vector2.h" />

View File

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

View File

@@ -12,7 +12,7 @@
class Animation
{
public:
//<2F><>ʾһ<CABE><D2BB><EFBFBD><EFBFBD><EFBFBD>Դ洢<D4B4>͵<EFBFBD><CDB5><EFBFBD><EFBFBD>޲<EFBFBD><DEB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><DEB7><EFBFBD>ֵ<EFBFBD>Ŀɵ<EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
//<2F><>ʾһ<CABE><D2BB>,<EFBFBD><EFBFBD><EFBFBD>Դ洢<EFBFBD>͵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>޲<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD>,<2C>ɵ<EFBFBD><EFBFBD>ö<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͡<EFBFBD>
typedef std::function<void()> PlayCallBack;
public:
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()
{
//<2F><><EFBFBD>ܼ<EFBFBD>ʱ<EFBFBD><CAB1>
timer_skill.set_one_shot(false);
timer_skill.set_on_timeout([&]() {on_skill_released(this); });
//<2F><><EFBFBD>׼<EFBFBD>ʱ<EFBFBD><CAB1>
timer_sketch.set_one_shot(true);
timer_sketch.set_wait_time(0.075);
timer_sketch.set_on_timeout([&]() {is_show_sketch = false; });
//<2F>ٶȻָ<C8BB><D6B8><EFBFBD>ʱ<EFBFBD><CAB1>
timer_restore_speed.set_one_shot(true);
timer_restore_speed.set_on_timeout([&]() {speed = max_speed;});
}
~Enemy() = default;
//֡<><D6A1><EFBFBD><EFBFBD>
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;
//<2F>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
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;
//<2F>Ƿ<EFBFBD>չʾˮƽ<CBAE><C6BD><EFBFBD><EFBFBD>
bool is_show_x_anim = (velocity.x) >= abs(velocity.y);
//1.<2E>Ƿ<EFBFBD>չʾ<D5B9><CABE>Ӱ 2.<2E>Ƿ<EFBFBD>չʾˮƽ<CBAE><C6BD><EFBFBD><EFBFBD>
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)
{
//Ѫ<><D1AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFA1A2><EFBFBD>߿򣬸<DFBF><F2A3ACB8><EFBFBD>)
static SDL_Rect rect;
static SDL_Point point;
static const int offset_y = 2;
static Vector2 size_hp_bar = { 40,8 };
//Ѫ<><D1AA><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD><DFBF><EFBFBD>ɫ
static const SDL_Color color_border = { 116,185,124,255 };
//Ѫ<><D1AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
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)
{
//<2F><><EFBFBD><EFBFBD>Ѫ<EFBFBD><D1AA>
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);
//<2F><><EFBFBD><EFBFBD>Ѫ<EFBFBD><D1AA><EFBFBD><EFBFBD><EFBFBD>߿<EFBFBD>
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;
}
//<2F><>ȡ<EFBFBD>ָ<EFBFBD><D6B8>
double get_recover_radius()const
{
//ת<><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return recover_range * SIZE_TILE;
}
double get_recover_intensity()const
{
return recover_intensity;
}
//<2F>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>enemy
bool can_move()
{
return !is_valid;
}
//<2F><>ȡenemy<6D><79>·<EFBFBD><C2B7><EFBFBD>ϵĽ<CFB5><C4BD><EFBFBD>
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;
//<2F><><EFBFBD>ٺ<EFBFBD><D9BA>ٶ<EFBFBD>
double speed = 0;
double max_speed = 0;
//<2F>Է<EFBFBD><D4B7><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>˺<EFBFBD>
double damage = 0;
//<2F><><EFBFBD><EFBFBD><EFBFBD>Ҹ<EFBFBD><D2B8><EFBFBD>
double reward_ratio = 0;
//<2F>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ܵļ<DCB5><C4BC><EFBFBD>
double recover_interval = 0;
//<2F>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ܵķ<DCB5>Χ
double recover_range = 0;
//<2F>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD>ܵ<EFBFBD>ǿ<EFBFBD><C7BF>
double recover_intensity = 0;
private:
//λ<><CEBB>
Vector2 position;
//<2F>ٶ<EFBFBD>
Vector2 velocity;
//<2F><><EFBFBD><EFBFBD>
Vector2 direction;
bool is_valid = true;
//<2F><><EFBFBD><EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>չʾ<D5B9><CABE><EFBFBD><EFBFBD>
Timer timer_sketch;
bool is_show_sketch = false;
//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>֡
Animation* anim_current = nullptr;
SkillCallback on_skill_released;
//<2F>ٶ<EFBFBD><D9B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD>ʱ<EFBFBD><CAB1>
Timer timer_restore_speed;
//<2F><><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
const Route* route = nullptr;
//<2F><>ǰ<EFBFBD><C7B0>Ŀ<EFBFBD>굥Ԫ<EAB5A5><D4AA>
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:
//һ<><D2BB>ȥ<EFBFBD><C8A5><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>ո<EFBFBD><D5B8><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD>
std::string trim_str(const std::string& str)
{
//<2F>ҵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD>ǿո<C7BF><D5B8><EFBFBD><EFBFBD>Ʊ<EFBFBD><C6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸλ<C4B8>ã<EFBFBD><C3A3>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ->nops
size_t begin_idx = str.find_first_not_of(" \t");
if (begin_idx == std::string::npos)
return "";

View File

@@ -10,7 +10,7 @@
class Route
{
public:
typedef std::vector<SDL_Point> Idxlist;
typedef std::vector<SDL_Point> IdxList;
public:
Route() = default;
@@ -63,13 +63,13 @@ public:
~Route() = default;
const Idxlist& get_idx_list() const
const IdxList& get_idx_list() const
{
return idx_list;
}
private:
Idxlist idx_list;
IdxList idx_list;
private:
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;
}
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)
@@ -81,7 +86,7 @@ public:
bool approx_zero() const
{
return length() < 0.00001;
return length() < 0.0001;
}
};