add basic animation
buildbot/windows Build done.
buildbot/linux Build done.

This commit is contained in:
Sven Balzer
2026-08-02 12:40:24 +02:00
parent 70fac5bd72
commit f72ca9def5
6 changed files with 53 additions and 23 deletions
+29 -16
View File
@@ -188,6 +188,7 @@ static Uint16 indices[] = {
struct Instance {
vec2 pos;
uint32_t sprite_selection;
};
static Instance player_instance = {{ 0.0f, 0.0f }};
@@ -205,16 +206,6 @@ struct Map {
static Map current_map;
struct Player {
i32vec2 position;
i32vec2 target_position;
bool is_moving;
vec2 visual_position;
};
static Player player;
struct alignas(16) PerFrame {
i32vec2 drag_start;
i32vec2 mouse;
@@ -233,6 +224,19 @@ typedef enum : Uint8 {
DIR_RIGHT,
} Direction;
struct Player {
i32vec2 position;
i32vec2 target_position;
Direction direction;
bool is_moving;
vec2 visual_position;
Uint64 animation_time;
};
static Player player;
typedef enum : Uint8 {
TILEKIND_ERROR = 0,
TILEKIND_NONE = 1,
@@ -905,7 +909,7 @@ static bool init_resources() {
return false;
}
player_texture = create_texture("decorations/strawberry.png");
player_texture = create_texture("characters/Basic Charakter Spritesheet.png");
if (!player_texture) {
log_error("Failed to create shader texture.");
return false;
@@ -1434,6 +1438,8 @@ static void update_state_game() {
const bool *keyboard_state = SDL_GetKeyboardState(NULL);
if (player.is_moving) {
player.animation_time += delta_time;
vec2 leftover_movement = vec2(player.target_position) - player.visual_position;
vec2 movement = clamp(min(vec2(0, 0), leftover_movement), normalize(leftover_movement) * (delta_t * character_speed * (keyboard_state[SDL_SCANCODE_LSHIFT] ? 2.0f : 1.0f)), max(vec2(0, 0), leftover_movement));
player.visual_position += movement;
@@ -1446,14 +1452,17 @@ static void update_state_game() {
if (!player.is_moving && (queued_movement || keyboard_state[SDL_SCANCODE_W] || keyboard_state[SDL_SCANCODE_A] || keyboard_state[SDL_SCANCODE_S] || keyboard_state[SDL_SCANCODE_D])) {
switch (queued_movement_direction) {
case DIR_UP: { player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, 1), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_LEFT: { player.target_position = clamp(ivec2(0, 0), player.position + ivec2(-1, 0), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_DOWN: { player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, -1), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_RIGHT: { player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 1, 0), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_UP: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, 1), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_LEFT: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2(-1, 0), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_DOWN: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, -1), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_RIGHT: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 1, 0), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
}
}
queued_movement = false;
if (!player.is_moving)
player.animation_time = 0;
if (!MIX_TrackPlaying(music_track)) {
MIX_SetTrackAudio(music_track, music_setting_off_piano);
MIX_PlayTrack(music_track, 0);
@@ -1467,7 +1476,11 @@ static void render_game() {
ZoneScopedN("update buffers");
{
ZoneScopedN("player_instance_buffer");
player_instance.pos = player.visual_position;
Uint64 variation_index = (player.animation_time / (100 * SDL_NS_PER_MS)) % 4;
player_instance.pos = player.visual_position;
player_instance.sprite_selection = variation_index << 16 | player.direction;
renderer_buffer_update(player_instance_buffer, 0, sizeof(player_instance), &player_instance);
}
+9 -3
View File
@@ -460,7 +460,7 @@ bool renderer_init(SDL_Window *window_) {
},
{
.slot = 1,
.pitch = 8,
.pitch = 12,
.input_rate = SDL_GPU_VERTEXINPUTRATE_INSTANCE,
.instance_step_rate = 0,
@@ -487,8 +487,14 @@ bool renderer_init(SDL_Window *window_) {
.format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
.offset = 0,
},
{
.location = 3,
.buffer_slot = 1,
.format = SDL_GPU_VERTEXELEMENTFORMAT_UINT,
.offset = 8,
},
},
.num_vertex_attributes = 3,
.num_vertex_attributes = 4,
},
.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
@@ -815,7 +821,7 @@ bool renderer_init(SDL_Window *window_) {
transfer_buffer = SDL_CreateGPUTransferBuffer(device, &(SDL_GPUTransferBufferCreateInfo){
.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
.size = 64 * 1024,
.size = 512 * 1024,
});
copy_command_buffer = SDL_AcquireGPUCommandBuffer(device);
+7 -2
View File
@@ -747,14 +747,19 @@ bool renderer_init(SDL_Window *window_) {
},
{
.stepMode = WGPUVertexStepMode_Instance,
.arrayStride = 8,
.attributeCount = 1,
.arrayStride = 12,
.attributeCount = 2,
.attributes = (WGPUVertexAttribute[]){
{
.format = WGPUVertexFormat_Float32x2,
.offset = 0,
.shaderLocation = 2,
},
{
.format = WGPUVertexFormat_Uint32,
.offset = 8,
.shaderLocation = 3,
},
},
},
},
Binary file not shown.
+6 -1
View File
@@ -10,6 +10,7 @@ struct VertexShaderInput {
// Per Instance
[vk::location(2)] float2 world_pos;
[vk::location(3)] uint sprite_selection;
};
struct VertexShaderOutput {
@@ -27,7 +28,11 @@ VertexShaderOutput main_vertex(VertexShaderInput input) {
var output: VertexShaderOutput;
output.pos = mul(float4(input.world_pos + input.pos.xy, 0, 1), view_projection_matrix);
output.uv = input.uv;
uint sprite_x = bitfieldExtract(input.sprite_selection, 16, 16);
uint sprite_y = bitfieldExtract(input.sprite_selection, 0, 16);
output.uv = (float2(sprite_x, sprite_y) + input.uv) * (1.0 / 4.0);
return output;
}
+2 -1
View File
@@ -20,6 +20,7 @@ struct vertexInput_0
@location(0) pos_1 : vec3<f32>,
@location(1) uv_1 : vec2<f32>,
@location(2) world_pos_0 : vec2<f32>,
@location(3) sprite_selection_0 : u32,
};
@vertex
@@ -27,7 +28,7 @@ fn main_vertex( _S1 : vertexInput_0, @builtin(vertex_index) vertex_index_0 : u32
{
var output_0 : VertexShaderOutput_0;
output_0.pos_0 = (((mat4x4<f32>(view_projection_matrix_0.data_0[i32(0)][i32(0)], view_projection_matrix_0.data_0[i32(1)][i32(0)], view_projection_matrix_0.data_0[i32(2)][i32(0)], view_projection_matrix_0.data_0[i32(3)][i32(0)], view_projection_matrix_0.data_0[i32(0)][i32(1)], view_projection_matrix_0.data_0[i32(1)][i32(1)], view_projection_matrix_0.data_0[i32(2)][i32(1)], view_projection_matrix_0.data_0[i32(3)][i32(1)], view_projection_matrix_0.data_0[i32(0)][i32(2)], view_projection_matrix_0.data_0[i32(1)][i32(2)], view_projection_matrix_0.data_0[i32(2)][i32(2)], view_projection_matrix_0.data_0[i32(3)][i32(2)], view_projection_matrix_0.data_0[i32(0)][i32(3)], view_projection_matrix_0.data_0[i32(1)][i32(3)], view_projection_matrix_0.data_0[i32(2)][i32(3)], view_projection_matrix_0.data_0[i32(3)][i32(3)])) * (vec4<f32>(_S1.world_pos_0 + _S1.pos_1.xy, 0.0f, 1.0f))));
output_0.uv_0 = _S1.uv_1;
output_0.uv_0 = (vec2<f32>(f32((u32(_S1.sprite_selection_0>>(u32(16)))&((((u32(1)<<u32(16))-u32(1)))))), f32((u32(_S1.sprite_selection_0>>(u32(0)))&((((u32(1)<<u32(16))-u32(1))))))) + _S1.uv_1) * vec2<f32>(0.25f);
return output_0;
}