add animations #28

Merged
odweta merged 3 commits from experiment/animations into dev 2026-10-10 13:33:35 +02:00
14 changed files with 176 additions and 38 deletions
Showing only changes of commit ea1e99f022 - Show all commits
+11 -2
View File
@@ -4,13 +4,22 @@
#include <stdbool.h>
#include <stdint.h>
typedef enum {
BASE,
OVERDRAW
} framebuffer_e;
typedef struct {
SDL_Event event;
bool is_running;
bool framebuffer_dirty;
bool framebuffer_base_dirty;
bool framebuffer_overdraw_dirty;
SDL_Rect dirty_rect;
uint16_t width, height;
uint32_t *framebuffer;
// base layer ~ layer 0
uint32_t *framebuffer_base;
// layer on top of that ~ layer 1
uint32_t *framebuffer_overdraw;
} game_state_t;
extern game_state_t *game_state;
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
/**
* animate a rectangle's position changing over time
* => x0 -> x1, y0 -> y1, all else stays the same
*/
void
anim_rect_pos(
uint32_t x0,
uint32_t y0,
uint32_t x1,
uint32_t y1,
uint32_t w,
uint32_t h,
uint32_t color
);
+4
View File
@@ -1,9 +1,12 @@
#pragma once
#include <dangerzone/engine.h>
#include <stdint.h>
void
put_pixel(
framebuffer_e framebuffer,
unsigned int x,
unsigned int y,
uint32_t color
@@ -11,5 +14,6 @@ put_pixel(
void
clear_framebuffer(
framebuffer_e framebuffer,
uint32_t color
);
+4
View File
@@ -1,9 +1,12 @@
#pragma once
#include <dangerzone/engine.h>
#include <stdint.h>
void
put_rect(
framebuffer_e framebuffer,
uint32_t x,
uint32_t y,
uint32_t w,
@@ -11,6 +14,7 @@ put_rect(
uint32_t color
);
// TODO: remove, deprecated, you can use put_rect for the same thing
void
clear_rect(int x, int y, int w, int h, uint32_t color);
+4
View File
@@ -1,9 +1,12 @@
#pragma once
#include <dangerzone/engine.h>
#include <stdint.h>
void
put_char(
framebuffer_e framebuffer,
char c,
uint32_t x,
uint32_t y,
@@ -14,6 +17,7 @@ put_char(
void
put_string(
framebuffer_e framebuffer,
const char *text,
uint32_t x,
uint32_t y,
+41 -9
View File
@@ -42,9 +42,15 @@ mark_dirty_rect(int x, int y, int w, int h)
.h = h
};
if (!game_state->framebuffer_dirty) {
if (!game_state->framebuffer_base_dirty) {
game_state->dirty_rect = rect;
game_state->framebuffer_dirty = true;
game_state->framebuffer_base_dirty = true;
return;
}
if (!game_state->framebuffer_overdraw_dirty) {
game_state->dirty_rect = rect;
game_state->framebuffer_overdraw_dirty = true;
return;
}
@@ -83,9 +89,24 @@ mark_dirty_rect(int x, int y, int w, int h)
}
bool
upload_dirty_texture(void)
{
if (!game_state->framebuffer_dirty) {
upload_dirty_texture(
framebuffer_e framebuffer
) {
uint32_t *current_framebuffer;
switch (framebuffer) {
case BASE:
current_framebuffer = game_state->framebuffer_base;
break;
case OVERDRAW:
current_framebuffer = game_state->framebuffer_overdraw;
break;
default:
break;
}
if (!game_state->framebuffer_base_dirty &&
!game_state->framebuffer_overdraw_dirty
) {
return true;
}
@@ -117,7 +138,7 @@ upload_dirty_texture(void)
(size_t)rect.w * sizeof(uint32_t);
const uint8_t *source =
(const uint8_t *)game_state->framebuffer +
(const uint8_t *)current_framebuffer +
(size_t)rect.y * source_pitch +
(size_t)rect.x * sizeof(uint32_t);
@@ -134,7 +155,16 @@ upload_dirty_texture(void)
SDL_UnlockTexture(texture);
game_state->framebuffer_dirty = false;
switch (framebuffer) {
case BASE:
game_state->framebuffer_base_dirty = false;
break;
case OVERDRAW:
game_state->framebuffer_overdraw_dirty = false;
break;
default:
break;
}
return true;
}
@@ -152,7 +182,8 @@ engine_start() {
internal_state->engine_update_framebuffer();
// update the texture with the modified framebuffer
upload_dirty_texture();
upload_dirty_texture(BASE);
upload_dirty_texture(OVERDRAW);
SDL_RenderClear(
internal_state->sdl_state->renderer
@@ -174,6 +205,7 @@ void
engine_stop() {
engine_sdl_destroy(internal_state->sdl_state);
free(internal_state);
free(game_state->framebuffer);
free(game_state->framebuffer_base);
free(game_state->framebuffer_overdraw);
free(game_state);
}
+15 -4
View File
@@ -160,14 +160,23 @@ engine_init(
return RCODE_FAILURE;
}
game_state->framebuffer = (uint32_t *)
game_state->framebuffer_base = (uint32_t *)
malloc(sizeof(uint32_t) * window_width * window_height);
if (game_state->framebuffer == NULL) {
if (game_state->framebuffer_base == NULL) {
free(internal_state);
free(game_state);
return RCODE_FAILURE;
}
game_state->framebuffer_overdraw = (uint32_t *)
malloc(sizeof(uint32_t) * window_width * window_height);
if (game_state->framebuffer_overdraw == NULL) {
free(internal_state);
free(game_state->framebuffer_base);
free(game_state);
return RCODE_FAILURE;
}
internal_state->engine_poll_events
= engine_poll_events;
@@ -181,13 +190,15 @@ engine_init(
);
if (internal_state->sdl_state == NULL) {
free(internal_state);
free(game_state->framebuffer);
free(game_state->framebuffer_base);
free(game_state->framebuffer_overdraw);
free(game_state);
return RCODE_FAILURE;
}
game_state->is_running = true;
game_state->framebuffer_dirty = true;
game_state->framebuffer_base_dirty = true;
game_state->framebuffer_overdraw_dirty = true;
game_state->dirty_rect = (SDL_Rect) {
.x = 0,
.y = 0,
+22
View File
@@ -0,0 +1,22 @@
#include <dangerzone/render/anim.h>
void
anim_rect_pos(
uint32_t x0,
uint32_t y0,
uint32_t x1,
uint32_t y1,
uint32_t w,
uint32_t h,
uint32_t color
) {
// TODO: I THINK I NEED LAYERED BUFFERS
// one step is one pixel
uint32_t stepsx = x1 - x0;
uint32_t stepsy = y1 - y0;
/**
* 1. get the row / column in the direction of the movement
*/
}
+25 -2
View File
@@ -2,16 +2,36 @@
#include <dangerzone/render/misc.h>
#include <dangerzone/render/rect.h>
#include "internal/engine_internal.h"
#include "internal/util/error.h"
#include <stdint.h>
// helper function to return the correct pointer to a framebuffer for drawing selection
uint32_t*
get_framebuffer(
framebuffer_e framebuffer
) {
switch (framebuffer) {
case BASE:
return game_state->framebuffer_base;
case OVERDRAW:
return game_state->framebuffer_overdraw;
default:
return game_state->framebuffer_base;
}
}
// alter a pixel at an imaginary x & y coordinates
void
put_pixel(
framebuffer_e framebuffer,
unsigned int x,
unsigned int y,
uint32_t color
) {
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
uint16_t w = game_state->width;
uint16_t h = game_state->height;
@@ -21,7 +41,7 @@ put_pixel(
"at x = %d, y = %d", x, y
);
} else {
game_state->framebuffer[game_state->width * y + x]
current_framebuffer[game_state->width * y + x]
= color;
mark_dirty_rect(x, y, 1, 1);
@@ -31,12 +51,15 @@ put_pixel(
// fill the entire framebuffer with a given color
void
clear_framebuffer(
framebuffer_e framebuffer,
uint32_t color
) {
uint32_t *current_framebuffer = get_framebuffer(framebuffer);
for (size_t i = 0;
i < (size_t)game_state->width * game_state->height;
++i) {
game_state->framebuffer[i] = color;
current_framebuffer[i] = color;
}
mark_dirty_rect(
+4 -2
View File
@@ -10,6 +10,7 @@
*/
void
put_rect(
framebuffer_e framebuffer,
uint32_t x,
uint32_t y,
uint32_t w,
@@ -18,12 +19,13 @@ put_rect(
) {
for (int i = x; i < x + w; i++) {
for (int j = y; j < y + h; j++) {
put_pixel(i, j, color);
put_pixel(framebuffer, i, j, color);
}
}
mark_dirty_rect(x, y, w, h);
}
// TODO: remove, see rect.h
void
clear_rect(int x, int y, int w, int h, uint32_t color)
{
@@ -33,7 +35,7 @@ clear_rect(int x, int y, int w, int h, uint32_t color)
px < game_state->width &&
py >= 0 &&
py < game_state->height) {
game_state->framebuffer[
game_state->framebuffer_base[
py * game_state->width + px
] = color;
}
+4 -1
View File
@@ -81,6 +81,7 @@ static const uint8_t font[128][FONT_ROWS] = {
*/
void
put_char(
framebuffer_e framebuffer,
char c,
uint32_t x,
uint32_t y,
@@ -107,6 +108,7 @@ put_char(
? fg_color : bg_color;
put_rect(
framebuffer,
x + col * size,
y + row * size,
size,
@@ -121,6 +123,7 @@ put_char(
void
put_string(
framebuffer_e framebuffer,
const char *text,
uint32_t x,
uint32_t y,
@@ -137,7 +140,7 @@ put_string(
x = start_x;
y += (FONT_ROWS + line_spacing) * size;
} else {
put_char(*text, x, y, size, fg_color, bg_color);
put_char(framebuffer, *text, x, y, size, fg_color, bg_color);
x += (FONT_COLS + spacing) * size;
}
+6 -4
View File
@@ -358,7 +358,8 @@ client_update_framebuffer()
// 20, 20, 2, 2, 3, 0x000000, 0xFFFF00
// );
clear_framebuffer(0x000000);
// FIXME: why?
//clear_framebuffer(BASE, 0x000000);
uint32_t tile_size = game_state->width / SIZE;
uint8_t border_width = 10;
@@ -373,7 +374,8 @@ client_update_framebuffer()
uint32_t w = tile_size - border_width;
uint32_t h = tile_size - border_width;
uint32_t background_color = colors(game.area[j][i]);
put_rect(x, y, w, h, background_color);
put_rect(BASE, x, y, w, h, 0xFFFFFF);
put_rect(OVERDRAW, x, y, w, h, background_color);
// number in foreground
uint32_t foreground_color = 0x000000;
@@ -389,7 +391,7 @@ client_update_framebuffer()
uint32_t n_rev = numrev(n);
uint32_t digit_offset = 1;
if (n != 0) {
put_string(n_str, x + border_width, y + border_width, font_size, digit_offset, 12, foreground_color, background_color);
put_string(OVERDRAW, n_str, x + border_width, y + border_width, font_size, digit_offset, 12, foreground_color, background_color);
}
}
}
@@ -402,7 +404,7 @@ client_update_framebuffer()
alloced = true;
sprintf(score_text, "score: %6d", game.score);
put_string(score_text, border_width / 2, tile_size * SIZE + border_width / 2, 6, 1, 12, 0xFFFFFF, 0x000000);
put_string(OVERDRAW, score_text, border_width / 2, tile_size * SIZE + border_width / 2, 6, 1, 12, 0xFFFFFF, 0x000000);
if (alloced) {
free(n_str);
+4 -4
View File
@@ -1,8 +1,8 @@
add_executable(game_snake snake.c)
target_link_libraries(game_snake PRIVATE dangerzone_engine)
#add_executable(game_snake snake.c)
#target_link_libraries(game_snake PRIVATE dangerzone_engine)
add_executable(game_2048 2048.c)
target_link_libraries(game_2048 PRIVATE dangerzone_engine)
add_executable(game_window window.c)
target_link_libraries(game_window PRIVATE dangerzone_engine)
#add_executable(game_window window.c)
#target_link_libraries(game_window PRIVATE dangerzone_engine)
+6 -2
View File
@@ -1,9 +1,9 @@
#pragma once
#include <dangerzone/engine.h>
#include <SDL3/SDL.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define WINDOW_NAME_MAX_LENGTH 128
@@ -47,3 +47,7 @@ engine_sdl_destroy(
engine_sdl_state_t *state
);
uint32_t*
get_framebuffer(
framebuffer_e framebuffer
);