You now have blood on your screen when below half health.
This commit is contained in:
parent
1c8f542c21
commit
d2700d2928
12 changed files with 90 additions and 13 deletions
BIN
assets/blood_splatter-256.png
Normal file
BIN
assets/blood_splatter-256.png
Normal file
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;
|
||||
|
|
59
gui.cpp
59
gui.cpp
|
@ -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,6 +218,9 @@ namespace gui {
|
|||
auto& debug = $level.world->get_the<Debug>();
|
||||
debug.FPS = !debug.FPS;
|
||||
debug.PATHS = !debug.PATHS;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
gui.hpp
2
gui.hpp
|
@ -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…
Add table
Add a link
Reference in a new issue