summary refs log tree commit diff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c148
1 files changed, 110 insertions, 38 deletions
diff --git a/src/main.c b/src/main.c
index 345f6fb..7afd152 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,6 +4,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
+#include <errno.h>
 
 #include "input.h"
 #include "loader.h"
@@ -21,7 +23,8 @@
 SDL_Window *window = NULL;
 SDL_Renderer *renderer = NULL;
 enum game_state game_state = STATE_PLAYING;
-char *game_next_level;
+char *game_level, *game_next_level;
+char *save_file_name;
 
 static void *particle_tex = NULL;
 
@@ -192,12 +195,9 @@ int game_update(void) {
 void game_render(SDL_Texture *framebuffer, int x, int y) {
 	SDL_SetRenderTarget(renderer, framebuffer);
 	tilemap_background(tilemap, x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
-	entities.player[0].draw(entities.player, x, y);
-	for (int i = 0, e = 0; i < 64 && e < entities.enemies; i++) {
-		if (entities.enemy[i].state) {
-			e++;
-			entities.enemy[i].draw(entities.enemy + i, x, y);
-		}
+	for (int i = 0; i < entities.particles; i++) {
+		struct particle *self = entities.particle + i;
+		SDL_RenderCopy(renderer, particle_tex, &self->rect, &(SDL_Rect) {from_fixed(self->x) - x, from_fixed(self->y) - y, self->rect.w, self->rect.h});
 	}
 	for (int i = 0, e = 0; i < 64 && e < entities.projectiles; i++) {
 		if (entities.projectile[i].state) {
@@ -205,11 +205,50 @@ void game_render(SDL_Texture *framebuffer, int x, int y) {
 			entities.projectile[i].draw(entities.projectile + i, x, y);
 		}
 	}
-	for (int i = 0; i < entities.particles; i++) {
-		struct particle *self = entities.particle + i;
-		SDL_RenderCopy(renderer, particle_tex, &self->rect, &(SDL_Rect) {from_fixed(self->x) - x, from_fixed(self->y) - y, self->rect.w, self->rect.h});
+	for (int i = 0, e = 0; i < 64 && e < entities.enemies; i++) {
+		if (entities.enemy[i].state) {
+			e++;
+			entities.enemy[i].draw(entities.enemy + i, x, y);
+		}
 	}
+	entities.player[0].draw(entities.player, x, y);
 	tilemap_foreground(tilemap, x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
+	// hacky hp render
+	if (entities.player[0].hp) {
+		SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
+		for (int i = 0; i < entities.player[0].hp; i++) {
+			SDL_RenderFillRect(renderer, &(SDL_Rect) {1, 1 + i * 5, 4, 4});
+		}
+	}
+}
+
+int game_load_level(char *level) {
+	struct blob blob = res_get_map(level);
+	next_tilemap = tilemap_load(blob.data, blob.size);
+	if (next_tilemap != NULL) {
+		if (entities_load(&next_entities, blob.data, blob.size, next_tilemap->input_bytes)) {
+			tilemap_free(next_tilemap);
+		} else {
+			tilemap_free(tilemap);
+			tilemap = next_tilemap;
+			game_level = level;
+			entities_free(&entities);
+			memcpy(&entities, &next_entities, sizeof (entities));
+
+			game_state = STATE_FADE_OUT;
+			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;}
+			
+			game_render(framebuffer, x, y);
+			SDL_SetRenderTarget(renderer, NULL);
+			SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
+			SDL_RenderClear(renderer);
+			return 0;
+		}
+	}
+	return 1;
 }
 
 void game_render_flush(SDL_Texture *framebuffer) {
@@ -222,6 +261,9 @@ void game_render_flush(SDL_Texture *framebuffer) {
 }
 
 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);
+	strcat(save_file_name, "save.sav");
 	struct option opts[] = {
 		{"help",       0, NULL, 'h'},
 		{"scale",      1, NULL, 's'},
@@ -364,6 +406,44 @@ int main(int const argc, char *const *const argv) {
 		
 		particle_tex = res_get_texture("particles").data;
 
+		player_new(&next_entities);
+		FILE *file = fopen(save_file_name, "rb");
+		if (file == NULL) {
+			if (errno != ENOENT) {
+				perror(save_file_name);
+				goto end;
+			}
+			player_property(next_entities.player, "x", "40");
+			player_property(next_entities.player, "y", "64");
+			game_load_level("untitled");
+		} else {
+			size_t filesize, len;
+			char *filedata = util_loadFile(file, &filesize); // hack: we leak a tiny bit of memory here
+			fclose(file);
+			char *level = filedata;
+			len = strnlen(filedata, filesize);
+			if (len == filesize) {
+				fputs("invalid save format\n", stderr);
+				goto end;
+			}
+			filedata += len + 1;
+			len = strnlen(filedata, filesize);
+			if (len == filesize) {
+				fputs("invalid save format\n", stderr);
+				goto end;
+			}
+			player_property(next_entities.player, "x", filedata);
+			filedata += len + 1;
+			len = strnlen(filedata, filesize);
+			if (len == filesize) {
+				fputs("invalid save format\n", stderr);
+				goto end;
+			}
+			player_property(next_entities.player, "y", filedata);
+			level = realloc(level, strlen(level) + 1);
+			game_load_level(level);
+		}
+		#if 0
 		struct blob blob = res_get_map("untitled");
 		next_tilemap = tilemap_load(blob.data, blob.size);
 		if (next_tilemap == NULL) {
@@ -376,6 +456,7 @@ int main(int const argc, char *const *const argv) {
 			goto end;
 		}
 		tilemap = next_tilemap;
+		#endif
 	}
 
 	/* unsigned error; // identical variable is declared higher up */
@@ -397,10 +478,6 @@ int main(int const argc, char *const *const argv) {
 
 	SDL_ShowWindow(window);
 	
-	player_new(&next_entities);
-	player_property(next_entities.player, "x", "40");
-	player_property(next_entities.player, "y", "64");
-	memcpy(&entities, &next_entities, sizeof (entities));
 #if defined(__EMSCRIPTEN__)
 	emscripten_set_main_loop(main_loop, 60, 0); // TODO: how do i query the framerate if i set it to 0?
 	return 0;
@@ -413,11 +490,11 @@ int main(int const argc, char *const *const argv) {
 	return 0;
 }
 
-int x = 0, y = 0, fade = 0;
+int x = 0, y = 0, fade = 255;
 
 void main_loop(void) {
 #else
-	int x = 0, y = 0, fade = 0;
+	int x = 0, y = 0, fade = 255;
 	while (1) {
 #endif
 		input_pressed = input_held;
@@ -432,10 +509,12 @@ void main_loop(void) {
 					if (evt.key.repeat)
 						break;
 					
+					#if !defined(__EMSCRIPTEN__)
 					// check for ^Q and exit if pressed
 					if (evt.key.state == SDL_PRESSED && evt.key.keysym.sym == SDLK_q && evt.key.keysym.mod & KMOD_CTRL) {
 						goto end;
 					}
+					#endif
 					
 					//static_assert(INPUT_LENGTH <= sizeof(input_held) * CHAR_BIT); // if this trips up, scope creep happened
 					for (unsigned key = 0, bit = 1; key < INPUT_LENGTH; key++, bit <<= 1) {
@@ -473,8 +552,12 @@ void main_loop(void) {
 				case SDL_FINGERDOWN:
 					i = evt.tfinger.fingerId;
 					if (i >= touch.allocated) {
+						size_t const start = touch.allocated;
 						touch.allocated = i + 1;
 						touch.positions = realloc(touch.positions, sizeof (struct touch_vec) * touch.allocated);
+						for (size_t index = start; index < i - 1; index++) {
+							touch.positions[index].active = 0;
+						}
 					}
 					touch.positions[i].active = 1;
 				case SDL_FINGERMOTION:
@@ -588,29 +671,18 @@ void main_loop(void) {
 				SDL_RenderFillRect(renderer, &(SDL_Rect) {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT});
 				SDL_RenderPresent(renderer);
 				if (fade == 255) {
-					struct blob blob = res_get_map(game_next_level);
-					next_tilemap = tilemap_load(blob.data, blob.size);
-					if (next_tilemap != NULL) {
-						if (entities_load(&next_entities, blob.data, blob.size, next_tilemap->input_bytes)) {
-							tilemap_free(next_tilemap);
-						} else {
-							tilemap_free(tilemap);
-							tilemap = next_tilemap;
-							entities_free(&entities);
-							memcpy(&entities, &next_entities, sizeof (entities));
-						}
+					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;}
+						
+						game_render(framebuffer, x, y);
+						SDL_SetRenderTarget(renderer, NULL);
+						SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
+						SDL_RenderClear(renderer);
 					}
-					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;}
-					
-					game_render(framebuffer, x, y);
-					SDL_SetRenderTarget(renderer, NULL);
-					SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
-					SDL_RenderClear(renderer);
 				}
 				break;