dynamically load/unload sprite frames; Location class

This commit is contained in:
Frank DeMarco 2018-12-28 00:41:35 -05:00
parent 8cd25fc099
commit db6b36cfb7
1 changed files with 202 additions and 37 deletions

239
main.cpp
View File

@ -1,3 +1,5 @@
// reset, pause, auto reset
#include <iostream>
#include <stdio.h>
#include <math.h>
@ -15,7 +17,7 @@
#include <SDL_ttf.h>
#include <SDL2_gfxPrimitives.h>
#if defined(__LINUX__) || defined(__MINGW32__)
#if defined(__LINUX__) or defined(__MINGW32__)
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#elif defined(__ANDROID__)
@ -38,7 +40,7 @@ char* file_to_buf(const char *path)
long length;
char *buf;
fp = fopen(path, "rb");
if (!fp)
if (not fp)
{
return NULL;
}
@ -128,7 +130,7 @@ void end_recording(std::list<SDL_Surface*> frames, bool *is_recording)
printf("end recording\n");
SDL_Surface *frame;
int ii = 0;
while (!frames.empty())
while (not frames.empty())
{
frame = frames.front();
char path[22];
@ -164,7 +166,7 @@ SDL_Surface* get_framerate_indicator_surface(int frame_count)
font, std::to_string(frame_count).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);
if (!flipped)
if (not flipped)
{
fprintf(stderr, "Could not create text %s\n", SDL_GetError());
}
@ -181,6 +183,35 @@ void set_framerate_indicator(int frame_count, GLuint id)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
struct Location
{
SDL_Rect rect = {0, 0, 0, 0};
glm::vec2 overflow;
Location() { };
template<typename T1, typename T2 = int>
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];
}
int get_x()
{
return rect.x;
}
int get_y()
{
return rect.y;
}
};
struct Game;
struct Node
@ -203,8 +234,9 @@ struct Sprite : Node
{
std::vector<SDL_Texture*> frames;
std::vector<std::filesystem::path> frame_paths;
int frame_ii = 0;
SDL_Rect rect = {0, 0, 16, 16};
Location location;
Sprite(Node *parent) : Node(parent)
{
@ -214,27 +246,37 @@ struct Sprite : Node
Sprite(Node *parent, std::string path) : Node(parent)
{
std::cout << "Constructing Sprite with " << parent << " and " << path << std::endl;
load(path);
associate(path);
}
void load(std::string);
void associate(std::string);
void load_file(std::string);
void load();
void load_file(std::filesystem::path);
void add_frame(SDL_Texture*);
void unload();
template<typename T1, typename T2 = int>
void move(T1, T2 = 0);
void update();
};
struct Mushroom : Sprite
{
int direction = 1;
Mushroom(Node *parent) : Sprite(parent)
Mushroom(Node *parent) : Sprite(parent, "resource/shrooms")
{
std::cout << "Constructing Mushroom with parent " << parent << std::endl;
}
void update();
};
struct Game : Node
@ -251,8 +293,9 @@ struct Game : Node
SDL_Texture *grass_texture;
int sw = 640, sh = 480, framerate = 60, recording_capture_framerate = 100,
frame_time_overflow = 0, capture_time_overflow = 0, frame_count = 0,
last_frame_timestamp, frame_count_timestamp, last_capture_timestamp, ticks;
bool done = false, is_recording = false, show_framerate = false, is_gl_context = true;
last_frame_timestamp, frame_count_timestamp, last_capture_timestamp, ticks, last_frame_length;
bool done = false, is_recording = false, show_framerate = false, is_gl_context = true,
right_active = false, down_active = false, left_active = false, up_active = false;
SDL_Event event;
float r = 0.0;
GLuint vbo, space_texture_id, mvp_id, framerate_texture_id, flat_program, world_program,
@ -261,6 +304,7 @@ struct Game : Node
std::list<SDL_Surface*> frames;
glm::mat4 projection, view, model = glm::mat4(1.0f), mvp;
Mushroom mushroom = Mushroom(this);
Sprite grass = Sprite(this, "resource/Field.png");
Game()
{
@ -291,7 +335,7 @@ struct Game : Node
print_sdl_error("Could not initialize SDL ttf");
flag_to_end();
}
load_gl_context();
load_sdl_context();
}
void print_error(std::string message)
@ -315,12 +359,8 @@ struct Game : Node
print_sdl_error("Could not create renderer");
flag_to_end();
}
if (!(grass_texture = IMG_LoadTexture(renderer, "resource/Field.png")))
{
print_sdl_error("Could not load image");
flag_to_end();
}
mushroom.load("resource/shrooms");
grass.load();
mushroom.load();
is_gl_context = false;
}
@ -330,6 +370,8 @@ struct Game : Node
{
SDL_DestroyRenderer(renderer);
}
grass.unload();
mushroom.unload();
if ((glcontext = SDL_GL_CreateContext(window)) == NULL)
{
print_sdl_error("Could not get GL context");
@ -397,6 +439,7 @@ struct Game : Node
SDL_Surface *surface = rotateSurface90Degrees(IMG_Load("resource/tile.png"), 2);
printf("tile.png bytes per pixel %i\n", surface->format->BytesPerPixel);
space_texture_id = get_gl_texture_from_surface(surface, GL_LINEAR);
SDL_FreeSurface(surface);
std::array<glm::vec2, 6> framerate_indicator_uv = {
{
{0, 1}, {1, 1}, {0, 0},
@ -482,14 +525,14 @@ struct Game : Node
void run()
{
while (!done)
while (not done)
{
ticks = SDL_GetTicks();
if (ticks - last_frame_timestamp + frame_time_overflow >= frame_length)
{
frame_count++;
frame_time_overflow = 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;
update();
}
@ -497,7 +540,7 @@ struct Game : Node
if (ticks - frame_count_timestamp >= 1000)
{
frame_count_timestamp = ticks;
if (show_framerate)
if (is_gl_context and show_framerate)
{
set_framerate_indicator(frame_count, framerate_texture_id);
}
@ -527,7 +570,7 @@ struct Game : Node
}
else if (event.key.keysym.sym == SDLK_F10)
{
if (!is_recording)
if (not is_recording)
{
start_recording(&is_recording);
}
@ -547,9 +590,36 @@ struct Game : Node
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
}
}
else if (event.key.keysym.sym == SDLK_f && SDL_GetModState() & KMOD_CTRL)
else if (SDL_GetModState() & KMOD_CTRL)
{
show_framerate = !show_framerate;
if (event.key.keysym.sym == SDLK_f)
{
show_framerate = not show_framerate;
}
else if (event.key.keysym.sym == SDLK_UP)
{
set_framerate(framerate + 1);
}
else if (event.key.keysym.sym == SDLK_DOWN)
{
set_framerate(framerate - 1);
}
}
else if (event.key.keysym.sym == SDLK_UP)
{
up_active = true;
}
else if (event.key.keysym.sym == SDLK_RIGHT)
{
right_active = true;
}
else if (event.key.keysym.sym == SDLK_DOWN)
{
down_active = true;
}
else if (event.key.keysym.sym == SDLK_LEFT)
{
left_active = true;
}
else if (event.key.keysym.sym == SDLK_SPACE)
{
@ -563,8 +633,27 @@ struct Game : Node
}
}
}
else if (event.type == SDL_KEYUP)
{
if (event.key.keysym.sym == SDLK_UP)
{
up_active = false;
}
else if (event.key.keysym.sym == SDLK_RIGHT)
{
right_active = false;
}
else if (event.key.keysym.sym == SDLK_DOWN)
{
down_active = false;
}
else if (event.key.keysym.sym == SDLK_LEFT)
{
left_active = false;
}
}
}
if (is_recording && ticks - last_capture_timestamp + capture_time_overflow >
if (is_recording and ticks - last_capture_timestamp + capture_time_overflow >
recording_capture_framerate)
{
frames.push_back(get_screen_surface(window));
@ -617,15 +706,44 @@ struct Game : Node
{
SDL_SetRenderDrawColor(renderer, 0x0f, 0x4f, 0x8f, 0xff);
SDL_RenderClear(renderer);
SDL_Rect rect = {0, 0, 240, 160};
SDL_RenderCopy(renderer, grass_texture, NULL, &rect);
roundedBoxColor(renderer, 300, 200, 500, 300, 10, 0x8f8fdfff);
aacircleColor(renderer, 300, 200, 30, 0xffef3fff);
int speed = 2;
if (up_active)
{
grass.move(0, -speed);
}
if (right_active)
{
grass.move(speed);
}
if (down_active)
{
grass.move(0, speed);
}
if (left_active)
{
grass.move(-speed, 0);
}
grass.update();
mushroom.update();
SDL_RenderPresent(renderer);
}
}
void set_framerate(int fps)
{
framerate = fps;
frame_length = 1000.0 / framerate;
std::cout << frame_length << " " << framerate << std::endl;
}
template<typename T>
float get_weighted_amount(T amount)
{
return (last_frame_length / (1000.0 / 60)) * amount;
}
void quit()
{
if (glcontext != NULL)
@ -659,12 +777,11 @@ Game* Node::get_root()
return static_cast<Game*>(current);
}
void Sprite::load(std::string path)
void Sprite::associate(std::string path)
{
Game *game = get_root();
if (std::filesystem::is_regular_file(path))
{
load_file(path);
frame_paths.push_back(std::filesystem::path(path));
}
else if (std::filesystem::is_directory(path))
{
@ -674,23 +791,31 @@ void Sprite::load(std::string path)
std::sort(paths.begin(), paths.end());
for (const std::filesystem::path &name : paths)
{
std::cout << name << std::endl;
load_file(name);
std::cout << "associating " << name << std::endl;
frame_paths.push_back(name);
}
}
else
{
std::ostringstream message;
message << "invalid path " << path;
game->print_error(message.str());
get_root()->print_error(message.str());
}
}
void Sprite::load_file(std::string path)
void Sprite::load()
{
for (const std::filesystem::path &path : frame_paths)
{
load_file(path);
}
}
void Sprite::load_file(std::filesystem::path path)
{
Game *game = get_root();
SDL_Texture *texture = IMG_LoadTexture(game->renderer, path.c_str());
if (!texture)
if (not texture)
{
game->print_sdl_error("Could not load image");
}
@ -705,15 +830,55 @@ void Sprite::add_frame(SDL_Texture *texture)
frames.push_back(texture);
}
void Sprite::unload()
{
while (not frames.empty())
{
SDL_DestroyTexture(frames.back());
frames.pop_back();
}
}
template<typename T1, typename T2>
void Sprite::move(T1 dx, T2 dy)
{
Game *game = get_root();
location.move_ip(game->get_weighted_amount(dx), game->get_weighted_amount(dy));
}
void Sprite::update()
{
SDL_RenderCopy(get_root()->renderer, frames[frame_ii++], NULL, &rect);
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);
if (frame_ii >= frames.size())
{
frame_ii = 0;
}
}
void Mushroom::update()
{
Game *game = get_root();
move(direction);
int x = location.get_x();
if (x > game->sw or x < 0)
{
direction = -direction;
if (x > game->sw)
{
move(game->sw - x);
}
else
{
move(-x);
}
}
Sprite::update();
}
int main(int argc, char *argv[])
{
Game g;