feat: panel基类

This commit is contained in:
sjm 2024-07-16 00:54:22 +08:00
parent 5fb76ce452
commit 60a00be813
15 changed files with 783 additions and 19 deletions

View File

@ -146,6 +146,7 @@
<ClInclude Include="bullet_manager.h" />
<ClInclude Include="bullet_type.h" />
<ClInclude Include="coin_manager.h" />
<ClInclude Include="coin_prop.h" />
<ClInclude Include="config_manager.h" />
<ClInclude Include="enemy.h" />
<ClInclude Include="enemy_manager.h" />
@ -159,14 +160,17 @@
<ClInclude Include="king_slime_enemy.h" />
<ClInclude Include="manager.h" />
<ClInclude Include="map.h" />
<ClInclude Include="panel.h" />
<ClInclude Include="resources_manager.h" />
<ClInclude Include="route.h" />
<ClInclude Include="shell_bullet.h" />
<ClInclude Include="skeleton_enemy.h" />
<ClInclude Include="slime_enemy.h" />
<ClInclude Include="status_bar.h" />
<ClInclude Include="tile.h" />
<ClInclude Include="timer.h" />
<ClInclude Include="tower.h" />
<ClInclude Include="tower_manager.h" />
<ClInclude Include="tower_type.h" />
<ClInclude Include="vector2.h" />
<ClInclude Include="wave.h" />

View File

@ -28,6 +28,12 @@
<Filter Include="头文件\tower">
<UniqueIdentifier>{934287b6-3a61-4491-8b40-951a2d797c87}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\ui">
<UniqueIdentifier>{897a51c7-844c-4f07-84bc-aac1ebca8e19}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\ui\panel">
<UniqueIdentifier>{eb558f9c-e602-498f-a18e-eb239eea8991}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
@ -140,5 +146,17 @@
<ClInclude Include="gunner_tower.h">
<Filter>头文件\tower</Filter>
</ClInclude>
<ClInclude Include="tower_manager.h">
<Filter>头文件\tower</Filter>
</ClInclude>
<ClInclude Include="coin_prop.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="status_bar.h">
<Filter>头文件\ui</Filter>
</ClInclude>
<ClInclude Include="panel.h">
<Filter>头文件\ui\panel</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -92,7 +92,7 @@ public:
rect_dst.x = pos_dst.x, rect_dst.y = pos_dst.y;
rect_dst.w = width_frame, rect_dst.h = height_frame;
//渲染器,纹理,裁剪矩形,目标矩形,角度,旋转中心点(默认1/2),翻转。 纹理绘制
//渲染器,纹理,裁剪矩形,目标矩形,角度,旋转中心点(默认1/2),翻转。
SDL_RenderCopyEx(renderer, texture, &rect_src_list[idx_frame], &rect_dst, angle, nullptr, SDL_RendererFlip::SDL_FLIP_NONE);
}
private:

View File

@ -12,7 +12,7 @@ public:
Bullet() = default;
~Bullet() = default;
void set_veloccity(const Vector2 velocity)
void set_veloccity(const Vector2& velocity)
{
this->velocity = velocity;
@ -23,7 +23,7 @@ public:
}
}
void set_position(const Vector2& size)
void set_position(const Vector2& position)
{
this->position = position;
}

View File

@ -2,11 +2,17 @@
#ifndef _COIN_MANAGER_H_
#define _COIN_MANAGER_H_
#include "coin_prop.h"
#include"manager.h"
#include "config_manager.h"
class CoinManager:public Manager<CoinManager>
{
friend class Manager<CoinManager>;
public:
typedef std::vector<CoinProp*> CoinPropList;
public:
void increase_coin(double val)
{
@ -20,19 +26,59 @@ public:
if (num_coin < 0)
num_coin = 0;
}
void on_update(double delta)
{
for (CoinProp* coin_prop : coin_prop_list)
coin_prop->on_update(delta);
coin_prop_list.erase(std::remove_if(coin_prop_list.begin(), coin_prop_list.end(), [](CoinProp* coin_prop)
{
bool deletable = coin_prop->can_remove();
if (deletable) delete coin_prop;
return deletable;
}),coin_prop_list.end());
}
void on_render(SDL_Renderer* renderer)
{
for (CoinProp* coin_prop : coin_prop_list)
coin_prop->on_render(renderer);
}
double get_current_coin_num() const
{
return num_coin;
}
CoinPropList& get_coin_prop_list()
{
return coin_prop_list;
}
void spawn_coin_prop(const Vector2& position)
{
CoinProp* coin_prop = new CoinProp();
coin_prop->set_position(position);
coin_prop_list.push_back(coin_prop);
}
protected:
CoinManager()
{
num_coin = ConfigManager::instance()->num_initial_coin;
}
~CoinManager()
{
for (CoinProp* coin_prop : coin_prop_list)
delete coin_prop;
}
private:
double num_coin = 0;
double num_coin = 100;
CoinPropList coin_prop_list;
};

108
TdGame/TdGame/coin_prop.h Normal file
View File

@ -0,0 +1,108 @@
#ifndef _COIN_PROP_H_
#define _COIN_PROP_H_
#include "tile.h"
#include "vector2.h"
#include "timer.h"
#include "resources_manager.h"
#include <SDL.H>
class CoinProp
{
public:
CoinProp()
{
timer_jump.set_one_shot(true);
timer_jump.set_wait_time(interval_jump);
timer_jump.set_on_timeout(
[&]()
{
is_jumping = false;
});
timer_disappear.set_one_shot(true);
timer_disappear.set_wait_time(interval_disappear);
timer_disappear.set_on_timeout(
[&]()
{
is_valid = false;
});
velocity.x = (rand() % 2 ? 1 : -1) * 2 * SIZE_TILE;
velocity.y = -3 * SIZE_TILE;
}
~CoinProp() = default;
void set_position(const Vector2& position)
{
this->position = position;
}
const Vector2 get_position() const
{
return position;
}
const Vector2& get_size() const
{
return size;
}
void make_invalid()
{
is_valid = false;
}
bool can_remove()
{
return !is_valid;
}
void on_update(double delta)
{
timer_jump.on_update(delta);
timer_disappear.on_update(delta);
if (is_jumping)
{
velocity.y += gravity * delta;
}
else
{
velocity.x = 0;
velocity.y = sin(SDL_GetTicks64() / 1000 * 4) * 30;
}
position += velocity * delta;
}
void on_render(SDL_Renderer* renderer)
{
static SDL_Rect rect = { 0, 0, (int)size.y, (int)size.y };
static SDL_Texture* tex_coin = ResourcesManager::instance()
->get_texture_pool().find(ResID::Tex_Coin)->second;
rect.x = (int)(position.x - size.x) / 2;
rect.y = (int)(position.y - size.y) / 2;
SDL_RenderCopy(renderer, tex_coin, nullptr, &rect);
}
private:
Vector2 position;
Vector2 velocity;
Timer timer_jump;
Timer timer_disappear;
bool is_valid = true;
bool is_jumping = true;
double gravity = 490;
double interval_jump = 0.75;
Vector2 size = { 16, 16 };
double interval_disappear = 10;
};
#endif // !_COIN_PROP_H_

View File

@ -11,6 +11,8 @@
#include "skeleton_enemy.h"
#include "goblin_enemy.h"
#include "goblin_priest_enemy.h"
#include "bullet_manager.h"
#include "coin_manager.h"
#include <vector>
#include <SDL.h>
@ -173,7 +175,52 @@ private:
//子弹碰撞检测
void process_bullet_collision()
{
static BulletManager::BulletList& bullet_list
= BulletManager::instance()->get_bullet_list();
for (Enemy* enemy : enemy_list)
{
if (enemy->can_remove()) continue;
const Vector2& size_enemy = enemy->get_size();
const Vector2& pos_enemy = enemy->get_position();
for (Bullet* bullet : bullet_list)
{
if (!bullet->can_collide()) continue;
const Vector2& pos_bullet = bullet->get_position();
if (pos_bullet.x >= pos_enemy.x - size_enemy.x / 2
&& pos_bullet.y >= pos_enemy.y - size_enemy.y / 2
&& pos_bullet.x <= pos_enemy.x + size_enemy.x / 2
&& pos_bullet.y <= pos_enemy.y + size_enemy.y / 2)
{
double damage = bullet->get_damage();
double damage_range = bullet->get_damage_range();
if (damage_range < 0)
{
enemy->decrease_hp(damage);
if (enemy->can_remove())
try_spawn_coin_prop(pos_enemy, enemy->get_reward_ratio());
}
else
{
for (Enemy* target_enemy : enemy_list)
{
const Vector2& pos_target_enemy = target_enemy->get_position();
if ((pos_target_enemy - pos_bullet).length() <= damage_range)
{
target_enemy->decrease_hp(damage);
if(target_enemy->can_remove())
try_spawn_coin_prop(pos_target_enemy, target_enemy->get_reward_ratio());
}
}
}
bullet->on_collide(enemy);
}
}
}
}
//移除无效敌人
void remove_invalid_enemy()
@ -186,6 +233,13 @@ private:
return deletable;
}), enemy_list.end());
}
void try_spawn_coin_prop(const Vector2& position, double ratio)
{
static CoinManager* instance = CoinManager::instance();
if ((double)(rand() % 100) / 100 <= ratio)
instance->spawn_coin_prop(position);
}
};
#endif // !_ENEMY_MANAGER_H

View File

@ -7,6 +7,9 @@
#include "resources_manager.h"
#include "enemy_manager.h"
#include "wave_manager.h"
#include "tower_manager.h"
#include "bullet_manager.h"
#include "status_bar.h"
#include <SDL.h>
#include <SDL_ttf.h>
@ -22,6 +25,8 @@ class GameManager : public Manager<GameManager>
public:
int run(int argc,char** argv)
{
TowerManager::instance()->place_tower(TowerType::Archer, { 5,0 });
Uint64 last_counter = SDL_GetPerformanceCounter();
const Uint64 counter_freq = SDL_GetPerformanceFrequency();
@ -83,6 +88,8 @@ protected:
init_assert(generate_tile_map_texture(),u8"生成瓦片地图类型失败!");
status_bar.set_position(15, 15);
}
~GameManager()
@ -100,6 +107,8 @@ private:
SDL_Event event;
bool is_quit = false;
StatusBar status_bar;
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
@ -125,9 +134,11 @@ private:
if (!instance->is_game_over)
{
status_bar.on_update(renderer);
WaveManager::instance()->on_update(delta);
EnemyManager::instance()->on_update(delta);
BulletManager::instance()->on_update(delta);
TowerManager::instance()->on_update(delta);
return;
}
}
@ -138,7 +149,15 @@ private:
static SDL_Rect& rect_dst = instance->rect_tile_map;
SDL_RenderCopy(renderer, tex_tile_map, nullptr, &rect_dst);
EnemyManager::instance()->on_render(renderer);
BulletManager::instance()->on_render(renderer);
TowerManager::instance()->on_render(renderer);
if (!instance->is_game_over)
{
status_bar.on_render(renderer);
}
}
bool generate_tile_map_texture()

View File

@ -12,7 +12,7 @@ class HomeManager:public Manager<HomeManager>
friend class Manager<HomeManager>;
public:
double get_current_hp()
double get_current_hp_num()
{
return num_hp;
}

240
TdGame/TdGame/panel.h Normal file
View File

@ -0,0 +1,240 @@
#ifndef _PANEL_H_
#define _PANEL_H_
#include "tile.h"
#include "resources_manager.h"
#include <SDL.h>
#include <String>
class Panel
{
public:
Panel()
{
tex_select_cursor = ResourcesManager::instance()->get_texture_pool().find(ResID::Tex_UISelectCursor)->second;
}
~Panel()
{
SDL_DestroyTexture(tex_text_background);
SDL_DestroyTexture(tex_text_foreground);
}
void show()
{
visible = true;
}
void set_idx_tile(const SDL_Point& idx)
{
idx_tile_selected = idx;
}
void set_center_position(const SDL_Point& pos)
{
center_pos = pos;
}
void on_input(const SDL_Event& event)
{
if (!visible) return;
switch (event.type)
{
case SDL_MOUSEMOTION:
{
SDL_Point pos_cursor = { event.motion.x,event.motion.y };
SDL_Rect rect_target = { 0, 0, size_button, size_button };
rect_target.x = center_pos.x - width / 2 + offset_top.x;
rect_target.y = center_pos.y - height / 2 + offset_top.y;
if (SDL_PointInRect(&pos_cursor, &rect_target))
{
hovered_target = HoveredTarget::Top;
return;
}
rect_target.x = center_pos.x - width / 2 + offset_left.x;
rect_target.y = center_pos.y - height / 2 + offset_left.y;
if (SDL_PointInRect(&pos_cursor, &rect_target))
{
hovered_target = HoveredTarget::Left;
return;
}
rect_target.x = center_pos.x - width / 2 + offset_right.x;
rect_target.y = center_pos.y - height / 2 + offset_right.y;
if (SDL_PointInRect(&pos_cursor, &rect_target))
{
hovered_target = HoveredTarget::Right;
return;
}
hovered_target = HoveredTarget::None;
}
break;
case SDL_MOUSEBUTTONUP:
{
switch (hovered_target)
{
case Panel::HoveredTarget::Top:
on_click_top_area;
break;
case Panel::HoveredTarget::Left:
on_click_left_area;
break;
case Panel::HoveredTarget::Right:
on_click_right_area;
break;
}
visible = false;
}
break;
default:
break;
}
}
virtual void on_update(SDL_Renderer* renderer)
{
static TTF_Font* font = ResourcesManager::instance()->get_font_pool().find(ResID::Font_Main)->second;
if (hovered_target == HoveredTarget::None)
return;
int val = 0;
switch (hovered_target)
{
case Panel::HoveredTarget::Top:
val = val_top;
break;
case Panel::HoveredTarget::Left:
val = val_left;
break;
case Panel::HoveredTarget::Right:
val = val_right;
break;
default:
break;
}
SDL_DestroyTexture(tex_text_background);
tex_text_background = nullptr;
SDL_DestroyTexture(tex_text_foreground);
tex_text_foreground = nullptr;
std::string str_val = val < 0 ? "MAX" : std::to_string(val);
SDL_Surface* suf_text_background = TTF_RenderText_Blended(font, str_val.c_str(), color_text_background);
SDL_Surface* suf_text_foreground = TTF_RenderText_Blended(font, str_val.c_str(), color_text_foreground);
width_text = suf_text_background->w; height_text = suf_text_background->h;
tex_text_background = SDL_CreateTextureFromSurface(renderer, suf_text_background);
tex_text_foreground = SDL_CreateTextureFromSurface(renderer, suf_text_foreground);
SDL_FreeSurface(suf_text_background);
SDL_FreeSurface(suf_text_foreground);
}
virtual void on_render(SDL_Renderer* renderer)
{
if (!visible) return;
SDL_Rect rect_dst_cursor =
{
center_pos.x = SIZE_TILE / 2,
center_pos.y = SIZE_TILE / 2,
SIZE_TILE, SIZE_TILE
};
SDL_RenderCopy(renderer, tex_select_cursor, nullptr, &rect_dst_cursor);
SDL_Rect rect_dst_panel =
{
center_pos.x - width / 2,
center_pos.y - height / 2,
width,height
};
SDL_Texture* tex_panel = nullptr;
switch (hovered_target)
{
case Panel::HoveredTarget::None:
tex_panel = tex_idle;
break;
case Panel::HoveredTarget::Top:
tex_panel = tex_hovered_top;
break;
case Panel::HoveredTarget::Left:
tex_panel = tex_hovered_left;
break;
case Panel::HoveredTarget::Right:
tex_panel = tex_hovered_right;
break;
}
SDL_RenderCopy(renderer, tex_panel, nullptr, &rect_dst_panel);
if (hovered_target == HoveredTarget::None) return;
SDL_Rect rect_dst_text;
rect_dst_text.x = center_pos.x - width_text / 2 + offset_shadow.x;
rect_dst_text.y = center_pos.y + height / 2 + offset_shadow.y;
rect_dst_text.w = width_text; rect_dst_text.h = height_text;
SDL_RenderCopy(renderer, tex_text_background, nullptr, &rect_dst_text);
rect_dst_text.x -= offset_shadow.x;
rect_dst_text.y -= offset_shadow.y;
SDL_RenderCopy(renderer, tex_text_foreground, nullptr, &rect_dst_text);
}
protected:
enum class HoveredTarget
{
None,
Top,
Left,
Right
};
protected:
bool visible = true;
SDL_Point idx_tile_selected;
SDL_Point center_pos = { 0 };
SDL_Texture* tex_idle = nullptr;
SDL_Texture* tex_hovered_top = nullptr;
SDL_Texture* tex_hovered_left = nullptr;
SDL_Texture* tex_hovered_right = nullptr;
SDL_Texture* tex_select_cursor = nullptr;
int val_top = 0, val_left = 0, val_right = 0;
HoveredTarget hovered_target = HoveredTarget::None;
protected:
virtual void on_click_top_area() = 0;
virtual void on_click_left_area() = 0;
virtual void on_click_right_area() = 0;
private:
const int size_button = 48;
const int width = 144, height = 144;
const SDL_Point offset_top = { 48,6 };
const SDL_Point offset_left = { 8,80 };
const SDL_Point offset_right = { 90,80 };
const SDL_Point offset_shadow = { 3,3 };
const SDL_Color color_text_background = { 175,175,175,255 };
const SDL_Color color_text_foreground = { 255,255,255,255 };
int width_text = 0, height_text = 0;
SDL_Texture* tex_text_background = nullptr;
SDL_Texture* tex_text_foreground = nullptr;
};
#endif // !_PANEL_H_

View File

@ -38,7 +38,7 @@ public:
void on_update(double delta) override
{
if (can_collide)
if (can_collide())
{
Bullet::on_update(delta);
return;
@ -48,7 +48,7 @@ public:
void on_render(SDL_Renderer* renderer) override
{
if (can_collide)
if (can_collide())
{
Bullet::on_render(renderer);
return;

118
TdGame/TdGame/status_bar.h Normal file
View File

@ -0,0 +1,118 @@
#ifndef _STATUES_BAR_H_
#define _STATUES_BAR_H_
#include "coin_manager.h"
#include "home_manager.h"
#include "resources_manager.h"
#include <string>
#include <SDL2_gfxPrimitives.h>
#include "SDL.h"
class StatusBar
{
public:
StatusBar() = default;
~StatusBar() = default;
void set_position(int x,int y)
{
position.x = x, position.y = y;
}
void on_update(SDL_Renderer* renderer)
{
static TTF_Font* font = ResourcesManager::instance()->get_font_pool().find(ResID::Font_Main)->second;
SDL_DestroyTexture(tex_text_background);
tex_text_background = nullptr;
SDL_DestroyTexture(tex_text_foreground);
tex_text_foreground = nullptr;
std::string str_val = std::to_string((int)CoinManager::instance()->get_current_coin_num());
SDL_Surface* suf_text_background = TTF_RenderText_Blended(font, str_val.c_str(), color_text_background);
SDL_Surface* suf_text_foreground = TTF_RenderText_Blended(font, str_val.c_str(), color_text_foredground);
width_text = suf_text_background->w, height_text = suf_text_background->h;
tex_text_background = SDL_CreateTextureFromSurface(renderer, suf_text_background);
tex_text_foreground = SDL_CreateTextureFromSurface(renderer, suf_text_foreground);
SDL_FreeSurface(suf_text_background);
SDL_FreeSurface(suf_text_foreground);
}
void on_render(SDL_Renderer* renderer)
{
static SDL_Rect rect_dst;
static const ResourcesManager::TexturePool& tex_pool = ResourcesManager::instance()->get_texture_pool();
static SDL_Texture* tex_coin = tex_pool.find(ResID::Tex_UICoin)->second;
static SDL_Texture* tex_heart = tex_pool.find(ResID::Tex_UIHeart)->second;
static SDL_Texture* tex_home_avatar = tex_pool.find(ResID::Tex_UIHomeAvatar)->second;
static SDL_Texture* tex_player_avatar = tex_pool.find(ResID::Tex_UIPlayerAvatar)->second;
rect_dst.x = position.x, rect_dst.y = position.y;
rect_dst.w = 78, rect_dst.h = 78;
SDL_RenderCopy(renderer, tex_home_avatar, nullptr, &rect_dst);
for (int i = 0; i < (int)HomeManager::instance()->get_current_hp_num(); i++)
{
rect_dst.x = position.x + 78 + 15 + i * (32 + 2);
rect_dst.y = position.y;
rect_dst.w = 32, rect_dst.h = 32;
SDL_RenderCopy(renderer, tex_heart, nullptr, &rect_dst);
}
rect_dst.x = position.x + 78 + 15;
rect_dst.y = position.y + 78 - 32;
rect_dst.w = 32, rect_dst.h = 32;
SDL_RenderCopy(renderer, tex_coin, nullptr, &rect_dst);
rect_dst.x += 32 + 10 + offset_shadow.x;
rect_dst.y = rect_dst.y + (32 - height_text) / 2 + offset_shadow.y;
rect_dst.w = width_text, rect_dst.h = height_text;
SDL_RenderCopy(renderer, tex_text_background, nullptr, &rect_dst);
rect_dst.x -= offset_shadow.x;
rect_dst.y -= offset_shadow.y;
SDL_RenderCopy(renderer, tex_text_foreground, nullptr, &rect_dst);
rect_dst.x = position.x + (78 - 65) / 2;
rect_dst.y = position.y + 78 + 5;
rect_dst.w = 65, rect_dst.h = 65;
SDL_RenderCopy(renderer, tex_player_avatar, nullptr, &rect_dst);
rect_dst.x = position.x + 78 + 15;
rect_dst.y += 10;
roundedBoxRGBA(renderer, rect_dst.x, rect_dst.y, rect_dst.x + width_mp_bar, rect_dst.y + height_mp_bar, 4,
color_mp_bar_background.r, color_mp_bar_background.g, color_mp_bar_background.b, color_mp_bar_background.a);
rect_dst.x += width_border_mp_bar;
rect_dst.y += width_border_mp_bar;
rect_dst.w = width_mp_bar - 2 * width_border_mp_bar;
rect_dst.h = height_mp_bar - 2 * width_border_mp_bar;
roundedBoxRGBA(renderer, rect_dst.x, rect_dst.y, rect_dst.x + rect_dst.w, rect_dst.y + rect_dst.h, 2,
color_mp_bar_foredground.r, color_mp_bar_foredground.g, color_mp_bar_foredground.b, color_mp_bar_foredground.a);
}
private:
const int size_heart = 32;
const int width_mp_bar = 200;
const int height_mp_bar = 20;
const int width_border_mp_bar = 4;
const SDL_Point offset_shadow = { 2,2 };
const SDL_Color color_text_background = { 175,175,175,255 };
const SDL_Color color_text_foredground = { 255,255,255,255 };
const SDL_Color color_mp_bar_background = { 48,40,51,255 };
const SDL_Color color_mp_bar_foredground = { 144,121,173,255 };
private:
SDL_Point position = { 0 };
int width_text = 0, height_text = 0;
SDL_Texture* tex_text_background = nullptr;
SDL_Texture* tex_text_foreground = nullptr;
};
#endif // !_STATUES_BAR_H_

View File

@ -1,4 +1,3 @@
#pragma once
#ifndef _TILE_H_
#define _TILE_H_

View File

@ -21,17 +21,17 @@ public:
}
);
anim_idle_up.set_loop(true);
anim_idle_up.set_loop(false);
anim_idle_up.set_interval(0.2);
anim_idle_down.set_loop(true);
anim_idle_down.set_loop(false);
anim_idle_down.set_interval(0.2);
anim_idle_left.set_loop(true);
anim_idle_left.set_loop(false);
anim_idle_left.set_interval(0.2);
anim_idle_right.set_loop(true);
anim_idle_right.set_loop(false);
anim_idle_right.set_interval(0.2);
anim_fire_up.set_loop(true);
anim_fire_up.set_loop(false);
anim_fire_up.set_interval(0.2);
anim_fire_up.set_on_finished(
[&]()
@ -39,7 +39,7 @@ public:
update_idle_animation();
});
anim_fire_down.set_loop(true);
anim_fire_down.set_loop(false);
anim_fire_down.set_interval(0.2);
anim_fire_down.set_on_finished(
[&]()
@ -47,7 +47,7 @@ public:
update_idle_animation();
});
anim_fire_left.set_loop(true);
anim_fire_left.set_loop(false);
anim_fire_left.set_interval(0.2);
anim_fire_left.set_on_finished(
[&]()
@ -55,7 +55,7 @@ public:
update_idle_animation();
});
anim_fire_right.set_loop(true);
anim_fire_right.set_loop(false);
anim_fire_right.set_interval(0.2);
anim_fire_right.set_on_finished(
[&]()
@ -208,7 +208,7 @@ private:
if (!target_enemy) return;
can_fire = true;
can_fire = false;
static ConfigManager* instance = ConfigManager::instance();
static const ResourcesManager::SoundPool& sound_pool =
ResourcesManager::instance()->get_sound_pool();

View File

@ -0,0 +1,158 @@
#ifndef _TOWER_MANAGER_H_
#define _TOWER_MANAGER_H_
#include "tower.h"
#include "tower_type.h"
#include "manager.h"
#include "archer_tower.h"
#include "axeman_tower.h"
#include "gunner_tower.h"
#include "config_manager.h"
#include "resources_manager.h"
#include <vector>
class TowerManager : public Manager<TowerManager>
{
friend class Manager<TowerManager>;
public:
void on_update(double delta)
{
for (Tower* tower : tower_list)
tower->on_update(delta);
}
void on_render(SDL_Renderer* renderer)
{
for (Tower* tower : tower_list)
tower->on_render(renderer);
}
double get_place_cost(TowerType type)
{
static ConfigManager* instance = ConfigManager::instance();
switch (type)
{
case Archer:
return instance->archer_template.cost[instance->level_archer];
break;
case Axeman:
return instance->axeman_template.cost[instance->level_axeman];
break;
case Gunner:
return instance->gunner_template.cost[instance->level_gunner];
break;
}
return 0;
}
double get_upgrade_cost(TowerType type)
{
static ConfigManager* instance = ConfigManager::instance();
switch (type)
{
case Archer:
return instance->level_archer == 9 ? -1 :
instance->archer_template.upgrade_cost[instance->level_archer];
break;
case Axeman:
return instance->level_axeman == 9 ? -1 :
instance->axeman_template.upgrade_cost[instance->level_axeman];
break;
case Gunner:
return instance->level_gunner == 9 ? -1 :
instance->gunner_template.upgrade_cost[instance->level_gunner];
break;
}
return 0;
}
double get_damage_range(TowerType type)
{
static ConfigManager* instance = ConfigManager::instance();
switch (type)
{
case Archer:
return instance->archer_template.view_range[instance->level_archer];
break;
case Axeman:
return instance->axeman_template.view_range[instance->level_axeman];
break;
case Gunner:
return instance->gunner_template.view_range[instance->level_gunner];
break;
}
return 0;
}
void place_tower(TowerType type,const SDL_Point& idx)
{
Tower* tower = nullptr;
switch (type)
{
case Archer:
tower = new ArcherTower();
break;
case Axeman:
tower = new AxemanTower();
break;
case Gunner:
tower = new GunnerTower();
break;
default:
tower = new ArcherTower();
break;
}
static Vector2 position;
static const SDL_Rect& rect = ConfigManager::instance()->rect_tile_map;
position.x = rect.x + idx.x * SIZE_TILE + SIZE_TILE / 2;
position.y = rect.y + idx.y * SIZE_TILE + SIZE_TILE / 2;
tower->set_position(position);
tower_list.push_back(tower);
static const ResourcesManager::SoundPool& sound_pool
= ResourcesManager::instance()->get_sound_pool();
Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_PlaceTower)->second, 0);
}
void upgrade_tower(TowerType type)
{
static ConfigManager* instance = ConfigManager::instance();
switch (type)
{
case Archer:
instance->level_archer = instance->level_archer >= 9 ? 9 : instance->level_archer + 1;
break;
case Axeman:
instance->level_axeman = instance->level_axeman >= 9 ? 9 : instance->level_axeman + 1;
break;
case Gunner:
instance->level_gunner = instance->level_gunner >= 9 ? 9 : instance->level_gunner + 1;
break;
}
static const ResourcesManager::SoundPool& sound_pool
= ResourcesManager::instance()->get_sound_pool();
Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_TowerLevelUp)->second, 0);
}
protected:
TowerManager() = default;
~TowerManager() = default;
private:
std::vector<Tower*> tower_list;
};
#endif // !_TOWER_MANAGER_H_