- replaced location with box, added get/set functions for size and

sides
- preprocessor statements for handling emscripten main loop
- pass floats to render functions
- added box and get/set box functions to sprite class
- functions for filling a texture with solid color or tile texture
This commit is contained in:
Frank DeMarco 2020-06-27 17:47:14 -04:00
parent bbc53d357c
commit 74ca4da69a
21 changed files with 570 additions and 124 deletions

37
README
View File

@ -1,25 +1,28 @@
SFW (SDL Framework)
===================
SFW is a library of C++ objects that facilitate the creation of SDL projects.
It is modeled after PGFW, a Pygame framework, which is an older project of mine.
It is currently in an early untested stage, but it comes with a simple program
that demonstrates how the framework can help set up a project in both SDL and
OpenGL contexts.
SFW is a C++ library that facilitates the creation of SDL projects and adds
useful game graphics oriented classes and functions. It is modeled after PGFW, a
Pygame framework, which simplifies the set up of Pygame projects and enhances
and adds some features to Pygame.
It is currently in an early untested stage. It comes with a simple program that
demonstrates how the framework can help set up a project in both SDL and OpenGL
contexts.
Requirements
------------
The SFW source comes with a few libraries in the lib/ folder, but there are
other libraries that must be present in order to compile a project which uses
the framework
The SFW source includes some external libraries in the lib/ folder, but there
are also other libraries that must be present in order to compile a project
which uses the framework
- libSDL2 (developed with 2.0.9)
- libSDL2-image
- libSDL2-ttf
- libSDL2-mixer
- Open GL
- compiler that supports C++17
* libSDL2 (developed against v2.0.12)
* libSDL2-image
* libSDL2-ttf
* libSDL2-mixer
* OpenGL
* compiler that supports C++17
Demo
----
@ -35,7 +38,7 @@ License
This software is dedicated to the public domain. See
http://creativecommons.org/publicdomain/zero/1.0/ for details.
Contact
-------
Author
------
You can email me at frank at shampoo.ooo
420 at shampoo dot ooo

View File

@ -9,7 +9,8 @@
relative coordinates, relative lengths, relative sizes, delta time, specify
config parameters on command line, effects chain, asset dict with metadata,
move added sprite locations by offset when location is changed, gradients,
level select code input, logging
level select code input, logging, variable screen resolution, debug display,
loading wheel animation
:) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :)
@ -131,7 +132,7 @@ Mushroom::Mushroom(Node *parent) : Sprite(parent, "resource/shrooms")
void Mushroom::update()
{
move(direction);
int x = location.get_x();
int x = box.get_x();
glm::ivec2 resolution = get_display().get_window_size();
if (x > resolution.x or x < 0)
{

View File

@ -33,7 +33,7 @@
#include "filesystem.hpp"
#include "Node.hpp"
#include "Game.hpp"
#include "Location.hpp"
#include "Box.hpp"
#include "Sprite.hpp"
#include "Input.hpp"
#include "Delegate.hpp"

View File

@ -36,7 +36,7 @@ $(SDLGFX2_DIR)%.o: $(SDLGFX2_DIR)%.c $(SDLGFX2_DIR)%.h
$(GLEW_DIR)%.o: $(GLEW_DIR)%.c $(GLEW_DIR)%.h
$(CC_LINUX) $(CFLAGS) $< -o $@
$(SFW_SRC_DIR)Sprite.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Location.*pp Node.*pp Animation.*pp)
$(SFW_SRC_DIR)Sprite.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Box.*pp Node.*pp Animation.*pp)
$(SFW_SRC_DIR)Game.o: $(addprefix $(SFW_SRC_DIR),Sprite.*pp Configuration.*pp Delegate.*pp Display.*pp \
Recorder.*pp Node.*pp Input.*pp)
$(SFW_SRC_DIR)Node.o: $(addprefix $(SFW_SRC_DIR),Game.*pp Configuration.*pp Delegate.*pp)
@ -49,11 +49,11 @@ $(SFW_SRC_DIR)Display.o: $(addprefix $(SFW_SRC_DIR),Node.*pp)
$(SFW_SRC_DIR)%.o: $(addprefix $(SFW_SRC_DIR),%.cpp %.hpp)
$(CPPC_LINUX) $(CPP_FLAGS) $(SDL_FLAGS) $< -o $@
Demo.o: Demo.cpp Demo.hpp $(addprefix $(SFW_SRC_DIR),Sprite.*pp Node.*pp Game.*pp Location.*pp Input.*pp \
Demo.o: Demo.cpp Demo.hpp $(addprefix $(SFW_SRC_DIR),Sprite.*pp Node.*pp Game.*pp Box.*pp Input.*pp \
Recorder.*pp Timer.*pp Animation.*pp extension.*pp)
$(CPPC_LINUX) $(CPP_FLAGS) $(SDL_FLAGS) $< -o $@
linux: Demo.o $(addprefix $(SFW_SRC_DIR),Sprite.o Node.o Game.o Location.o Configuration.o Input.o Delegate.o \
linux: Demo.o $(addprefix $(SFW_SRC_DIR),Sprite.o Node.o Game.o Box.o Configuration.o Input.o Delegate.o \
Display.o Recorder.o Timer.o Animation.o extension.o) \
$(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o)
$(CPPC_LINUX) $(LFLAGS) -D__LINUX__ $^ -lGL -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lstdc++fs -o demo

View File

@ -69,6 +69,10 @@ void Animation::update()
{
reset();
}
if (overflow > frame_length)
{
overflow = 0;
}
}
}
}

View File

@ -14,8 +14,8 @@ struct Animation
{
bool playing = false, ending = false, paused = false;
int previous_step_time = 0, overflow = 0, count = 0;
float delay = 0, frame_length;
int previous_step_time = 0, count = 0;
float delay = 0, overflow = 0, frame_length;
callback step;
Node* containing_object;
Timer timer = Timer();

187
src/Box.cpp Normal file
View File

@ -0,0 +1,187 @@
#include "Box.hpp"
Box::Box(glm::vec2 nw, glm::vec2 size)
{
set_nw(nw);
set_size(size);
}
float Box::get_x()
{
return rect.x;
}
float Box::get_y()
{
return rect.y;
}
float Box::get_w()
{
return rect.w;
}
float Box::get_h()
{
return rect.h;
}
void Box::set_x(float x)
{
rect.x = x;
}
void Box::set_y(float y)
{
rect.y = y;
}
void Box::set_w(float w)
{
rect.w = w;
}
void Box::set_h(float h)
{
rect.h = h;
}
glm::vec2 Box::get_size()
{
return glm::vec2(get_w(), get_h());
}
void Box::set_size(glm::vec2 size)
{
set_w(size.x);
set_h(size.y);
}
float Box::get_top()
{
return get_y();
}
float Box::get_right()
{
return get_x() + get_w();
}
float Box::get_bottom()
{
return get_y() + get_h();
}
float Box::get_left()
{
return get_x();
}
void Box::set_top(float top)
{
set_y(top);
}
void Box::set_right(float right)
{
move(glm::vec2(right - get_right(), 0));
}
void Box::set_bottom(float bottom)
{
move(glm::vec2(0, bottom - get_bottom()));
}
void Box::set_left(float left)
{
set_x(left);
}
glm::vec2 Box::get_nw()
{
return glm::vec2(get_x(), get_y());
}
glm::vec2 Box::get_north()
{
return glm::vec2(get_x() + get_w() / 2, get_y());
}
glm::vec2 Box::get_east()
{
return glm::vec2(get_right(), get_y() + get_h() / 2);
}
glm::vec2 Box::get_south()
{
return glm::vec2(get_x() + get_w() / 2, get_bottom());
}
glm::vec2 Box::get_west()
{
return glm::vec2(get_x(), get_y() + get_h() / 2);
}
glm::vec2 Box::get_center()
{
return glm::vec2(get_x() + get_w() / 2, get_y() + get_h() / 2);
}
void Box::set_nw(glm::vec2 nw)
{
set_x(nw.x);
set_y(nw.y);
}
void Box::set_north(glm::vec2 n)
{
move(n - get_north());
}
void Box::set_east(glm::vec2 e)
{
move(e - get_east());
}
void Box::set_south(glm::vec2 s)
{
move(s - get_south());
}
void Box::set_west(glm::vec2 w)
{
move(w - get_west());
}
void Box::set_center(glm::vec2 center)
{
move(center - get_center());
}
SDL_FRect* Box::get_rect()
{
return &rect;
}
void Box::zero()
{
set_nw(glm::vec2(0, 0));
set_size(glm::vec2(0, 0));
}
void Box::move(glm::vec2 delta)
{
set_x(get_x() + delta.x);
set_y(get_y() + delta.y);
}
std::ostream& Box::to_string (std::ostream& out) const
{
out << "{(" << rect.x << ", " << rect.y << "), (" << rect.w << ", " << rect.h << ")}";
return out;
}
std::ostream& operator<< (std::ostream& out, const Box& box)
{
return box.to_string(out);
}

59
src/Box.hpp Normal file
View File

@ -0,0 +1,59 @@
#ifndef Box_h_
#define Box_h_
#include <iostream>
#include <SDL.h>
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/common.hpp"
#include "glm/vec2.hpp"
struct Box
{
SDL_FRect rect = {0, 0, 0, 0};
Box(glm::vec2 = {0, 0}, glm::vec2 = {0, 0});
float get_x();
float get_y();
float get_w();
float get_h();
void set_x(float);
void set_y(float);
void set_w(float);
void set_h(float);
glm::vec2 get_size();
void set_size(glm::vec2);
float get_top();
float get_right();
float get_bottom();
float get_left();
void set_top(float);
void set_right(float);
void set_bottom(float);
void set_left(float);
glm::vec2 get_nw();
glm::vec2 get_north();
glm::vec2 get_east();
glm::vec2 get_south();
glm::vec2 get_west();
glm::vec2 get_center();
void set_nw(glm::vec2);
void set_north(glm::vec2);
void set_east(glm::vec2);
void set_south(glm::vec2);
void set_west(glm::vec2);
void set_center(glm::vec2);
SDL_FRect* get_rect();
void zero();
void move(glm::vec2);
std::string get_class_name() { return "Box"; }
std::ostream& to_string (std::ostream&) const;
};
std::ostream& operator<< (std::ostream&, const Box&);
#include "extension.hpp"
#endif

View File

@ -31,7 +31,8 @@ void Configuration::set_defaults()
};
sys_config["display"] = {
{"dimensions", {640, 480}},
{"fps", 60}
{"fps", 60},
{"title", "sfw"}
};
sys_config["recording"] = {
{"enabled", false},

View File

@ -2,14 +2,19 @@
#include "Game.hpp"
Display::Display(Node* parent) : Node(parent) {}
glm::ivec2 Display::get_window_size()
{
glm::ivec2 size;
SDL_GetWindowSize(get_root()->window, &size.x, &size.y);
SDL_GetWindowSize(get_root()->get_window(), &size.x, &size.y);
return size;
}
Box Display::get_window_box()
{
return Box(glm::vec2(0, 0), get_window_size());
}
void Display::get_screen_pixels(unsigned char* pixels, int w, int h, int x, int y)
{
if (get_root()->is_gl_context)

View File

@ -8,13 +8,14 @@
#define GLEW_STATIC
#include "glew/glew.h"
#include "SDL.h"
#include <SDL_image.h>
#include "sdl2-gfx/SDL2_gfxPrimitives.h"
#include "sdl2-gfx/SDL2_rotozoom.h"
#include "SDL.h"
#include "Node.hpp"
#include "Box.hpp"
struct Display : Node
{
@ -23,6 +24,7 @@ struct Display : Node
Display(Node*);
glm::ivec2 get_window_size();
Box get_window_box();
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);

View File

@ -38,8 +38,9 @@ Game::Game()
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
print_gl_attributes();
std::vector<int> window_size = get_configuration()["display"]["dimensions"];
window = SDL_CreateWindow("TARE control", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
window_size[0], window_size[1], SDL_WINDOW_OPENGL);
window = SDL_CreateWindow(
get_configuration()["display"]["title"].get_ref<const std::string&>().c_str(), SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, window_size[0], window_size[1], SDL_WINDOW_OPENGL);
if (window == NULL)
{
print_sdl_error("Could not create window");
@ -56,6 +57,7 @@ Game::Game()
SDL_Log("initialized SDL ttf %d.%d.%d", SDL_TTF_MAJOR_VERSION,
SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL);
}
#if !defined(__EMSCRIPTEN__)
if (Mix_Init(MIX_INIT_FLAC) == 0)
{
print_sdl_error("Could not initialize SDL mixer");
@ -66,6 +68,7 @@ Game::Game()
SDL_Log("initialized SDL mixer %d.%d.%d", SDL_MIXER_MAJOR_VERSION,
SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL);
}
#endif
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
MIX_DEFAULT_CHANNELS, 1024) < 0)
{
@ -171,14 +174,6 @@ void Game::load_gl_context()
log_display_mode();
}
GLuint Game::create_gl_texture()
{
GLuint id;
glCreateTextures(GL_TEXTURE_2D, 1, &id);
glBindTexture(GL_TEXTURE_2D, id);
return id;
}
bool Game::log_gl_errors(std::string suffix)
{
GLenum error;
@ -398,29 +393,81 @@ std::string Game::get_pixel_format_string(Uint32 format)
return pixel_format;
}
SDL_Window* Game::get_window()
{
return window;
}
SDL_Renderer* Game::get_renderer()
{
return renderer;
}
void Game::run()
{
#if defined(__EMSCRIPTEN__)
emscripten_set_main_loop_arg(&loop, this, -1, true);
#else
while (not done)
{
ticks = SDL_GetTicks();
if (ticks - last_frame_timestamp + frame_time_overflow >= frame_length)
{
last_frame_length = ticks - last_frame_timestamp;
frame_time_overflow = last_frame_length + frame_time_overflow - frame_length;
last_frame_timestamp = ticks;
recorder.update();
delegate.dispatch();
update();
}
frame(SDL_GetTicks());
SDL_Delay(8);
}
#endif
}
void Game::frame(float ticks)
{
// std::cout << "ticks: " << ticks << ", last_frame_timestamp: " << last_frame_timestamp <<
// ", frame_time_overflow: " << frame_time_overflow;
if (ticks - last_frame_timestamp + frame_time_overflow >= frame_length)
{
last_frame_length = ticks - last_frame_timestamp;
// std::cout << ", last_frame_length: " << last_frame_length << " [rendering frame]";
frame_time_overflow = last_frame_length + frame_time_overflow - frame_length;
last_frame_timestamp = ticks;
recorder.update();
delegate.dispatch();
update();
if (frame_time_overflow > frame_length)
{
SDL_Log("%i frame(s) dropped", ((int) (frame_time_overflow / frame_length)));
frame_time_overflow = 0;
}
}
// std::cout << std::endl;
}
#if defined(__EMSCRIPTEN__)
void loop(void* context)
{
Game* game = static_cast<Game*>(context);
game->frame(emscripten_performance_now());
if (game->done)
{
emscripten_cancel_main_loop();
}
}
#endif
void Game::flag_to_end()
{
done = true;
}
glm::vec2 Game::weight(glm::vec2 motion)
{
return glm::vec2(weight(motion.x), weight(motion.y));
}
void Game::set_framerate(int fps)
{
if (fps < 1)

View File

@ -13,8 +13,19 @@
#define GL_GLEXT_PROTOTYPES
#define GLEW_STATIC
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
#include <emscripten/html5.h>
#include <GL/glew.h>
#else
#include "glew/glew.h"
#endif
#include "Node.hpp"
#include "Configuration.hpp"
#include "Delegate.hpp"
@ -43,9 +54,9 @@ struct Game : Node
SDL_GLContext glcontext = NULL;
// 768, 432
// 864, 486
int frame_time_overflow = 0, framerate, ticks, last_frame_timestamp,
frame_count_timestamp, last_frame_length;
float frame_length;
int framerate, ticks, last_frame_length;
float frame_length = 1000.0 / 60.0, frame_time_overflow = 0,
last_frame_timestamp, emscripten_previous_time;
bool done = false, show_framerate = true, is_gl_context = true;
Configuration configuration = Configuration(this);
Delegate delegate = Delegate(this);
@ -60,27 +71,36 @@ struct Game : Node
void print_gl_attributes();
void load_sdl_context();
void load_gl_context();
GLuint create_gl_texture();
bool log_gl_errors(std::string);
void log_display_mode();
void log_surface_format(SDL_Surface*, std::string = "surface");
std::string get_pixel_format_string(Uint32);
SDL_Window* get_window();
SDL_Renderer* get_renderer();
void run();
void frame(float);
void flag_to_end();
virtual void update() {};
glm::vec2 weight(glm::vec2);
void set_framerate(int);
void handle_quit_event(SDL_Event&);
void quit();
std::string get_class_name() { return "Game"; }
template<typename T>
float get_weighted_amount(T amount)
float weight(T amount)
{
return (last_frame_length / (1000.0 / 60)) * amount;
}
};
#if defined(__EMSCRIPTEN__)
void loop(void*);
#endif
#include "Sprite.hpp"
#endif

View File

@ -1,11 +0,0 @@
#include "Location.hpp"
int Location::get_x()
{
return rect.x;
}
int Location::get_y()
{
return rect.y;
}

View File

@ -1,34 +0,0 @@
#ifndef Location_h_
#define Location_h_
#include <iostream>
#include <SDL.h>
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/common.hpp"
#include "glm/vec2.hpp"
struct Location
{
SDL_Rect rect = {0, 0, 0, 0};
glm::vec2 overflow;
Location() { };
int get_x();
int get_y();
std::string get_class_name() { return "Location"; }
template<typename T1, typename T2>
void move_ip(T1 dx, T2 dy = 0)
{
overflow += glm::vec2(dx, dy);
glm::vec2 motion = glm::floor(overflow);
overflow -= motion;
rect.x += motion[0];
rect.y += motion[1];
}
};
#endif

View File

@ -359,9 +359,9 @@ void Recorder::update()
animation.update();
}
void process_audio(void* user_data, Uint8* stream, int len)
void process_audio(void* context, Uint8* stream, int len)
{
Recorder* recorder = static_cast<Recorder*>(user_data);
Recorder* recorder = static_cast<Recorder*>(context);
if (recorder->is_active())
{
int max_length = recorder->get_configuration()["recording"]["max-stash-length"];

View File

@ -1,17 +1,19 @@
#include "Sprite.hpp"
#include "Game.hpp"
Sprite::Sprite(Node *parent) : Node(parent, true) {}
Sprite::Sprite(Node* parent) : Node(parent, true)
{
frame_animation.play();
}
Sprite::Sprite(Node *parent, std::string path) : Node(parent, true)
Sprite::Sprite(Node* parent, std::string path) : Sprite(parent)
{
associate(path);
animation.play();
}
void Sprite::set_frame_length(float length)
{
animation.set_frame_length(length);
frame_animation.set_frame_length(length);
}
void Sprite::associate(std::string path)
@ -62,8 +64,18 @@ void Sprite::load_file(fs::path path)
}
}
void Sprite::add_frame(SDL_Texture *texture)
void Sprite::add_frame(SDL_Texture* texture)
{
int w, h;
SDL_QueryTexture(texture, NULL, NULL, &w, &h);
if (box.get_w() < w)
{
box.set_w(w);
}
if (box.get_h() < h)
{
box.set_h(h);
}
frames.push_back(texture);
}
@ -74,6 +86,7 @@ void Sprite::unload()
SDL_DestroyTexture(frames.back());
frames.pop_back();
}
box.zero();
}
void Sprite::advance_frame()
@ -84,15 +97,105 @@ void Sprite::advance_frame()
}
}
void Sprite::hide()
{
is_hidden = true;
}
void Sprite::unhide()
{
is_hidden = false;
}
void Sprite::toggle_hidden()
{
is_hidden = !is_hidden;
}
void Sprite::set_step(glm::vec2 s)
{
step.x = s.x;
step.y = s.y;
}
float Sprite::get_w()
{
return box.get_w();
}
float Sprite::get_h()
{
return box.get_h();
}
glm::vec2 Sprite::get_size()
{
return box.get_size();
}
float Sprite::get_top()
{
return box.get_top();
}
float Sprite::get_right()
{
return box.get_right();
}
float Sprite::get_bottom()
{
return box.get_bottom();
}
float Sprite::get_left()
{
return box.get_left();
}
glm::vec2 Sprite::get_nw()
{
return box.get_nw();
}
glm::vec2 Sprite::get_north()
{
return box.get_north();
}
glm::vec2 Sprite::get_west()
{
return box.get_west();
}
void Sprite::set_nw(glm::vec2 nw)
{
box.set_nw(nw);
}
void Sprite::move(glm::vec2 delta, bool weighted)
{
Game *game = get_root();
if (weighted)
{
delta = game->weight(delta);
}
box.move(delta);
}
void Sprite::update()
{
if (active)
{
animation.update();
int w, h;
SDL_Texture *frame = frames[frame_ii];
SDL_QueryTexture(frame, NULL, NULL, &w, &h);
SDL_Rect frame_rect = {location.get_x(), location.get_y(), w, h};
SDL_RenderCopy(get_root()->renderer, frame, NULL, &frame_rect);
move(step);
frame_animation.update();
blink_animation.update();
if (frames.size() && !is_hidden)
{
SDL_Texture* texture = frames[frame_ii];
SDL_Renderer* renderer = get_root()->renderer;
SDL_SetRenderTarget(renderer, NULL);
SDL_RenderCopyF(renderer, texture, NULL, box.get_rect());
}
}
}

View File

@ -11,7 +11,7 @@
#include "Node.hpp"
#include "Game.hpp"
#include "Location.hpp"
#include "Box.hpp"
#include "Animation.hpp"
struct Sprite : Node
@ -20,8 +20,11 @@ struct Sprite : Node
std::vector<SDL_Texture*> frames;
std::vector<fs::path> frame_paths;
int frame_ii = 0;
Location location;
Animation animation = Animation(&Sprite::advance_frame, this);
Box box;
Animation frame_animation = Animation(&Sprite::advance_frame, this);
Animation blink_animation = Animation(&Sprite::toggle_hidden, this, 500);
bool is_hidden = false;
glm::vec2 step = {0, 0};
Sprite(Node*);
Sprite(Node*, std::string);
@ -32,15 +35,25 @@ struct Sprite : Node
void add_frame(SDL_Texture*);
void unload();
void advance_frame();
void hide();
void unhide();
void toggle_hidden();
void set_step(glm::vec2);
float get_w();
float get_h();
glm::vec2 get_size();
float get_top();
float get_right();
float get_bottom();
float get_left();
glm::vec2 get_nw();
glm::vec2 get_north();
glm::vec2 get_west();
void set_nw(glm::vec2);
void move(glm::vec2, bool = true);
void update();
std::string get_class_name() { return "Sprite"; }
template<typename T1, typename T2 = int>
void move(T1 dx, T2 dy = 0)
{
Game *game = get_root();
location.move_ip(game->get_weighted_amount(dx), game->get_weighted_amount(dy));
}
~Sprite() { unload(); }
};

View File

@ -8,7 +8,7 @@ Timer::Timer()
void Timer::toggle()
{
is_timing = not is_timing;
is_timing = !is_timing;
}
void Timer::toggle(bool state)

View File

@ -1,5 +1,40 @@
#include "extension.hpp"
glm::vec2 sfw::get_step(glm::vec2 start, glm::vec2 end, float speed)
{
float angle = glm::atan(end.x - start.x, end.y - start.y);
return glm::vec2(speed * glm::sin(angle), speed * glm::cos(angle));
}
Box sfw::get_texture_box(SDL_Texture* texture)
{
int w, h;
SDL_QueryTexture(texture, NULL, NULL, &w, &h);
return Box(glm::vec2(0, 0), glm::vec2(w, h));
}
void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, int r, int g, int b, int a)
{
SDL_SetRenderTarget(renderer, texture);
SDL_SetRenderDrawColor(renderer, r, g, b, a);
SDL_RenderFillRect(renderer, NULL);
}
void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture* tile)
{
SDL_SetRenderTarget(renderer, texture);
Box texture_box = get_texture_box(texture), tile_box = get_texture_box(tile);
SDL_FRect draw_rect;
for (int x = 0; x < texture_box.get_w(); x += tile_box.get_w())
{
for (int y = 0; y < texture_box.get_h(); y += tile_box.get_h())
{
draw_rect = {(float) x, (float) y, tile_box.get_w(), tile_box.get_h()};
SDL_RenderCopyF(renderer, tile, NULL, &draw_rect);
}
}
}
std::vector<fs::path> sfw::glob(fs::path query)
{
fs::path basename = query.parent_path();

View File

@ -8,10 +8,21 @@
#include <algorithm>
#include <iomanip>
#define GLM_ENABLE_EXPERIMENTAL
#include "glm/trigonometric.hpp"
#include "glm/vec2.hpp"
#include "SDL.h"
#include "Box.hpp"
#include "filesystem.hpp"
namespace sfw
{
glm::vec2 get_step(glm::vec2, glm::vec2, float);
Box get_texture_box(SDL_Texture*);
void fill_texture(SDL_Renderer*, SDL_Texture*, int, int, int, int = 0xff);
void fill_texture(SDL_Renderer*, SDL_Texture*, SDL_Texture*);
std::vector<fs::path> glob(fs::path);
fs::path get_next_file_name(
fs::path, int = 0, std::string = "", std::string = "");