diff --git a/TdGame/TdGame/TdGame.vcxproj b/TdGame/TdGame/TdGame.vcxproj index 4b8785a..8f1d853 100644 --- a/TdGame/TdGame/TdGame.vcxproj +++ b/TdGame/TdGame/TdGame.vcxproj @@ -138,6 +138,11 @@ + + + + + @@ -152,6 +157,7 @@ + diff --git a/TdGame/TdGame/TdGame.vcxproj.filters b/TdGame/TdGame/TdGame.vcxproj.filters index 059e962..0d784fb 100644 --- a/TdGame/TdGame/TdGame.vcxproj.filters +++ b/TdGame/TdGame/TdGame.vcxproj.filters @@ -22,6 +22,9 @@ {26456ec2-6d40-4a7f-9935-8248edc2bef2} + + {dbc74129-2d94-42c1-83b7-40d05f5b8aa2} + @@ -98,5 +101,23 @@ 头文件\manager + + 头文件\bullet + + + 头文件\bullet + + + 头文件\bullet + + + 头文件\bullet + + + 头文件\manager + + + 头文件\bullet + \ No newline at end of file diff --git a/TdGame/TdGame/arrow_bullet.h b/TdGame/TdGame/arrow_bullet.h new file mode 100644 index 0000000..3744c88 --- /dev/null +++ b/TdGame/TdGame/arrow_bullet.h @@ -0,0 +1,52 @@ +#ifndef _ARROW_BULLET_H_ +#define _ARROW_BULLET_H_ + +#include "bullet.h" +#include "resources_manager.h" + + +class ArrowBullet:public Bullet +{ +public: + ArrowBullet() + { + static SDL_Texture* tex_arrow = ResourcesManager::instance() + ->get_texture_pool().find(ResID::Tex_BulletArrow)->second; + + static const std::vector idx_list = { 0, 1 }; + + animation.set_loop(true); + animation.set_interval(0.1); + animation.set_frame_data(tex_arrow, 2, 1, idx_list); + + can_rotated = true; + size.x = 48, size.y = 48; + + } + ~ArrowBullet() = default; + + void on_collide(Enemy* enemy) override + { + static const ResourcesManager::SoundPool& sound_pool + = ResourcesManager::instance()->get_sound_pool(); + + switch (rand() % 3) + { + case 0: + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_ArrowHit_1)->second, 0); + break; + case 1: + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_ArrowHit_2)->second, 0); + break; + case 2: + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_ArrowHit_3)->second, 0); + break; + } + + Bullet::on_collide(enemy); + } + +}; + + +#endif // !_ARROW_BULLET_H_ diff --git a/TdGame/TdGame/axe_bullet.h b/TdGame/TdGame/axe_bullet.h new file mode 100644 index 0000000..c97c880 --- /dev/null +++ b/TdGame/TdGame/axe_bullet.h @@ -0,0 +1,52 @@ +#ifndef _AXE_BULLET_H_ +#define _AXE_BULLET_H_ + +#include "bullet.h" +#include "resources_manager.h" + +class AxeBullet : public Bullet +{ +public: + AxeBullet() + { + static SDL_Texture* tex_axe = ResourcesManager::instance() + ->get_texture_pool().find(ResID::Tex_BulletAxe)->second; + + static const std::vector idx_list = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + + animation.set_loop(true); + animation.set_interval(0.1); + animation.set_frame_data(tex_axe, 4, 2, idx_list); + + size.x = 48, size.y = 48; + } + ~AxeBullet() = default; + + //ײЧ + void on_collide(Enemy* enemy) override + { + static const ResourcesManager::SoundPool& sound_pool + = ResourcesManager::instance()->get_sound_pool(); + + switch (rand() % 3) + { + case 0: + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_AxeHit_1)->second, 0); + break; + case 1: + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_AxeHit_2)->second, 0); + break; + case 2: + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_AxeHit_3)->second, 0); + break; + } + + enemy->slow_down(); + + Bullet::on_collide(enemy); + } + + +}; + +#endif // !_AXE_BULLET_H_ diff --git a/TdGame/TdGame/bullet.h b/TdGame/TdGame/bullet.h new file mode 100644 index 0000000..b81ea0f --- /dev/null +++ b/TdGame/TdGame/bullet.h @@ -0,0 +1,133 @@ +#ifndef _BULLET_H_ +#define_BULLET_H_ + +#include "vector2.h" +#include "animation.h" +#include "config_manager.h" +#include"enemy.h" + +class Bullet +{ +public: + Bullet() = default; + ~Bullet() = default; + + void set_veloccity(const Vector2 velocity) + { + this->velocity = velocity; + + if (can_rotated) + { + double radian = std::atan2(velocity.y, velocity.x); + angle_anim_rotated = radian * 180 / 3.14159265; + } + } + + void set_position(const Vector2& size) + { + this->position = position; + } + + void set_damage(double damage) + { + this->damage = damage; + } + + const Vector2& get_size() const + { + return size; + } + + const Vector2& get_position() const + { + return position; + } + + double get_damage() const + { + return damage; + } + + double get_damage_range() const + { + return damage_range; + } + + bool can_collide() const + { + return is_collisional; + } + + void disable_collide() + { + is_collisional = false; + } + + void make_invalid() + { + is_valid = false; + is_collisional = false; + } + + bool can_remove() const + { + return !is_valid; + } + + //麯ڻжúΪҪд + virtual void on_update(double delta) + { + animation.on_update(delta); + position += velocity * delta; + + static const SDL_Rect& rect_map + = ConfigManager::instance()->rect_tile_map; + + if (position.x - size.x / 2 <= rect_map.x + || position.x + size.x / 2 >= rect_map.x + rect_map.w + || position.y - size.y / 2 <= rect_map.y + || position.y + size.y / 2 >= rect_map.y + rect_map.h) + { + is_valid = false; + } + } + + virtual void on_render(SDL_Renderer* renderer) + { + static SDL_Point point; + + point.x = (int)(position.x - size.x / 2); + point.y = (int)(position.y - size.y / 2); + + animation.on_render(renderer, point, angle_anim_rotated); + } + + /* + param:ײ + */ + virtual void on_collide(Enemy* enemy) + { + is_valid = false; + is_collisional = false; + } +protected: + Vector2 size; + Vector2 velocity; + Vector2 position; + + Animation animation; + //Ƿת + bool can_rotated = false; + + double damage = 0; + double damage_range = -1; + +private: + bool is_valid = true; + //Ƿɼײ + bool is_collisional = true; + double angle_anim_rotated = 0; + +}; + +#endif // !_BULLET_H_ \ No newline at end of file diff --git a/TdGame/TdGame/bullet_manager.h b/TdGame/TdGame/bullet_manager.h new file mode 100644 index 0000000..0622574 --- /dev/null +++ b/TdGame/TdGame/bullet_manager.h @@ -0,0 +1,91 @@ +#ifndef _BULLET_MANAGER_H +#define _BULLET_MANAGER_H + +#include "manager.h" +#include "bullet.h" +#include "bullet_type.h" +#include "arrow_bullet.h" +#include "axe_bullet.h" +#include "shell_bullet.h" + +#include + + +class BulletManager : public Manager +{ + friend class Manager; + +public: + typedef std::vector BulletList; + +public: + void on_update(double delta) + { + for (Bullet* bullet : bullet_list) + bullet->on_update(delta); + + bullet_list.erase(std::remove_if( + bullet_list.begin(), bullet_list.end(), + [](const Bullet* bullet) + { + bool deletable = bullet->can_remove(); + if (deletable) delete bullet; + return deletable; + }), bullet_list.end()); + } + + void on_render(SDL_Renderer* renderer) + { + for (Bullet* bullet : bullet_list) + bullet->on_render(renderer); + } + + //ⲿȡӵбײ֮߼ + BulletList& get_bullet_list() + { + return bullet_list; + } + + //ⲿӵ + void fire_bullet(BulletType type,const Vector2& position,const Vector2& velocity,double damage) + { + Bullet* bullet = nullptr; + + switch (type) + { + case Arrow: + bullet = new ArrowBullet(); + break; + case Axe: + bullet = new AxeBullet(); + break; + case Shell: + bullet = new ShellBullet(); + break; + default: + bullet = new ArrowBullet(); + break; + } + + bullet->set_position(position); + bullet->set_damage(damage); + bullet->set_veloccity(velocity); + + bullet_list.push_back(bullet); + } + +protected: + BulletManager() = default; + + ~BulletManager() + { + for (Bullet* bullet : bullet_list) + delete bullet; + } + +private: + BulletList bullet_list; +}; + +#endif // !_BULLET_MANAGER_H + diff --git a/TdGame/TdGame/bullet_type.h b/TdGame/TdGame/bullet_type.h new file mode 100644 index 0000000..ef05a2a --- /dev/null +++ b/TdGame/TdGame/bullet_type.h @@ -0,0 +1,12 @@ +#pragma once +#ifndef _BULLET_TYPE_H_ +#define _BULLET_TYPE_H_ + +enum BulletType +{ + Arrow, + Axe, + Shell +}; + +#endif diff --git a/TdGame/TdGame/shell_bullet.h b/TdGame/TdGame/shell_bullet.h new file mode 100644 index 0000000..4ba979f --- /dev/null +++ b/TdGame/TdGame/shell_bullet.h @@ -0,0 +1,80 @@ +#ifndef _SHELL_BULLET_H +#define _SHELL_BULLET_H + +#include "bullet.h" +#include "resources_manager.h" + +class ShellBullet : public Bullet +{ +public: + ShellBullet() + { + static SDL_Texture* tex_shell = ResourcesManager::instance() + ->get_texture_pool().find(ResID::Tex_BulletShell)->second; + static SDL_Texture* tex_explode = ResourcesManager::instance() + ->get_texture_pool().find(ResID::Tex_EffectExplode)->second; + + static const std::vector idx_list = { 0, 1}; + static const std::vector idx_explode_list = { 0, 1, 2, 3, 4}; + + animation.set_loop(true); + animation.set_interval(0.1); + animation.set_frame_data(tex_shell, 2, 1, idx_list); + + animation_explode.set_loop(true); + animation_explode.set_interval(0.1); + animation_explode.set_frame_data(tex_shell, 5, 1, idx_explode_list); + animation_explode.set_on_finished( + [&]() + { + make_invalid(); + }); + + damage_range = 96; + size.x = 48, size.y = 48; + } + + ~ShellBullet() = default; + + void on_update(double delta) override + { + if (can_collide) + { + Bullet::on_update(delta); + return; + } + animation_explode.on_update(delta); + } + + void on_render(SDL_Renderer* renderer) override + { + if (can_collide) + { + Bullet::on_render(renderer); + return; + } + + static SDL_Point point; + + point.x = (int)(position.x - 96 / 2); + point.y = (int)(position.y - 96 / 2); + + animation_explode.on_render(renderer, point); + } + + //ײЧ + void on_collide(Enemy* enemy) override + { + static const ResourcesManager::SoundPool& sound_pool + = ResourcesManager::instance()->get_sound_pool(); + + Mix_PlayChannel(-1, sound_pool.find(ResID::Sound_ShellHit)->second, 0); + + //Bullet::on_collide(enemy); ըֻײ + disable_collide(); + } + +private: + Animation animation_explode; +}; +#endif // !_SHELL_BULLET_H