aboutsummaryrefslogtreecommitdiff
path: root/src/camera
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2021-07-03 00:49:03 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-03-30 08:20:20 +0200
commit6b9f686913efc3725b2690033cd4f398e07076ba (patch)
treee9aa91a6b9f617d78123ebe7ad272fc42a60d306 /src/camera
parentc9e6ae44a9aeb89b3f48f3443d6baa80103f7445 (diff)
downloadjancity-6b9f686913efc3725b2690033cd4f398e07076ba.tar.gz
Add project source code
Diffstat (limited to 'src/camera')
-rw-r--r--src/camera/CMakeLists.txt3
-rw-r--r--src/camera/inc/camera.h42
-rw-r--r--src/camera/src/camera.c203
3 files changed, 248 insertions, 0 deletions
diff --git a/src/camera/CMakeLists.txt b/src/camera/CMakeLists.txt
new file mode 100644
index 0000000..fd029b0
--- /dev/null
+++ b/src/camera/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_library(camera "src/camera.c")
+target_include_directories(camera PUBLIC "inc")
+target_link_libraries(camera PUBLIC container pad util PRIVATE gfx terrain)
diff --git a/src/camera/inc/camera.h b/src/camera/inc/camera.h
new file mode 100644
index 0000000..1daebd2
--- /dev/null
+++ b/src/camera/inc/camera.h
@@ -0,0 +1,42 @@
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <pad.h>
+#include <util.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct camera
+{
+ int x, y, x_speed, y_speed;
+ unsigned int xt, yt;
+
+ struct cursor
+ {
+ unsigned int x, y, x_init, y_init;
+ enum
+ {
+ CURSOR_STATE_IDLE,
+ CURSOR_STATE_PRESSED
+ } state;
+ } cursor;
+};
+
+extern struct sprite cursor_sprite;
+
+void camera_update(struct camera *cam, const struct pad *p);
+bool camera_translate(const struct camera *cam, const struct util_rect *dim, short *x, short *y);
+void cursor_init(struct cursor *c);
+bool cursor_collision(const struct camera *cam, const struct util_rect *d);
+void cursor_pos(const struct camera *cam, unsigned long *x, unsigned long *y);
+int cursor_render(const struct cursor *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CAMERA_H */
diff --git a/src/camera/src/camera.c b/src/camera/src/camera.c
new file mode 100644
index 0000000..4b046e1
--- /dev/null
+++ b/src/camera/src/camera.c
@@ -0,0 +1,203 @@
+#include <camera.h>
+#include <gfx.h>
+#include <pad.h>
+#include <terrain.h>
+#include <util.h>
+#include <limits.h>
+#include <stdbool.h>
+
+struct sprite cursor_sprite;
+
+enum
+{
+ CURSOR_WIDTH = 20,
+ CURSOR_HEIGHT = 20
+};
+
+bool cursor_collision(const struct camera *const cam, const struct util_rect *const d)
+{
+ unsigned long x, y;
+
+ cursor_pos(cam, &x, &y);
+
+ const struct util_rect cd =
+ {
+ .x = x,
+ .y = y,
+ .w = CURSOR_WIDTH / 4,
+ .h = CURSOR_HEIGHT / 4
+ };
+
+ return util_collision(d, &cd);
+}
+
+void cursor_pos(const struct camera *const cam, unsigned long *const x,
+ unsigned long *const y)
+{
+ const struct cursor *const c = &cam->cursor;
+
+ *x = c->x - cam->x;
+ *y = c->y - cam->y;
+}
+
+static void cursor_update(struct camera *const cam, const struct pad *const p)
+{
+ struct cursor *const c = &cam->cursor;
+ enum {STEP = 4};
+
+ if (pad_pressed(p, PAD_KEY_LEFT)
+ && (c->x - STEP)
+ && (!cam->x || c->x != c->x_init))
+ c->x -= STEP;
+ else if (pad_pressed(p, PAD_KEY_RIGHT)
+ && (c->x + STEP < screen_w)
+ && (c->x != c->x_init || cam->x <= -MAP_X))
+ c->x += STEP;
+
+ if (pad_pressed(p, PAD_KEY_UP)
+ && (c->y - STEP)
+ && (c->y != c->y_init || !cam->y))
+ c->y -= STEP;
+ else if (pad_pressed(p, PAD_KEY_DOWN)
+ && (c->y + STEP < screen_h)
+ && (c->y != c->y_init || cam->y <= -MAP_Y))
+ c->y += STEP;
+
+ c->state = pad_pressed(p, PAD_KEY_A) || pad_pressed(p, PAD_KEY_B) ?
+ CURSOR_STATE_PRESSED: CURSOR_STATE_IDLE;
+}
+
+int cursor_render(const struct cursor *const c)
+{
+ struct sprite *const s = sprite_get();
+
+ if (!s || sprite_clone(&cursor_sprite, s))
+ return -1;
+
+ s->x = c->x;
+ s->y = c->y;
+ s->w = CURSOR_WIDTH;
+ s->h = CURSOR_HEIGHT;
+
+ switch (c->state)
+ {
+ case CURSOR_STATE_IDLE:
+ s->u += CURSOR_WIDTH;
+ break;
+
+ case CURSOR_STATE_PRESSED:
+ break;
+ }
+
+ sprite_sort(s);
+ return 0;
+}
+
+void cursor_init(struct cursor *const c)
+{
+ c->x = c->x_init = (screen_w / 2) - CURSOR_WIDTH;
+ c->y = c->y_init = (screen_h / 2) - CURSOR_HEIGHT;
+}
+
+static void update_speed(struct camera *const cam, const struct pad *const p)
+{
+ enum
+ {
+ MAX_SPEED = 10,
+ STEP = 1,
+ T_STEP = 3
+ };
+
+ const struct cursor *const c = &cam->cursor;
+
+ if (c->x == c->x_init
+ && (!cam->x_speed || ++cam->xt >= T_STEP))
+ {
+ if (pad_pressed(p, PAD_KEY_RIGHT))
+ {
+ if (cam->x_speed > 0)
+ cam->x_speed = -STEP;
+ else if (cam->x_speed - STEP >= -MAX_SPEED)
+ cam->x_speed -= STEP;
+ }
+ else if (pad_pressed(p, PAD_KEY_LEFT))
+ {
+ if (cam->x_speed < 0)
+ cam->x_speed = STEP;
+ else if (cam->x_speed + STEP <= MAX_SPEED)
+ cam->x_speed += STEP;
+ }
+ else
+ cam->x_speed = 0;
+
+ cam->xt = 0;
+ }
+ else if (c->x != c->x_init)
+ cam->x_speed = 0;
+
+ if (c->y == c->y_init
+ && (!cam->y_speed || ++cam->yt >= T_STEP))
+ {
+ if (pad_pressed(p, PAD_KEY_DOWN))
+ {
+ if (cam->y_speed > 0)
+ cam->y_speed = STEP;
+ else if (cam->y_speed - STEP >= -MAX_SPEED)
+ cam->y_speed -= STEP;
+ }
+ else if (pad_pressed(p, PAD_KEY_UP))
+ {
+ if (cam->y_speed < 0)
+ cam->y_speed = -STEP;
+ else if (cam->y_speed + STEP <= MAX_SPEED)
+ cam->y_speed += STEP;
+ }
+ else
+ cam->y_speed = 0;
+
+ cam->yt = 0;
+ }
+ else if (c->y != c->y_init)
+ cam->y_speed = 0;
+}
+
+static void update_pos(struct camera *const cam)
+{
+ const int x = cam->x + cam->x_speed;
+
+ cam->x = x;
+
+ if (cam->x > 0)
+ cam->x = 0;
+ else if (cam->x < -MAP_X)
+ cam->x = -MAP_X;
+
+ const int y = cam->y + cam->y_speed;
+
+ cam->y = y;
+
+ if (cam->y > 0)
+ cam->y = 0;
+ else if (cam->y < -MAP_Y)
+ cam->y = -MAP_Y;
+}
+
+void camera_update(struct camera *const cam, const struct pad *const p)
+{
+ cursor_update(cam, p);
+ update_speed(cam, p);
+ update_pos(cam);
+}
+
+bool camera_translate(const struct camera *const cam, const struct util_rect *const dim,
+ short *const x, short *const y)
+{
+ const long tx = dim->x + cam->x, ty = dim->y + cam->y;
+
+ if (!gfx_inside_drawenv(tx, ty, dim->w, dim->h))
+ return false;
+
+ *x = tx;
+ *y = ty;
+ return true;
+}