Sprite sheet animation and window woopsie fix
This commit is contained in:
parent
1b200bd162
commit
a296f2c660
7 changed files with 119 additions and 15 deletions
3
build.c
3
build.c
|
@ -33,7 +33,7 @@ typedef struct Context_Extra {
|
||||||
//
|
//
|
||||||
|
|
||||||
// This is a minimal starting point for new projects. Copy & rename to get started
|
// This is a minimal starting point for new projects. Copy & rename to get started
|
||||||
#include "oogabooga/examples/minimal_game_loop.c"
|
// #include "oogabooga/examples/minimal_game_loop.c"
|
||||||
|
|
||||||
// #include "oogabooga/examples/text_rendering.c"
|
// #include "oogabooga/examples/text_rendering.c"
|
||||||
// #include "oogabooga/examples/custom_logger.c"
|
// #include "oogabooga/examples/custom_logger.c"
|
||||||
|
@ -43,6 +43,7 @@ typedef struct Context_Extra {
|
||||||
// #include "oogabooga/examples/custom_shader.c"
|
// #include "oogabooga/examples/custom_shader.c"
|
||||||
// #include "oogabooga/examples/growing_array_example.c"
|
// #include "oogabooga/examples/growing_array_example.c"
|
||||||
// #include "oogabooga/examples/input_example.c"
|
// #include "oogabooga/examples/input_example.c"
|
||||||
|
#include "oogabooga/examples/sprite_animation.c"
|
||||||
|
|
||||||
// #include "oogabooga/examples/sanity_tests.c"
|
// #include "oogabooga/examples/sanity_tests.c"
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
This also gets rid of the weird window resize and reposition at startup.
|
This also gets rid of the weird window resize and reposition at startup.
|
||||||
- Renderer
|
- Renderer
|
||||||
- Added gfx_read_image_data() to read pixels from a Gfx_Image*
|
- Added gfx_read_image_data() to read pixels from a Gfx_Image*
|
||||||
|
|
||||||
|
- Misc
|
||||||
|
- Added examples/sprite_animation.c
|
||||||
|
|
||||||
## v0.01.004 - Gamepad input, text wrapping, bug fixes
|
## v0.01.004 - Gamepad input, text wrapping, bug fixes
|
||||||
- Input
|
- Input
|
||||||
|
|
BIN
oogabooga/examples/male_animation.png
Normal file
BIN
oogabooga/examples/male_animation.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
95
oogabooga/examples/sprite_animation.c
Normal file
95
oogabooga/examples/sprite_animation.c
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int entry(int argc, char **argv) {
|
||||||
|
|
||||||
|
window.title = STR("Sprite animation example");
|
||||||
|
|
||||||
|
Gfx_Image *anim_sheet = load_image_from_disk(STR("oogabooga/examples/male_animation.png"), get_heap_allocator());
|
||||||
|
assert(anim_sheet, "Could not open oogabooga/examples/male_animation.png");
|
||||||
|
|
||||||
|
// Configure information about the whole image as a sprite sheet
|
||||||
|
u32 number_of_columns = 10;
|
||||||
|
u32 number_of_rows = 6;
|
||||||
|
u32 total_number_of_frames = number_of_rows * number_of_columns;
|
||||||
|
|
||||||
|
u32 anim_frame_width = anim_sheet->width / number_of_columns;
|
||||||
|
u32 anim_frame_height = anim_sheet->height / number_of_rows;
|
||||||
|
|
||||||
|
// Configure the animation by setting the start & end frames in the grid of frames
|
||||||
|
// (Inspect sheet image and count the frame indices you want)
|
||||||
|
// In sprite sheet animations, it usually goes down. So Y 0 is actuall the top of the
|
||||||
|
// sprite sheet, and +Y is down on the sprite sheet.
|
||||||
|
u32 anim_start_frame_x = 2;
|
||||||
|
u32 anim_start_frame_y = 1;
|
||||||
|
u32 anim_end_frame_x = 6;
|
||||||
|
u32 anim_end_frame_y = 2;
|
||||||
|
u32 anim_start_index = anim_start_frame_y * number_of_columns + anim_start_frame_x;
|
||||||
|
u32 anim_end_index = anim_end_frame_y * number_of_columns + anim_end_frame_x;
|
||||||
|
u32 anim_number_of_frames = max(anim_end_index, anim_start_index)-min(anim_end_index, anim_start_index)+1;
|
||||||
|
|
||||||
|
// Sanity check configuration
|
||||||
|
assert(anim_end_index > anim_start_index, "The last frame must come before the first frame");
|
||||||
|
assert(anim_start_frame_x < number_of_columns, "anim_start_frame_x is out of bounds");
|
||||||
|
assert(anim_start_frame_y < number_of_rows, "anim_start_frame_y is out of bounds");
|
||||||
|
assert(anim_end_frame_x < number_of_columns, "anim_end_frame_x is out of bounds");
|
||||||
|
assert(anim_end_frame_y < number_of_rows, "anim_end_frame_y is out of bounds");
|
||||||
|
|
||||||
|
// Calculate duration per frame in seconds
|
||||||
|
float32 playback_fps = 4;
|
||||||
|
float32 anim_time_per_frame = 1.0 / playback_fps;
|
||||||
|
float32 anim_duration = anim_time_per_frame * (float32)anim_number_of_frames;
|
||||||
|
|
||||||
|
float32 anim_start_time = os_get_elapsed_seconds();
|
||||||
|
|
||||||
|
float64 last_time = os_get_elapsed_seconds();
|
||||||
|
while (!window.should_close) {
|
||||||
|
reset_temporary_storage();
|
||||||
|
|
||||||
|
|
||||||
|
float64 now = os_get_elapsed_seconds();
|
||||||
|
float64 delta = now-last_time;
|
||||||
|
last_time = now;
|
||||||
|
|
||||||
|
draw_frame.projection = m4_make_orthographic_projection(window.pixel_width * -0.5, window.pixel_width * 0.5, window.pixel_height * -0.5, window.pixel_height * 0.5, -1, 10);
|
||||||
|
|
||||||
|
// Float modulus to "loop" around the timer over the anim duration
|
||||||
|
float32 anim_elapsed = fmodf(now - anim_start_time, anim_duration);
|
||||||
|
|
||||||
|
// Get current progression in animation from 0.0 to 1.0
|
||||||
|
float32 anim_progression_factor = anim_elapsed / anim_duration;
|
||||||
|
|
||||||
|
u32 anim_current_index = anim_number_of_frames * anim_progression_factor;
|
||||||
|
u32 anim_absolute_index_in_sheet = anim_start_index + anim_current_index;
|
||||||
|
|
||||||
|
u32 anim_index_x = anim_absolute_index_in_sheet % number_of_columns;
|
||||||
|
u32 anim_index_y = anim_absolute_index_in_sheet / number_of_columns + 1;
|
||||||
|
|
||||||
|
u32 anim_sheet_pos_x = anim_index_x * anim_frame_width;
|
||||||
|
u32 anim_sheet_pos_y = (number_of_rows - anim_index_y) * anim_frame_height; // Remember, Y inverted.
|
||||||
|
|
||||||
|
// Draw the sprite sheet, with the uv box for the current frame.
|
||||||
|
// Uv box is a Vector4 of x1, y1, x2, y2 where each value is a percentage value 0.0 to 1.0
|
||||||
|
// from left to right / bottom to top in the texture.
|
||||||
|
Draw_Quad *quad = draw_image(anim_sheet, v2(0, 0), v2(anim_frame_width*4, anim_frame_height*4), COLOR_WHITE);
|
||||||
|
quad->uv.x1 = (float32)(anim_sheet_pos_x)/(float32)anim_sheet->width;
|
||||||
|
quad->uv.y1 = (float32)(anim_sheet_pos_y)/(float32)anim_sheet->height;
|
||||||
|
quad->uv.x2 = (float32)(anim_sheet_pos_x+anim_frame_width) /(float32)anim_sheet->width;
|
||||||
|
quad->uv.y2 = (float32)(anim_sheet_pos_y+anim_frame_height)/(float32)anim_sheet->height;
|
||||||
|
|
||||||
|
|
||||||
|
// Visualize sprite sheet animation
|
||||||
|
Vector2 sheet_pos = v2(-window.width/2+40, -window.height/2+40);
|
||||||
|
Vector2 sheet_size = v2(anim_sheet->width, anim_sheet->height);
|
||||||
|
Vector2 frame_pos_in_sheet = v2(anim_sheet_pos_x, anim_sheet_pos_y);
|
||||||
|
Vector2 frame_size = v2(anim_frame_width, anim_frame_height);
|
||||||
|
draw_rect(sheet_pos, sheet_size, COLOR_BLACK); // Draw black background
|
||||||
|
draw_rect(v2_add(sheet_pos, frame_pos_in_sheet), frame_size, COLOR_WHITE); // Draw white rect on current frame
|
||||||
|
draw_image(anim_sheet, sheet_pos, sheet_size, COLOR_WHITE); // Draw the seet
|
||||||
|
|
||||||
|
os_update();
|
||||||
|
gfx_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -319,6 +319,10 @@ Matrix4 m4_scalar(float32 scalar) {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Matrix4 m4_identity() {
|
||||||
|
return m4_scalar(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
Matrix4 m4_make_translation(Vector3 translation) {
|
Matrix4 m4_make_translation(Vector3 translation) {
|
||||||
Matrix4 m = m4_scalar(1.0);
|
Matrix4 m = m4_scalar(1.0);
|
||||||
m.m[0][0] = 1.0f; m.m[1][1] = 1.0f; m.m[2][2] = 1.0f; m.m[3][3] = 1.0f;
|
m.m[0][0] = 1.0f; m.m[1][1] = 1.0f; m.m[2][2] = 1.0f; m.m[3][3] = 1.0f;
|
||||||
|
|
|
@ -297,10 +297,10 @@ win32_init_window() {
|
||||||
memset(&window, 0, sizeof(window));
|
memset(&window, 0, sizeof(window));
|
||||||
|
|
||||||
window.title = STR("Unnamed Window");
|
window.title = STR("Unnamed Window");
|
||||||
window.width = 1280;
|
window.scaled_width = 1280;
|
||||||
window.height = 720;
|
window.scaled_height = 720;
|
||||||
window.x = 0;
|
window.x = 200;
|
||||||
window.y = 0;
|
window.y = 150;
|
||||||
window.should_close = false;
|
window.should_close = false;
|
||||||
window._initialized = false;
|
window._initialized = false;
|
||||||
window.clear_color.r = 0.392f;
|
window.clear_color.r = 0.392f;
|
||||||
|
@ -348,10 +348,10 @@ win32_init_window() {
|
||||||
UpdateWindow(window._os_handle);
|
UpdateWindow(window._os_handle);
|
||||||
|
|
||||||
ShowWindow(window._os_handle, SW_HIDE);
|
ShowWindow(window._os_handle, SW_HIDE);
|
||||||
style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
|
//style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
|
||||||
style &= ~WS_EX_APPWINDOW; // Remove from taskbar
|
//style &= ~WS_EX_APPWINDOW; // Remove from taskbar
|
||||||
style |= WS_EX_TOOLWINDOW; // Make it a tool window
|
//style |= WS_EX_TOOLWINDOW; // Make it a tool window
|
||||||
SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
|
//SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1877,10 +1877,10 @@ void os_update() {
|
||||||
// Only show window after first call to os_update
|
// Only show window after first call to os_update
|
||||||
if (!has_os_update_been_called_at_all) {
|
if (!has_os_update_been_called_at_all) {
|
||||||
ShowWindow(window._os_handle, SW_SHOW);
|
ShowWindow(window._os_handle, SW_SHOW);
|
||||||
DWORD style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
|
//DWORD style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
|
||||||
style &= ~WS_EX_TOOLWINDOW;
|
//style &= ~(WS_EX_TOOLWINDOW);
|
||||||
style |= WS_EX_APPWINDOW;
|
//style |= WS_EX_APPWINDOW;
|
||||||
SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
|
//SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
has_os_update_been_called_at_all = true;
|
has_os_update_been_called_at_all = true;
|
||||||
|
|
|
@ -99,4 +99,6 @@ void merge_sort(void *collection, void *help_buffer, u64 item_count, u64 item_si
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool bytes_match(void *a, void *b, u64 count) { return memcmp(a, b, count) == 0; }
|
inline bool bytes_match(void *a, void *b, u64 count) { return memcmp(a, b, count) == 0; }
|
||||||
|
|
||||||
|
#define swap(a, b, type) { type t = a; a = b; b = t; }
|
Reference in a new issue