From 677a7d9a61cc3221eb1034be70238844816c63b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BB=BA=E6=98=8E=20=E6=B2=88?= <2431685932@qq.com>
Date: Wed, 26 Jun 2024 13:21:36 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20enemy=E6=95=8C=E4=BA=BA=E5=9F=BA?=
=?UTF-8?q?=E7=B1=BB=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
TdGame/TdGame/TdGame.vcxproj | 2 +
TdGame/TdGame/TdGame.vcxproj.filters | 6 +
TdGame/TdGame/animation.h | 2 +-
TdGame/TdGame/enemy.h | 297 +++++++++++++++++++++++++++
TdGame/TdGame/map.h | 1 +
TdGame/TdGame/route.h | 6 +-
TdGame/TdGame/slime_enemy.h | 20 ++
TdGame/TdGame/vector2.h | 11 +-
8 files changed, 338 insertions(+), 7 deletions(-)
create mode 100644 TdGame/TdGame/enemy.h
create mode 100644 TdGame/TdGame/slime_enemy.h
diff --git a/TdGame/TdGame/TdGame.vcxproj b/TdGame/TdGame/TdGame.vcxproj
index 755509a..e1fbe71 100644
--- a/TdGame/TdGame/TdGame.vcxproj
+++ b/TdGame/TdGame/TdGame.vcxproj
@@ -138,12 +138,14 @@
+
+
diff --git a/TdGame/TdGame/TdGame.vcxproj.filters b/TdGame/TdGame/TdGame.vcxproj.filters
index 9057f12..0a681fd 100644
--- a/TdGame/TdGame/TdGame.vcxproj.filters
+++ b/TdGame/TdGame/TdGame.vcxproj.filters
@@ -68,5 +68,11 @@
头文件
+
+ 头文件\enemy
+
+
+ 头文件\enemy
+
\ No newline at end of file
diff --git a/TdGame/TdGame/animation.h b/TdGame/TdGame/animation.h
index bebccf3..48a9e8c 100644
--- a/TdGame/TdGame/animation.h
+++ b/TdGame/TdGame/animation.h
@@ -12,7 +12,7 @@
class Animation
{
public:
- //±íʾһ¸ö¿ÉÒÔ´æ´¢ºÍµ÷ÓÃÎÞ²ÎÊýÇÒÎÞ·µ»ØÖµµÄ¿Éµ÷ÓöÔÏóÀàÐÍ¡£
+ //±íʾһ¸ö,¿ÉÒÔ´æ´¢ºÍµ÷ÓÃÎÞ²ÎÊýÇÒÎÞ·µ»ØÖµµÄ,¿Éµ÷ÓöÔÏóÀàÐÍ¡£
typedef std::function PlayCallBack;
public:
Animation()
diff --git a/TdGame/TdGame/enemy.h b/TdGame/TdGame/enemy.h
new file mode 100644
index 0000000..69b19a0
--- /dev/null
+++ b/TdGame/TdGame/enemy.h
@@ -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 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_
diff --git a/TdGame/TdGame/map.h b/TdGame/TdGame/map.h
index 9bd3f33..709ae26 100644
--- a/TdGame/TdGame/map.h
+++ b/TdGame/TdGame/map.h
@@ -110,6 +110,7 @@ private:
//Ò»¸öÈ¥³ý×Ö·û´®Ç°ºó¿Õ¸ñºÍÖƱí·ûµÄº¯Êý
std::string trim_str(const std::string& str)
{
+ //ÕÒµÚÒ»¸ö²»ÊÇ¿Õ¸ñºÍÖƱí·ûµÄ×ÖĸλÖã¬ÕÒ²»µ½·µ»ØÕâ¸öÖµ->nops
size_t begin_idx = str.find_first_not_of(" \t");
if (begin_idx == std::string::npos)
return "";
diff --git a/TdGame/TdGame/route.h b/TdGame/TdGame/route.h
index a8b1093..0174cf3 100644
--- a/TdGame/TdGame/route.h
+++ b/TdGame/TdGame/route.h
@@ -10,7 +10,7 @@
class Route
{
public:
- typedef std::vector Idxlist;
+ typedef std::vector 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)
diff --git a/TdGame/TdGame/slime_enemy.h b/TdGame/TdGame/slime_enemy.h
new file mode 100644
index 0000000..cbc4856
--- /dev/null
+++ b/TdGame/TdGame/slime_enemy.h
@@ -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_
diff --git a/TdGame/TdGame/vector2.h b/TdGame/TdGame/vector2.h
index 7074361..92e09e9 100644
--- a/TdGame/TdGame/vector2.h
+++ b/TdGame/TdGame/vector2.h
@@ -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;
}
};