feat:子弹类的实现(基类,派生,管理器)
This commit is contained in:
parent
0c0e27ff32
commit
9adb54a5fb
@ -138,6 +138,11 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="animation.h" />
|
<ClInclude Include="animation.h" />
|
||||||
|
<ClInclude Include="arrow_bullet.h" />
|
||||||
|
<ClInclude Include="axe_bullet.h" />
|
||||||
|
<ClInclude Include="bullet.h" />
|
||||||
|
<ClInclude Include="bullet_manager.h" />
|
||||||
|
<ClInclude Include="bullet_type.h" />
|
||||||
<ClInclude Include="coin_manager.h" />
|
<ClInclude Include="coin_manager.h" />
|
||||||
<ClInclude Include="config_manager.h" />
|
<ClInclude Include="config_manager.h" />
|
||||||
<ClInclude Include="enemy.h" />
|
<ClInclude Include="enemy.h" />
|
||||||
@ -152,6 +157,7 @@
|
|||||||
<ClInclude Include="map.h" />
|
<ClInclude Include="map.h" />
|
||||||
<ClInclude Include="resources_manager.h" />
|
<ClInclude Include="resources_manager.h" />
|
||||||
<ClInclude Include="route.h" />
|
<ClInclude Include="route.h" />
|
||||||
|
<ClInclude Include="shell_bullet.h" />
|
||||||
<ClInclude Include="skeleton_enemy.h" />
|
<ClInclude Include="skeleton_enemy.h" />
|
||||||
<ClInclude Include="slime_enemy.h" />
|
<ClInclude Include="slime_enemy.h" />
|
||||||
<ClInclude Include="tile.h" />
|
<ClInclude Include="tile.h" />
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
<Filter Include="源文件\cJSON">
|
<Filter Include="源文件\cJSON">
|
||||||
<UniqueIdentifier>{26456ec2-6d40-4a7f-9935-8248edc2bef2}</UniqueIdentifier>
|
<UniqueIdentifier>{26456ec2-6d40-4a7f-9935-8248edc2bef2}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="头文件\bullet">
|
||||||
|
<UniqueIdentifier>{dbc74129-2d94-42c1-83b7-40d05f5b8aa2}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
@ -98,5 +101,23 @@
|
|||||||
<ClInclude Include="coin_manager.h">
|
<ClInclude Include="coin_manager.h">
|
||||||
<Filter>头文件\manager</Filter>
|
<Filter>头文件\manager</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="bullet.h">
|
||||||
|
<Filter>头文件\bullet</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="arrow_bullet.h">
|
||||||
|
<Filter>头文件\bullet</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="axe_bullet.h">
|
||||||
|
<Filter>头文件\bullet</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="shell_bullet.h">
|
||||||
|
<Filter>头文件\bullet</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="bullet_manager.h">
|
||||||
|
<Filter>头文件\manager</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="bullet_type.h">
|
||||||
|
<Filter>头文件\bullet</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
52
TdGame/TdGame/arrow_bullet.h
Normal file
52
TdGame/TdGame/arrow_bullet.h
Normal file
@ -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<int> 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_
|
52
TdGame/TdGame/axe_bullet.h
Normal file
52
TdGame/TdGame/axe_bullet.h
Normal file
@ -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<int> 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_
|
133
TdGame/TdGame/bullet.h
Normal file
133
TdGame/TdGame/bullet.h
Normal file
@ -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_
|
91
TdGame/TdGame/bullet_manager.h
Normal file
91
TdGame/TdGame/bullet_manager.h
Normal file
@ -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 <vector>
|
||||||
|
|
||||||
|
|
||||||
|
class BulletManager : public Manager<BulletManager>
|
||||||
|
{
|
||||||
|
friend class Manager<BulletManager>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef std::vector<Bullet*> 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
|
||||||
|
|
12
TdGame/TdGame/bullet_type.h
Normal file
12
TdGame/TdGame/bullet_type.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _BULLET_TYPE_H_
|
||||||
|
#define _BULLET_TYPE_H_
|
||||||
|
|
||||||
|
enum BulletType
|
||||||
|
{
|
||||||
|
Arrow,
|
||||||
|
Axe,
|
||||||
|
Shell
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
80
TdGame/TdGame/shell_bullet.h
Normal file
80
TdGame/TdGame/shell_bullet.h
Normal file
@ -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<int> idx_list = { 0, 1};
|
||||||
|
static const std::vector<int> 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
|
Loading…
Reference in New Issue
Block a user