mirror of
https://github.com/zoriya/Bomberman.git
synced 2026-06-15 06:05:53 +00:00
fe62e13433
# Conflicts: # sources/System/BombHolder/BombHolderSystem.cpp
202 lines
8.2 KiB
C++
202 lines
8.2 KiB
C++
//
|
|
// Created by Zoe Roux on 5/31/21.
|
|
//
|
|
|
|
#include <Component/Bomb/BasicBombComponent.hpp>
|
|
#include "Component/Timer/TimerComponent.hpp"
|
|
#include "System/Event/EventSystem.hpp"
|
|
#include "Component/Renderer/Drawable3DComponent.hpp"
|
|
#include "BombHolderSystem.hpp"
|
|
#include "Component/Health/HealthComponent.hpp"
|
|
#include <functional>
|
|
#include <Map/Map.hpp>
|
|
#include <Meshes/MeshSphere.hpp>
|
|
#include "Component/Shaders/Items/BombExplosionShaderComponent.hpp"
|
|
#include <chrono>
|
|
#include "Component/Shaders/ShaderComponent.hpp"
|
|
#include "Component/Collision/CollisionComponent.hpp"
|
|
#include "Component/Tag/TagComponent.hpp"
|
|
#include "Component/Shaders/Items/WhiteShaderComponent.hpp"
|
|
|
|
using namespace std::chrono_literals;
|
|
namespace RAY3D = RAY::Drawables::Drawables3D;
|
|
|
|
namespace BBM
|
|
{
|
|
std::chrono::nanoseconds BombHolderSystem::explosionTimer = 2s;
|
|
|
|
void BombHolderSystem::_bombCollide(WAL::Entity &entity,
|
|
const WAL::Entity &bomb,
|
|
CollisionComponent::CollidedAxis collidedAxis)
|
|
{
|
|
auto &bombInfo = bomb.getComponent<BasicBombComponent>();
|
|
auto found = std::find(bombInfo.ignoredEntities.begin(), bombInfo.ignoredEntities.end(), entity.getUid());
|
|
if (found != bombInfo.ignoredEntities.end())
|
|
return;
|
|
return MapGenerator::wallCollided(entity, bomb, collidedAxis);
|
|
}
|
|
|
|
BombHolderSystem::BombHolderSystem(WAL::Wal &wal)
|
|
: System(wal)
|
|
{}
|
|
|
|
void BombHolderSystem::_dispatchExplosion(const Vector3f &position,
|
|
WAL::Wal &wal,
|
|
int size,
|
|
ExpansionDirection expansionDirections)
|
|
{
|
|
if (size <= 0)
|
|
return;
|
|
wal.getScene()->scheduleNewEntity("explosion")
|
|
.addComponent<PositionComponent>(position)
|
|
.addComponent<BombExplosionShaderComponent>()
|
|
.addComponent<ShaderComponentModel>("assets/shaders/explosion.fs", "assets/shaders/explosion.vs", [](WAL::Entity &entity, WAL::Wal &, std::chrono::nanoseconds dtime) {
|
|
auto &ctx = entity.getComponent<BombExplosionShaderComponent>();
|
|
auto &shader = entity.getComponent<ShaderComponentModel>();
|
|
auto &pos = entity.getComponent<PositionComponent>();
|
|
|
|
ctx.clock += dtime;
|
|
if (duration_cast<std::chrono::milliseconds>(ctx.clock).count() <= 10)
|
|
return;
|
|
ctx.clock = 0ns;
|
|
ctx.explosionRadius -= 0.6;
|
|
if (ctx.explosionRadius < BombExplosionShaderComponent::maxRadius) {
|
|
ctx.explosionRadius = BombExplosionShaderComponent::maxRadius;
|
|
ctx.alpha -= 0.1;
|
|
// slow the explosion movement
|
|
ctx.frameCounter -= 0.1;
|
|
}
|
|
ctx.frameCounter += 0.2;
|
|
shader.shader.setShaderUniformVar("frame", ctx.frameCounter);
|
|
shader.shader.setShaderUniformVar("alpha", ctx.alpha);
|
|
shader.shader.setShaderUniformVar("radius", ctx.explosionRadius);
|
|
shader.shader.setShaderUniformVar("center", pos.position);
|
|
}, true)
|
|
.addComponent<TimerComponent>(500ms, [](WAL::Entity &explosion, WAL::Wal &) {
|
|
explosion.scheduleDeletion();
|
|
})
|
|
.addComponent<Drawable3DComponent, RAY3D::Model>(RAY::Mesh::MeshSphere(0.5, 16, 16),
|
|
std::make_pair(
|
|
MAP_DIFFUSE,
|
|
"assets/bombs/explosion/blast.png"
|
|
));
|
|
wal.getSystem<EventSystem>().dispatchEvent([position, size, expansionDirections](WAL::Wal &myWal) {
|
|
for (auto &[entity, pos, _] : myWal.getScene()->view<PositionComponent, TagComponent<Blowable>>()) {
|
|
if (pos.position.round() == position) {
|
|
if (auto *health = entity.tryGetComponent<HealthComponent>())
|
|
health->takeDmg(1);
|
|
return;
|
|
}
|
|
}
|
|
for (auto &[entity, pos, _] : myWal.getScene()->view<PositionComponent, TagComponent<BlowablePass>>()) {
|
|
if (pos.position.round() == position) {
|
|
if (auto *health = entity.tryGetComponent<HealthComponent>())
|
|
health->takeDmg(1);
|
|
}
|
|
}
|
|
if (expansionDirections & ExpansionDirection::FRONT) {
|
|
_dispatchExplosion(position + Vector3f{1, 0, 0}, myWal, size - 1, ExpansionDirection::FRONT);
|
|
}
|
|
if (expansionDirections & ExpansionDirection::BACK) {
|
|
_dispatchExplosion(position + Vector3f{-1, 0, 0}, myWal, size - 1, ExpansionDirection::BACK);
|
|
}
|
|
if (expansionDirections & ExpansionDirection::LEFT) {
|
|
_dispatchExplosion(position + Vector3f{0, 0, 1}, myWal, size - 1, ExpansionDirection::LEFT);
|
|
}
|
|
if (expansionDirections & ExpansionDirection::RIGHT) {
|
|
_dispatchExplosion(position + Vector3f{0, 0, -1}, myWal, size - 1, ExpansionDirection::RIGHT);
|
|
}
|
|
});
|
|
}
|
|
|
|
void BombHolderSystem::_bombExplosion(WAL::Entity &bomb, WAL::Wal &wal)
|
|
{
|
|
bomb.scheduleDeletion();
|
|
auto position = bomb.getComponent<PositionComponent>().position.round();
|
|
auto explosionRadius = bomb.getComponent<BasicBombComponent>().explosionRadius;
|
|
_dispatchExplosion(position, wal, explosionRadius);
|
|
}
|
|
|
|
void BombHolderSystem::_spawnBomb(Vector3f position, BombHolderComponent &holder)
|
|
{
|
|
std::vector<unsigned> overlapping;
|
|
|
|
for (auto &[entity, pos, _] : this->_wal.getScene()->view<PositionComponent, BombHolderComponent>()) {
|
|
if (position.distance(pos.position) <= 1.1)
|
|
overlapping.emplace_back(entity.getUid());
|
|
}
|
|
|
|
this->_wal.getScene()->scheduleNewEntity("Bomb")
|
|
.addComponent<PositionComponent>(position)
|
|
.addComponent<HealthComponent>(1, [](WAL::Entity &entity, WAL::Wal &wal) {
|
|
// the bomb explode when hit
|
|
entity.scheduleDeletion();
|
|
auto &pos = entity.getComponent<PositionComponent>();
|
|
auto &bombDetails = entity.getComponent<BasicBombComponent>();
|
|
BombHolderSystem::_dispatchExplosion(pos.position, wal, bombDetails.explosionRadius);
|
|
})
|
|
.addComponent<ShaderComponentModel>("assets/shaders/white.fs", "", [](WAL::Entity &entity, WAL::Wal &wal, std::chrono::nanoseconds dtime) {
|
|
auto &ctx = entity.getComponent<WhiteShaderComponent>();
|
|
auto &shader = entity.getComponent<ShaderComponentModel>();
|
|
auto &timer = entity.getComponent<TimerComponent>();
|
|
|
|
if (ctx.whiteValue >= 1)
|
|
ctx.balance = -1;
|
|
if (ctx.whiteValue <= 0)
|
|
ctx.balance = 1;
|
|
auto nbMilliSec = duration_cast<std::chrono::milliseconds>(timer.ringIn).count();
|
|
|
|
float step;
|
|
|
|
if (nbMilliSec > 1000) {
|
|
step = 0.07;
|
|
} else if (nbMilliSec > 500) {
|
|
step = 0.15;
|
|
} else if (nbMilliSec > 100) {
|
|
step = 0.26;
|
|
} else {
|
|
step = 0.5;
|
|
}
|
|
|
|
ctx.whiteValue += static_cast<float>(step * ctx.balance);
|
|
shader.shader.setShaderUniformVar("white", ctx.whiteValue);
|
|
})
|
|
.addComponent<WhiteShaderComponent>()
|
|
.addComponent<TagComponent<BlowablePass>>()
|
|
.addComponent<BasicBombComponent>(holder.damage, holder.explosionRadius, overlapping)
|
|
.addComponent<TimerComponent>(BombHolderSystem::explosionTimer, &BombHolderSystem::_bombExplosion)
|
|
.addComponent<CollisionComponent>(
|
|
WAL::Callback<WAL::Entity &, const WAL::Entity &, CollisionComponent::CollidedAxis>(),
|
|
&BombHolderSystem::_bombCollide, 0.25, .75)
|
|
.addComponent<Drawable3DComponent, RAY3D::Model>("assets/bombs/bomb.obj", false,
|
|
std::make_pair(
|
|
MAP_DIFFUSE,
|
|
"assets/bombs/bomb_normal.png"
|
|
));
|
|
}
|
|
|
|
void BombHolderSystem::onUpdate(WAL::ViewEntity<PositionComponent, BombHolderComponent, ControllableComponent> &entity,
|
|
std::chrono::nanoseconds dtime)
|
|
{
|
|
auto &holder = entity.get<BombHolderComponent>();
|
|
auto &position = entity.get<PositionComponent>();
|
|
auto &controllable = entity.get<ControllableComponent>();
|
|
|
|
if (holder.bombCount < holder.maxBombCount) {
|
|
holder.nextBombRefill -= dtime;
|
|
if (holder.nextBombRefill <= 0ns) {
|
|
holder.nextBombRefill = holder.refillRate;
|
|
holder.bombCount++;
|
|
}
|
|
}
|
|
if (controllable.bomb && holder.bombCount > 0) {
|
|
auto spawnPos = position.position.round();
|
|
for (auto &eachEntity: this->_wal.getScene()->view<PositionComponent, BasicBombComponent>()) {
|
|
if (eachEntity.get<PositionComponent>().position == spawnPos)
|
|
return;
|
|
}
|
|
holder.bombCount--;
|
|
this->_spawnBomb(spawnPos, holder);
|
|
}
|
|
}
|
|
} |