diff options
| -rw-r--r-- | CMakeLists.txt | 1 | ||||
| -rw-r--r-- | demos/isomap/isomap.c | 28 | ||||
| -rw-r--r-- | include/isogfx/isogfx.h | 3 | ||||
| -rw-r--r-- | src/isogfx.c | 24 |
4 files changed, 48 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 498adc8..72429c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -17,6 +17,7 @@ target_include_directories(isogfx PUBLIC | |||
| 17 | 17 | ||
| 18 | target_link_libraries(isogfx PUBLIC | 18 | target_link_libraries(isogfx PUBLIC |
| 19 | filesystem | 19 | filesystem |
| 20 | math | ||
| 20 | memstack) | 21 | memstack) |
| 21 | 22 | ||
| 22 | target_compile_options(isogfx PRIVATE -Wall -Wextra -Wpedantic) | 23 | target_compile_options(isogfx PRIVATE -Wall -Wextra -Wpedantic) |
diff --git a/demos/isomap/isomap.c b/demos/isomap/isomap.c index efae7fd..a940535 100644 --- a/demos/isomap/isomap.c +++ b/demos/isomap/isomap.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #include <isogfx/isogfx.h> | 2 | #include <isogfx/isogfx.h> |
| 3 | 3 | ||
| 4 | #include <gfx/app.h> | 4 | #include <gfx/app.h> |
| 5 | #include <math/vec2.h> | ||
| 5 | 6 | ||
| 6 | #include <assert.h> | 7 | #include <assert.h> |
| 7 | #include <stdbool.h> | 8 | #include <stdbool.h> |
| @@ -15,6 +16,8 @@ static const int MAX_FPS = 60; | |||
| 15 | static const int SCREEN_WIDTH = 704; | 16 | static const int SCREEN_WIDTH = 704; |
| 16 | static const int SCREEN_HEIGHT = 480; | 17 | static const int SCREEN_HEIGHT = 480; |
| 17 | 18 | ||
| 19 | static const R CAMERA_SPEED = 400; | ||
| 20 | |||
| 18 | #define MEMORY_SIZE (2 * 1024 * 1024) | 21 | #define MEMORY_SIZE (2 * 1024 * 1024) |
| 19 | uint8_t MEMORY[MEMORY_SIZE]; | 22 | uint8_t MEMORY[MEMORY_SIZE]; |
| 20 | 23 | ||
| @@ -23,6 +26,7 @@ typedef struct GfxAppState { | |||
| 23 | IsoGfx* iso; | 26 | IsoGfx* iso; |
| 24 | int xpick; | 27 | int xpick; |
| 25 | int ypick; | 28 | int ypick; |
| 29 | vec2 camera; | ||
| 26 | SpriteSheet stag_sheet; | 30 | SpriteSheet stag_sheet; |
| 27 | Sprite stag; | 31 | Sprite stag; |
| 28 | } GfxAppState; | 32 | } GfxAppState; |
| @@ -67,11 +71,33 @@ static void shutdown(GfxAppState* state) { | |||
| 67 | // | 71 | // |
| 68 | } | 72 | } |
| 69 | 73 | ||
| 74 | static vec2 get_camera_movement(R dt) { | ||
| 75 | vec2 offset = {0}; | ||
| 76 | if (gfx_app_is_key_pressed(KeyA)) { | ||
| 77 | offset.x -= 1; | ||
| 78 | } | ||
| 79 | if (gfx_app_is_key_pressed(KeyD)) { | ||
| 80 | offset.x += 1; | ||
| 81 | } | ||
| 82 | if (gfx_app_is_key_pressed(KeyW)) { | ||
| 83 | offset.y -= 1; | ||
| 84 | } | ||
| 85 | if (gfx_app_is_key_pressed(KeyS)) { | ||
| 86 | offset.y += 1; | ||
| 87 | } | ||
| 88 | if ((offset.x != 0) || (offset.y != 0)) { | ||
| 89 | offset = vec2_scale(vec2_normalize(offset), dt * CAMERA_SPEED); | ||
| 90 | } | ||
| 91 | return offset; | ||
| 92 | } | ||
| 93 | |||
| 70 | static void update(GfxAppState* state, double t, double dt) { | 94 | static void update(GfxAppState* state, double t, double dt) { |
| 71 | assert(state); | 95 | assert(state); |
| 72 | (void)dt; | 96 | |
| 97 | state->camera = vec2_add(state->camera, get_camera_movement((R)dt)); | ||
| 73 | 98 | ||
| 74 | IsoGfx* iso = state->iso; | 99 | IsoGfx* iso = state->iso; |
| 100 | isogfx_set_camera(iso, (int)state->camera.x, (int)state->camera.y); | ||
| 75 | isogfx_update(iso, t); | 101 | isogfx_update(iso, t); |
| 76 | } | 102 | } |
| 77 | 103 | ||
diff --git a/include/isogfx/isogfx.h b/include/isogfx/isogfx.h index 93c6d4e..e901231 100644 --- a/include/isogfx/isogfx.h +++ b/include/isogfx/isogfx.h | |||
| @@ -102,6 +102,9 @@ void isogfx_set_sprite_animation(IsoGfx*, Sprite, int animation); | |||
| 102 | /// Currently this updates the sprite animations. | 102 | /// Currently this updates the sprite animations. |
| 103 | void isogfx_update(IsoGfx*, double t); | 103 | void isogfx_update(IsoGfx*, double t); |
| 104 | 104 | ||
| 105 | /// Set the camera. | ||
| 106 | void isogfx_set_camera(IsoGfx*, int x, int y); | ||
| 107 | |||
| 105 | /// Render the world. | 108 | /// Render the world. |
| 106 | void isogfx_render(IsoGfx*); | 109 | void isogfx_render(IsoGfx*); |
| 107 | 110 | ||
diff --git a/src/isogfx.c b/src/isogfx.c index 0aaeb9d..5d23ae4 100644 --- a/src/isogfx.c +++ b/src/isogfx.c | |||
| @@ -55,6 +55,7 @@ typedef struct SpriteInstance { | |||
| 55 | typedef struct IsoGfx { | 55 | typedef struct IsoGfx { |
| 56 | Screen screen; | 56 | Screen screen; |
| 57 | CoordSystem iso_space; | 57 | CoordSystem iso_space; |
| 58 | ivec2 camera; | ||
| 58 | double last_animation_time; | 59 | double last_animation_time; |
| 59 | Tile next_tile; // For procedurally-generated tiles. | 60 | Tile next_tile; // For procedurally-generated tiles. |
| 60 | Tm_Map* map; | 61 | Tm_Map* map; |
| @@ -76,6 +77,8 @@ static inline ivec2 ivec2_scale(ivec2 a, int s) { | |||
| 76 | return (ivec2){.x = a.x * s, .y = a.y * s}; | 77 | return (ivec2){.x = a.x * s, .y = a.y * s}; |
| 77 | } | 78 | } |
| 78 | 79 | ||
| 80 | static inline ivec2 ivec2_neg(ivec2 a) { return (ivec2){.x = -a.x, .y = -a.y}; } | ||
| 81 | |||
| 79 | static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) { | 82 | static inline ivec2 iso2cart(ivec2 iso, int s, int t, int w) { |
| 80 | return (ivec2){.x = (iso.x - iso.y) * (s / 2) + (w / 2), | 83 | return (ivec2){.x = (iso.x - iso.y) * (s / 2) + (w / 2), |
| 81 | .y = (iso.x + iso.y) * (t / 2)}; | 84 | .y = (iso.x + iso.y) * (t / 2)}; |
| @@ -490,13 +493,13 @@ void isogfx_update(IsoGfx* iso, double t) { | |||
| 490 | /// Get the screen position of the top diamond-corner of the tile at world | 493 | /// Get the screen position of the top diamond-corner of the tile at world |
| 491 | /// (x,y). | 494 | /// (x,y). |
| 492 | static ivec2 GetTileScreenOrigin( | 495 | static ivec2 GetTileScreenOrigin( |
| 493 | const CoordSystem iso_space, int world_x, int world_y) { | 496 | const CoordSystem iso_space, ivec2 camera, int world_x, int world_y) { |
| 494 | const ivec2 vx_offset = ivec2_scale(iso_space.x, world_x); | 497 | const ivec2 vx_offset = ivec2_scale(iso_space.x, world_x); |
| 495 | const ivec2 vy_offset = ivec2_scale(iso_space.y, world_y); | 498 | const ivec2 vy_offset = ivec2_scale(iso_space.y, world_y); |
| 496 | const ivec2 screen_origin = | 499 | const ivec2 screen_origin = |
| 497 | ivec2_add(iso_space.o, ivec2_add(vx_offset, vy_offset)); | 500 | ivec2_add(iso_space.o, ivec2_add(vx_offset, vy_offset)); |
| 498 | 501 | const ivec2 origin_view_space = ivec2_add(screen_origin, ivec2_neg(camera)); | |
| 499 | return screen_origin; | 502 | return origin_view_space; |
| 500 | } | 503 | } |
| 501 | 504 | ||
| 502 | static Pixel alpha_blend(Pixel src, Pixel dst) { | 505 | static Pixel alpha_blend(Pixel src, Pixel dst) { |
| @@ -598,8 +601,9 @@ static void draw_world(IsoGfx* iso) { | |||
| 598 | // screen-centric approach would juggle multiple tiles throughout the scan. | 601 | // screen-centric approach would juggle multiple tiles throughout the scan. |
| 599 | for (int wy = 0; wy < iso->map->world_height; ++wy) { | 602 | for (int wy = 0; wy < iso->map->world_height; ++wy) { |
| 600 | for (int wx = 0; wx < iso->map->world_width; ++wx) { | 603 | for (int wx = 0; wx < iso->map->world_width; ++wx) { |
| 601 | const Tile tile = tm_layer_get_tile(iso->map, layer, wx, wy); | 604 | const Tile tile = tm_layer_get_tile(iso->map, layer, wx, wy); |
| 602 | const ivec2 screen_origin = GetTileScreenOrigin(iso->iso_space, wx, wy); | 605 | const ivec2 screen_origin = |
| 606 | GetTileScreenOrigin(iso->iso_space, iso->camera, wx, wy); | ||
| 603 | draw_tile(iso, screen_origin, tile); | 607 | draw_tile(iso, screen_origin, tile); |
| 604 | } | 608 | } |
| 605 | } | 609 | } |
| @@ -631,11 +635,16 @@ static void draw_sprites(IsoGfx* iso) { | |||
| 631 | assert(sheet); | 635 | assert(sheet); |
| 632 | 636 | ||
| 633 | const ivec2 screen_origin = GetTileScreenOrigin( | 637 | const ivec2 screen_origin = GetTileScreenOrigin( |
| 634 | iso->iso_space, sprite->position.x, sprite->position.y); | 638 | iso->iso_space, iso->camera, sprite->position.x, sprite->position.y); |
| 635 | draw_sprite(iso, screen_origin, sprite, sheet); | 639 | draw_sprite(iso, screen_origin, sprite, sheet); |
| 636 | } | 640 | } |
| 637 | } | 641 | } |
| 638 | 642 | ||
| 643 | void isogfx_set_camera(IsoGfx* iso, int x, int y) { | ||
| 644 | assert(iso); | ||
| 645 | iso->camera = (ivec2){x, y}; | ||
| 646 | } | ||
| 647 | |||
| 639 | void isogfx_render(IsoGfx* iso) { | 648 | void isogfx_render(IsoGfx* iso) { |
| 640 | assert(iso); | 649 | assert(iso); |
| 641 | draw_world(iso); | 650 | draw_world(iso); |
| @@ -649,7 +658,8 @@ void isogfx_draw_tile(IsoGfx* iso, int x, int y, Tile tile) { | |||
| 649 | assert(x < iso->map->world_width); | 658 | assert(x < iso->map->world_width); |
| 650 | assert(y < iso->map->world_height); | 659 | assert(y < iso->map->world_height); |
| 651 | 660 | ||
| 652 | const ivec2 screen_origin = GetTileScreenOrigin(iso->iso_space, x, y); | 661 | const ivec2 screen_origin = |
| 662 | GetTileScreenOrigin(iso->iso_space, iso->camera, x, y); | ||
| 653 | draw_tile(iso, screen_origin, tile); | 663 | draw_tile(iso, screen_origin, tile); |
| 654 | } | 664 | } |
| 655 | 665 | ||
