diff options
-rw-r--r-- | GNUmakefile | 8 | ||||
-rw-r--r-- | README.md | 18 | ||||
-rw-r--r-- | src/disk.c | 1 | ||||
-rw-r--r-- | src/entity.h | 2 | ||||
-rw-r--r-- | src/flier.c | 9 | ||||
-rw-r--r-- | src/hvy_guns.c | 12 | ||||
-rw-r--r-- | src/incbin.h | 2 | ||||
-rw-r--r-- | src/loader.c | 4 | ||||
-rw-r--r-- | src/loader.h | 2 | ||||
-rw-r--r-- | src/main.c | 100 | ||||
-rw-r--r-- | src/main.h | 3 | ||||
-rw-r--r-- | src/pacer.c | 2 | ||||
-rw-r--r-- | src/particles.c | 2 | ||||
-rw-r--r-- | src/particles.h | 2 | ||||
-rw-r--r-- | src/player.c | 27 | ||||
-rw-r--r-- | src/res/enemy.ase | bin | 914 -> 724 bytes | |||
-rw-r--r-- | src/res/flier.ase | bin | 964 -> 691 bytes | |||
-rw-r--r-- | src/res/icon.png | bin | 239 -> 211 bytes | |||
-rw-r--r-- | src/res/pacer.ase | bin | 504 -> 504 bytes | |||
-rw-r--r-- | src/res/padding.ase | bin | 401 -> 350 bytes | |||
-rw-r--r-- | src/res/test.tmx | 4 | ||||
-rw-r--r-- | src/res/tiny.tmx | 54 | ||||
-rw-r--r-- | src/tilemap.c | 45 | ||||
-rw-r--r-- | src/tilemap.h | 3 | ||||
-rw-r--r-- | src/walker.c | 2 | ||||
-rw-r--r-- | src/warp.c | 2 |
26 files changed, 208 insertions, 96 deletions
diff --git a/GNUmakefile b/GNUmakefile index f1720b7..583b370 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -13,9 +13,13 @@ srcs := $(wildcard src/*.c) objs := $(addprefix out/${NS}/,$(notdir ${srcs:.c=.o})) deps := $(addprefix out/${NS}/,$(notdir $(patsubst %.c,%.d,$(wildcard src/*.c)))) -.PHONY: all run clean +.PHONY: all bin res run clean -all: out/${NS}/a.${EXTENSION} out/assets.res +all: bin res + +bin: out/${NS}/a.${EXTENSION} + +res: out/assets.res run: out/${NS}/a.${EXTENSION} out/assets.res ./$^ diff --git a/README.md b/README.md index 904a6a2..8244643 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,19 @@ # yet another sdl project -## libraries +platformer game thats stuck in dev hell since 2024 -heres a list of what i DIDNT write, and what its licensed under +## credits -- libplum is public domain +### source code modules (libraries included in the repo) -- cJSON is MIT licensed +- [libplum](<https://github.com/aaaaaa123456789/libplum>) (`src/libplum.[ch]`) is public domain (unlicense) + +- [cJSON](<https://github.com/DaveGamble/cJSON>) (`utl/json2map/cJSON.[ch]`) is MIT licensed + +### external libraries (not included in the repo but required to build the game) + +- [SDL2](<https://libsdl.org/>) is zlib licensed + +- [zlib](<https://www.zlib.net/>) is zlib licensed + +anything not mentioned above was probably written/drawn by me, sylvie diff --git a/src/disk.c b/src/disk.c index 084533f..7469337 100644 --- a/src/disk.c +++ b/src/disk.c @@ -6,6 +6,7 @@ #include "util.h" #include "save.h" #include <string.h> +#include <stdlib.h> #include <stdio.h> enum { diff --git a/src/entity.h b/src/entity.h index 038b62a..614d15f 100644 --- a/src/entity.h +++ b/src/entity.h @@ -1,6 +1,6 @@ #pragma once -#include <SDL2/SDL.h> +#include <SDL2/SDL_rect.h> #define from_fixed(a) ((a) / 16) #define to_fixed(a) ((a) * 16) diff --git a/src/flier.c b/src/flier.c index c507bd2..1fd3092 100644 --- a/src/flier.c +++ b/src/flier.c @@ -3,6 +3,7 @@ #include "loader.h" #include "tilemap.h" #include <stdbool.h> +#include <stdlib.h> #include <math.h> #include <string.h> #include "particles.h" @@ -302,6 +303,7 @@ static int flier_update(struct entity *self) { } if (abs(entities.player[0].x - self->x) + abs(entities.player[0].y - self->y) > to_fixed(96)) { self->state = FLIER_IDLE; + ext->reached_x = ext->reached_y = false; // not doing this makes them get lost and confused } self->timer--; if (self->timer == 0) { @@ -320,6 +322,12 @@ static int flier_update(struct entity *self) { self->state = FLIER_ALERT_IDLE; self->timer = ext->attack_delay; } + if (abs(entities.player[0].x - self->x) + abs(entities.player[0].y - self->y) > to_fixed(96)) { + anim(self, FLIER_A_IDLE); + self->state = FLIER_IDLE; + self->timer = ext->idle_time; + ext->reached_x = ext->reached_y = false; // not doing this makes them get lost and confused + } break; case FLIER_ALERT_ATTACK: @@ -339,6 +347,7 @@ static int flier_update(struct entity *self) { anim(self, FLIER_A_IDLE); self->state = FLIER_IDLE; self->timer = ext->idle_time; + ext->reached_x = ext->reached_y = false; // not doing this makes them get lost and confused } break; } diff --git a/src/hvy_guns.c b/src/hvy_guns.c index 1eabbe2..106cea6 100644 --- a/src/hvy_guns.c +++ b/src/hvy_guns.c @@ -324,8 +324,16 @@ int hvy_chaingun(struct gun *self, struct entity *parent, struct entity *target) entities.projectiles++; if (self->counter > HVY_CHAINGUN_MIN_RELOAD) { self->counter--; + self->timer = self->counter; + } else { + // this allows the projectiles to keep cycling up and down + // without the fire rate getting all wonky + self->counter--; + self->timer = HVY_CHAINGUN_MIN_RELOAD; + if (self->counter <= HVY_CHAINGUN_MIN_RELOAD - 4) { + self->counter = HVY_CHAINGUN_MIN_RELOAD; + } } - self->timer = self->counter; } else { self->counter = HVY_CHAINGUN_RELOAD; } @@ -335,7 +343,7 @@ int hvy_chaingun(struct gun *self, struct entity *parent, struct entity *target) void hvy_chaingun_new(struct gun *self, int x, int y) { self->update = hvy_chaingun; self->timer = HVY_CHAINGUN_RELOAD; - self->counter = 0; + self->counter = HVY_CHAINGUN_RELOAD; self->x = to_fixed(x); self->y = to_fixed(y); } diff --git a/src/incbin.h b/src/incbin.h index d768006..5dbd575 100644 --- a/src/incbin.h +++ b/src/incbin.h @@ -1,6 +1,6 @@ #pragma once -#if defined(__APPLE__) +#if defined(__APPLE__) || (defined(__MINGW32__) && !defined(__MINGW64__)) extern char const game_icon[], game_icon_end[]; #else extern char const _game_icon[], _game_icon_end[]; diff --git a/src/loader.c b/src/loader.c index 54425d9..fed2a7c 100644 --- a/src/loader.c +++ b/src/loader.c @@ -4,13 +4,11 @@ #include <zlib.h> #include <stdbool.h> -#include <SDL2/SDL.h> - #include "libplum.h" #include "zip.h" #include "loader.h" #include "util.h" -#include "main.h" +#include "main.h" // renderer #include "collision.h" static void *inflateWrapped(void *const restrict data, uint32_t const outsize); diff --git a/src/loader.h b/src/loader.h index 800ef0b..44f9d9f 100644 --- a/src/loader.h +++ b/src/loader.h @@ -2,7 +2,7 @@ #include <stddef.h> #include "entity.h" -#include "main.h" +#include "main.h" // struct entities typedef char * name_T; diff --git a/src/main.c b/src/main.c index 41c239b..922ca20 100644 --- a/src/main.c +++ b/src/main.c @@ -4,8 +4,8 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <inttypes.h> -#include <errno.h> +#include <errno.h> // ENOENT +#include <math.h> // used by vk2dSleep #include "input.h" #include "loader.h" @@ -14,8 +14,8 @@ #include "tilemap.h" -#include "incbin.h" -#include "libplum.h" +#include "incbin.h" // game icon +#include "libplum.h" // decoding game icon #include "main.h" @@ -240,10 +240,19 @@ int game_load_level(char *level) { game_state = STATE_FADE_OUT; fade = 255; - int x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); - int y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); - if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} - if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + int x, y; + if (tilemap->width < WINDOW_WIDTH / 8) { + x = -((WINDOW_WIDTH - tilemap->width * 8) / 2); + } else { + x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); + if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} + } + if (tilemap->height <= WINDOW_HEIGHT / 8) { + y = -((WINDOW_HEIGHT - tilemap->height * 8) / 2); + } else { + y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); + if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + } game_render(framebuffer, x, y); SDL_SetRenderTarget(renderer, NULL); @@ -264,6 +273,27 @@ void game_render_flush(SDL_Texture *framebuffer) { SDL_RenderPresent(renderer); } +// from libertea / <https://github.com/PaoloMazzon> +double getTime(void) { + static double time = -1; + if (time == -1) + time = SDL_GetPerformanceCounter(); + return (double)(SDL_GetPerformanceCounter() - time) / SDL_GetPerformanceFrequency(); +} + +// also from libertea / <https://github.com/PaoloMazzon> +void vk2dSleep(double seconds) { + if (seconds <= 0) + return; + double start = SDL_GetPerformanceCounter(); + double milliseconds = floor(seconds * 1000); + SDL_Delay(milliseconds); + while ((SDL_GetPerformanceCounter() - start) / (double)SDL_GetPerformanceFrequency() < seconds) { + volatile int i = 0; + (void) i; + } +} + int main(int const argc, char *const *const argv) { save_file_name = SDL_GetPrefPath("sylvie", "game"); save_file_name = SDL_realloc(save_file_name, strlen(save_file_name) + strlen("save.sav") + 1); @@ -349,12 +379,13 @@ int main(int const argc, char *const *const argv) { #if defined(__EMSCRIPTEN__) scale = 1; #else - if (scale <= 0) { // this looks very wrong + if (scale <= 0) { // because we used atoi, the user can set scale to -1 or something SDL_DisplayMode dm; if (SDL_GetDesktopDisplayMode(0, &dm) != 0) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "couldnt get desktop size", SDL_GetError(), NULL); - fprintf(stderr, "info: couldnt get desktop size %s\n", SDL_GetError()); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "couldnt get desktop size", SDL_GetError(), NULL); + fprintf(stderr, "warn: couldnt get desktop size %s\n", SDL_GetError()); flags |= SDL_WINDOW_RESIZABLE; + scale = 3; } else { int x = dm.w / 2 / WINDOW_WIDTH; int y = dm.h / 2 / WINDOW_HEIGHT; @@ -366,8 +397,10 @@ int main(int const argc, char *const *const argv) { if (scale == 0) { scale = 1; } - if (dm.refresh_rate != 60) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "refresh rate", "this game currently only runs well on 60Hz displays", NULL); + if (dm.refresh_rate < 59) { + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "refresh rate", "your monitor appears to have a refresh rate below 60Hz, the game will run slower\n" + "you can compile the game from source to disable vsync, unlocking the framerate\n" + "TODO: disabling vsync without a recompile", NULL); } } } @@ -375,12 +408,15 @@ int main(int const argc, char *const *const argv) { window = SDL_CreateWindow(":3", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH * scale, WINDOW_HEIGHT * scale, flags | SDL_WINDOW_HIDDEN); if (window == NULL) { + fprintf(stderr, "failed to create the game window: %s\n", SDL_GetError()); goto end; } + SDL_SetWindowMinimumSize(window, WINDOW_WIDTH, WINDOW_HEIGHT); SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); // hack, i dont wanna deal with windows discarding render textures renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_PRESENTVSYNC); if (renderer == NULL) { + fprintf(stderr, "failed to create a rendering context: %s\n", SDL_GetError()); goto end; } SDL_RenderSetLogicalSize(renderer, WINDOW_WIDTH, WINDOW_HEIGHT); @@ -482,6 +518,8 @@ void main_loop(void) { int x = 0, y = 0; while (1) { #endif + double const begin_time = getTime(); + input_pressed = input_held; SDL_Event evt; while (SDL_PollEvent(&evt)) { @@ -551,7 +589,7 @@ void main_loop(void) { i = evt.tfinger.fingerId; touch.positions[i].x = evt.tfinger.x; touch.positions[i].y = evt.tfinger.y; - printf("%" PRIu64 " %" PRIu64 " %f %f\n", evt.tfinger.touchId, evt.tfinger.fingerId, evt.tfinger.x, evt.tfinger.y); + //printf("%" PRIu64 " %" PRIu64 " %f %f\n", evt.tfinger.touchId, evt.tfinger.fingerId, evt.tfinger.x, evt.tfinger.y); reset_touch: touch.input_touch = 0; for (size_t i = 0; i < touch.allocated; i++) { @@ -654,10 +692,18 @@ void main_loop(void) { } } - x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); - y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); - if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} - if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + if (tilemap->width < WINDOW_WIDTH / 8) { + x = -((WINDOW_WIDTH - tilemap->width * 8) / 2); + } else { + x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); + if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} + } + if (tilemap->height <= WINDOW_HEIGHT / 8) { + y = -((WINDOW_HEIGHT - tilemap->height * 8) / 2); + } else { + y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); + if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + } game_render(framebuffer, x, y); game_render_flush(framebuffer); @@ -675,10 +721,18 @@ void main_loop(void) { if (fade == 255) { if (game_load_level(game_next_level)) { game_state = STATE_FADE_OUT; - x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); - y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); - if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} - if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + if (tilemap->width < WINDOW_WIDTH / 8) { + x = -((WINDOW_WIDTH - tilemap->width * 8) / 2); + } else { + x = (entities.player[0].x / 16) - (WINDOW_WIDTH / 2); + if (x < 0) {x = 0;} else if (x + WINDOW_WIDTH > tilemap->width * 8) {x = tilemap->width * 8 - WINDOW_WIDTH;} + } + if (tilemap->height <= WINDOW_HEIGHT / 8) { + y = -((WINDOW_HEIGHT - tilemap->height * 8) / 2); + } else { + y = (entities.player[0].y / 16) - (WINDOW_HEIGHT / 2); + if (y < 0) {y = 0;} else if (y + WINDOW_HEIGHT > tilemap->height * 8) {y = tilemap->height * 8 - WINDOW_HEIGHT;} + } game_render(framebuffer, x, y); SDL_SetRenderTarget(renderer, NULL); @@ -705,6 +759,8 @@ void main_loop(void) { #if defined(__EMSCRIPTEN__) return; #else + double const end_time = getTime(); + vk2dSleep(1.0/60.0 - (end_time - begin_time)); } #endif diff --git a/src/main.h b/src/main.h index ecd8250..2766a84 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,7 @@ #pragma once -#include <SDL2/SDL.h> +#include <SDL2/SDL_video.h> +#include <SDL2/SDL_render.h> #include "entity.h" extern SDL_Window *window; extern SDL_Renderer *renderer; diff --git a/src/pacer.c b/src/pacer.c index 9bbcfb6..de9a94d 100644 --- a/src/pacer.c +++ b/src/pacer.c @@ -3,6 +3,8 @@ #include "loader.h" #include "tilemap.h" #include <stdbool.h> +#include <stdlib.h> +#include <string.h> #include <math.h> #include "particles.h" #include "gun.h" diff --git a/src/particles.c b/src/particles.c index 3655f23..4432780 100644 --- a/src/particles.c +++ b/src/particles.c @@ -1,4 +1,4 @@ -#include <SDL2/SDL.h> +#include "particles.h" SDL_Rect const particle_gray = {0, 0, 4, 4}; SDL_Rect const particle_red = {4, 0, 4, 4}; diff --git a/src/particles.h b/src/particles.h index c841817..bcfa6fe 100644 --- a/src/particles.h +++ b/src/particles.h @@ -1,5 +1,5 @@ #pragma once -#include <SDL2/SDL.h> +#include <SDL2/SDL_rect.h> extern SDL_Rect const particle_gray; extern SDL_Rect const particle_red; diff --git a/src/player.c b/src/player.c index 40c5f6f..a28a6c9 100644 --- a/src/player.c +++ b/src/player.c @@ -4,6 +4,8 @@ #include "input.h" #include "tilemap.h" #include <stdbool.h> +#include <stdlib.h> +#include <string.h> #include <math.h> #include "particles.h" @@ -76,10 +78,10 @@ static int slash_update(struct projectile *self) { } else { self->hp++; } - int x = from_fixed(self->x) + self->facing * sin(self->hp / 2) * SLASH_REACH_X; - int y = from_fixed(self->y) - cos(self->hp / 2) * SLASH_REACH_Y; - int xx = from_fixed(self->x) + self->facing * sin(self->hp / 2 + 1) * SLASH_REACH_X; - int yy = from_fixed(self->y) - cos(self->hp / 2 + 1) * SLASH_REACH_Y; + int x = from_fixed(self->x) + self->facing * sin(self->hp / 2.0) * SLASH_REACH_X; + int y = from_fixed(self->y) - cos(self->hp / 2.0) * SLASH_REACH_Y; + int xx = from_fixed(self->x) + self->facing * sin(self->hp / 2.0 + 1) * SLASH_REACH_X; + int yy = from_fixed(self->y) - cos(self->hp / 2.0 + 1) * SLASH_REACH_Y; self->hitbox = (struct hitbox) {.left = x - 2, .right = x + 2, .top = y - 2, .bottom = y + 2}; for (int i = 0, e = entities.enemies; i < 64 && e; i++) { if (entities.enemy[i].state) { @@ -116,18 +118,18 @@ static int slash_draw(struct projectile *self, int camX, int camY) { int const x = from_fixed(self->x) - camX, y = from_fixed(self->y) - camY; if (self->hp >= 0) { SDL_Vertex vertices[4] = { - {.position = {x + from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2 - 1) * SLASH_REACH_X, y - cos(self->hp / 2 - 1) * SLASH_REACH_Y}, .color = {255, 191, 63, 255}}, - {.position = {x + self->facing * sin(self->hp / 2 + 0) * SLASH_REACH_X, y - cos(self->hp / 2 + 0) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, - {.position = {x - from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2 + 1) * SLASH_REACH_X, y - cos(self->hp / 2 + 1) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, - {.position = {x - from_fixed(self->velocity.x * 2) + self->facing * sin(self->hp / 2 + 2) * SLASH_REACH_X, y - cos(self->hp / 2 + 2) * SLASH_REACH_Y}, .color = {255, 127, 0, 0}}, + {.position = {x + from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2.0 - 1) * SLASH_REACH_X, y - cos(self->hp / 2.0 - 1) * SLASH_REACH_Y}, .color = {255, 191, 63, 255}}, + {.position = {x + self->facing * sin(self->hp / 2.0 + 0) * SLASH_REACH_X, y - cos(self->hp / 2.0 + 0) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, + {.position = {x - from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2.0 + 1) * SLASH_REACH_X, y - cos(self->hp / 2.0 + 1) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, + {.position = {x - from_fixed(self->velocity.x * 2) + self->facing * sin(self->hp / 2.0 + 2) * SLASH_REACH_X, y - cos(self->hp / 2.0 + 2) * SLASH_REACH_Y}, .color = {255, 127, 0, 0}}, }; SDL_RenderGeometry(renderer, NULL, vertices, 4, (int []) {0, 1, 2, 0, 2, 3}, 6); } else { SDL_Vertex vertices[4] = { - {.position = {x - from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2 + 1) * SLASH_REACH_X, y - cos(self->hp / 2 + 1) * SLASH_REACH_Y}, .color = {255, 191, 63, 255}}, - {.position = {x + + self->facing * sin(self->hp / 2 + 0) * SLASH_REACH_X, y - cos(self->hp / 2 + 0) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, - {.position = {x + from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2 - 1) * SLASH_REACH_X, y - cos(self->hp / 2 - 1) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, - {.position = {x + from_fixed(self->velocity.x * 2) + self->facing * sin(self->hp / 2 - 2) * SLASH_REACH_X, y - cos(self->hp / 2 - 2) * SLASH_REACH_Y}, .color = {255, 127, 0, 0}}, + {.position = {x - from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2.0 + 1) * SLASH_REACH_X, y - cos(self->hp / 2.0 + 1) * SLASH_REACH_Y}, .color = {255, 191, 63, 255}}, + {.position = {x + + self->facing * sin(self->hp / 2.0 + 0) * SLASH_REACH_X, y - cos(self->hp / 2.0 + 0) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, + {.position = {x + from_fixed(self->velocity.x) + self->facing * sin(self->hp / 2.0 - 1) * SLASH_REACH_X, y - cos(self->hp / 2.0 - 1) * SLASH_REACH_Y}, .color = {255, 127, 0, 255}}, + {.position = {x + from_fixed(self->velocity.x * 2) + self->facing * sin(self->hp / 2.0 - 2) * SLASH_REACH_X, y - cos(self->hp / 2.0 - 2) * SLASH_REACH_Y}, .color = {255, 127, 0, 0}}, }; SDL_RenderGeometry(renderer, NULL, vertices, 4, (int []) {0, 1, 2, 0, 2, 3}, 6); } @@ -332,6 +334,7 @@ static int player_update(struct entity *self) { self->timer = 60; } if (self->timer-- == 0) { + anim(self, PLAYER_A_IDLE); self->state = PLAYER_IDLE; } break; diff --git a/src/res/enemy.ase b/src/res/enemy.ase index aa73c16..ce1bad6 100644 --- a/src/res/enemy.ase +++ b/src/res/enemy.ase Binary files differdiff --git a/src/res/flier.ase b/src/res/flier.ase index 741409a..0577788 100644 --- a/src/res/flier.ase +++ b/src/res/flier.ase Binary files differdiff --git a/src/res/icon.png b/src/res/icon.png index 04d5199..1298225 100644 --- a/src/res/icon.png +++ b/src/res/icon.png Binary files differdiff --git a/src/res/pacer.ase b/src/res/pacer.ase index 6e05528..a9ff0ea 100644 --- a/src/res/pacer.ase +++ b/src/res/pacer.ase Binary files differdiff --git a/src/res/padding.ase b/src/res/padding.ase index 3bdd076..39f4cfc 100644 --- a/src/res/padding.ase +++ b/src/res/padding.ase Binary files differdiff --git a/src/res/test.tmx b/src/res/test.tmx index 5ac87be..a449d81 100644 --- a/src/res/test.tmx +++ b/src/res/test.tmx @@ -43,8 +43,8 @@ <object id="5" name="tiny" type="warp" x="0" y="96" width="8" height="40"> <properties> <property name="map" type="file" value="tiny.tmx"/> - <property name="tox" type="int" value="96"/> - <property name="toy" type="int" value="64"/> + <property name="tox" type="int" value="48"/> + <property name="toy" type="int" value="48"/> </properties> </object> <object id="6" name="walky" type="walker" x="112" y="112"> diff --git a/src/res/tiny.tmx b/src/res/tiny.tmx index 6d593af..ece2481 100644 --- a/src/res/tiny.tmx +++ b/src/res/tiny.tmx @@ -1,16 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> -<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="21" height="13" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="3"> +<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="11" height="9" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="3"> <tileset firstgid="1" source="autotiles.tsx"/> <tileset firstgid="33" source="tileset.tsx"/> <objectgroup id="4" name="Object Layer 1"> - <object id="1" name="test" type="warp" x="104" y="32" width="8" height="32"> + <object id="1" name="test" type="warp" x="64" y="16" width="8" height="32"> <properties> <property name="map" type="file" value="test.tmx"/> <property name="tox" type="int" value="16"/> <property name="toy" type="int" value="128"/> </properties> </object> - <object id="2" name="lavender disk" type="save" x="88" y="64"> + <object id="2" name="lavender disk" type="save" x="48" y="48"> <properties> <property name="color" type="color" value="#ff9d56d0"/> </properties> @@ -21,38 +21,30 @@ <properties> <property name="middleground" type="bool" value="true"/> </properties> - <layer id="1" name="Tile Layer 1" width="21" height="13" offsetx="-4" offsety="-4"> + <layer id="1" name="Tile Layer 1" width="11" height="9" offsetx="-4" offsety="-4"> <data encoding="csv"> -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,9,13,13,13,13,13,5,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,3,4,4,4,4,4,2,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,9,13,13,13,13,13,5,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,3,4,4,4,4,4,2,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0, +0,0,9,13,13,13,13,13,5,0,0, +0,0,3,4,4,4,4,4,2,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,9,13,13,13,13,13,5,0,0, +0,0,3,4,4,4,4,4,2,0,0, +0,0,0,0,0,0,0,0,0,0,0 </data> </layer> - <layer id="2" name="Tile Layer 2" width="21" height="13"> + <layer id="2" name="Tile Layer 2" width="11" height="9"> <data encoding="csv"> -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,38,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,56,53,54,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,38,0,0,0, +0,0,56,53,54,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0 </data> </layer> </group> diff --git a/src/tilemap.c b/src/tilemap.c index 34e7c43..ccfe990 100644 --- a/src/tilemap.c +++ b/src/tilemap.c @@ -1,11 +1,11 @@ #include <stdio.h> +#include <stdlib.h> #include <stdint.h> #include <string.h> - -#include <SDL2/SDL.h> +#include <limits.h> #include "loader.h" -#include "main.h" +#include "main.h" // renderer #include "tilemap.h" #include "collision.h" @@ -71,17 +71,13 @@ collision_T tilemap_area(struct tilemap *tilemap, int x1, int y1, int x2, int y2 if (x1 < 0) { x1 = 0; } - if (x2 < 0) { - x2 = 0; - } else if (x2 >= tilemap->width) { + if (x2 >= (signed) tilemap->width) { x2 = tilemap->width - 1; } if (y1 < 0) { y1 = 0; } - if (y2 < 0) { // for some reason you can bonk your head on nothing without this - y2 = 0; - } else if (y2 >= tilemap->height) { + if (y2 >= (signed) tilemap->height) { y2 = tilemap->height - 1; } return tilemap_area_raw(tilemap, x1, y1, x2, y2); @@ -90,14 +86,36 @@ collision_T tilemap_area(struct tilemap *tilemap, int x1, int y1, int x2, int y2 void tilemap_background(struct tilemap *tilemap, int x, int y, int w, int h) { SDL_SetRenderDrawColor(renderer, tilemap->backdrop.r, tilemap->backdrop.g, tilemap->backdrop.b, tilemap->backdrop.a); SDL_RenderFillRect(renderer, &(SDL_Rect) {0, 0, w, h}); + int bx = 0, by = 0, vw = w, vh = h; + if (x < 0) { + bx = -x; + vw = w + x * 2; + x = 0; + } + if (y < 0) { + by = -y; + vh = h + y * 2; + y = 0; + } for (int i = 0; i < tilemap->middleground; i++) { - SDL_RenderCopy(renderer, tilemap->tilemaps[i], &(SDL_Rect) {x * tilemap->parallax[i].x, y * tilemap->parallax[i].y, w, h}, &(SDL_Rect) {0, 0, w, h}); + SDL_RenderCopy(renderer, tilemap->tilemaps[i], &(SDL_Rect) {x * tilemap->parallax[i].x, y * tilemap->parallax[i].y, vw, vh}, &(SDL_Rect) {bx, by, vw, vh}); } } void tilemap_foreground(struct tilemap *tilemap, int x, int y, int w, int h) { + int bx = 0, by = 0, vw = w, vh = h; + if (x < 0) { + bx = -x; + vw = w + x * 2; + x = 0; + } + if (y < 0) { + by = -y; + vh = h + y * 2; + y = 0; + } for (int i = tilemap->middleground; i < tilemap->layers; i++) { - SDL_RenderCopy(renderer, tilemap->tilemaps[i], &(SDL_Rect) {x * tilemap->parallax[i].x, y * tilemap->parallax[i].y, w, h}, &(SDL_Rect) {0, 0, w, h}); + SDL_RenderCopy(renderer, tilemap->tilemaps[i], &(SDL_Rect) {x * tilemap->parallax[i].x, y * tilemap->parallax[i].y, vw, vh}, &(SDL_Rect) {bx, by, vw, vh}); } } @@ -163,7 +181,7 @@ struct tilemap *tilemap_load(void *data, size_t size) { struct blob col = res_get_collision(str); SDL_RenderCopy(renderer, tex, &(SDL_Rect) {0, 0, 128, height}, &(SDL_Rect) {0, y, 128, height}); - if (col.data != NULL) { // silence -fsanitize=undefined + if (col.data != NULL) { // col.data is only NULL when col.size is 0 but -fsanitize=undefined doesnt know that if (col.size + y * 2 > 0xf0) { fprintf(stderr, "warn: '%s' overflows tile properties\n", str); col.size = 0xf0 - y * 2; @@ -213,6 +231,9 @@ struct tilemap *tilemap_load(void *data, size_t size) { if (map->width * map->height * map->layers > size - sizeof (struct map)) { goto fail; } + if (map->width > INT_MAX || map->height > INT_MAX) { + goto fail; + } tilemap->backdrop.r = map->backdrop.r; tilemap->backdrop.g = map->backdrop.g; diff --git a/src/tilemap.h b/src/tilemap.h index 0f2bebe..4b6774a 100644 --- a/src/tilemap.h +++ b/src/tilemap.h @@ -21,6 +21,9 @@ extern struct tilemap { } *tilemap, *next_tilemap; // tilemap collision functions +// public functions use pixel coordinates (not subpixel) +// raw functions have no bounds checking and use tile coordinates +// you shouldnt need to use the raw functions collision_T tilemap_tile_raw(struct tilemap *tilemap, int x, int y); collision_T tilemap_tile(struct tilemap *tilemap, int x, int y); diff --git a/src/walker.c b/src/walker.c index 6441909..b3dc680 100644 --- a/src/walker.c +++ b/src/walker.c @@ -3,6 +3,8 @@ #include "loader.h" #include "tilemap.h" #include <stdbool.h> +#include <stdlib.h> +#include <string.h> #include <math.h> #include "particles.h" diff --git a/src/warp.c b/src/warp.c index 3556ef3..c9bb1b4 100644 --- a/src/warp.c +++ b/src/warp.c @@ -2,6 +2,8 @@ #include "entity.h" #include "loader.h" #include "tilemap.h" +#include <string.h> +#include <stdlib.h> static int warp_update(struct warp *self) { if ( |