From 1c429f33d3e81cc3586dd7a3bd933d18f0392b0c Mon Sep 17 00:00:00 2001 From: Steve Date: Sun, 21 Jan 2018 09:31:38 +0000 Subject: [PATCH] Start of v0.1 --- .gitignore | 6 + common.mk | 31 ++++ makefile | 97 ++++++++++++ src/common.h | 30 ++++ src/defs.h | 85 ++++++++++ src/game/game.c | 25 +++ src/game/game.h | 21 +++ src/game/title.c | 38 +++++ src/game/title.h | 23 +++ src/main.c | 95 +++++++++++ src/main.h | 35 +++++ src/plat/unix/unixInit.c | 53 +++++++ src/plat/unix/unixInit.h | 29 ++++ src/plat/win32/win32Init.c | 51 ++++++ src/plat/win32/win32Init.h | 28 ++++ src/structs.h | 114 ++++++++++++++ src/system/draw.c | 199 +++++++++++++++++++++++ src/system/draw.h | 24 +++ src/system/init.c | 108 +++++++++++++ src/system/init.h | 37 +++++ src/system/input.c | 159 +++++++++++++++++++ src/system/input.h | 25 +++ src/system/io.c | 163 +++++++++++++++++++ src/system/io.h | 26 +++ src/system/lookup.c | 147 +++++++++++++++++ src/system/lookup.h | 23 +++ src/system/text.c | 314 +++++++++++++++++++++++++++++++++++++ src/system/text.h | 30 ++++ src/system/textures.c | 111 +++++++++++++ src/system/textures.h | 28 ++++ src/util/maths.c | 82 ++++++++++ src/util/maths.h | 22 +++ src/util/util.c | 49 ++++++ src/util/util.h | 22 +++ 34 files changed, 2330 insertions(+) create mode 100644 .gitignore create mode 100644 common.mk create mode 100644 makefile create mode 100644 src/common.h create mode 100644 src/defs.h create mode 100644 src/game/game.c create mode 100644 src/game/game.h create mode 100644 src/game/title.c create mode 100644 src/game/title.h create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/plat/unix/unixInit.c create mode 100644 src/plat/unix/unixInit.h create mode 100644 src/plat/win32/win32Init.c create mode 100644 src/plat/win32/win32Init.h create mode 100644 src/structs.h create mode 100644 src/system/draw.c create mode 100644 src/system/draw.h create mode 100644 src/system/init.c create mode 100644 src/system/init.h create mode 100644 src/system/input.c create mode 100644 src/system/input.h create mode 100644 src/system/io.c create mode 100644 src/system/io.h create mode 100644 src/system/lookup.c create mode 100644 src/system/lookup.h create mode 100644 src/system/text.c create mode 100644 src/system/text.h create mode 100644 src/system/textures.c create mode 100644 src/system/textures.h create mode 100644 src/util/maths.c create mode 100644 src/util/maths.h create mode 100644 src/util/util.c create mode 100644 src/util/util.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5d6fdf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +data +gfx +music +sound +blobwarsAttrition +*.o diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..dc935f0 --- /dev/null +++ b/common.mk @@ -0,0 +1,31 @@ +VERSION = 0.1 +REVISION = $(shell git rev-list HEAD 2>/dev/null | wc -l) +LOCALE_MO = $(patsubst %.po,%.mo,$(wildcard locale/*.po)) + +SEARCHPATH += src src/game src/system src/util +vpath %.c $(SEARCHPATH) +vpath %.h $(SEARCHPATH) + +DEPS += defs.h structs.h + +OBJS += draw.o +OBJS += game.o +OBJS += init.o input.o io.o +OBJS += lookup.o +OBJS += main.o maths.o +OBJS += text.o textures.o title.o +OBJS += util.o + +# top-level rule to create the program. +all: $(PROG) $(LOCALE_MO) + +# compiling other source files. +%.o: %.c %.h $(DEPS) + $(CC) $(CFLAGS) $(CXXFLAGS) -c $< + +%.mo: %.po + msgfmt -c -o $@ $< + +# cleaning everything that can be automatically recreated with "make". +clean: + $(RM) $(OBJS) $(PROG) $(LOCALE_MO) diff --git a/makefile b/makefile new file mode 100644 index 0000000..bcb2215 --- /dev/null +++ b/makefile @@ -0,0 +1,97 @@ +PROG = blobwarsAttrition +CC = gcc +PREFIX ?= /usr +BIN_DIR ?= $(PREFIX)/bin +DATA_DIR ?= /opt/$(PROG) +LOCALE_DIR = $(PREFIX)/share/locale +ICON_DIR = $(PREFIX)/share/icons/hicolor +DESKTOP_DIR = $(PREFIX)/share/applications + +DESTDIR ?= +INST_BIN_DIR = $(DESTDIR)$(BIN_DIR) +INST_DATA_DIR = $(DESTDIR)$(DATA_DIR) +INST_LOCALE_DIR = $(DESTDIR)$(LOCALE_DIR) +INST_ICON_DIR = $(DESTDIR)$(ICON_DIR) +INST_DESKTOP_DIR = $(DESTDIR)$(DESKTOP_DIR) + +SEARCHPATH += src/plat/unix +OBJS += unixInit.o + +include common.mk + +CXXFLAGS += `sdl2-config --cflags` -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\" +CXXFLAGS += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds +CXXFLAGS += -g -lefence + +LDFLAGS += `sdl2-config --libs` -lSDL2_mixer -lSDL2_image -lSDL2_ttf -lm + +SHARED_FILES = CHANGELOG LICENSE README.md data gfx manual music sound icons +DIST_FILES = $(SHARED_FILES) locale $(PROG) +SRC_DIST_FILES = $(SHARED_FILES) src makefile* common.mk + +# linking the program. +$(PROG): $(OBJS) + $(CC) -o $@ $(OBJS) $(LDFLAGS) + +install: + mkdir -p $(INST_BIN_DIR) + install -m 0755 $(PROG) $(INST_BIN_DIR) + mkdir -p $(INST_DATA_DIR) + cp -r data $(INST_DATA_DIR) + cp -r gfx $(INST_DATA_DIR) + cp -r manual $(INST_DATA_DIR) + cp -r music $(INST_DATA_DIR) + cp -r sound $(INST_DATA_DIR) + mkdir -p $(INST_ICON_DIR)/16x16/apps + mkdir -p $(INST_ICON_DIR)/32x32/apps + mkdir -p $(INST_ICON_DIR)/64x64/apps + mkdir -p $(INST_ICON_DIR)/128x128/apps + cp -p icons/$(PROG)-16x16.png $(INST_ICON_DIR)/16x16/apps/$(PROG).png + cp -p icons/$(PROG)-32x32.png $(INST_ICON_DIR)/32x32/apps/$(PROG).png + cp -p icons/$(PROG)-64x64.png $(INST_ICON_DIR)/64x64/apps/$(PROG).png + cp -p icons/$(PROG)-128x128.png $(INST_ICON_DIR)/128x128/apps/$(PROG).png + mkdir -p $(INST_DESKTOP_DIR) + cp -p icons/$(PROG).desktop $(INST_DESKTOP_DIR) + + @for f in $(LOCALE_MO); do \ + lang=`echo $$f | sed -e 's/^locale\///;s/\.mo$$//'`; \ + mkdir -p $(INST_LOCALE_DIR)/$$lang/LC_MESSAGES; \ + cp -v $$f $(INST_LOCALE_DIR)/$$lang/LC_MESSAGES/$(PROG).mo; \ + done + +uninstall: + $(RM) $(BIN_DIR)/$(PROG) + $(RM) -rf $(DATA_DIR) + $(RM) $(ICON_DIR)/16x16/apps/$(PROG).png + $(RM) $(ICON_DIR)/32x32/apps/$(PROG).png + $(RM) $(ICON_DIR)/64x64/apps/$(PROG).png + $(RM) $(ICON_DIR)/128x128/apps/$(PROG).png + $(RM) $(DESKTOP_DIR)/$(PROG).desktop + + @for f in $(LOCALE_MO); do \ + lang=`echo $$f | sed -e 's/^locale\///;s/\.mo$$//'`; \ + $(RM) -v $(LOCALE_DIR)/$$lang/LC_MESSAGES/$(PROG).mo; \ + done + +# prepare an archive for the program +dist: + $(RM) -rf $(PROG)-$(VERSION) + mkdir $(PROG)-$(VERSION) + cp -r $(DIST_FILES) $(PROG)-$(VERSION) + tar czf $(PROG)-$(VERSION)-$(REVISION).linux-x86.tar.gz $(PROG)-$(VERSION) + mkdir -p dist + mv $(PROG)-$(VERSION)-$(REVISION).linux-x86.tar.gz dist + $(RM) -rf $(PROG)-$(VERSION) + +# prepare an archive for the program +src-dist: + $(RM) -rf $(PROG)-$(VERSION) + mkdir $(PROG)-$(VERSION) + cp -r $(SRC_DIST_FILES) $(PROG)-$(VERSION) + git log --pretty=format:"%h%x09%an%x09%ad%x09%s" --date=short >$(PROG)-$(VERSION)/CHANGELOG.raw + tar czf $(PROG)-$(VERSION)-$(REVISION).src.tar.gz $(PROG)-$(VERSION) + mkdir -p dist + mv $(PROG)-$(VERSION)-$(REVISION).src.tar.gz dist + $(RM) -rf $(PROG)-$(VERSION) + +.PHONY: dist diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..a4ea668 --- /dev/null +++ b/src/common.h @@ -0,0 +1,30 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "stdlib.h" +#include "stdio.h" +#include "string.h" +#include "math.h" +#include "ctype.h" + +#include "SDL2/SDL.h" + +#include "defs.h" +#include "structs.h" diff --git a/src/defs.h b/src/defs.h new file mode 100644 index 0000000..a871cd6 --- /dev/null +++ b/src/defs.h @@ -0,0 +1,85 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef REVISION +#define REVISION 0 +#endif + +#ifndef DATA_DIR +#define DATA_DIR "" +#endif + +#define _(string) getTranslatedString(string) + +#define PI 3.14159265358979323846 +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define STRNCPY(dest, src, n) strncpy(dest, src, n); dest[n - 1] = '\0' +#define TO_RAIDANS(angleDegrees) (angleDegrees * PI / 180.0) +#define TO_DEGREES(angleRadians) (angleRadians * 180.0 / PI) + +#define SAVE_FILENAME "game.save" +#define CONFIG_FILENAME "config.json" + +#define SCREEN_WIDTH 1280 +#define SCREEN_HEIGHT 720 + +#define MAX_KEYBOARD_KEYS 350 +#define MAX_MOUSE_BUTTONS 6 + +#define FPS 60 +#define LOGIC_RATE (1000.0 / FPS) + +#define MAX_FONTS 64 +#define NUM_TEXT_BUCKETS 64 +#define TEXT_TTL (1000 * 20) + +#define MAX_NAME_LENGTH 32 +#define MAX_DESCRIPTION_LENGTH 512 +#define MAX_LINE_LENGTH 1024 +#define MAX_FILENAME_LENGTH 1024 + +#define NUM_TEXTURE_BUCKETS 32 + +enum +{ + CONTROL_LEFT, + CONTROL_RIGHT, + CONTROL_UP, + CONTROL_DOWN, + CONTROL_FIRE, + CONTROL_JUMP, + CONTROL_JETPACK, + CONTROL_SCREENSHOT, + CONTROL_MAX +}; + +enum +{ + TA_LEFT, + TA_RIGHT, + TA_CENTER +}; + +enum +{ + CH_PLAYER, + CH_MAX +}; diff --git a/src/game/game.c b/src/game/game.c new file mode 100644 index 0000000..c888d61 --- /dev/null +++ b/src/game/game.c @@ -0,0 +1,25 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "game.h" + +void destroyGame(void) +{ +} diff --git a/src/game/game.h b/src/game/game.h new file mode 100644 index 0000000..8ad0dc9 --- /dev/null +++ b/src/game/game.h @@ -0,0 +1,21 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" diff --git a/src/game/title.c b/src/game/title.c new file mode 100644 index 0000000..fa681ee --- /dev/null +++ b/src/game/title.c @@ -0,0 +1,38 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "title.h" + +static void logic(void); +static void draw(void); + +void initTitle(void) +{ + app.delegate.logic = &logic; + app.delegate.draw = &draw; +} + +static void logic(void) +{ +} + +static void draw(void) +{ +} diff --git a/src/game/title.h b/src/game/title.h new file mode 100644 index 0000000..2ed81bd --- /dev/null +++ b/src/game/title.h @@ -0,0 +1,23 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern App app; diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5e4785b --- /dev/null +++ b/src/main.c @@ -0,0 +1,95 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "main.h" + +static long capFrameRate(const long then); +static void handleCommandLine(int argc, const char *argv[]); + +int main(int argc, const char *argv[]) +{ + long then, nextSecond; + + atexit(cleanup); + + srand(time(NULL)); + + initSDL(); + + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG); + + initGameSystem(); + + handleCommandLine(argc, argv); + + nextSecond = SDL_GetTicks() + 1000; + + while (1) + { + then = SDL_GetTicks(); + + handleInput(); + + app.delegate.logic(); + + prepareScene(); + + app.delegate.draw(); + + presentScene(); + + then = capFrameRate(then); + + if (SDL_GetTicks() >= nextSecond) + { + game.timePlayed++; + + nextSecond = SDL_GetTicks() + 1000; + } + } + + return 0; +} + +static long capFrameRate(const long then) +{ + long wait; + + wait = 16 - (SDL_GetTicks() - then); + + if (wait > 0) + { + SDL_Delay(wait); + } + + return SDL_GetTicks(); +} + +static void handleCommandLine(int argc, const char *argv[]) +{ + int i; + + for (i = 1 ; i < argc ; i++) + { + + } + + initTitle(); +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..b956343 --- /dev/null +++ b/src/main.h @@ -0,0 +1,35 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "common.h" +#include + +extern void cleanup(void); +extern void initSDL(void); +extern void initGameSystem(void); +extern void handleInput(void); +extern void prepareScene(void); +extern void presentScene(void); +extern void initTitle(void); + +App app; +Colors colors; +Dev dev; +Game game; diff --git a/src/plat/unix/unixInit.c b/src/plat/unix/unixInit.c new file mode 100644 index 0000000..a3ddb10 --- /dev/null +++ b/src/plat/unix/unixInit.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "unixInit.h" + +void createSaveFolder(void) +{ + char *userHome; + char dir[MAX_FILENAME_LENGTH]; + + userHome = getenv("HOME"); + + if (!userHome) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Unable to determine user save folder. Will save to current dir."); + return; + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "User home = %s", userHome); + + sprintf(dir, "%s/.local/share/blobwarsAttrition", userHome); + if (mkdir(dir, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH) != 0 && errno != EEXIST) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to create save dir '%s'. Will save to current dir.", dir); + return; + } + + STRNCPY(app.saveDir, dir, MAX_FILENAME_LENGTH); +} + +void createScreenshotFolder(void) +{ + mkdir("/tmp/blobwarsAttrition", S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); + + dev.screenshotFolder = "/tmp/blobwarsAttrition"; +} diff --git a/src/plat/unix/unixInit.h b/src/plat/unix/unixInit.h new file mode 100644 index 0000000..3d612a0 --- /dev/null +++ b/src/plat/unix/unixInit.h @@ -0,0 +1,29 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include +#include +#include + +#include "../../common.h" + +extern App app; +extern Dev dev; diff --git a/src/plat/win32/win32Init.c b/src/plat/win32/win32Init.c new file mode 100644 index 0000000..3ded1ab --- /dev/null +++ b/src/plat/win32/win32Init.c @@ -0,0 +1,51 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "win32Init.h" + +void createSaveFolder(void) +{ + char *userHome; + char dir[MAX_FILENAME_LENGTH]; + + userHome = getenv("USERPROFILE"); + + if (!userHome) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Unable to determine user save folder. Will save to current dir."); + return; + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "User home = %s", userHome); + + sprintf(dir, "%s\\blobwarsAttrition", userHome); + if (mkdir(dir) != 0 && errno != EEXIST) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to create save dir '%s'. Will save to current dir.", dir); + return; + } + + STRNCPY(app.saveDir, dir, MAX_FILENAME_LENGTH); +} + +void createScreenshotFolder(void) +{ + dev.screenshotFolder = "./"; +} diff --git a/src/plat/win32/win32Init.h b/src/plat/win32/win32Init.h new file mode 100644 index 0000000..6579e25 --- /dev/null +++ b/src/plat/win32/win32Init.h @@ -0,0 +1,28 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include +#include +#include + +#include "../../common.h" + +extern App app; +extern Dev dev; diff --git a/src/structs.h b/src/structs.h new file mode 100644 index 0000000..11a2b4b --- /dev/null +++ b/src/structs.h @@ -0,0 +1,114 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +typedef struct Texture Texture; +typedef struct Lookup Lookup; +typedef struct Entity Entity; + +typedef struct { + int debug; + int takeScreenshots; + char *screenshotFolder; + int noAIWeapons; + int showFPS; + int playerImmortal; + int playerUnlimitedMissiles; + int noEntityActions; + int allImmortal; + int fps; +} Dev; + +struct Texture { + char name[MAX_DESCRIPTION_LENGTH]; + long hash; + long ttl; + SDL_Texture *texture; + Texture *next; +}; + +typedef struct { + SDL_Color red; + SDL_Color orange; + SDL_Color yellow; + SDL_Color green; + SDL_Color blue; + SDL_Color cyan; + SDL_Color purple; + SDL_Color white; + SDL_Color black; + SDL_Color lightGrey; + SDL_Color darkGrey; +} Colors; + +struct Lookup { + char name[MAX_NAME_LENGTH]; + long value; + Lookup *next; +}; + +typedef struct { + void (*logic)(void); + void (*draw)(void); + void (*handleClick)(int x, int y, int btn); + void (*handleDrag)(int x, int y, int dx, int dy, int cx, int cy); + void (*handleMouseUp)(int x, int y, int btn); +} Delegate; + +struct Entity { + float x; + float y; +}; + +typedef struct { + int x; + int y; + int w; + int h; + int dx; + int dy; + int button[MAX_MOUSE_BUTTONS]; + int dragging; +} Mouse; + +typedef struct { + char saveDir[MAX_FILENAME_LENGTH]; + int winWidth; + int winHeight; + float scaleX; + float scaleY; + int fullscreen; + int musicVolume; + int soundVolume; + int hideMouse; + Mouse mouse; + int keyboard[MAX_KEYBOARD_KEYS]; + SDL_Texture *backBuffer; + SDL_Renderer *renderer; + SDL_Window *window; + Delegate delegate; + int awaitingWidgetInput; + int lastKeyPressed; + int lastButtonPressed; + int keyControls[CONTROL_MAX]; +} App; + +typedef struct { + long timePlayed; +} Game; diff --git a/src/system/draw.c b/src/system/draw.c new file mode 100644 index 0000000..223ac48 --- /dev/null +++ b/src/system/draw.c @@ -0,0 +1,199 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "draw.h" + +static void initColor(SDL_Color *c, int r, int g, int b); + +void initGraphics(void) +{ + initColor(&colors.red, 255, 0, 0); + initColor(&colors.orange, 255, 128, 0); + initColor(&colors.yellow, 255, 255, 0); + initColor(&colors.green, 0, 255, 0); + initColor(&colors.blue, 0, 0, 255); + initColor(&colors.cyan, 0, 255, 255); + initColor(&colors.purple, 255, 0, 255); + initColor(&colors.white, 255, 255, 255); + initColor(&colors.black, 0, 0, 0); + initColor(&colors.lightGrey, 192, 192, 192); + initColor(&colors.darkGrey, 128, 128, 128); + + app.backBuffer = SDL_CreateTexture(app.renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, SCREEN_WIDTH, SCREEN_HEIGHT); +} + +void prepareScene(void) +{ + SDL_SetRenderTarget(app.renderer, app.backBuffer); + SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, 255); + SDL_RenderClear(app.renderer); +} + +void presentScene(void) +{ + SDL_SetRenderTarget(app.renderer, NULL); + SDL_RenderCopy(app.renderer, app.backBuffer, NULL, NULL); + SDL_RenderPresent(app.renderer); +} + +void clearScreen(void) +{ + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(app.renderer, 0, 0, 0, 255); + SDL_RenderFillRect(app.renderer, NULL); +} + +void blit(SDL_Texture *texture, int x, int y, int center) +{ + SDL_Rect dstRect; + + dstRect.x = x; + dstRect.y = y; + SDL_QueryTexture(texture, NULL, NULL, &dstRect.w, &dstRect.h); + + if (center) + { + dstRect.x -= (dstRect.w / 2); + dstRect.y -= (dstRect.h / 2); + } + + SDL_RenderCopy(app.renderer, texture, NULL, &dstRect); +} + +void blitFlip(SDL_Texture *texture, int x, int y, int center, SDL_RendererFlip flip) +{ + SDL_Rect dstRect; + + dstRect.x = x; + dstRect.y = y; + SDL_QueryTexture(texture, NULL, NULL, &dstRect.w, &dstRect.h); + + SDL_RenderCopyEx(app.renderer, texture, NULL, &dstRect, 0, NULL, flip); +} + +void blitScaled(SDL_Texture *texture, int x, int y, int w, int h, int center) +{ + SDL_Rect dstRect; + + dstRect.x = x; + dstRect.y = y; + dstRect.w = w; + dstRect.h = h; + + if (center) + { + dstRect.x -= (dstRect.w / 2); + dstRect.y -= (dstRect.h / 2); + } + + SDL_RenderCopy(app.renderer, texture, NULL, &dstRect); +} + +void blitRotated(SDL_Texture *texture, int x, int y, float angle) +{ + SDL_Rect dstRect; + + dstRect.x = x; + dstRect.y = y; + SDL_QueryTexture(texture, NULL, NULL, &dstRect.w, &dstRect.h); + dstRect.x -= (dstRect.w / 2); + dstRect.y -= (dstRect.h / 2); + + SDL_RenderCopyEx(app.renderer, texture, NULL, &dstRect, angle, NULL, SDL_FLIP_NONE); +} + +void drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int a) +{ + SDL_SetRenderDrawColor(app.renderer, r, g, b, a); + SDL_RenderDrawLine(app.renderer, x1, y1, x2, y2); +} + +void drawCircle(int cx, int cy, int radius, int r, int g, int b, int a) +{ + int x = radius; + int y = 0; + int radiusError = 1 - x; + SDL_Point p[8]; + + SDL_SetRenderDrawColor(app.renderer, r, g, b, a); + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_BLEND); + + while (x >= y) + { + p[0].x = x + cx; p[0].y = y + cy; + p[1].x = y + cx; p[1].y = x + cy; + p[2].x = -x + cx; p[2].y = y + cy; + p[3].x = -y + cx; p[3].y = x + cy; + p[4].x = -x + cx; p[4].y = -y + cy; + p[5].x = -y + cx; p[5].y = -x + cy; + p[6].x = x + cx; p[6].y = -y + cy; + p[7].x = y + cx; p[7].y = -x + cy; + SDL_RenderDrawPoints(app.renderer, p, 8); + + y++; + + if (radiusError < 0) + { + radiusError += 2 * y + 1; + } + else + { + x--; + radiusError += 2 * (y - x) + 1; + } + } + + SDL_SetRenderDrawBlendMode(app.renderer, SDL_BLENDMODE_NONE); +} + +void drawRect(int x, int y, int w, int h, int r, int g, int b, int a) +{ + SDL_Rect rect; + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + + SDL_SetRenderDrawBlendMode(app.renderer, a < 255 ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(app.renderer, r, g, b, a); + SDL_RenderFillRect(app.renderer, &rect); +} + +void drawOutlineRect(int x, int y, int w, int h, int r, int g, int b, int a) +{ + SDL_Rect rect; + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + + SDL_SetRenderDrawBlendMode(app.renderer, a < 255 ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE); + SDL_SetRenderDrawColor(app.renderer, r, g, b, a); + SDL_RenderDrawRect(app.renderer, &rect); +} + +static void initColor(SDL_Color *c, int r, int g, int b) +{ + memset(c, 0, sizeof(SDL_Color)); + c->r = r; + c->g = g; + c->b = b; + c->a = 255; +} diff --git a/src/system/draw.h b/src/system/draw.h new file mode 100644 index 0000000..456adfa --- /dev/null +++ b/src/system/draw.h @@ -0,0 +1,24 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern App app; +extern Colors colors; diff --git a/src/system/init.c b/src/system/init.c new file mode 100644 index 0000000..86c1763 --- /dev/null +++ b/src/system/init.c @@ -0,0 +1,108 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "init.h" + +void initSDL(void) +{ + int rendererFlags, windowFlags; + + /* done in src/plat/ */ + createSaveFolder(); + + app.winWidth = SCREEN_WIDTH; + app.winHeight = SCREEN_HEIGHT; + + rendererFlags = SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC; + + windowFlags = 0; + + if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO) < 0) + { + printf("Couldn't initialize SDL: %s\n", SDL_GetError()); + exit(1); + } + + if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) == -1) + { + printf("Couldn't initialize SDL Mixer\n"); + exit(1); + } + + Mix_AllocateChannels(CH_MAX); + + app.window = SDL_CreateWindow("Blob Wars : Attrition", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, app.winWidth, app.winHeight, windowFlags); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + + app.renderer = SDL_CreateRenderer(app.window, -1, rendererFlags); + + IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG); + + if (TTF_Init() < 0) + { + printf("Couldn't initialize SDL TTF: %s\n", SDL_GetError()); + exit(1); + } +} + +void initGameSystem(void) +{ + int i, numInitFuns; + void (*initFuncs[]) (void) = { + initLookups, + initGraphics, + initFonts + }; + + numInitFuns = sizeof(initFuncs) / sizeof(void*); + + for (i = 0 ; i < numInitFuns ; i++) + { + /*showLoadingStep(i + 1, numInitFuns);*/ + + initFuncs[i](); + } +} + +void cleanup(void) +{ + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Cleaning up ..."); + + destroyLookups(); + + destroyFonts(); + + destroyTextures(); + + expireTexts(1); + + destroyGame(); + + SDL_DestroyRenderer(app.renderer); + + SDL_DestroyWindow(app.window); + + TTF_Quit(); + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Done."); + + SDL_Quit(); +} diff --git a/src/system/init.h b/src/system/init.h new file mode 100644 index 0000000..d3ad3af --- /dev/null +++ b/src/system/init.h @@ -0,0 +1,37 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +#include "SDL2/SDL_image.h" +#include "SDL2/SDL_mixer.h" +#include "SDL2/SDL_ttf.h" + +extern void createSaveFolder(void); +extern void initLookups(void); +extern void initGraphics(void); +extern void initFonts(void); +extern void destroyLookups(void); +extern void destroyFonts(void); +extern void destroyTextures(void); +extern void expireTexts(int all); +extern void destroyGame(void); + +extern App app; diff --git a/src/system/input.c b/src/system/input.c new file mode 100644 index 0000000..4345782 --- /dev/null +++ b/src/system/input.c @@ -0,0 +1,159 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "input.h" + +static int mouseDownTimer; +static SDL_Point dragStart; + +void initInput(void) +{ + mouseDownTimer = 0; +} + +static void doKeyDown(SDL_KeyboardEvent *event) +{ + if (event->keysym.scancode >= 0 && event->keysym.scancode < MAX_KEYBOARD_KEYS && event->repeat == 0) + { + app.keyboard[event->keysym.scancode] = 1; + } +} + +static void doKeyUp(SDL_KeyboardEvent *event) +{ + if (event->keysym.scancode >= 0 && event->keysym.scancode < MAX_KEYBOARD_KEYS) + { + app.keyboard[event->keysym.scancode] = 0; + } +} + +static void doMouseDown(SDL_MouseButtonEvent *event) +{ + if (event->button >= 0 && event->button < MAX_MOUSE_BUTTONS) + { + app.mouse.button[event->button] = 1; + } +} + +static void doMouseUp(SDL_MouseButtonEvent *event) +{ + if (event->button >= 0 && event->button < MAX_MOUSE_BUTTONS) + { + app.mouse.button[event->button] = 0; + + if (event->button == SDL_BUTTON_LEFT) + { + app.mouse.dragging = 0; + + mouseDownTimer = 0; + } + } +} + +/* + * Note: the following assumes that SDL_BUTTON_X1 and SDL_BUTTON_X2 are 4 and 5, respectively. They usually are. + */ +static void doMouseWheel(SDL_MouseWheelEvent *event) +{ + if (event->y == -1) + { + app.mouse.button[SDL_BUTTON_X1] = 1; + } + + if (event->y == 1) + { + app.mouse.button[SDL_BUTTON_X2] = 1; + } +} + +static void doMouseMotion(SDL_MouseMotionEvent *event) +{ + if (event->state & SDL_BUTTON_LMASK) + { + if (++mouseDownTimer >= 4 && (abs(dragStart.x - event->x) >= MOUSE_DRAG_THRESHOLD || abs(dragStart.y - event->y) >= MOUSE_DRAG_THRESHOLD)) + { + app.mouse.dx = event->xrel; + app.mouse.dy = event->yrel; + app.mouse.dragging = 1; + dragStart.x = event->x; + dragStart.y = event->y; + } + } + else + { + mouseDownTimer = 0; + } +} + +void clearInput(void) +{ + SDL_Event event; + + memset(app.keyboard, 0, sizeof(int) * MAX_KEYBOARD_KEYS); + memset(&app.mouse, 0, sizeof(Mouse)); + + while (SDL_PollEvent(&event)) + { + } +} + +void handleInput(void) +{ + SDL_Event event; + + app.mouse.dx = 0; + app.mouse.dy = 0; + + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_MOUSEMOTION: + doMouseMotion(&event.motion); + break; + + case SDL_MOUSEWHEEL: + doMouseWheel(&event.wheel); + break; + + case SDL_MOUSEBUTTONDOWN: + doMouseDown(&event.button); + break; + + case SDL_MOUSEBUTTONUP: + doMouseUp(&event.button); + break; + + case SDL_KEYDOWN: + doKeyDown(&event.key); + break; + + case SDL_KEYUP: + doKeyUp(&event.key); + break; + + case SDL_QUIT: + exit(0); + break; + } + } + + SDL_GetMouseState(&app.mouse.x, &app.mouse.y); +} diff --git a/src/system/input.h b/src/system/input.h new file mode 100644 index 0000000..e775197 --- /dev/null +++ b/src/system/input.h @@ -0,0 +1,25 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#define MOUSE_DRAG_THRESHOLD 4 + +#include "../common.h" + +extern App app; diff --git a/src/system/io.c b/src/system/io.c new file mode 100644 index 0000000..0b4ac85 --- /dev/null +++ b/src/system/io.c @@ -0,0 +1,163 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "io.h" + +static int stringComparator(const void *a, const void *b); + +int fileExists(const char *filename) +{ + struct stat buffer; + + return (stat(filename, &buffer) == 0); +} + +const char *getFileLocation(const char *filename) +{ + static char path[MAX_FILENAME_LENGTH]; + memset(path, '\0', MAX_FILENAME_LENGTH); + + if (fileExists(filename)) + { + return filename; + } + + sprintf(path, DATA_DIR"/%s", filename); + + if (!fileExists(path)) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, "No such file '%s'", path); + exit(1); + } + + return path; +} + +char *readFile(const char *filename) +{ + char *buffer = 0; + unsigned long length; + FILE *file = fopen(getFileLocation(filename), "rb"); + + if (file) + { + fseek(file, 0, SEEK_END); + length = ftell(file); + fseek(file, 0, SEEK_SET); + + buffer = malloc(length + 1); + memset(buffer, 0, length + 1); + fread(buffer, 1, length, file); + + fclose(file); + + buffer[length] = '\0'; + } + + return buffer; +} + +int writeFile(const char *filename, const char *data) +{ + FILE *file = fopen(filename, "wb"); + + if (file) + { + fprintf(file, "%s\n", data); + fclose(file); + return 1; + } + + return 0; +} + +char *getSaveFilePath(const char *filename) +{ + static char path[MAX_FILENAME_LENGTH]; + memset(path, '\0', MAX_FILENAME_LENGTH); + + sprintf(path, "%s/%s", app.saveDir, filename); + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "getSaveFilePath = '%s'", path); + + return path; +} + +char **getFileList(const char *dir, int *count) +{ + DIR *d; + int i; + struct dirent *ent; + char **filenames; + + i = 0; + filenames = NULL; + + if ((d = opendir(getFileLocation(dir))) != NULL) + { + while ((ent = readdir(d)) != NULL) + { + if (ent->d_name[0] != '.') + { + i++; + } + } + + if (i > 0) + { + filenames = malloc(sizeof(char*) * i); + memset(filenames, 0, sizeof(char*) * i); + + rewinddir(d); + + i = 0; + + while ((ent = readdir(d)) != NULL) + { + if (ent->d_name[0] != '.') + { + filenames[i] = malloc(sizeof(char) * MAX_FILENAME_LENGTH); + + STRNCPY(filenames[i], ent->d_name, MAX_FILENAME_LENGTH); + + i++; + } + } + } + + closedir(d); + } + + *count = i; + + if (filenames) + { + qsort(filenames, i, sizeof(char*), stringComparator); + } + + return filenames; +} + +static int stringComparator(const void *a, const void *b) +{ + char **s1 = (char **)a; + char **s2 = (char **)b; + return strcmp(*s1, *s2); +} diff --git a/src/system/io.h b/src/system/io.h new file mode 100644 index 0000000..a1ee589 --- /dev/null +++ b/src/system/io.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +#include "sys/stat.h" +#include "dirent.h" + +extern App app; diff --git a/src/system/lookup.c b/src/system/lookup.c new file mode 100644 index 0000000..6423d88 --- /dev/null +++ b/src/system/lookup.c @@ -0,0 +1,147 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "lookup.h" + +static Lookup head; +static Lookup *tail; + +static void addLookup(const char *name, long value); + +void initLookups(void) +{ + memset(&head, 0, sizeof(Lookup)); + tail = &head; + + addLookup("DUMMY", 0); +} + +static void addLookup(const char *name, long value) +{ + Lookup *lookup = malloc(sizeof(Lookup)); + memset(lookup, 0, sizeof(Lookup)); + + STRNCPY(lookup->name, name, MAX_NAME_LENGTH); + lookup->value = value; + + tail->next = lookup; + tail = lookup; +} + +long lookup(const char *name) +{ + Lookup *l; + + for (l = head.next ; l != NULL ; l = l->next) + { + if (strcmp(l->name, name) == 0) + { + return l->value; + } + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "No such lookup value '%s'", name); + exit(1); + + return 0; +} + +char *getLookupName(const char *prefix, long num) +{ + Lookup *l; + + for (l = head.next ; l != NULL ; l = l->next) + { + if (l->value == num && strncmp(prefix, l->name, strlen(prefix)) == 0) + { + return l->name; + } + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "No such lookup value %ld, prefix=%s", num, prefix); + exit(1); + + return ""; +} + +const char *getFlagValues(const char *prefix, long flags) +{ + static char flagStr[MAX_DESCRIPTION_LENGTH]; + int requirePlus; + Lookup *l; + + memset(flagStr, '\0', MAX_DESCRIPTION_LENGTH); + + requirePlus = 0; + + for (l = head.next ; l != NULL ; l = l->next) + { + if (flags & l->value && strncmp(prefix, l->name, strlen(prefix)) == 0) + { + if (requirePlus) + { + strcat(flagStr, "+"); + } + + strcat(flagStr, l->name); + + requirePlus = 1; + } + } + + return flagStr; +} + +long flagsToLong(const char *in) +{ + char *flag, *flags; + long total; + + total = 0; + + if (strlen(in) > 0) + { + flags = malloc(strlen(in) + 1); + STRNCPY(flags, in, strlen(in) + 1); + + flag = strtok(flags, "+"); + while (flag) + { + total += lookup(flag); + flag = strtok(NULL, "+"); + } + + free(flags); + } + + return total; +} + +void destroyLookups(void) +{ + Lookup *l; + + while (head.next) + { + l = head.next; + head.next = l->next; + free(l); + } +} diff --git a/src/system/lookup.h b/src/system/lookup.h new file mode 100644 index 0000000..716f681 --- /dev/null +++ b/src/system/lookup.h @@ -0,0 +1,23 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +long flagsToLong(const char *in); diff --git a/src/system/text.c b/src/system/text.c new file mode 100644 index 0000000..92ae42b --- /dev/null +++ b/src/system/text.c @@ -0,0 +1,314 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "text.h" + +static void loadFont(int size); +static SDL_Texture *getCachedText(unsigned long hash); +static void cacheText(unsigned long hash, SDL_Texture *t); +static void drawTextNormal(int x, int y, int size, int align, SDL_Color c, const char *text); +static void drawTextSplit(int x, int y, int size, int align, SDL_Color c, char *text); +void textSize(const char *text, int size, int *w, int *h); + +static char drawTextBuffer[MAX_LINE_LENGTH]; +static TTF_Font *font[MAX_FONTS]; +static Texture textures[NUM_TEXT_BUCKETS]; +static int maxWidth = 0; +static int cacheSize = 0; +static int textShadow = 1; +static SDL_Color textShadowColor; + +void initFonts(void) +{ + memset(&font, 0, sizeof(TTF_Font*) * MAX_FONTS); + memset(&textures, 0, sizeof(Texture) * NUM_TEXT_BUCKETS); +} + +void drawText(int x, int y, int size, int align, SDL_Color c, const char *format, ...) +{ + va_list args; + + memset(&drawTextBuffer, '\0', sizeof(drawTextBuffer)); + + va_start(args, format); + vsprintf(drawTextBuffer, format, args); + va_end(args); + + if (maxWidth == 0) + { + drawTextNormal(x, y, size, align, c, drawTextBuffer); + } + else + { + drawTextSplit(x, y, size, align, c, drawTextBuffer); + } +} + +static void drawTextNormal(int x, int y, int size, int align, SDL_Color c, const char *text) +{ + SDL_Surface *surface; + SDL_Texture *t; + int w, h; + long hash; + + if (size >= MAX_FONTS) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, "ERROR: %d exceeds max font size index of %d\n", size, MAX_FONTS); + exit(1); + } + + if (!font[size]) + { + loadFont(size); + } + + hash = hashcode(text) + size; + + t = getCachedText(hash); + + if (!t) + { + surface = TTF_RenderText_Blended(font[size], text, colors.white); + t = SDL_CreateTextureFromSurface(app.renderer, surface); + SDL_FreeSurface(surface); + + cacheText(hash, t); + } + + SDL_QueryTexture(t, NULL, NULL, &w, &h); + + if (align == TA_CENTER) + { + x -= (w / 2); + } + else if (align == TA_RIGHT) + { + x -= w; + } + + if (textShadow) + { + SDL_SetTextureColorMod(t, textShadowColor.r, textShadowColor.g, textShadowColor.b); + + blit(t, x + 1, y + 1, 0); + blit(t, x + 2, y + 2, 0); + } + + SDL_SetTextureColorMod(t, c.r, c.g, c.b); + + blit(t, x, y, 0); +} + +static void drawTextSplit(int x, int y, int size, int align, SDL_Color c, char *text) +{ + char drawTextBuffer[MAX_DESCRIPTION_LENGTH]; + char *token; + int w, h, currentWidth; + + memset(&drawTextBuffer, '\0', sizeof(drawTextBuffer)); + + token = strtok(text, " "); + + currentWidth = 0; + + while (token) + { + textSize(token, size, &w, &h); + + if (currentWidth + w > maxWidth) + { + drawTextNormal(x, y, size, align, c, drawTextBuffer); + + currentWidth = 0; + y += h; + memset(&drawTextBuffer, '\0', sizeof(drawTextBuffer)); + } + + strcat(drawTextBuffer, token); + strcat(drawTextBuffer, " "); + + currentWidth += w; + + token = strtok(NULL, " "); + } + + drawTextNormal(x, y, size, align, c, drawTextBuffer); +} + +int getWrappedTextHeight(const char *text, int size) +{ + char textBuffer[MAX_DESCRIPTION_LENGTH]; + char *token; + int w, h, currentWidth; + int y; + + STRNCPY(textBuffer, text, MAX_DESCRIPTION_LENGTH); + + token = strtok(textBuffer, " "); + + y = 0; + currentWidth = 0; + + while (token) + { + textSize(token, size, &w, &h); + + if (currentWidth + w > maxWidth) + { + currentWidth = 0; + y += h; + } + + currentWidth += w; + + token = strtok(NULL, " "); + } + + return y + h; +} + +void textSize(const char *text, int size, int *w, int *h) +{ + if (!font[size]) + { + loadFont(size); + } + + TTF_SizeText(font[size], text, w, h); +} + +void limitTextWidth(int width) +{ + maxWidth = width; +} + +void useTextShadow(int enable, int r, int g, int b) +{ + textShadow = 1; + textShadowColor.r = r; + textShadowColor.g = g; + textShadowColor.b = b; +} + +static SDL_Texture *getCachedText(unsigned long hash) +{ + Texture *t; + int i; + + i = hash % NUM_TEXT_BUCKETS; + + t = textures[i].next; + + for (t = textures[i].next ; t != NULL ; t = t->next) + { + if (t->hash == hash) + { + t->ttl = SDL_GetTicks() + TEXT_TTL; + return t->texture; + } + } + + return NULL; +} + +static void cacheText(unsigned long hash, SDL_Texture *texture) +{ + Texture *t, *new; + int i; + + i = hash % NUM_TEXT_BUCKETS; + + t = &textures[i]; + + /* horrible bit to find the tail */ + while (t->next) + { + t = t->next; + } + + new = malloc(sizeof(Texture)); + memset(new, 0, sizeof(Texture)); + + new->hash = hash; + new->texture = texture; + new->ttl = SDL_GetTicks() + TEXT_TTL; + + t->next = new; + + cacheSize++; +} + +void expireTexts(int all) +{ + Texture *t, *prev; + int i, n; + long now; + + n = 0; + now = SDL_GetTicks(); + + for (i = 0 ; i < NUM_TEXT_BUCKETS ; i++) + { + prev = &textures[i]; + + for (t = textures[i].next ; t != NULL ; t = t->next) + { + if (t->ttl <= now || all) + { + prev->next = t->next; + SDL_DestroyTexture(t->texture); + free(t); + + cacheSize--; + + n++; + + t = prev; + } + + prev = t; + } + } + + if (n > 0) + { + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "Expired %d texts", n); + } +} + +static void loadFont(int size) +{ + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "loadFonts(%d)", size); + + font[size] = TTF_OpenFont(getFileLocation("data/fonts/LiberationMono-Regular.ttf"), size); +} + +void destroyFonts(void) +{ + int i; + + for (i = 0 ; i < MAX_FONTS ; i++) + { + if (font[i]) + { + TTF_CloseFont(font[i]); + } + } +} diff --git a/src/system/text.h b/src/system/text.h new file mode 100644 index 0000000..663a84d --- /dev/null +++ b/src/system/text.h @@ -0,0 +1,30 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +#include "SDL2/SDL_ttf.h" + +extern void blit(SDL_Texture *texture, int x, int y, int centered); +extern char *getFileLocation(const char *filename); +extern unsigned long hashcode(const char *str); + +extern App app; +extern Colors colors; diff --git a/src/system/textures.c b/src/system/textures.c new file mode 100644 index 0000000..b2ffd36 --- /dev/null +++ b/src/system/textures.c @@ -0,0 +1,111 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "textures.h" + +static Texture textures[NUM_TEXTURE_BUCKETS]; + +static Texture *addTextureToCache(const char *name, SDL_Texture *texture); +Texture *getTexture(const char *name); + +void initTextures(void) +{ + memset(&textures, 0, sizeof(Texture) * NUM_TEXTURE_BUCKETS); +} + +static Texture *addTextureToCache(const char *name, SDL_Texture *texture) +{ + Texture *t, *new; + int i; + + i = hashcode(name) % NUM_TEXTURE_BUCKETS; + + t = &textures[i]; + + /* horrible bit to look for the tail */ + while (t->next) + { + t = t->next; + } + + new = malloc(sizeof(Texture)); + memset(new, 0, sizeof(Texture)); + + STRNCPY(new->name, name, MAX_DESCRIPTION_LENGTH); + new->texture = texture; + + t->next = new; + + return new; +} + +static Texture *loadTexture(const char *filename) +{ + SDL_Texture *texture; + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Loading %s", filename); + + texture = IMG_LoadTexture(app.renderer, getFileLocation(filename)); + + return addTextureToCache(filename, texture); +} + + +Texture *getTexture(const char *filename) +{ + Texture *t; + int i; + + i = hashcode(filename) % NUM_TEXTURE_BUCKETS; + + /* check if the texture is already loaded */ + for (t = textures[i].next ; t != NULL ; t = t->next) + { + if (strcmp(t->name, filename) == 0) + { + return t; + } + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG, "%s not in texture cache", filename); + + return loadTexture(filename); +} + +void destroyTextures(void) +{ + Texture *t, *next; + int i; + + for (i = 0 ; i < NUM_TEXTURE_BUCKETS ; i++) + { + t = textures[i].next; + + while (t) + { + next = t->next; + SDL_DestroyTexture(t->texture); + free(t); + t = next; + } + + textures[i].next = NULL; + } +} diff --git a/src/system/textures.h b/src/system/textures.h new file mode 100644 index 0000000..4cbb518 --- /dev/null +++ b/src/system/textures.h @@ -0,0 +1,28 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +#include "SDL2/SDL_image.h" + +extern char *getFileLocation(const char *filename); +extern unsigned long hashcode(const char *str); + +extern App app; diff --git a/src/util/maths.c b/src/util/maths.c new file mode 100644 index 0000000..6efd80c --- /dev/null +++ b/src/util/maths.c @@ -0,0 +1,82 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "maths.h" + +int mod(int n, int x) +{ + return ((n % x) + x) % x; +} + +int rrnd(int low, int high) +{ + return low + rand() % ((high - low) + 1); +} + +int getPercent(float current, float total) +{ + return (current / total) * 100; +} + +int getDistance(int x1, int y1, int x2, int y2) +{ + int x, y; + + x = x2 - x1; + y = y2 - y1; + + return sqrt(x * x + y *y); +} + +void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy) +{ + int steps = MAX(abs(x1 - x2), abs(y1 - y2)); + + if (steps == 0) + { + *dx = *dy = 0; + return; + } + + *dx = (x1 - x2); + *dx /= steps; + + *dy = (y1 - y2); + *dy /= steps; +} + +unsigned long hashcode(const char *str) +{ + unsigned long hash = 5381; + int c; + + c = *str; + + while (c) + { + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + c = *str++; + } + + hash = ((hash << 5) + hash); + + return hash; +} diff --git a/src/util/maths.h b/src/util/maths.h new file mode 100644 index 0000000..c3b03ff --- /dev/null +++ b/src/util/maths.h @@ -0,0 +1,22 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + diff --git a/src/util/util.c b/src/util/util.c new file mode 100644 index 0000000..2fb34c8 --- /dev/null +++ b/src/util/util.c @@ -0,0 +1,49 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "util.h" + +int collision(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) +{ + return (MAX(x1, x2) < MIN(x1 + w1, x2 + w2)) && (MAX(y1, y2) < MIN(y1 + h1, y2 + h2)); +} + +char *timeToString(long millis, int showHours) +{ + static char TIME[MAX_NAME_LENGTH]; + + int hours, minutes, seconds; + + seconds = millis / FPS; + minutes = (seconds / FPS) % 60; + hours = seconds / (FPS * FPS); + seconds %= 60; + + if (showHours) + { + sprintf(TIME, "%dh %02dm %02ds", hours, minutes, seconds); + } + else + { + sprintf(TIME, "%dm %02ds", minutes, seconds); + } + + return TIME; +} diff --git a/src/util/util.h b/src/util/util.h new file mode 100644 index 0000000..c3b03ff --- /dev/null +++ b/src/util/util.h @@ -0,0 +1,22 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" +