commit 4ca59d402d47862140956aa39b48f291fe63a56d
parent 52c7683e46472bb86513218491fa42f265a08628
Author: amin <dev@aminmesbah.com>
Date: Sat, 5 Aug 2017 10:23:29 +0000
Add ability to zoom in and out.
FossilOrigin-Name: c927846f6865abf6d47a087a4bf579618e06caa3cacb9811b9b9dc0603e78322
Diffstat:
4 files changed, 106 insertions(+), 75 deletions(-)
diff --git a/README.md b/README.md
@@ -11,8 +11,11 @@ efficiently calculate the forces acting on each star.
### Keyboard Shortcuts
- `WASD` or `HJKL`: Pan.
-- `Arrow Keys`: Slow Pan.
-- `Home`: Center View.
+- `Arrow Keys`: Slow pan.
+- `=`: Zoom in.
+- `-`: Zoom out.
+- `0`: Zoom standard.
+- `Home`: Return to original view.
- `b`: Toggle bounding box rendering.
- `f`: Toggle brute-force mode. Stars turn blue when this mode is active, and
gravitational attraction is calculated for every single pair of stars. The
diff --git a/src/platform_sdl.c b/src/platform_sdl.c
@@ -210,40 +210,53 @@ int main(int argc, char *argv[])
// TODO: move this to a function
if (keystate[SDL_SCANCODE_A] || keystate[SDL_SCANCODE_H])
{
- sim_state.view.dx += 5;
+ sim_state.view.dx += 5 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_D] || keystate[SDL_SCANCODE_L])
{
- sim_state.view.dx -= 5;
+ sim_state.view.dx -= 5 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_W] || keystate[SDL_SCANCODE_K])
{
- sim_state.view.dy += 5;
+ sim_state.view.dy += 5 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_S] || keystate[SDL_SCANCODE_J])
{
- sim_state.view.dy -= 5;
+ sim_state.view.dy -= 5 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_LEFT])
{
- sim_state.view.dx++;
+ sim_state.view.dx += 1 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_RIGHT])
{
- sim_state.view.dx--;
+ sim_state.view.dx -= 1 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_UP])
{
- sim_state.view.dy++;
+ sim_state.view.dy += 1 / sim_state.view.zoom;
}
if (keystate[SDL_SCANCODE_DOWN])
{
- sim_state.view.dy--;
+ sim_state.view.dy -= 1 / sim_state.view.zoom;
+ }
+ if (keystate[SDL_SCANCODE_EQUALS])
+ {
+ sim_state.view.zoom *= 1.01;
+ }
+ if (keystate[SDL_SCANCODE_MINUS])
+ {
+ sim_state.view.zoom *= 0.99;
+ }
+ if (keystate[SDL_SCANCODE_0])
+ {
+ sim_state.view.zoom = 1;
}
if (keystate[SDL_SCANCODE_HOME])
{
sim_state.view.dx = 0;
sim_state.view.dy = 0;
+ sim_state.view.zoom = 1;
}
struct OffscreenBuffer buffer;
diff --git a/src/star_garden.c b/src/star_garden.c
@@ -26,6 +26,7 @@ void sim_init(struct SimState *sim_state, int field_width, int field_height)
sim_state->view.dx = 0;
sim_state->view.dy = 0;
+ sim_state->view.zoom = 1;
float min_x = field_width / 2;
float max_x = field_width / 2;
@@ -181,69 +182,44 @@ void sim_render(struct OffscreenBuffer *buffer, float dt, struct SimState *sim_s
return;
}
- float dx = sim_state->view.dx;
- float dy = sim_state->view.dy;
int num_stars = sim_state->num_stars;
struct Star *stars = sim_state->stars;
struct QuadTree *qt = sim_state->qt;
- //printf("%f\n", dt);
- if (BRUTE_FORCE)
+
+ float dx = sim_state->view.dx;
+ float dy = sim_state->view.dy;
+ float zoom = sim_state->view.zoom;
+
+ for (int i = 0; i < num_stars; ++i)
{
- for (int i = 0; i < num_stars; ++i)
+ uint32_t color;
+ if (BRUTE_FORCE)
{
- sim_set_pixel(
- buffer,
- (stars[i].x + (sinf(stars[i].angle) * stars[i].speed) * dt) + dx,
- (stars[i].y - (cosf(stars[i].angle) * stars[i].speed) * dt) + dy,
- COLOR_CYAN);
+ color = COLOR_CYAN;
}
- }
- else
- {
- for (int i = 0; i < num_stars; ++i)
+ else
{
- sim_set_pixel(
- buffer,
- (stars[i].x + (sinf(stars[i].angle) * stars[i].speed) * dt) + dx,
- (stars[i].y - (cosf(stars[i].angle) * stars[i].speed) * dt) + dy,
- stars[i].color);
+ color = stars[i].color;
}
+ sim_set_pixel(
+ buffer,
+ sim_calc_render_offset(zoom, dx, stars[i].x + (sinf(stars[i].angle) * stars[i].speed) * dt, buffer->width/2),
+ sim_calc_render_offset(zoom, dy, stars[i].y - (cosf(stars[i].angle) * stars[i].speed) * dt, buffer->height/2),
+ color);
}
if (RENDER_GRID)
{
- sim_grid_render(buffer, qt->root, COLOR_GREEN, dx, dy);
+ sim_grid_render(buffer, qt->root, COLOR_GREEN, &sim_state->view);
}
if (RENDER_BOUNDING_BOX)
{
- sim_bounding_box_render(buffer, &sim_state->bounding_box, COLOR_RED, dx, dy);
- }
-}
-
-
-void sim_set_pixel(struct OffscreenBuffer *buffer, uint32_t x, uint32_t y, uint32_t color)
-{
- if (!buffer)
- {
- // TODO: handle invalid pointer error
- return;
- }
-
- /* Origin is (0, 0) on the upper left.
- * To go one pixel right, increment by 32 bits.
- * To go one pixel down, increment by (buffer.width * 32) bits.
- */
- if (x < buffer->width && y < buffer->height)
- {
- uint8_t *pixel_pos = (uint8_t *)buffer->memory;
- pixel_pos += ((BYTES_PER_PIXEL*x) + (buffer->pitch * y));
- uint32_t *pixel = (uint32_t *)pixel_pos;
- *pixel = color;
+ sim_bounding_box_render(buffer, &sim_state->bounding_box, COLOR_RED, &sim_state->view);
}
}
-void sim_grid_render(struct OffscreenBuffer *buffer, struct QuadTreeNode *node, uint32_t color, float dx, float dy)
+void sim_grid_render(struct OffscreenBuffer *buffer, struct QuadTreeNode *node, uint32_t color, struct SimView *view)
{
if (!buffer)
{
@@ -257,25 +233,33 @@ void sim_grid_render(struct OffscreenBuffer *buffer, struct QuadTreeNode *node,
x <= (node->cell->center_x + node->cell->distance_x);
++x)
{
- sim_set_pixel(buffer, x + dx, node->cell->center_y + dy, color);
+ sim_set_pixel(
+ buffer,
+ sim_calc_render_offset(view->zoom, view->dx, x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, node->cell->center_y, buffer->height/2),
+ color);
}
for (int y = (node->cell->center_y - node->cell->distance_y);
y <= (node->cell->center_y + node->cell->distance_y);
++y)
{
- sim_set_pixel(buffer, node->cell->center_x + dx, y + dy, color);
+ sim_set_pixel(
+ buffer,
+ sim_calc_render_offset(view->zoom, view->dx, node->cell->center_x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, y, buffer->height/2),
+ color);
}
- sim_grid_render(buffer, node->ne, color, dx, dy);
- sim_grid_render(buffer, node->nw, color, dx, dy);
- sim_grid_render(buffer, node->sw, color, dx, dy);
- sim_grid_render(buffer, node->se, color, dx, dy);
+ sim_grid_render(buffer, node->ne, color, view);
+ sim_grid_render(buffer, node->nw, color, view);
+ sim_grid_render(buffer, node->sw, color, view);
+ sim_grid_render(buffer, node->se, color, view);
}
}
-void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *bounding_box, uint32_t color, float dx, float dy)
+void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *bounding_box, uint32_t color, struct SimView *view)
{
if (!buffer)
{
@@ -291,8 +275,9 @@ void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *b
x++)
{
sim_set_pixel(
- buffer, x + dx,
- bounding_box->center_y + dy,
+ buffer,
+ sim_calc_render_offset(view->zoom, view->dx, x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, bounding_box->center_y, buffer->height/2),
color);
}
for (int y = bounding_box->center_y - reticle_radius;
@@ -301,8 +286,8 @@ void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *b
{
sim_set_pixel(
buffer,
- bounding_box->center_x + dx,
- y + dy,
+ sim_calc_render_offset(view->zoom, view->dx, bounding_box->center_x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, y, buffer->height/2),
color);
}
@@ -315,13 +300,13 @@ void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *b
{
sim_set_pixel(
buffer,
- x + dx,
- bounding_box->center_y - half_length_y + dy,
+ sim_calc_render_offset(view->zoom, view->dx, x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, bounding_box->center_y - half_length_y, buffer->height/2),
color);
sim_set_pixel(
buffer,
- x + dx,
- bounding_box->center_y + half_length_y + dy,
+ sim_calc_render_offset(view->zoom, view->dx, x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, bounding_box->center_y + half_length_y, buffer->height/2),
color);
}
@@ -331,19 +316,47 @@ void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *b
{
sim_set_pixel(
buffer,
- bounding_box->center_x - half_length_x + dx,
- y + dy,
+ sim_calc_render_offset(view->zoom, view->dx, bounding_box->center_x - half_length_x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, y, buffer->height/2),
color);
sim_set_pixel(
buffer,
- bounding_box->center_x + half_length_x + dx,
- y + dy,
+ sim_calc_render_offset(view->zoom, view->dx, bounding_box->center_x + half_length_x, buffer->width/2),
+ sim_calc_render_offset(view->zoom, view->dy, y, buffer->height/2),
color);
}
}
}
+float sim_calc_render_offset(float zoom, float delta, float pos, float center)
+{
+ return ((1 - zoom) * center) + (pos + delta) * zoom;
+}
+
+
+void sim_set_pixel(struct OffscreenBuffer *buffer, uint32_t x, uint32_t y, uint32_t color)
+{
+ if (!buffer)
+ {
+ // TODO: handle invalid pointer error
+ return;
+ }
+
+ /* Origin is (0, 0) on the upper left.
+ * To go one pixel right, increment by 32 bits.
+ * To go one pixel down, increment by (buffer.width * 32) bits.
+ */
+ if (x < buffer->width && y < buffer->height)
+ {
+ uint8_t *pixel_pos = (uint8_t *)buffer->memory;
+ pixel_pos += ((BYTES_PER_PIXEL*x) + (buffer->pitch * y));
+ uint32_t *pixel = (uint32_t *)pixel_pos;
+ *pixel = color;
+ }
+}
+
+
void sim_cleanup(struct SimState *sim_state)
{
if (!sim_state)
diff --git a/src/star_garden.h b/src/star_garden.h
@@ -66,6 +66,7 @@ struct SimView
{
float dx;
float dy;
+ float zoom;
};
struct SimState
@@ -90,9 +91,10 @@ void sim_init(struct SimState *sim_state, int field_width, int field_height);
void sim_update(struct SimState *sim_state, int field_width, int field_height);
void sim_bounding_box_update(struct SimBounds *bounds, float min_x, float min_y, float max_x, float max_y);
void sim_render(struct OffscreenBuffer *buffer, float dt, struct SimState *sim_state);
+void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *bounding_box, uint32_t color, struct SimView *view);
+void sim_grid_render(struct OffscreenBuffer *buffer, struct QuadTreeNode *node, uint32_t color, struct SimView *view);
+float sim_calc_render_offset(float zoom, float delta, float pos, float center);
void sim_set_pixel(struct OffscreenBuffer *buffer, uint32_t x, uint32_t y, uint32_t color);
-void sim_bounding_box_render(struct OffscreenBuffer *buffer, struct SimBounds *bounding_box, uint32_t color, float dx, float dy);
-void sim_grid_render(struct OffscreenBuffer *buffer, struct QuadTreeNode *node, uint32_t color, float dx, float dy);
void sim_cleanup(struct SimState *sim_state);
#define STAR_GARDEN_H