You now have blood on your screen when below half health.

master
Zed A. Shaw 3 weeks ago
parent 1c8f542c21
commit d2700d2928
  1. BIN
      assets/blood_splatter-256.png
  2. 5
      assets/config.json
  3. 6
      assets/enemies.json
  4. 2
      assets/items.json
  5. 2
      components.cpp
  6. 1
      components.hpp
  7. 1
      constants.hpp
  8. 61
      gui.cpp
  9. 2
      gui.hpp
  10. 17
      status_ui.cpp
  11. 4
      status_ui.hpp
  12. 2
      systems.cpp

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

@ -16,7 +16,8 @@
"rope_vines_up": "assets/rope_vines_up-256.png",
"tripwire_trap": "assets/tripwire_trap-256.png",
"cinqueda": "assets/cinqueda_1-256.png",
"left_gui": "assets/left_gui.png"
"left_gui": "assets/left_gui.png",
"blood_splatter": "assets/blood_splatter-256.png"
},
"enemy": {
"HEARING_DISTANCE": 20
@ -24,7 +25,7 @@
"player": {
},
"worldgen": {
"enemy_probability": 20,
"enemy_probability": 80,
"empty_room_probability": 10,
"device_probability": 30
}

@ -6,7 +6,7 @@
"foreground": [255, 200, 125],
"background": [30, 20, 75]
},
{"_type": "Combat", "hp": 200, "damage": 15, "dead": false},
{"_type": "Combat", "hp": 200, "max_hp": 200, "damage": 15, "dead": false},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
{"_type": "LightSource", "strength": 60, "radius": 1.8},
{"_type": "EnemyConfig", "hearing_distance": 5},
@ -19,7 +19,7 @@
"foreground": [131, 213, 238],
"background": [30, 20, 75]
},
{"_type": "Combat", "hp": 20, "damage": 1, "dead": false},
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
{"_type": "LightSource", "strength": 40, "radius": 1.2},
{"_type": "EnemyConfig", "hearing_distance": 5},
@ -32,7 +32,7 @@
"foreground": [205, 164, 246],
"background": [30, 20, 75]
},
{"_type": "Combat", "hp": 50, "damage": 10, "dead": false},
{"_type": "Combat", "hp": 50, "max_hp": 20, "damage": 50, "dead": false},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
{"_type": "EnemyConfig", "hearing_distance": 10},
{"_type": "Sprite", "name": "evil_eye"}

@ -65,7 +65,7 @@
"foreground": [255, 205, 189],
"background": [255, 205, 189]
},
{"_type": "Curative", "hp": 20},
{"_type": "Curative", "hp": 200},
{"_type": "Sprite", "name": "healing_potion_small"}
]
}

@ -8,7 +8,7 @@ namespace components {
ENROLL_COMPONENT(Curative, hp);
ENROLL_COMPONENT(EnemyConfig, hearing_distance);
ENROLL_COMPONENT(Motion, dx, dy, random);
ENROLL_COMPONENT(Combat, hp, damage, dead);
ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead);
ENROLL_COMPONENT(LightSource, strength, radius);
ENROLL_COMPONENT(Device, config, events);
ENROLL_COMPONENT(Sprite, name);

@ -58,6 +58,7 @@ namespace components {
struct Combat {
int hp;
int max_hp;
int damage;
/* NOTE: This is used to _mark_ entities as dead, to detect ones that have just died. Don't make attack automatically set it.*/

@ -13,6 +13,7 @@ constexpr const int RAY_VIEW_Y=0;
constexpr const bool VSYNC=false;
constexpr const int FRAME_LIMIT=60;
constexpr const int NUM_SPRITES=1;
constexpr const int MAX_LOG_MESSAGES=20;
#ifdef NDEBUG
constexpr const bool DEBUG_BUILD=false;

@ -6,6 +6,7 @@
#include "components.hpp"
#include <numbers>
#include "systems.hpp"
#include "events.hpp"
namespace gui {
@ -50,6 +51,7 @@ namespace gui {
$rayview.position_camera($player.x + 0.5, $player.y + 0.5);
$status_view.create_render();
$status_view.log("Welcome to the game!");
$renderer.init_terminal();
$map_view.create_render();
@ -143,6 +145,7 @@ namespace gui {
state(State::MAPPING);
break;
case ATTACK:
$status_view.log("You attack!");
$rotation = -30.0f;
state(State::ATTACKING);
break;
@ -215,7 +218,10 @@ namespace gui {
auto& debug = $level.world->get_the<Debug>();
debug.FPS = !debug.FPS;
debug.PATHS = !debug.PATHS;
} break;
auto player = $level.world->get_the<Player>();
auto& player_combat = $level.world->get<Combat>(player.entity);
player_combat.hp = player_combat.max_hp;
} break;
default:
break; // ignored
}
@ -253,6 +259,18 @@ namespace gui {
$window.draw($text);
}
void FSM::draw_blood() {
auto player = $level.world->get_the<Player>();
auto player_combat = $level.world->get<Combat>(player.entity);
if(float(player_combat.hp) / float(player_combat.max_hp) < 0.5) {
auto blood = $textures.sprite_textures.at("blood_splatter").sprite;
blood->setPosition({RAY_VIEW_X,0});
blood->setScale({3.0, 3.0});
$window.draw(*blood);
}
}
void FSM::draw_gui() {
sf::RectangleShape rect({SCREEN_WIDTH - RAY_VIEW_WIDTH, SCREEN_HEIGHT});
rect.setPosition({0,0});
@ -290,6 +308,7 @@ namespace gui {
$stats.sample(1/elapsed.count());
draw_gui();
draw_blood();
draw_weapon();
}
@ -314,9 +333,49 @@ namespace gui {
System::motion($level);
System::lighting($level);
System::death($level);
handle_world_events();
}
bool FSM::active() {
return !in_state(State::END);
}
void FSM::handle_world_events() {
using eGUI = Events::GUI;
auto& world = *$level.world;
while(world.has_event<eGUI>()) {
auto [evt, entity, data] = world.recv<eGUI>();
switch(evt) {
case eGUI::COMBAT: {
auto &damage = std::any_cast<Events::Combat&>(data);
auto enemy_combat = world.get<Combat>(entity);
if(damage.enemy_did > 0) {
$status_view.log(fmt::format("Enemy HIT YOU for {} damage!", damage.enemy_did));
$status_view.log(fmt::format("-- Enemy has {} HP left.", enemy_combat.hp));
} else {
$status_view.log("Enemy MISSED YOU.");
}
if(damage.player_did > 0) {
$status_view.log(fmt::format("You HIT enemy for {} damage!", damage.player_did));
} else {
$status_view.log("You MISSED the enemy.");
}
}
break;
case eGUI::LOOT: {
// auto &item = std::any_cast<InventoryItem&>(data);
// $status_view.log(fmt::format("You picked up a {}.",
// std::string(item.data["name"])));
$status_view.log("You picked up an item.");
}
break;
default:
$status_view.log(fmt::format("INVALID EVENT! {},{}", evt, entity));
}
}
}
}

@ -74,10 +74,12 @@ namespace gui {
void draw_weapon();
void draw_stats();
void draw_gui();
void draw_blood();
void render();
void mouse();
void generate_map();
bool active();
void run_systems();
void handle_world_events();
};
}

@ -25,10 +25,7 @@ namespace gui {
const auto& player_combat = $level.world->get<Combat>(player.entity);
const auto& combat = $level.world->get<Combat>(player.entity);
std::vector<Element> log_list;
log_list.push_back(text("Log messages here."));
auto log_box = vbox(log_list) | yflex_grow;
auto log_box = vbox($log_list) | yflex_grow | border;
return hbox({
hflow(
@ -45,4 +42,16 @@ namespace gui {
set_renderer(status_rend);
}
void StatusUI::log(std::string msg) {
$messages.push_front(msg);
if($messages.size() > MAX_LOG_MESSAGES) {
$messages.pop_back();
}
$log_list.clear();
for(auto msg : $messages) {
$log_list.push_back(text(msg));
}
}
}

@ -2,13 +2,17 @@
#include "panel.hpp"
#include "levelmanager.hpp"
#include "constants.hpp"
#include <deque>
namespace gui {
class StatusUI : public Panel {
public:
std::vector<Element> $log_list;
std::deque<std::string> $messages;
GameLevel $level;
StatusUI(GameLevel level);
void create_render();
void update_level(GameLevel &level) { $level = level; }
void log(std::string msg);
};
}

@ -180,7 +180,7 @@ void System::collision(GameLevel &level) {
if(world.has<Curative>(entity)) {
auto& cure = world.get<Curative>(entity);
player_combat.hp += cure.hp;
player_combat.hp = std::min(player_combat.hp + cure.hp, player_combat.max_hp);
world.remove<Curative>(entity);
}

Loading…
Cancel
Save