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": {
|
||||
},
|
||||
"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;
|
||||
|
|
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();
|
||||
$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);
|
||||
break;
|
||||
case MOVE_RIGHT:
|
||||
try_move(-1, true);
|
||||
break;
|
||||
case ROTATE_LEFT:
|
||||
$main_ui.plan_rotate(1);
|
||||
state(State::ROTATING);
|
||||
case MOVE_RIGHT:
|
||||
try_move(1, true);
|
||||
break;
|
||||
case ROTATE_RIGHT:
|
||||
case ROTATE_LEFT:
|
||||
$main_ui.plan_rotate(-1);
|
||||
state(State::ROTATING);
|
||||
break;
|
||||
case ROTATE_RIGHT:
|
||||
$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))
|
||||
};
|
||||
}
|
||||
|
||||
|
|
40
main_ui.cpp
40
main_ui.cpp
|
@ -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) {
|
||||
$show_level = false;
|
||||
$level.world->send<Events::GUI>(Events::GUI::STAIRS_DOWN, $level.player, {});
|
||||
$overlay_ui.close_label("middle");
|
||||
$overlay_ui.$gui.mouse(x, 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;
|
||||
|
|
|
@ -40,7 +40,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
if build_machine.system() == 'windows'
|
||||
sfml_main = dependency('sfml_main')
|
||||
sfml_main = dependency('sfml_main')
|
||||
opengl32 = cc.find_library('opengl32', required: true)
|
||||
winmm = cc.find_library('winmm', required: true)
|
||||
gdi32 = cc.find_library('gdi32', required: true)
|
||||
|
|
|
@ -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
|
||||
|
|
13
stats.hpp
13
stats.hpp
|
@ -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,13 +244,11 @@ 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;
|
||||
auto entity = configure_entity_in_map(world, entity_data, last_room);
|
||||
check_player(world, entity);
|
||||
}
|
||||
auto& device_config = config.devices.json();
|
||||
auto entity_data = device_config["STAIRS_DOWN"];
|
||||
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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue