Implement map dragging and zooming
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user