We can go down a level and there's a loading screen for it. The map and motion now matches the directions shown in the raycasting. There's now a compass that shows you the direction you're facing.

master
Zed A. Shaw 2 weeks ago
parent e9accf14e6
commit 54fbf22b6d
  1. 2
      assets/config.json
  2. BIN
      assets/down_the_well.jpg
  3. 2
      constants.hpp
  4. 40
      easings.hpp
  5. 16
      gui_fsm.cpp
  6. 4
      levelmanager.cpp
  7. 32
      main_ui.cpp
  8. 6
      main_ui.hpp
  9. 3
      map_view.cpp
  10. 7
      overlay_ui.cpp
  11. 1
      overlay_ui.hpp
  12. 2
      raycaster.cpp
  13. 2
      raycaster.hpp
  14. 13
      stats.hpp
  15. 2
      status_ui.cpp
  16. 4
      worldbuilder.cpp

@ -39,7 +39,7 @@
"player": {
},
"worldgen": {
"enemy_probability": 30,
"enemy_probability": 50,
"empty_room_probability": 10,
"device_probability": 10
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 KiB

After

Width:  |  Height:  |  Size: 113 KiB

@ -42,7 +42,7 @@ constexpr int WORLDBUILD_DIVISION = 4;
constexpr int WORLDBUILD_SHRINK = 2;
constexpr int WORLDBUILD_MAX_PATH = 200;
constexpr int UI_FONT_SIZE=20;
constexpr int BASE_MAP_FONT_SIZE=90;
constexpr int BASE_MAP_FONT_SIZE=80;
constexpr int GAME_MAP_PIXEL_POS = 600;
constexpr int MAX_FONT_SIZE = 140;
constexpr int MIN_FONT_SIZE = 20;

@ -0,0 +1,40 @@
#pragma once
#include <cmath>
namespace ease {
inline double sine(double x) {
return (std::sin(x) + 1.0) / 2.0;
}
inline double out_circ(double x) {
return std::sqrt(1.0f - std::pow(x - 1.0f, 2.0f));
}
inline double out_bounce(double x) {
constexpr const double n1 = 7.5625;
constexpr const double d1 = 2.75;
if (x < 1 / d1) {
return n1 * x * x;
} else if (x < 2 / d1) {
x -= 1.5;
return n1 * (x / d1) * x + 0.75;
} else if (x < 2.5 / d1) {
x -= 2.25;
return n1 * (x / d1) * x + 0.9375;
} else {
x -= 2.625;
return n1 * (x / d1) * x + 0.984375;
}
}
inline double in_out_back(double x) {
constexpr const double c1 = 1.70158;
constexpr const double c2 = c1 * 1.525;
return x < 0.5
? (std::pow(2.0 * x, 2.0) * ((c2 + 1.0) * 2.0 * x - c2)) / 2.0
: (std::pow(2.0 * x - 2.0, 2.0) * ((c2 + 1.0) * (x * 2.0 - 2.0) + c2) + 2.0) / 2.0;
}
}

@ -53,7 +53,7 @@ namespace gui {
$renderer.init_terminal();
$map_ui.create_render();
$map_ui.resize_canvas();
$renderer.resize_grid(MAX_FONT_SIZE, $map_ui);
$renderer.resize_grid(BASE_MAP_FONT_SIZE, $map_ui);
run_systems();
state(State::IDLE);
@ -133,21 +133,21 @@ namespace gui {
try_move(-1, false);
break;
case MOVE_LEFT:
try_move(1, true);
try_move(-1, true);
break;
case MOVE_RIGHT:
try_move(-1, true);
try_move(1, true);
break;
case ROTATE_LEFT:
$main_ui.plan_rotate(1);
$main_ui.plan_rotate(-1);
state(State::ROTATING);
break;
case ROTATE_RIGHT:
$main_ui.plan_rotate(-1);
$main_ui.plan_rotate(1);
state(State::ROTATING);
break;
case MAP_OPEN:
$renderer.resize_grid(MAX_FONT_SIZE, $map_ui);
$renderer.resize_grid(BASE_MAP_FONT_SIZE, $map_ui);
$map_ui.resize_canvas();
state(State::MAPPING);
break;
@ -196,11 +196,11 @@ namespace gui {
state(State::ATTACKING);
break;
case ROTATE_LEFT:
$main_ui.plan_rotate(1);
$main_ui.plan_rotate(-1);
state(State::COMBAT_ROTATE);
break;
case ROTATE_RIGHT:
$main_ui.plan_rotate(-1);
$main_ui.plan_rotate(1);
state(State::COMBAT_ROTATE);
break;
case STOP_COMBAT:

@ -16,8 +16,8 @@ LevelManager::LevelManager() {
LevelScaling LevelManager::scale_level() {
return {
30 + (5 * int($current_level)),
20 + (5 * int($current_level))
20 + (5 * int($current_level)),
15 + (5 * int($current_level))
};
}

@ -1,5 +1,6 @@
#include "main_ui.hpp"
#include "components.hpp"
#include "easings.hpp"
namespace gui {
using namespace components;
@ -43,13 +44,15 @@ namespace gui {
"sdev: {:>8.5}\n"
"min: {:>8.5}\n"
"max: {:>8.5}\n"
"count:{:<10}\n\n"
"count:{:<10}\n"
"level: {} size: {}x{}\n\n"
"dir: {:0.2},{:0.2}\n\n"
"VSync? {}\n"
"FR Limit: {}\n"
"Debug? {}\n\n",
player_combat.hp, $stats.mean(), $stats.stddev(), $stats.min,
$stats.max, $stats.n, $level.index, map->width(), map->height(),
$rayview.$dir_x, $rayview.$dir_y,
VSYNC, FRAME_LIMIT, DEBUG_BUILD);
$overlay_ui.update_text("top_left", stats);
@ -70,9 +73,13 @@ namespace gui {
$rayview.set_position(RAY_VIEW_X, RAY_VIEW_Y);
$rayview.position_camera($player.x + 0.5, $player.y + 0.5);
$overlay_ui.show_label("top", $compass[$compass_dir]);
auto st = textures::get("down_the_well");
st.sprite->setPosition({RAY_VIEW_X, RAY_VIEW_Y});
st.sprite->setScale({0.5, 0.5});
auto bounds = st.sprite->getLocalBounds();
st.sprite->setPosition({RAY_VIEW_X + bounds.size.x / 2,
RAY_VIEW_Y + bounds.size.y / 2});
st.sprite->setOrigin({bounds.size.x / 2, bounds.size.y / 2});
$overlay_ui.render();
}
@ -81,11 +88,18 @@ namespace gui {
$show_level = true;
}
void MainUI::draw() {
auto start = std::chrono::high_resolution_clock::now();
auto start = $stats.time_start();
if($show_level) {
auto time = $clock.getElapsedTime();
auto st = textures::get("down_the_well");
float tick = ease::in_out_back(ease::sine(time.asSeconds()));
float scale = std::lerp(1.0, 1.3, tick);
st.sprite->setScale({scale, scale});
$window.draw(*st.sprite);
$overlay_ui.show_label("middle", "INTO THE WELL YOU GO...");
} else {
@ -93,9 +107,7 @@ namespace gui {
$rayview.draw($window);
}
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration<double>(end - start);
$stats.sample(1/elapsed.count());
$stats.sample_time(start);
$overlay_ui.draw($window);
@ -125,6 +137,9 @@ namespace gui {
}
void MainUI::plan_rotate(int dir) {
// -1 is left, 1 is right
$compass_dir = ($compass_dir + dir) % $compass.size();
$overlay_ui.update_label("top", $compass[$compass_dir]);
$camera.plan_rotate($rayview, dir);
}
@ -151,9 +166,12 @@ namespace gui {
}
void MainUI::mouse(int x, int y) {
if($show_level) {
$show_level = false;
$level.world->send<Events::GUI>(Events::GUI::STAIRS_DOWN, $level.player, {});
$overlay_ui.close_label("middle");
} else {
$overlay_ui.$gui.mouse(x, y);
}
}
}

@ -1,6 +1,7 @@
#pragma once
#include "levelmanager.hpp"
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include "stats.hpp"
#include "overlay_ui.hpp"
#include "raycaster.hpp"
@ -11,10 +12,15 @@ namespace gui {
class MainUI {
public:
int $compass_dir = 0;
std::array<std::string, 8> $compass{
"E", "SE", "S", "SW", "W", "NW", "N", "NE"
};
bool $show_level = false;
bool $needs_render = true;
Point $player{0,0};
Stats $stats;
sf::Clock $clock;
sf::RenderWindow& $window;
GameLevel $level;
OverlayUI $overlay_ui;

@ -10,7 +10,8 @@ namespace gui {
MapViewUI::MapViewUI(GameLevel &level) :
Panel(0, 0, 0, 0, true),
$level(level)
{}
{
}
void MapViewUI::update_level(GameLevel &level) {
$level = level;

@ -56,6 +56,13 @@ namespace gui {
}
}
void OverlayUI::update_label(string region, string content) {
auto ent = $gui.entity(region);
if(auto text = $gui.get_if<Label>(ent)) {
text->text->setString(content);
}
}
void OverlayUI::close_text(string region) {
auto ent = $gui.entity(region);
$gui.remove<Textual>(ent);

@ -20,6 +20,7 @@ namespace gui {
void update_text(std::string region, std::string content);
void close_text(std::string region);
void show_label(std::string region, std::string content);
void update_label(std::string region, std::string content);
void close_label(std::string region);
};
}

@ -373,6 +373,8 @@ void Raycaster::update_level(GameLevel level) {
auto& tiles = $level.map->tiles();
$map = textures::convert_char_to_texture(tiles.$tile_ids);
$dir_x = 1; // reset dir vector
$dir_y = 0;
$level.world->query<components::Sprite>([&](const auto ent, auto& sprite) {
// player doesn't need a sprite

@ -17,7 +17,7 @@ struct Raycaster {
double $pos_y = 0;
// initial direction vector
double $dir_x = -1;
double $dir_x = 1;
double $dir_y = 0;
// the 2d raycaster version of camera plane

@ -1,7 +1,10 @@
#pragma once
#include <cmath>
#include <chrono>
struct Stats {
using TimeBullshit = std::chrono::time_point<std::chrono::high_resolution_clock>;
double sum = 0.0;
double sumsq = 0.0;
unsigned long n = 0L;
@ -41,5 +44,15 @@ struct Stats {
n += 1;
}
inline TimeBullshit time_start() {
return std::chrono::high_resolution_clock::now();
}
inline void sample_time(TimeBullshit start) {
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration<double>(end - start);
sample(1/elapsed.count());
}
void dump();
};

@ -30,6 +30,8 @@ namespace gui {
}
void StatusUI::render() {
$gui.world().set_the<Background>({$gui.$parser});
for(auto& [name, cell] : $gui.cells()) {
if(name == "log_view") {
$log_to = $gui.entity("log_view");

@ -244,14 +244,12 @@ void WorldBuilder::randomize_entities(DinkyECS::World &world, GameConfig &config
}
void WorldBuilder::place_stairs(DinkyECS::World& world, GameConfig& config) {
for(size_t i = 1; i < $map.room_count() - 1; i++) {
auto& device_config = config.devices.json();
auto entity_data = device_config["STAIRS_DOWN"];
int last_room = i;
int last_room = $map.room_count() - 1;
auto entity = configure_entity_in_map(world, entity_data, last_room);
check_player(world, entity);
}
}
void WorldBuilder::place_entities(DinkyECS::World &world) {
auto &config = world.get_the<GameConfig>();

Loading…
Cancel
Save