Sprite sheet animation and window woopsie fix

This commit is contained in:
Charlie Malmqvist 2024-08-23 18:13:02 +02:00
parent 1b200bd162
commit a296f2c660
7 changed files with 119 additions and 15 deletions

View file

@ -33,7 +33,7 @@ typedef struct Context_Extra {
//
// 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/custom_logger.c"
@ -43,6 +43,7 @@ typedef struct Context_Extra {
// #include "oogabooga/examples/custom_shader.c"
// #include "oogabooga/examples/growing_array_example.c"
// #include "oogabooga/examples/input_example.c"
#include "oogabooga/examples/sprite_animation.c"
// #include "oogabooga/examples/sanity_tests.c"

View file

@ -8,7 +8,9 @@
This also gets rid of the weird window resize and reposition at startup.
- Renderer
- 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
- Input

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View 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;
}

View file

@ -319,6 +319,10 @@ Matrix4 m4_scalar(float32 scalar) {
return m;
}
inline Matrix4 m4_identity() {
return m4_scalar(1.0);
}
Matrix4 m4_make_translation(Vector3 translation) {
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;

View file

@ -297,10 +297,10 @@ win32_init_window() {
memset(&window, 0, sizeof(window));
window.title = STR("Unnamed Window");
window.width = 1280;
window.height = 720;
window.x = 0;
window.y = 0;
window.scaled_width = 1280;
window.scaled_height = 720;
window.x = 200;
window.y = 150;
window.should_close = false;
window._initialized = false;
window.clear_color.r = 0.392f;
@ -348,10 +348,10 @@ win32_init_window() {
UpdateWindow(window._os_handle);
ShowWindow(window._os_handle, SW_HIDE);
style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
style &= ~WS_EX_APPWINDOW; // Remove from taskbar
style |= WS_EX_TOOLWINDOW; // Make it a tool window
SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
//style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
//style &= ~WS_EX_APPWINDOW; // Remove from taskbar
//style |= WS_EX_TOOLWINDOW; // Make it a tool window
//SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
}
void
@ -1877,10 +1877,10 @@ void os_update() {
// Only show window after first call to os_update
if (!has_os_update_been_called_at_all) {
ShowWindow(window._os_handle, SW_SHOW);
DWORD style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
style &= ~WS_EX_TOOLWINDOW;
style |= WS_EX_APPWINDOW;
SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
//DWORD style = GetWindowLong(window._os_handle, GWL_EXSTYLE);
//style &= ~(WS_EX_TOOLWINDOW);
//style |= WS_EX_APPWINDOW;
//SetWindowLong(window._os_handle, GWL_EXSTYLE, style);
}
has_os_update_been_called_at_all = true;

View file

@ -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; }