summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/disk.c1
-rw-r--r--src/entity.h2
-rw-r--r--src/flier.c9
-rw-r--r--src/hvy_guns.c12
-rw-r--r--src/incbin.h2
-rw-r--r--src/loader.c4
-rw-r--r--src/loader.h2
-rw-r--r--src/main.c100
-rw-r--r--src/main.h3
-rw-r--r--src/pacer.c2
-rw-r--r--src/particles.c2
-rw-r--r--src/particles.h2
-rw-r--r--src/player.c27
-rw-r--r--src/res/enemy.asebin914 -> 724 bytes
-rw-r--r--src/res/flier.asebin964 -> 691 bytes
-rw-r--r--src/res/icon.pngbin239 -> 211 bytes
-rw-r--r--src/res/pacer.asebin504 -> 504 bytes
-rw-r--r--src/res/padding.asebin401 -> 350 bytes
-rw-r--r--src/res/test.tmx4
-rw-r--r--src/res/tiny.tmx54
-rw-r--r--src/tilemap.c45
-rw-r--r--src/tilemap.h3
-rw-r--r--src/walker.c2
-rw-r--r--src/warp.c2
24 files changed, 188 insertions, 90 deletions
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 differ
diff --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 differ
diff --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 differ
diff --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 differ
diff --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 differ
diff --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 (