diff --git a/src/main.cpp b/src/main.cpp index 0059ed6..46ed1e0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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); } diff --git a/src/renderer_sdlgpu.c b/src/renderer_sdlgpu.c index 2301402..9971dc6 100644 --- a/src/renderer_sdlgpu.c +++ b/src/renderer_sdlgpu.c @@ -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); diff --git a/src/renderer_wgpu.c b/src/renderer_wgpu.c index b63988e..93c4511 100644 --- a/src/renderer_wgpu.c +++ b/src/renderer_wgpu.c @@ -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, + }, }, }, }, diff --git a/src/shaders/spirv/basic.spv b/src/shaders/spirv/basic.spv index 7ca8a50..b4ea3cd 100644 Binary files a/src/shaders/spirv/basic.spv and b/src/shaders/spirv/basic.spv differ diff --git a/src/shaders/src/basic.slang b/src/shaders/src/basic.slang index 9389277..f55ce24 100644 --- a/src/shaders/src/basic.slang +++ b/src/shaders/src/basic.slang @@ -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; } diff --git a/src/shaders/wgsl/basic.wgsl b/src/shaders/wgsl/basic.wgsl index 1291d0e..0f97f35 100644 --- a/src/shaders/wgsl/basic.wgsl +++ b/src/shaders/wgsl/basic.wgsl @@ -20,6 +20,7 @@ struct vertexInput_0 @location(0) pos_1 : vec3, @location(1) uv_1 : vec2, @location(2) world_pos_0 : vec2, + @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(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(_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((u32(_S1.sprite_selection_0>>(u32(16)))&((((u32(1)<>(u32(0)))&((((u32(1)<(0.25f); return output_0; }