dynamically load/unload sprite frames; Location class
This commit is contained in:
parent
8cd25fc099
commit
db6b36cfb7
239
main.cpp
239
main.cpp
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue