Now I can attach arbitrary shaders to sprites based on things that happen in the world.

master
Zed A. Shaw 22 hours ago
parent bec8fe0a13
commit 787be78a69
  1. 6
      components.hpp
  2. 9
      raycaster.cpp
  3. 1
      raycaster.hpp
  4. 26
      shaders.cpp
  5. 24
      systems.cpp
  6. 3
      systems.hpp

@ -4,6 +4,7 @@
#include "dinkyecs.hpp" #include "dinkyecs.hpp"
#include "point.hpp" #include "point.hpp"
#include <SFML/Graphics/Rect.hpp> #include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Shader.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <functional> #include <functional>
#include <optional> #include <optional>
@ -15,6 +16,11 @@
namespace components { namespace components {
using namespace nlohmann; using namespace nlohmann;
struct SpriteEffect {
int frames;
std::shared_ptr<sf::Shader> effect;
};
struct Position { struct Position {
Point location; Point location;
}; };

@ -9,6 +9,7 @@
#include <numbers> #include <numbers>
#include "components.hpp" #include "components.hpp"
#include "textures.hpp" #include "textures.hpp"
#include "systems.hpp"
using namespace fmt; using namespace fmt;
using std::make_unique; using std::make_unique;
@ -180,10 +181,9 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) {
// float level = sqrt(rec.first); // float level = sqrt(rec.first);
float level = lights[sprite_pos.location.y][sprite_pos.location.x] * PERCENT; float level = lights[sprite_pos.location.y][sprite_pos.location.x] * PERCENT;
shared_ptr<sf::Shader> effect = nullptr; shared_ptr<sf::Shader> effect = System::sprite_effect($level, rec.second);
if(rec.second == aiming_at) { if(effect) {
effect = $flame;
apply_sprite_effect(effect, sprite_width, sprite_height); apply_sprite_effect(effect, sprite_width, sprite_height);
} else { } else {
effect = $brightness; effect = $brightness;
@ -411,7 +411,4 @@ void Raycaster::update_level(GameLevel level) {
void Raycaster::init_shaders() { void Raycaster::init_shaders() {
$brightness = shaders::get("rayview_sprites"); $brightness = shaders::get("rayview_sprites");
$brightness->setUniform("source", sf::Shader::CurrentTexture);
$flame = shaders::get("flame");
$flame->setUniform("source", sf::Shader::CurrentTexture);
} }

@ -13,7 +13,6 @@ struct Raycaster {
int $pitch=0; int $pitch=0;
sf::Clock $clock; sf::Clock $clock;
std::shared_ptr<sf::Shader> $brightness = nullptr; std::shared_ptr<sf::Shader> $brightness = nullptr;
std::shared_ptr<sf::Shader> $flame = nullptr;
double $pos_x = 0; double $pos_x = 0;
double $pos_y = 0; double $pos_y = 0;

@ -7,17 +7,25 @@
#include <memory> #include <memory>
namespace shaders { namespace shaders {
using std::shared_ptr, std::make_shared; using std::shared_ptr, std::make_shared;
static ShaderManager SMGR; static ShaderManager SMGR;
static bool INITIALIZED = false; static bool INITIALIZED = false;
static int VERSION = 0; static int VERSION = 0;
bool load_shader(std::string name, nlohmann::json& settings) { inline void configure_shader_defaults(std::shared_ptr<sf::Shader> ptr) {
std::string file_name = settings["file_name"]; ptr->setUniform("source", sf::Shader::CurrentTexture);
auto ptr = std::make_shared<sf::Shader>(); }
bool good = ptr->loadFromFile(file_name, sf::Shader::Type::Fragment);
if(good) SMGR.shaders.try_emplace(name, name, file_name, ptr); bool load_shader(std::string name, nlohmann::json& settings) {
std::string file_name = settings["file_name"];
auto ptr = std::make_shared<sf::Shader>();
bool good = ptr->loadFromFile(file_name, sf::Shader::Type::Fragment);
if(good) {
configure_shader_defaults(ptr);
SMGR.shaders.try_emplace(name, name, file_name, ptr);
}
return good; return good;
} }

@ -15,6 +15,7 @@
#include "rituals.hpp" #include "rituals.hpp"
#include "battle.hpp" #include "battle.hpp"
#include <iostream> #include <iostream>
#include "shaders.hpp"
using std::string; using std::string;
using namespace fmt; using namespace fmt;
@ -176,6 +177,7 @@ void System::death(GameLevel &level, components::ComponentMap& components) {
world.remove<Personality>(ent); world.remove<Personality>(ent);
world.remove<ai::EntityAI>(ent); world.remove<ai::EntityAI>(ent);
world.remove<Animation>(ent); world.remove<Animation>(ent);
world.remove<SpriteEffect>(ent);
if(auto snd = world.get_if<Sound>(ent)) { if(auto snd = world.get_if<Sound>(ent)) {
sound::stop(snd->attack); sound::stop(snd->attack);
@ -235,6 +237,11 @@ void System::combat(GameLevel &level) {
player_combat.attack(enemy.combat), 0 player_combat.attack(enemy.combat), 0
}; };
if(result.player_did > 0) {
auto effect = shaders::get("flame");
world.set<SpriteEffect>(enemy.entity, {100, effect});
}
if(enemy.ai.wants_to("kill_enemy")) { if(enemy.ai.wants_to("kill_enemy")) {
result.enemy_did = enemy.combat.attack(player_combat); result.enemy_did = enemy.combat.attack(player_combat);
animate_entity(world, enemy.entity); animate_entity(world, enemy.entity);
@ -390,3 +397,20 @@ std::wstring System::draw_map(GameLevel level, size_t view_x, size_t view_y, int
return result; return result;
} }
std::shared_ptr<sf::Shader> System::sprite_effect(GameLevel &level, DinkyECS::Entity entity) {
if(level.world->has<SpriteEffect>(entity)) {
auto& se = level.world->get<SpriteEffect>(entity);
if(se.frames > 0) {
se.frames--;
return se.effect;
} else {
level.world->remove<SpriteEffect>(entity);
return nullptr;
}
} else {
return nullptr;
}
}

@ -21,4 +21,7 @@ namespace System {
void enemy_ai(GameLevel &level); void enemy_ai(GameLevel &level);
void combat(GameLevel &level); void combat(GameLevel &level);
std::shared_ptr<sf::Shader> sprite_effect(GameLevel &level, DinkyECS::Entity entity);
} }

Loading…
Cancel
Save