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.
This commit is contained in:
parent
e9accf14e6
commit
54fbf22b6d
17 changed files with 124 additions and 36 deletions
|
@ -39,7 +39,7 @@
|
||||||
"player": {
|
"player": {
|
||||||
},
|
},
|
||||||
"worldgen": {
|
"worldgen": {
|
||||||
"enemy_probability": 30,
|
"enemy_probability": 50,
|
||||||
"empty_room_probability": 10,
|
"empty_room_probability": 10,
|
||||||
"device_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_SHRINK = 2;
|
||||||
constexpr int WORLDBUILD_MAX_PATH = 200;
|
constexpr int WORLDBUILD_MAX_PATH = 200;
|
||||||
constexpr int UI_FONT_SIZE=20;
|
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 GAME_MAP_PIXEL_POS = 600;
|
||||||
constexpr int MAX_FONT_SIZE = 140;
|
constexpr int MAX_FONT_SIZE = 140;
|
||||||
constexpr int MIN_FONT_SIZE = 20;
|
constexpr int MIN_FONT_SIZE = 20;
|
||||||
|
|
40
easings.hpp
Normal file
40
easings.hpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
22
gui_fsm.cpp
22
gui_fsm.cpp
|
@ -53,7 +53,7 @@ namespace gui {
|
||||||
$renderer.init_terminal();
|
$renderer.init_terminal();
|
||||||
$map_ui.create_render();
|
$map_ui.create_render();
|
||||||
$map_ui.resize_canvas();
|
$map_ui.resize_canvas();
|
||||||
$renderer.resize_grid(MAX_FONT_SIZE, $map_ui);
|
$renderer.resize_grid(BASE_MAP_FONT_SIZE, $map_ui);
|
||||||
|
|
||||||
run_systems();
|
run_systems();
|
||||||
state(State::IDLE);
|
state(State::IDLE);
|
||||||
|
@ -133,21 +133,21 @@ namespace gui {
|
||||||
try_move(-1, false);
|
try_move(-1, false);
|
||||||
break;
|
break;
|
||||||
case MOVE_LEFT:
|
case MOVE_LEFT:
|
||||||
try_move(1, true);
|
|
||||||
break;
|
|
||||||
case MOVE_RIGHT:
|
|
||||||
try_move(-1, true);
|
try_move(-1, true);
|
||||||
break;
|
break;
|
||||||
case ROTATE_LEFT:
|
case MOVE_RIGHT:
|
||||||
$main_ui.plan_rotate(1);
|
try_move(1, true);
|
||||||
state(State::ROTATING);
|
|
||||||
break;
|
break;
|
||||||
case ROTATE_RIGHT:
|
case ROTATE_LEFT:
|
||||||
$main_ui.plan_rotate(-1);
|
$main_ui.plan_rotate(-1);
|
||||||
state(State::ROTATING);
|
state(State::ROTATING);
|
||||||
break;
|
break;
|
||||||
|
case ROTATE_RIGHT:
|
||||||
|
$main_ui.plan_rotate(1);
|
||||||
|
state(State::ROTATING);
|
||||||
|
break;
|
||||||
case MAP_OPEN:
|
case MAP_OPEN:
|
||||||
$renderer.resize_grid(MAX_FONT_SIZE, $map_ui);
|
$renderer.resize_grid(BASE_MAP_FONT_SIZE, $map_ui);
|
||||||
$map_ui.resize_canvas();
|
$map_ui.resize_canvas();
|
||||||
state(State::MAPPING);
|
state(State::MAPPING);
|
||||||
break;
|
break;
|
||||||
|
@ -196,11 +196,11 @@ namespace gui {
|
||||||
state(State::ATTACKING);
|
state(State::ATTACKING);
|
||||||
break;
|
break;
|
||||||
case ROTATE_LEFT:
|
case ROTATE_LEFT:
|
||||||
$main_ui.plan_rotate(1);
|
$main_ui.plan_rotate(-1);
|
||||||
state(State::COMBAT_ROTATE);
|
state(State::COMBAT_ROTATE);
|
||||||
break;
|
break;
|
||||||
case ROTATE_RIGHT:
|
case ROTATE_RIGHT:
|
||||||
$main_ui.plan_rotate(-1);
|
$main_ui.plan_rotate(1);
|
||||||
state(State::COMBAT_ROTATE);
|
state(State::COMBAT_ROTATE);
|
||||||
break;
|
break;
|
||||||
case STOP_COMBAT:
|
case STOP_COMBAT:
|
||||||
|
|
|
@ -16,8 +16,8 @@ LevelManager::LevelManager() {
|
||||||
|
|
||||||
LevelScaling LevelManager::scale_level() {
|
LevelScaling LevelManager::scale_level() {
|
||||||
return {
|
return {
|
||||||
30 + (5 * int($current_level)),
|
20 + (5 * int($current_level)),
|
||||||
20 + (5 * int($current_level))
|
15 + (5 * int($current_level))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
main_ui.cpp
32
main_ui.cpp
|
@ -1,5 +1,6 @@
|
||||||
#include "main_ui.hpp"
|
#include "main_ui.hpp"
|
||||||
#include "components.hpp"
|
#include "components.hpp"
|
||||||
|
#include "easings.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
using namespace components;
|
using namespace components;
|
||||||
|
@ -43,13 +44,15 @@ namespace gui {
|
||||||
"sdev: {:>8.5}\n"
|
"sdev: {:>8.5}\n"
|
||||||
"min: {:>8.5}\n"
|
"min: {:>8.5}\n"
|
||||||
"max: {:>8.5}\n"
|
"max: {:>8.5}\n"
|
||||||
"count:{:<10}\n\n"
|
"count:{:<10}\n"
|
||||||
"level: {} size: {}x{}\n\n"
|
"level: {} size: {}x{}\n\n"
|
||||||
|
"dir: {:0.2},{:0.2}\n\n"
|
||||||
"VSync? {}\n"
|
"VSync? {}\n"
|
||||||
"FR Limit: {}\n"
|
"FR Limit: {}\n"
|
||||||
"Debug? {}\n\n",
|
"Debug? {}\n\n",
|
||||||
player_combat.hp, $stats.mean(), $stats.stddev(), $stats.min,
|
player_combat.hp, $stats.mean(), $stats.stddev(), $stats.min,
|
||||||
$stats.max, $stats.n, $level.index, map->width(), map->height(),
|
$stats.max, $stats.n, $level.index, map->width(), map->height(),
|
||||||
|
$rayview.$dir_x, $rayview.$dir_y,
|
||||||
VSYNC, FRAME_LIMIT, DEBUG_BUILD);
|
VSYNC, FRAME_LIMIT, DEBUG_BUILD);
|
||||||
|
|
||||||
$overlay_ui.update_text("top_left", stats);
|
$overlay_ui.update_text("top_left", stats);
|
||||||
|
@ -70,9 +73,13 @@ namespace gui {
|
||||||
$rayview.set_position(RAY_VIEW_X, RAY_VIEW_Y);
|
$rayview.set_position(RAY_VIEW_X, RAY_VIEW_Y);
|
||||||
$rayview.position_camera($player.x + 0.5, $player.y + 0.5);
|
$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");
|
auto st = textures::get("down_the_well");
|
||||||
st.sprite->setPosition({RAY_VIEW_X, RAY_VIEW_Y});
|
auto bounds = st.sprite->getLocalBounds();
|
||||||
st.sprite->setScale({0.5, 0.5});
|
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();
|
$overlay_ui.render();
|
||||||
}
|
}
|
||||||
|
@ -81,11 +88,18 @@ namespace gui {
|
||||||
$show_level = true;
|
$show_level = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MainUI::draw() {
|
void MainUI::draw() {
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = $stats.time_start();
|
||||||
|
|
||||||
if($show_level) {
|
if($show_level) {
|
||||||
|
auto time = $clock.getElapsedTime();
|
||||||
auto st = textures::get("down_the_well");
|
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);
|
$window.draw(*st.sprite);
|
||||||
$overlay_ui.show_label("middle", "INTO THE WELL YOU GO...");
|
$overlay_ui.show_label("middle", "INTO THE WELL YOU GO...");
|
||||||
} else {
|
} else {
|
||||||
|
@ -93,9 +107,7 @@ namespace gui {
|
||||||
$rayview.draw($window);
|
$rayview.draw($window);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
$stats.sample_time(start);
|
||||||
auto elapsed = std::chrono::duration<double>(end - start);
|
|
||||||
$stats.sample(1/elapsed.count());
|
|
||||||
|
|
||||||
$overlay_ui.draw($window);
|
$overlay_ui.draw($window);
|
||||||
|
|
||||||
|
@ -125,6 +137,9 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainUI::plan_rotate(int dir) {
|
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);
|
$camera.plan_rotate($rayview, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,9 +166,12 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainUI::mouse(int x, int y) {
|
void MainUI::mouse(int x, int y) {
|
||||||
|
if($show_level) {
|
||||||
$show_level = false;
|
$show_level = false;
|
||||||
$level.world->send<Events::GUI>(Events::GUI::STAIRS_DOWN, $level.player, {});
|
$level.world->send<Events::GUI>(Events::GUI::STAIRS_DOWN, $level.player, {});
|
||||||
$overlay_ui.close_label("middle");
|
$overlay_ui.close_label("middle");
|
||||||
|
} else {
|
||||||
$overlay_ui.$gui.mouse(x, y);
|
$overlay_ui.$gui.mouse(x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "levelmanager.hpp"
|
#include "levelmanager.hpp"
|
||||||
#include <SFML/Graphics/RenderWindow.hpp>
|
#include <SFML/Graphics/RenderWindow.hpp>
|
||||||
|
#include <SFML/System/Clock.hpp>
|
||||||
#include "stats.hpp"
|
#include "stats.hpp"
|
||||||
#include "overlay_ui.hpp"
|
#include "overlay_ui.hpp"
|
||||||
#include "raycaster.hpp"
|
#include "raycaster.hpp"
|
||||||
|
@ -11,10 +12,15 @@ namespace gui {
|
||||||
|
|
||||||
class MainUI {
|
class MainUI {
|
||||||
public:
|
public:
|
||||||
|
int $compass_dir = 0;
|
||||||
|
std::array<std::string, 8> $compass{
|
||||||
|
"E", "SE", "S", "SW", "W", "NW", "N", "NE"
|
||||||
|
};
|
||||||
bool $show_level = false;
|
bool $show_level = false;
|
||||||
bool $needs_render = true;
|
bool $needs_render = true;
|
||||||
Point $player{0,0};
|
Point $player{0,0};
|
||||||
Stats $stats;
|
Stats $stats;
|
||||||
|
sf::Clock $clock;
|
||||||
sf::RenderWindow& $window;
|
sf::RenderWindow& $window;
|
||||||
GameLevel $level;
|
GameLevel $level;
|
||||||
OverlayUI $overlay_ui;
|
OverlayUI $overlay_ui;
|
||||||
|
|
|
@ -10,7 +10,8 @@ namespace gui {
|
||||||
MapViewUI::MapViewUI(GameLevel &level) :
|
MapViewUI::MapViewUI(GameLevel &level) :
|
||||||
Panel(0, 0, 0, 0, true),
|
Panel(0, 0, 0, 0, true),
|
||||||
$level(level)
|
$level(level)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void MapViewUI::update_level(GameLevel &level) {
|
void MapViewUI::update_level(GameLevel &level) {
|
||||||
$level = 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) {
|
void OverlayUI::close_text(string region) {
|
||||||
auto ent = $gui.entity(region);
|
auto ent = $gui.entity(region);
|
||||||
$gui.remove<Textual>(ent);
|
$gui.remove<Textual>(ent);
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace gui {
|
||||||
void update_text(std::string region, std::string content);
|
void update_text(std::string region, std::string content);
|
||||||
void close_text(std::string region);
|
void close_text(std::string region);
|
||||||
void show_label(std::string region, std::string content);
|
void show_label(std::string region, std::string content);
|
||||||
|
void update_label(std::string region, std::string content);
|
||||||
void close_label(std::string region);
|
void close_label(std::string region);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -373,6 +373,8 @@ void Raycaster::update_level(GameLevel level) {
|
||||||
|
|
||||||
auto& tiles = $level.map->tiles();
|
auto& tiles = $level.map->tiles();
|
||||||
$map = textures::convert_char_to_texture(tiles.$tile_ids);
|
$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) {
|
$level.world->query<components::Sprite>([&](const auto ent, auto& sprite) {
|
||||||
// player doesn't need a sprite
|
// player doesn't need a sprite
|
||||||
|
|
|
@ -17,7 +17,7 @@ struct Raycaster {
|
||||||
double $pos_y = 0;
|
double $pos_y = 0;
|
||||||
|
|
||||||
// initial direction vector
|
// initial direction vector
|
||||||
double $dir_x = -1;
|
double $dir_x = 1;
|
||||||
double $dir_y = 0;
|
double $dir_y = 0;
|
||||||
|
|
||||||
// the 2d raycaster version of camera plane
|
// the 2d raycaster version of camera plane
|
||||||
|
|
13
stats.hpp
13
stats.hpp
|
@ -1,7 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
struct Stats {
|
struct Stats {
|
||||||
|
using TimeBullshit = std::chrono::time_point<std::chrono::high_resolution_clock>;
|
||||||
|
|
||||||
double sum = 0.0;
|
double sum = 0.0;
|
||||||
double sumsq = 0.0;
|
double sumsq = 0.0;
|
||||||
unsigned long n = 0L;
|
unsigned long n = 0L;
|
||||||
|
@ -41,5 +44,15 @@ struct Stats {
|
||||||
n += 1;
|
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();
|
void dump();
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,6 +30,8 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusUI::render() {
|
void StatusUI::render() {
|
||||||
|
$gui.world().set_the<Background>({$gui.$parser});
|
||||||
|
|
||||||
for(auto& [name, cell] : $gui.cells()) {
|
for(auto& [name, cell] : $gui.cells()) {
|
||||||
if(name == "log_view") {
|
if(name == "log_view") {
|
||||||
$log_to = $gui.entity("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) {
|
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& device_config = config.devices.json();
|
||||||
auto entity_data = device_config["STAIRS_DOWN"];
|
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);
|
auto entity = configure_entity_in_map(world, entity_data, last_room);
|
||||||
check_player(world, entity);
|
check_player(world, entity);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void WorldBuilder::place_entities(DinkyECS::World &world) {
|
void WorldBuilder::place_entities(DinkyECS::World &world) {
|
||||||
auto &config = world.get_the<GameConfig>();
|
auto &config = world.get_the<GameConfig>();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue