[Add] Implement system boot sequence screen.
This commit is contained in:
parent
e72cc987ff
commit
6876cbff95
24
assets/boot_messages.txt
Normal file
24
assets/boot_messages.txt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[ 0.000000] Bettola version 6.1.0-bettola (dev@bettola)
|
||||||
|
[ 0.000000] Command line: BOOT_IMAGE=/vmbettola-6.1.0 ro quiet
|
||||||
|
[ 0.134589] ACPI: PM-Timer IO Port: 0x808
|
||||||
|
[ 0.345821] pci 0000:00:02.0: vgaarb: setting as boot VGA device
|
||||||
|
[ 0.345911] pci 0000:00:03.0: enp0s3: identified as [B77A:1337]
|
||||||
|
[ 0.582190] systemd[1]: Starting systemd-journald.service...
|
||||||
|
[ 0.621337] systemd-journald[218]: Journal started.
|
||||||
|
[ 1.123456] EXT4-fs (sda1): mounted filesystem with ordered data mode.
|
||||||
|
[ 1.567890] systemd[1]: Reached target Local File Systems.
|
||||||
|
[ 1.890123] systemd[1]: Starting systemd-logind.service...
|
||||||
|
[ 2.101122] systemd[1]: Starting NetworkManager.service...
|
||||||
|
[ 2.334455] NetworkManager[310]: <info> [1678886400.123] NetworkManager (version 1.40.0) is
|
||||||
|
starting...
|
||||||
|
[ 2.800100] enp0s3: Link is up at 1000 Mbps, full duplex.
|
||||||
|
[ 3.123456] systemd[1]: Reached target Network.
|
||||||
|
[ 3.500000] systemd[1]: Starting Bettola Daemon...
|
||||||
|
[ 3.600000] bettolad[420]: Initializing VFS...
|
||||||
|
[ 3.700000] bettolad[420]: Generating world...
|
||||||
|
[ 4.100000] bettolad[420]: World generation complete. Seed: 0xDEADBEEF
|
||||||
|
[ 4.200000] bettolad[420]: Listening on 0.0.0.0:1337
|
||||||
|
[ 4.500000] systemd[1]: Started Bettola Daemon.
|
||||||
|
[ 4.800000] systemd[1]: Reached target Multi-User System.
|
||||||
|
[ 5.000000] systemd[1]: Starting Graphical Interface.
|
||||||
|
[ 5.500000] bettolac-greeter: Starting display manager...
|
||||||
@ -12,6 +12,7 @@
|
|||||||
#include "ui/desktop.h"
|
#include "ui/desktop.h"
|
||||||
#include "ui/ui_window.h"
|
#include "ui/ui_window.h"
|
||||||
#include <ui/main_menu.h>
|
#include <ui/main_menu.h>
|
||||||
|
#include <ui/boot_sequence.h>
|
||||||
|
|
||||||
void GameState::_init_desktop(void) {
|
void GameState::_init_desktop(void) {
|
||||||
_desktop = std::make_unique<Desktop>();
|
_desktop = std::make_unique<Desktop>();
|
||||||
@ -92,24 +93,29 @@ void GameState::update(void) {
|
|||||||
_main_menu.reset(); /* Free mem. */
|
_main_menu.reset(); /* Free mem. */
|
||||||
|
|
||||||
if(_current_screen == Screen::BOOTING) {
|
if(_current_screen == Screen::BOOTING) {
|
||||||
fprintf(stdout, "Starting in single-player mode...\n");
|
_boot_sequence = std::make_unique<BootSequence>();
|
||||||
std::thread server_thread(&GameState::_run_server, this);
|
|
||||||
server_thread.detach();
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
|
||||||
|
|
||||||
if(!_network->connect("127.0.0.1", 1337)) {
|
|
||||||
/* TODO: Handle connection failure. */
|
|
||||||
}
|
|
||||||
/* TODO: transition to book screen. */
|
|
||||||
_current_screen = Screen::DESKTOP;
|
|
||||||
_init_desktop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Screen::BOOTING:
|
case Screen::BOOTING: {
|
||||||
/* TODO: */
|
if(!_boot_sequence) break; /* Shouldn't happen. */
|
||||||
|
if(_boot_sequence->is_finished()) {
|
||||||
|
/* Connect to server. */
|
||||||
|
fprintf(stdout, "Starting in single-player mode...\n");
|
||||||
|
std::thread server_thread(&GameState::_run_server, this);
|
||||||
|
server_thread.detach();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
|
||||||
|
if(!_network->connect("127.0.0.1", 1337)) {
|
||||||
|
/* TODO: Handle connection failure. */
|
||||||
|
}
|
||||||
|
_current_screen = Screen::DESKTOP;
|
||||||
|
_init_desktop();
|
||||||
|
_boot_sequence.reset(); /* Free mem. */
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Screen::DESKTOP: {
|
case Screen::DESKTOP: {
|
||||||
std::string server_msg;
|
std::string server_msg;
|
||||||
while(_network->poll_message(server_msg)) {
|
while(_network->poll_message(server_msg)) {
|
||||||
@ -157,7 +163,9 @@ void GameState::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Screen::BOOTING:
|
case Screen::BOOTING:
|
||||||
/* TODO: */
|
if(_boot_sequence) {
|
||||||
|
_boot_sequence->render(txt_renderer, screen_height);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Screen::DESKTOP:
|
case Screen::DESKTOP:
|
||||||
if(_desktop) {
|
if(_desktop) {
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
class ClientNetwork;
|
class ClientNetwork;
|
||||||
class Desktop;
|
class Desktop;
|
||||||
|
class BootSequence;
|
||||||
class MainMenu;
|
class MainMenu;
|
||||||
class ShapeRenderer;
|
class ShapeRenderer;
|
||||||
class TextRenderer;
|
class TextRenderer;
|
||||||
@ -30,6 +31,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<ClientNetwork> _network;
|
std::unique_ptr<ClientNetwork> _network;
|
||||||
std::unique_ptr<Desktop> _desktop;
|
std::unique_ptr<Desktop> _desktop;
|
||||||
|
std::unique_ptr<BootSequence> _boot_sequence;
|
||||||
std::unique_ptr<MainMenu> _main_menu;
|
std::unique_ptr<MainMenu> _main_menu;
|
||||||
Screen _current_screen;
|
Screen _current_screen;
|
||||||
|
|
||||||
|
|||||||
54
client/src/ui/boot_sequence.cpp
Normal file
54
client/src/ui/boot_sequence.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <cstdio>
|
||||||
|
#include "gfx/txt_renderer.h"
|
||||||
|
|
||||||
|
#include "boot_sequence.h"
|
||||||
|
#include <SDL3/SDL_timer.h>
|
||||||
|
|
||||||
|
BootSequence::BootSequence(void) {
|
||||||
|
/* Load boot messages. */
|
||||||
|
std::ifstream boot_file("assets/boot_messages.txt");
|
||||||
|
if(!boot_file.is_open()) {
|
||||||
|
printf("ERROR: Failed to open assets/boot_messages.txt\n");
|
||||||
|
_messages.push_back("ERROR: boot_messages.txt not found.");
|
||||||
|
} else {
|
||||||
|
std::string line;
|
||||||
|
while(std::getline(boot_file, line)) {
|
||||||
|
if(!line.empty()) {
|
||||||
|
_messages.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init timings. */
|
||||||
|
_start_time = SDL_GetTicks();
|
||||||
|
_line_interval_ms = 150; /* 150ms between each line. */
|
||||||
|
/* Total duration is time for all lines plus a 2-second pause at the end. */
|
||||||
|
_total_duration_ms = (_messages.size() * _line_interval_ms) + 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootSequence::~BootSequence(void) {}
|
||||||
|
|
||||||
|
bool BootSequence::is_finished(void) {
|
||||||
|
return (SDL_GetTicks() - _start_time) >= _total_duration_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BootSequence::render(TextRenderer* txt_renderer, int screen_height) {
|
||||||
|
const Color text_color = { 0.9f, 0.9f, 0.9f }; /* grey/white */
|
||||||
|
const float line_height = 18.0f;
|
||||||
|
const float padding = 15.0f;
|
||||||
|
|
||||||
|
Uint32 elapsed_time = SDL_GetTicks() - _start_time;
|
||||||
|
int lines_to_show = elapsed_time / _line_interval_ms;
|
||||||
|
|
||||||
|
if(lines_to_show > _messages.size()) {
|
||||||
|
lines_to_show = _messages.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < lines_to_show; ++i) {
|
||||||
|
float y_pos = (screen_height - padding) - (i * line_height);
|
||||||
|
txt_renderer->render_text(_messages[i].c_str(), padding, y_pos, 1.0f, text_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
client/src/ui/boot_sequence.h
Normal file
21
client/src/ui/boot_sequence.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include "gfx/txt_renderer.h"
|
||||||
|
|
||||||
|
class BootSequence {
|
||||||
|
public:
|
||||||
|
BootSequence(void);
|
||||||
|
~BootSequence(void);
|
||||||
|
|
||||||
|
bool is_finished(void);
|
||||||
|
void render(TextRenderer* txt_renderer, int screen_height);
|
||||||
|
private:
|
||||||
|
std::vector<std::string> _messages;
|
||||||
|
Uint32 _start_time;
|
||||||
|
Uint32 _line_interval_ms; /* Time for each line to appear. */
|
||||||
|
Uint32 _total_duration_ms; /* Total time for the whole sequence. */
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user