- framerate indicator sprite added to Game class

- functions to build vectors from an integer range (from https://stackoverflow.com/a/30312659/1256386)
- fullscreen toggle added to Display class
This commit is contained in:
Frank DeMarco 2020-07-19 15:43:47 -04:00
parent 1df303fe17
commit 0ccc00f201
16 changed files with 176 additions and 40 deletions

BIN
BPmono.ttf Executable file

Binary file not shown.

View File

@ -107,6 +107,11 @@ glm::vec2 Box::get_north() const
return glm::vec2(get_x() + get_w() / 2, get_y());
}
glm::vec2 Box::get_ne() const
{
return glm::vec2(get_right(), get_y());
}
glm::vec2 Box::get_east() const
{
return glm::vec2(get_right(), get_y() + get_h() / 2);
@ -138,6 +143,11 @@ void Box::set_north(const glm::vec2& n)
move(n - get_north());
}
void Box::set_ne(const glm::vec2& ne)
{
move(ne - get_ne());
}
void Box::set_east(const glm::vec2& e)
{
move(e - get_east());

View File

@ -34,12 +34,14 @@ struct Box
void set_left(float);
glm::vec2 get_nw() const;
glm::vec2 get_north() const;
glm::vec2 get_ne() const;
glm::vec2 get_east() const;
glm::vec2 get_south() const;
glm::vec2 get_west() const;
glm::vec2 get_center() const;
void set_nw(const glm::vec2&);
void set_north(const glm::vec2&);
void set_ne(const glm::vec2&);
void set_east(const glm::vec2&);
void set_south(const glm::vec2&);
void set_west(const glm::vec2&);

View File

@ -23,7 +23,7 @@ void Configuration::set_defaults()
{"left", "left"},
{"pause", "enter"},
{"fullscreen", {"ALT", "enter"}},
{"show-fps", {"CTRL", "f"}}
{"toggle-framerate", {"CTRL", "f"}}
};
sys_config["path"] = {
{"screenshots", "."},
@ -31,7 +31,7 @@ void Configuration::set_defaults()
};
sys_config["display"] = {
{"dimensions", {640, 480}},
{"fps", 60},
{"framerate", 60},
{"title", "sfw"}
};
sys_config["recording"] = {

View File

@ -1,7 +1,10 @@
#include "Display.hpp"
#include "Game.hpp"
Display::Display(Node* parent) : Node(parent) {}
Display::Display(Node* parent) : Node(parent)
{
get_delegate().subscribe(&Display::respond, this);
}
glm::ivec2 Display::get_window_size()
{
@ -88,3 +91,25 @@ SDL_Surface* Display::get_screen_surface_from_pixels(
}
return surface;
}
void Display::respond(SDL_Event& event)
{
if (get_delegate().compare(event, "fullscreen"))
{
toggle_fullscreen();
}
}
void Display::toggle_fullscreen()
{
if (SDL_GetWindowFlags(get_root()->get_window()) & SDL_WINDOW_FULLSCREEN)
{
SDL_Log("fullscreen requested");
SDL_SetWindowFullscreen(get_root()->window, 0);
}
else
{
SDL_Log("exit fullscreen requested");
SDL_SetWindowFullscreen(get_root()->get_window(), SDL_WINDOW_FULLSCREEN);
}
}

View File

@ -28,6 +28,8 @@ struct Display : Node
void get_screen_pixels(unsigned char*, int, int, int = 0, int = 0);
SDL_Surface* get_screen_surface();
SDL_Surface* get_screen_surface_from_pixels(unsigned char*, bool);
void respond(SDL_Event&);
void toggle_fullscreen();
};

View File

@ -1,16 +1,53 @@
#include "Game.hpp"
// FPSIndicator::FPSIndicator(Node* parent) : Node(parent) {}
FramerateIndicator::FramerateIndicator(Node* parent) : Sprite(parent)
{
get_delegate().subscribe(&FramerateIndicator::respond, this);
hide();
}
// FPSIndicator::update()
// {
// }
void FramerateIndicator::respond(SDL_Event& event)
{
if (get_delegate().compare(event, "toggle-framerate"))
{
toggle_hidden();
}
}
SDL_Surface* FramerateIndicator::get_surface()
{
std::string padded = sfw::pad(get_root()->frame_count_this_second, 2);
SDL_Surface* shaded = TTF_RenderText_Shaded(
get_root()->bp_mono_font, padded.c_str(), {0, 0, 0}, {255, 255, 255});
// SDL_Surface* converted = SDL_ConvertSurfaceFormat(
// shaded, SDL_PIXELFORMAT_ARGB8888, 0);
// SDL_Surface* flipped = zoomSurface(converted, 1, -1, SMOOTHING_OFF);
// SDL_FreeSurface(shaded);
// SDL_FreeSurface(converted);
if (!shaded)
{
get_root()->print_sdl_error("Could not create text");
}
return shaded;
}
void FramerateIndicator::refresh()
{
if (!is_hidden() && get_root()->bp_mono_font != NULL)
{
unload();
SDL_Surface* surface = get_surface();
SDL_Texture* texture = SDL_CreateTextureFromSurface(get_root()->get_renderer(), surface);
add_frame(texture);
SDL_FreeSurface(surface);
box.set_ne(get_display().get_window_box().get_ne());
}
}
Game::Game()
{
frame_length_history.reserve(5000);
set_framerate(get_configuration()["display"]["fps"]);
set_framerate(get_configuration()["display"]["framerate"]);
delegate.subscribe(&Game::handle_quit_event, this, SDL_QUIT);
SDL_Log("GLEW %s", glewGetString(GLEW_VERSION));
putenv("SDL_VIDEO_X11_LEGACY_FULLSCREEN=0");
@ -58,6 +95,10 @@ Game::Game()
SDL_Log("initialized SDL ttf %d.%d.%d", SDL_TTF_MAJOR_VERSION,
SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL);
}
if ((bp_mono_font = TTF_OpenFont("BPmono.ttf", 14)) == NULL)
{
print_error("Could not load BPmono.ttf");
}
#if !defined(__EMSCRIPTEN__)
if (Mix_Init(MIX_INIT_FLAC) == 0)
{
@ -452,11 +493,23 @@ void Game::frame(float ticks)
recorder.update();
delegate.dispatch();
update();
framerate_indicator.update();
if (!is_gl_context)
{
SDL_RenderPresent(renderer);
}
if (frame_time_overflow > frame_length)
{
// SDL_Log("%i frame(s) dropped", ((int) (frame_time_overflow / frame_length)));
frame_time_overflow = 0;
}
frame_count_this_second++;
if (ticks - last_frame_count_timestamp >= 1000)
{
framerate_indicator.refresh();
last_frame_count_timestamp = ticks;
frame_count_this_second = 0;
}
}
// std::cout << std::endl;
}
@ -485,13 +538,13 @@ glm::vec2 Game::weight(glm::vec2 motion)
return glm::vec2(weight(motion.x), weight(motion.y));
}
void Game::set_framerate(int fps)
void Game::set_framerate(int f)
{
if (fps < 1)
if (f < 1)
{
fps = 1;
f = 1;
}
framerate = fps;
framerate = f;
frame_length = 1000.0 / framerate;
}
@ -519,6 +572,7 @@ void Game::quit()
}
if (TTF_WasInit())
{
TTF_CloseFont(bp_mono_font);
TTF_Quit();
}
Mix_CloseAudio();

View File

@ -27,19 +27,19 @@
#endif
#include "Node.hpp"
#include "Configuration.hpp"
#include "Delegate.hpp"
#include "Display.hpp"
#include "Recorder.hpp"
#include "Input.hpp"
// #include "Sprite.hpp"
#include "Recorder.hpp"
#include "Sprite.hpp"
// struct FPSIndicator : Sprite
// {
struct FramerateIndicator : Sprite
{
// FPSIndicator(Node*);
FramerateIndicator(Node*);
void respond(SDL_Event&);
SDL_Surface* get_surface();
void refresh();
// };
};
struct Game : Node
{
@ -54,9 +54,9 @@ struct Game : Node
SDL_GLContext glcontext = NULL;
// 768, 432
// 864, 486
int framerate, ticks, last_frame_length;
float frame_length = 1000.0 / 60.0, frame_time_overflow = 0,
last_frame_timestamp, emscripten_previous_time;
int frame_count_this_second = 0, framerate, ticks, last_frame_length;
float frame_length = 1000.0 / 60.0, frame_time_overflow = 0, last_frame_timestamp,
last_frame_count_timestamp, emscripten_previous_time;
bool done = false, show_framerate = true, is_gl_context = true;
Configuration configuration = Configuration(this);
Delegate delegate = Delegate(this);
@ -64,6 +64,8 @@ struct Game : Node
Recorder recorder = Recorder(this);
Input input = Input(this);
std::vector<float> frame_length_history;
TTF_Font* bp_mono_font = NULL;
FramerateIndicator framerate_indicator = FramerateIndicator(this);
Game();
~Game();
@ -103,6 +105,4 @@ void loop(void*);
#endif
#include "Sprite.hpp"
#endif

View File

@ -9,7 +9,6 @@
#include "SDL.h"
#include "Node.hpp"
#include "Delegate.hpp"
struct KeyCombination
{

View File

@ -1,7 +1,5 @@
#include "Node.hpp"
#include "Game.hpp"
// #include "Display.hpp"
// #include "Delegate.hpp"
Node::Node() : Node(NULL) {}

View File

@ -11,7 +11,6 @@
struct Game;
struct Delegate;
struct Display;
struct TimeFilter;
struct Node
{
@ -35,4 +34,8 @@ struct Node
};
#include "Configuration.hpp"
#include "Delegate.hpp"
#include "Display.hpp"
#endif

View File

@ -1,4 +1,3 @@
#include "Game.hpp"
#include "Recorder.hpp"
#include "gif-h/gif.h"

View File

@ -6,8 +6,10 @@
#include <thread>
#include <functional>
#include <cstdlib>
#include <fstream>
#include "SDL.h"
#include "SDL_mixer.h"
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/ext.hpp"
@ -15,9 +17,8 @@
#include "json/json.hpp"
#include "filesystem.hpp"
#include "Node.hpp"
#include "Animation.hpp"
#include "Delegate.hpp"
#include "Display.hpp"
#include "extension.hpp"
struct Stash
@ -67,4 +68,6 @@ struct Recorder : Node
void process_audio(void*, Uint8*, int);
#include "Game.hpp"
#endif

View File

@ -136,17 +136,22 @@ void Sprite::advance_frame()
void Sprite::hide()
{
is_hidden = true;
hidden = true;
}
void Sprite::unhide()
{
is_hidden = false;
hidden = false;
}
void Sprite::toggle_hidden()
{
is_hidden = !is_hidden;
hidden = !hidden;
}
bool Sprite::is_hidden() const
{
return hidden;
}
void Sprite::set_step(glm::vec2 s)
@ -227,7 +232,7 @@ void Sprite::update()
move(step);
frame_animation.update();
blink_animation.update();
if (is_loaded() && !is_hidden && get_current_frameset().get_frame_count())
if (is_loaded() && !is_hidden() && get_current_frameset().get_frame_count())
{
int index = get_current_frameset().get_current_frame_index();
SDL_Texture* texture = frames[index];

View File

@ -11,11 +11,11 @@
#include <SDL_image.h>
#include "Node.hpp"
#include "Game.hpp"
#include "Box.hpp"
#include "Animation.hpp"
#include "extension.hpp"
struct Game;
struct Frameset;
struct Sprite : Node
@ -26,7 +26,7 @@ struct Sprite : Node
Box box;
Animation frame_animation = Animation(&Sprite::advance_frame, this);
Animation blink_animation = Animation(&Sprite::toggle_hidden, this, 500);
bool is_hidden = false;
bool hidden = false;
glm::vec2 step = {0, 0};
Uint8 alpha_mod = 255;
std::map<std::string, Frameset> framesets;
@ -51,6 +51,7 @@ struct Sprite : Node
void hide();
void unhide();
void toggle_hidden();
bool is_hidden() const;
void set_step(glm::vec2);
float get_w() const;
float get_h() const;
@ -101,4 +102,6 @@ struct Frameset
};
#include "Game.hpp"
#endif

View File

@ -7,6 +7,7 @@
#include <sstream>
#include <algorithm>
#include <iomanip>
#include <stdexcept>
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/trigonometric.hpp"
@ -39,6 +40,38 @@ namespace sfw
padded << end;
return padded.str();
}
// from https://stackoverflow.com/a/30312659/1256386
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
if (step == IntType(0))
{
throw std::invalid_argument("step for range must be non-zero");
}
std::vector<IntType> result;
IntType i = start;
while ((step > 0) ? (i < stop) : (i > stop))
{
result.push_back(i);
i += step;
}
return result;
}
// from https://stackoverflow.com/a/30312659/1256386
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
return range(start, stop, IntType(1));
}
// from https://stackoverflow.com/a/30312659/1256386
template <typename IntType>
std::vector<IntType> range(IntType stop)
{
return range(IntType(0), stop, IntType(1));
}
}
std::ostream& operator<<(std::ostream&, const glm::vec2&);