feat: panel基类
This commit is contained in:
parent
5fb76ce452
commit
60a00be813
@ -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" />
|
||||
|
@ -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>
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
@ -21,18 +27,58 @@ public:
|
||||
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
108
TdGame/TdGame/coin_prop.h
Normal 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_
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
240
TdGame/TdGame/panel.h
Normal 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_
|
@ -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
118
TdGame/TdGame/status_bar.h
Normal 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_
|
@ -1,4 +1,3 @@
|
||||
#pragma once
|
||||
#ifndef _TILE_H_
|
||||
#define _TILE_H_
|
||||
|
||||
|
@ -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();
|
||||
|
158
TdGame/TdGame/tower_manager.h
Normal file
158
TdGame/TdGame/tower_manager.h
Normal 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_
|
Loading…
Reference in New Issue
Block a user