Implement map dragging and zooming

This commit is contained in:
2025-09-25 09:57:27 +02:00
parent 295cbdb0a1
commit 22c14129c1
3 changed files with 88 additions and 2 deletions
+62
View File
@@ -83,6 +83,68 @@ SDL_AppEvent (void *appstate, SDL_Event *event)
return SDL_APP_SUCCESS;
}
/* TODO: implement an event manager so this isn't in the main client
file. */
static bool dragging = false;
static float drag_start_x = 0, drag_start_y = 0;
static float drag_origin_x = 0, drag_origin_y = 0;
if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN &&
event->button.button == SDL_BUTTON_LEFT)
{
dragging = true;
drag_start_x = event->button.x;
drag_start_y = event->button.y;
drag_origin_x = gfx_ctx->world_x_offset;
drag_origin_y = gfx_ctx->world_y_offset;
}
else if (event->type == SDL_EVENT_MOUSE_BUTTON_UP &&
event->button.button == SDL_BUTTON_LEFT)
{
dragging = false;
}
else if (event->type == SDL_EVENT_MOUSE_MOTION && dragging)
{
float dx = event->motion.x - drag_start_x;
float dy = event->motion.y - drag_start_y;
gfx_ctx->world_x_offset = drag_origin_x + dx;
gfx_ctx->world_y_offset = drag_origin_y + dy;
}
if (event->type == SDL_EVENT_MOUSE_WHEEL)
{
float zoom_factor = 1.0f + (event->wheel.y * 0.1f); /* ±10% per notch */
/* Zoom around the mouse cursor */
int win_w, win_h;
SDL_GetWindowSize (gfx_ctx->window, &win_w, &win_h);
float mouse_x = event->wheel.mouse_x;
float mouse_y = event->wheel.mouse_y;
float before_x = (mouse_x - gfx_ctx->world_x_offset) / gfx_ctx->world_scale;
float before_y = (mouse_y - gfx_ctx->world_y_offset) / gfx_ctx->world_scale;
gfx_ctx->world_scale *= zoom_factor;
if (gfx_ctx->world_scale < 0.1f)
{
gfx_ctx->world_scale = 0.1f; /* clamp */
}
if (gfx_ctx->world_scale > 10.0f)
{
gfx_ctx->world_scale = 10.0f;
}
float after_x = before_x * gfx_ctx->world_scale;
float after_y = before_y * gfx_ctx->world_scale;
gfx_ctx->world_x_offset = mouse_x - after_x;
gfx_ctx->world_y_offset = mouse_y - after_y;
}
return SDL_APP_CONTINUE;
}
+24 -2
View File
@@ -42,6 +42,8 @@ GfxContext_new ()
SDL_GetError ());
}
GfxContext_reset (self);
return self;
}
@@ -53,12 +55,30 @@ GfxContext_render (GfxContext *self)
if (self->world_texture)
{
SDL_RenderTexture (self->renderer, self->world_texture, NULL, NULL);
float tex_w, tex_h;
SDL_GetTextureSize (self->world_texture, &tex_w, &tex_h);
SDL_FRect dst = {
.x = self->world_x_offset,
.y = self->world_y_offset,
.w = tex_w * self->world_scale,
.h = tex_h * self->world_scale
};
SDL_RenderTexture (self->renderer, self->world_texture, NULL, &dst);
}
SDL_RenderPresent (self->renderer);
}
void
GfxContext_reset (GfxContext *self)
{
self->world_scale = 1.0;
self->world_x_offset = 0.0;
self->world_y_offset = 0.0;
}
void
GfxContext_free (GfxContext *self)
{
@@ -99,7 +119,9 @@ GfxContext_cache_World (GfxContext *self, World *world)
g_array_index (world->tiles, MapTile *, y * world->width + x);
if (!mt)
continue;
{
continue;
}
switch (mt->terrain_type)
{
+2
View File
@@ -38,10 +38,12 @@ typedef struct GfxContext
and it could be done
concurrently. */
float world_scale, world_x_offset, world_y_offset;
} GfxContext;
GfxContext *GfxContext_new ();
void GfxContext_render (GfxContext * self);
void GfxContext_reset (GfxContext *self);
void GfxContext_free (GfxContext * self);
void GfxContext_cache_World (GfxContext * self, World * world);