diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..9db382b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,65 @@ +{ + "configurations": [ + { + "name": "Win32", + "includePath": [ + "C:/raylib/raylib/src/**", + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE", + "GRAPHICS_API_OPENGL_33", + "PLATFORM_DESKTOP" + ], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c99", + "cppStandard": "c++14", + "intelliSenseMode": "gcc-x64" + }, + { + "name": "Mac", + "includePath": [ + "/src/**", + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE", + "GRAPHICS_API_OPENGL_33", + "PLATFORM_DESKTOP" + ], + "macFrameworkPath": [ + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++14", + "intelliSenseMode": "clang-x64" + }, + { + "name": "Linux", + "includePath": [ + "/usr/include", + "${workspaceFolder}/src", + "${workspaceFolder}/src/**", + "${workspaceFolder}/**" + ], + "defines": [ + "_DEBUG", + "UNICODE", + "_UNICODE", + "GRAPHICS_API_OPENGL_33", + "PLATFORM_DESKTOP" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++14", + "intelliSenseMode": "clang-x64" + + } + ], + "version": 4 +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ee4c90f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/pns", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "linux": { + "miDebuggerPath": "/usr/bin/gdb" + }, + "preLaunchTask": "build debug" + }, + { + "name": "Run", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/pns", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "linux": { + "miDebuggerPath": "/usr/bin/gdb" + }, + "preLaunchTask": "build release" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e98318a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/*.o": true, + "**/*.exe": true, + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..df2fac4 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,35 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build debug", + "type": "process", + "command": "make", + "args": [], + "group": { + "kind": "build", + "isDefault": false + }, + "problemMatcher": [ + "$gcc" + ] + }, + { + "label": "build release", + "type": "process", + "command": "make", + "args": [], + "problemMatcher": [ + "$gcc" + ] + }, + { + "label": "clean", + "type": "process", + "command": "make", + "args": [ + "clean" + ] + } + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bc11538 --- /dev/null +++ b/Makefile @@ -0,0 +1,45 @@ +# Compiler +CC = gcc + +# Build mode +BUILD_MODE ?= RELEASE +INCLUDE_DIRS := $(shell find src -type d) + +ifeq ($(BUILD_MODE),DEBUG) + CFLAGS = -Wall -Wextra -std=c11 $(addprefix -I,$(INCLUDE_DIRS)) -g -O0 +else + CFLAGS = -Wall -Wextra -std=c11 $(addprefix -I,$(INCLUDE_DIRS)) -O2 +endif + +# Linker flags +LDFLAGS = -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 + +# Carpeta de build +BUILD_DIR = build + +# Target final +TARGET = $(BUILD_DIR)/pns + +# Fuentes y objetos +SRC = $(shell find src -name "*.c") +OBJ = $(patsubst src/%.c,$(BUILD_DIR)/%.o,$(SRC)) + +# Phony targets +.PHONY: all clean + +# Target por defecto +all: $(TARGET) + +# Linking +$(TARGET): $(OBJ) + $(CC) $(OBJ) -o $@ $(LDFLAGS) + +# Compilación de objetos +# mkdir -p crea la carpeta automáticamente si no existe +$(BUILD_DIR)/%.o: src/%.c + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ + +# Limpiar todo +clean: + rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/Makefile.Android b/Makefile.Android new file mode 100644 index 0000000..8764b39 --- /dev/null +++ b/Makefile.Android @@ -0,0 +1,300 @@ +#************************************************************************************************** +# +# raylib makefile for Android project (APK building) +# +# Copyright (c) 2017 Ramon Santamaria (@raysan5) +# +# This software is provided "as-is", without any express or implied warranty. In no event +# will the authors be held liable for any damages arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, including commercial +# applications, and to alter it and redistribute it freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not claim that you +# wrote the original software. If you use this software in a product, an acknowledgment +# in the product documentation would be appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as such, and must not be misrepresented +# as being the original software. +# +# 3. This notice may not be removed or altered from any source distribution. +# +#************************************************************************************************** + +# Define required raylib variables +PLATFORM ?= PLATFORM_ANDROID +RAYLIB_PATH ?= ..\.. + +# Define Android architecture (armeabi-v7a, arm64-v8a, x86, x86-64) and API version +ANDROID_ARCH ?= ARM +ANDROID_API_VERSION = 21 +ifeq ($(ANDROID_ARCH),ARM) + ANDROID_ARCH_NAME = armeabi-v7a +endif +ifeq ($(ANDROID_ARCH),ARM64) + ANDROID_ARCH_NAME = arm64-v8a +endif + +# Required path variables +# NOTE: JAVA_HOME must be set to JDK +JAVA_HOME ?= C:/JavaJDK +ANDROID_HOME = C:/android-sdk +ANDROID_TOOLCHAIN = C:/android_toolchain_$(ANDROID_ARCH)_API$(ANDROID_API_VERSION) +ANDROID_BUILD_TOOLS = $(ANDROID_HOME)/build-tools/28.0.1 +ANDROID_PLATFORM_TOOLS = $(ANDROID_HOME)/platform-tools + +# Android project configuration variables +PROJECT_NAME ?= punk_n_spray +PROJECT_LIBRARY_NAME ?= main +PROJECT_BUILD_PATH ?= android.$(PROJECT_NAME) +PROJECT_RESOURCES_PATH ?= resources +PROJECT_SOURCE_FILES ?= raylib_game.c + +# Some source files are placed in directories, when compiling to some +# output directory other than source, that directory must pre-exist. +# Here we get a list of required folders that need to be created on +# code output folder $(PROJECT_BUILD_PATH)\obj to avoid GCC errors. +PROJECT_SOURCE_DIRS = $(sort $(dir $(PROJECT_SOURCE_FILES))) + +# Android app configuration variables +APP_LABEL_NAME ?= rGame +APP_COMPANY_NAME ?= raylib +APP_PRODUCT_NAME ?= rgame +APP_VERSION_CODE ?= 1 +APP_VERSION_NAME ?= 1.0 +APP_ICON_LDPI ?= $(RAYLIB_PATH)\logo\raylib_36x36.png +APP_ICON_MDPI ?= $(RAYLIB_PATH)\logo\raylib_48x48.png +APP_ICON_HDPI ?= $(RAYLIB_PATH)\logo\raylib_72x72.png +APP_SCREEN_ORIENTATION ?= landscape +APP_KEYSTORE_PASS ?= raylib + +# Library type used for raylib: STATIC (.a) or SHARED (.so/.dll) +RAYLIB_LIBTYPE ?= STATIC + +# Library path for libraylib.a/libraylib.so +RAYLIB_LIB_PATH = $(RAYLIB_PATH)\src + +# Shared libs must be added to APK if required +# NOTE: Generated NativeLoader.java automatically load those libraries +ifeq ($(RAYLIB_LIBTYPE),SHARED) + PROJECT_SHARED_LIBS = lib/$(ANDROID_ARCH_NAME)/libraylib.so +endif + +# Compiler and archiver +# NOTE: GCC is being deprecated in Android NDK r16 +ifeq ($(ANDROID_ARCH),ARM) + CC = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-clang + AR = $(ANDROID_TOOLCHAIN)/bin/arm-linux-androideabi-ar +endif +ifeq ($(ANDROID_ARCH),ARM64) + CC = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-clang + AR = $(ANDROID_TOOLCHAIN)/bin/aarch64-linux-android-ar +endif + +# Compiler flags for arquitecture +ifeq ($(ANDROID_ARCH),ARM) + CFLAGS = -std=c99 -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 +endif +ifeq ($(ANDROID_ARCH),ARM64) + CFLAGS = -std=c99 -mfix-cortex-a53-835769 +endif +# Compilation functions attributes options +CFLAGS += -ffunction-sections -funwind-tables -fstack-protector-strong -fPIC +# Compiler options for the linker +CFLAGS += -Wall -Wa,--noexecstack -Wformat -Werror=format-security -no-canonical-prefixes +# Preprocessor macro definitions +CFLAGS += -DANDROID -DPLATFORM_ANDROID -D__ANDROID_API__=$(ANDROID_API_VERSION) + +# Paths containing required header files +INCLUDE_PATHS = -I. -I$(RAYLIB_PATH)/src -I$(RAYLIB_PATH)/src/external/android/native_app_glue + +# Linker options +LDFLAGS = -Wl,-soname,lib$(PROJECT_LIBRARY_NAME).so -Wl,--exclude-libs,libatomic.a +LDFLAGS += -Wl,--build-id -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--warn-shared-textrel -Wl,--fatal-warnings +# Force linking of library module to define symbol +LDFLAGS += -u ANativeActivity_onCreate +# Library paths containing required libs +LDFLAGS += -L. -L$(PROJECT_BUILD_PATH)/obj -L$(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME) -L$(ANDROID_TOOLCHAIN)\sysroot\usr\lib + +# Define any libraries to link into executable +# if you want to link libraries (libname.so or libname.a), use the -lname +LDLIBS = -lm -lc -lraylib -llog -landroid -lEGL -lGLESv2 -lOpenSLES -ldl + +# Generate target objects list from PROJECT_SOURCE_FILES +OBJS = $(patsubst %.c, $(PROJECT_BUILD_PATH)/obj/%.o, $(PROJECT_SOURCE_FILES)) + +# Android APK building process... some steps required... +# NOTE: typing 'make' will invoke the default target entry called 'all', +all: create_temp_project_dirs \ + copy_project_required_libs \ + copy_project_resources \ + generate_loader_script \ + generate_android_manifest \ + generate_apk_keystore \ + config_project_package \ + compile_project_code \ + compile_project_class \ + compile_project_class_dex \ + create_project_apk_package \ + sign_project_apk_package \ + zipalign_project_apk_package + +# Create required temp directories for APK building +create_temp_project_dirs: + if not exist $(PROJECT_BUILD_PATH) mkdir $(PROJECT_BUILD_PATH) + if not exist $(PROJECT_BUILD_PATH)\obj mkdir $(PROJECT_BUILD_PATH)\obj + if not exist $(PROJECT_BUILD_PATH)\src mkdir $(PROJECT_BUILD_PATH)\src + if not exist $(PROJECT_BUILD_PATH)\src\com mkdir $(PROJECT_BUILD_PATH)\src\com + if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME) + if not exist $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) mkdir $(PROJECT_BUILD_PATH)\src\com\$(APP_COMPANY_NAME)\$(APP_PRODUCT_NAME) + if not exist $(PROJECT_BUILD_PATH)\lib mkdir $(PROJECT_BUILD_PATH)\lib + if not exist $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) mkdir $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME) + if not exist $(PROJECT_BUILD_PATH)\bin mkdir $(PROJECT_BUILD_PATH)\bin + if not exist $(PROJECT_BUILD_PATH)\res mkdir $(PROJECT_BUILD_PATH)\res + if not exist $(PROJECT_BUILD_PATH)\res\drawable-ldpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-ldpi + if not exist $(PROJECT_BUILD_PATH)\res\drawable-mdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-mdpi + if not exist $(PROJECT_BUILD_PATH)\res\drawable-hdpi mkdir $(PROJECT_BUILD_PATH)\res\drawable-hdpi + if not exist $(PROJECT_BUILD_PATH)\res\values mkdir $(PROJECT_BUILD_PATH)\res\values + if not exist $(PROJECT_BUILD_PATH)\assets mkdir $(PROJECT_BUILD_PATH)\assets + if not exist $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) mkdir $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) + if not exist $(PROJECT_BUILD_PATH)\obj\screens mkdir $(PROJECT_BUILD_PATH)\obj\screens + $(foreach dir, $(PROJECT_SOURCE_DIRS), $(call create_dir, $(dir))) + +define create_dir + if not exist $(PROJECT_BUILD_PATH)\obj\$(1) mkdir $(PROJECT_BUILD_PATH)\obj\$(1) +endef + +# Copy required shared libs for integration into APK +# NOTE: If using shared libs they are loaded by generated NativeLoader.java +copy_project_required_libs: +ifeq ($(RAYLIB_LIBTYPE),SHARED) + copy /Y $(RAYLIB_LIB_PATH)\libraylib.so $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.so +endif +ifeq ($(RAYLIB_LIBTYPE),STATIC) + copy /Y $(RAYLIB_LIB_PATH)\libraylib.a $(PROJECT_BUILD_PATH)\lib\$(ANDROID_ARCH_NAME)\libraylib.a +endif + +# Copy project required resources: strings.xml, icon.png, assets +# NOTE: Required strings.xml is generated and game resources are copied to assets folder +# TODO: Review xcopy usage, it can not be found in some systems! +copy_project_resources: + copy $(APP_ICON_LDPI) $(PROJECT_BUILD_PATH)\res\drawable-ldpi\icon.png /Y + copy $(APP_ICON_MDPI) $(PROJECT_BUILD_PATH)\res\drawable-mdpi\icon.png /Y + copy $(APP_ICON_HDPI) $(PROJECT_BUILD_PATH)\res\drawable-hdpi\icon.png /Y + @echo ^ > $(PROJECT_BUILD_PATH)/res/values/strings.xml + @echo ^^$(APP_LABEL_NAME)^^ >> $(PROJECT_BUILD_PATH)/res/values/strings.xml + if exist $(PROJECT_RESOURCES_PATH) C:\Windows\System32\xcopy $(PROJECT_RESOURCES_PATH) $(PROJECT_BUILD_PATH)\assets\$(PROJECT_RESOURCES_PATH) /Y /E /F + +# Generate NativeLoader.java to load required shared libraries +# NOTE: Probably not the bet way to generate this file... but it works. +generate_loader_script: + @echo package com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME); > $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo. >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo public class NativeLoader extends android.app.NativeActivity { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo static { >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java +ifeq ($(RAYLIB_LIBTYPE),SHARED) + @echo System.loadLibrary("raylib"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java +endif + @echo System.loadLibrary("$(PROJECT_LIBRARY_NAME)"); >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + @echo } >> $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + +# Generate AndroidManifest.xml with all the required options +# NOTE: Probably not the bet way to generate this file... but it works. +generate_android_manifest: + @echo ^ > $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo package="com.$(APP_COMPANY_NAME).$(APP_PRODUCT_NAME)" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:versionCode="$(APP_VERSION_CODE)" android:versionName="$(APP_VERSION_NAME)" ^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:configChanges="orientation|keyboardHidden|screenSize" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:screenOrientation="$(APP_SCREEN_ORIENTATION)" android:launchMode="singleTask" >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo android:clearTaskOnLaunch="true"^> >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + @echo ^ >> $(PROJECT_BUILD_PATH)/AndroidManifest.xml + +# Generate storekey for APK signing: $(PROJECT_NAME).keystore +# NOTE: Configure here your Distinguished Names (-dname) if required! +generate_apk_keystore: + if not exist $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore $(JAVA_HOME)/bin/keytool -genkeypair -validity 1000 -dname "CN=$(APP_COMPANY_NAME),O=Android,C=ES" -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -alias $(PROJECT_NAME)Key -keyalg RSA + +# Config project package and resource using AndroidManifest.xml and res/values/strings.xml +# NOTE: Generates resources file: src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java +config_project_package: + $(ANDROID_BUILD_TOOLS)/aapt package -f -m -S $(PROJECT_BUILD_PATH)/res -J $(PROJECT_BUILD_PATH)/src -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar + +# Compile native_app_glue code as static library: obj/libnative_app_glue.a +compile_native_app_glue: + $(CC) -c $(RAYLIB_PATH)/src/external/android/native_app_glue/android_native_app_glue.c -o $(PROJECT_BUILD_PATH)/obj/native_app_glue.o $(CFLAGS) + $(AR) rcs $(PROJECT_BUILD_PATH)/obj/libnative_app_glue.a $(PROJECT_BUILD_PATH)/obj/native_app_glue.o + +# Compile project code into a shared library: lib/lib$(PROJECT_LIBRARY_NAME).so +compile_project_code: $(OBJS) + $(CC) -o $(PROJECT_BUILD_PATH)/lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(OBJS) -shared $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) + +# Compile all .c files required into object (.o) files +# NOTE: Those files will be linked into a shared library +$(PROJECT_BUILD_PATH)/obj/%.o:%.c + $(CC) -c $^ -o $@ $(INCLUDE_PATHS) $(CFLAGS) --sysroot=$(ANDROID_TOOLCHAIN)/sysroot + +# Compile project .java code into .class (Java bytecode) +compile_project_class: + $(JAVA_HOME)/bin/javac -verbose -source 1.7 -target 1.7 -d $(PROJECT_BUILD_PATH)/obj -bootclasspath $(JAVA_HOME)/jre/lib/rt.jar -classpath $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar;$(PROJECT_BUILD_PATH)/obj -sourcepath $(PROJECT_BUILD_PATH)/src $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/R.java $(PROJECT_BUILD_PATH)/src/com/$(APP_COMPANY_NAME)/$(APP_PRODUCT_NAME)/NativeLoader.java + +# Compile .class files into Dalvik executable bytecode (.dex) +# NOTE: Since Android 5.0, Dalvik interpreter (JIT) has been replaced by ART (AOT) +compile_project_class_dex: + $(ANDROID_BUILD_TOOLS)/dx --verbose --dex --output=$(PROJECT_BUILD_PATH)/bin/classes.dex $(PROJECT_BUILD_PATH)/obj + +# Create Android APK package: bin/$(PROJECT_NAME).unsigned.apk +# NOTE: Requires compiled classes.dex and lib$(PROJECT_LIBRARY_NAME).so +# NOTE: Use -A resources to define additional directory in which to find raw asset files +create_project_apk_package: + $(ANDROID_BUILD_TOOLS)/aapt package -f -M $(PROJECT_BUILD_PATH)/AndroidManifest.xml -S $(PROJECT_BUILD_PATH)/res -A $(PROJECT_BUILD_PATH)/assets -I $(ANDROID_HOME)/platforms/android-$(ANDROID_API_VERSION)/android.jar -F $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_BUILD_PATH)/bin + cd $(PROJECT_BUILD_PATH) && $(ANDROID_BUILD_TOOLS)/aapt add bin/$(PROJECT_NAME).unsigned.apk lib/$(ANDROID_ARCH_NAME)/lib$(PROJECT_LIBRARY_NAME).so $(PROJECT_SHARED_LIBS) + +# Create signed APK package using generated Key: bin/$(PROJECT_NAME).signed.apk +sign_project_apk_package: + $(JAVA_HOME)/bin/jarsigner -keystore $(PROJECT_BUILD_PATH)/$(PROJECT_NAME).keystore -storepass $(APP_KEYSTORE_PASS) -keypass $(APP_KEYSTORE_PASS) -signedjar $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).unsigned.apk $(PROJECT_NAME)Key + +# Create zip-aligned APK package: $(PROJECT_NAME).apk +zipalign_project_apk_package: + $(ANDROID_BUILD_TOOLS)/zipalign -f 4 $(PROJECT_BUILD_PATH)/bin/$(PROJECT_NAME).signed.apk $(PROJECT_NAME).apk + +# Install $(PROJECT_NAME).apk to default emulator/device +# NOTE: Use -e (emulator) or -d (device) parameters if required +install: + $(ANDROID_PLATFORM_TOOLS)/adb install --abi $(ANDROID_ARCH_NAME) -rds $(PROJECT_NAME).apk + +# Check supported ABI for the device (armeabi-v7a, arm64-v8a, x86, x86_64) +check_device_abi: + $(ANDROID_PLATFORM_TOOLS)/adb shell getprop ro.product.cpu.abi + +# Monitorize output log coming from device, only raylib tag +logcat: + $(ANDROID_PLATFORM_TOOLS)/adb logcat -c + $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S + +# Install and monitorize $(PROJECT_NAME).apk to default emulator/device +deploy: + $(ANDROID_PLATFORM_TOOLS)/adb install -r $(PROJECT_NAME).apk + $(ANDROID_PLATFORM_TOOLS)/adb logcat -c + $(ANDROID_PLATFORM_TOOLS)/adb logcat raylib:V *:S + +#$(ANDROID_PLATFORM_TOOLS)/adb logcat *:W + +# Clean everything +clean: + del $(PROJECT_BUILD_PATH)\ */f /s /q + rmdir $(PROJECT_BUILD_PATH) /s /q + @echo Cleaning done diff --git a/build/pns b/build/pns new file mode 100755 index 0000000..6cb67dd Binary files /dev/null and b/build/pns differ diff --git a/main.code-workspace b/main.code-workspace new file mode 100644 index 0000000..267248e --- /dev/null +++ b/main.code-workspace @@ -0,0 +1,16 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "files.associations": { + "raylib.h": "c", + "math.h": "c", + "blocks.h": "c", + "stdio.h": "c", + "*.m": "c" + } + } +} \ No newline at end of file diff --git a/resources/fonts/CyberpunkRegular.ttf b/resources/fonts/CyberpunkRegular.ttf new file mode 100644 index 0000000..91b2512 Binary files /dev/null and b/resources/fonts/CyberpunkRegular.ttf differ diff --git a/resources/fonts/CyberpunkTitles.ttf b/resources/fonts/CyberpunkTitles.ttf new file mode 100644 index 0000000..8d0d966 Binary files /dev/null and b/resources/fonts/CyberpunkTitles.ttf differ diff --git a/resources/images/Miarma.png b/resources/images/Miarma.png new file mode 100644 index 0000000..5351e28 Binary files /dev/null and b/resources/images/Miarma.png differ diff --git a/resources/images/PunkNSpray.png b/resources/images/PunkNSpray.png new file mode 100644 index 0000000..be67ecc Binary files /dev/null and b/resources/images/PunkNSpray.png differ diff --git a/resources/textures/crouch_idle_48x48.png b/resources/textures/crouch_idle_48x48.png new file mode 100644 index 0000000..fe7b4ad Binary files /dev/null and b/resources/textures/crouch_idle_48x48.png differ diff --git a/resources/textures/crouch_walk_48x48.png b/resources/textures/crouch_walk_48x48.png new file mode 100644 index 0000000..902ef2a Binary files /dev/null and b/resources/textures/crouch_walk_48x48.png differ diff --git a/resources/textures/cute_backgrounds.png b/resources/textures/cute_backgrounds.png new file mode 100644 index 0000000..3e13040 Binary files /dev/null and b/resources/textures/cute_backgrounds.png differ diff --git a/resources/textures/cute_characters.png b/resources/textures/cute_characters.png new file mode 100644 index 0000000..8b1285a Binary files /dev/null and b/resources/textures/cute_characters.png differ diff --git a/resources/textures/cute_tiles.png b/resources/textures/cute_tiles.png new file mode 100644 index 0000000..798044f Binary files /dev/null and b/resources/textures/cute_tiles.png differ diff --git a/resources/textures/idle_48x48.png b/resources/textures/idle_48x48.png new file mode 100644 index 0000000..b618511 Binary files /dev/null and b/resources/textures/idle_48x48.png differ diff --git a/resources/textures/jump_48x48.png b/resources/textures/jump_48x48.png new file mode 100644 index 0000000..2551816 Binary files /dev/null and b/resources/textures/jump_48x48.png differ diff --git a/resources/textures/land_48x48.png b/resources/textures/land_48x48.png new file mode 100644 index 0000000..2c24d6f Binary files /dev/null and b/resources/textures/land_48x48.png differ diff --git a/resources/textures/run_48x48.png b/resources/textures/run_48x48.png new file mode 100644 index 0000000..aca5b55 Binary files /dev/null and b/resources/textures/run_48x48.png differ diff --git a/resources/textures/walk_48x48.png b/resources/textures/walk_48x48.png new file mode 100644 index 0000000..653bd2f Binary files /dev/null and b/resources/textures/walk_48x48.png differ diff --git a/src/components/collider.h b/src/components/collider.h new file mode 100644 index 0000000..e85752a --- /dev/null +++ b/src/components/collider.h @@ -0,0 +1,18 @@ +#ifndef COLLIDER_H +#define COLLIDER_H + +#include "raylib.h" +#include "entity.h" + +typedef struct { + float width; + float height; + bool isTrigger; +} Collider; + +typedef struct { + EntityId id; + Collider collider; +} ColliderComponent; + +#endif \ No newline at end of file diff --git a/src/components/input.h b/src/components/input.h new file mode 100644 index 0000000..f321265 --- /dev/null +++ b/src/components/input.h @@ -0,0 +1,16 @@ +#ifndef INPUT_H +#define INPUT_H + +#include "raylib.h" +#include "entity.h" + +typedef struct { + bool up, down, left, right; +} Input; + +typedef struct { + EntityId id; + Input input; +} InputComponent; + +#endif \ No newline at end of file diff --git a/src/components/movement.h b/src/components/movement.h new file mode 100644 index 0000000..2403cd5 --- /dev/null +++ b/src/components/movement.h @@ -0,0 +1,12 @@ +#ifndef MOVEMENT_H +#define MOVEMENT_H + +#include "raylib.h" +#include + +typedef struct { + Vector2 direction; + bool running; +} MovementIntent; + +#endif \ No newline at end of file diff --git a/src/components/position.h b/src/components/position.h new file mode 100644 index 0000000..d0cc2b7 --- /dev/null +++ b/src/components/position.h @@ -0,0 +1,12 @@ +#ifndef POSITION_H +#define POSITION_H + +#include "raylib.h" +#include "entity.h" + +typedef struct { + EntityId id; + Vector2 position; +} PositionComponent; + +#endif \ No newline at end of file diff --git a/src/components/renderable.h b/src/components/renderable.h new file mode 100644 index 0000000..ec284f3 --- /dev/null +++ b/src/components/renderable.h @@ -0,0 +1,19 @@ +#ifndef RENDERABLE_H +#define RENDERABLE_H + +#include "raylib.h" +#include "entity.h" + +typedef struct { + Texture2D texture; + Rectangle source; + Vector2 origin; + float scale; +} Renderable; + +typedef struct { + EntityId id; + Renderable renderable; +} RenderableComponent; + +#endif \ No newline at end of file diff --git a/src/components/sprite.h b/src/components/sprite.h new file mode 100644 index 0000000..355c70c --- /dev/null +++ b/src/components/sprite.h @@ -0,0 +1,26 @@ +#ifndef SPRITE_H +#define SPRITE_H + +#include "raylib.h" + +typedef struct { + Texture2D texture; + int frameCount; + int currentFrame; + float frameTime; + float elapsedTime; + Rectangle source; + float scale; + Vector2 origin; + float rotation; +} Animation; + +typedef struct { + Animation *animations; + Animation *mirroredAnimations; + int animationCount; + int currentAnimation; + Animation *currentAnimationPtr; +} SpriteComponent; + +#endif \ No newline at end of file diff --git a/src/components/velocity.h b/src/components/velocity.h new file mode 100644 index 0000000..7670ea7 --- /dev/null +++ b/src/components/velocity.h @@ -0,0 +1,12 @@ +#ifndef VELOCITY_H +#define VELOCITY_H + +#include "raylib.h" +#include "entity.h" + +typedef struct { + EntityId id; + Vector2 velocity; +} VelocityComponent; + +#endif \ No newline at end of file diff --git a/src/core/game.c b/src/core/game.c new file mode 100644 index 0000000..d928db2 --- /dev/null +++ b/src/core/game.c @@ -0,0 +1,103 @@ +#include "game.h" + +#define MAX_ENTITIES 100 + +typedef struct +{ + Camera2D camera; + bool running; + int score; + int level; +} GameState; + +static GameState game; + +int entityCount = 0; + +Entity *entities = NULL; +InputComponent *inputs = NULL; +PositionComponent *positions = NULL; +VelocityComponent *velocities = NULL; +MovementIntent *intents = NULL; +SpriteComponent *sprites = NULL; + +Result InitGame(void) +{ + game.camera = (Camera2D){0}; + game.running = true; + game.score = 0; + + if (InitGameWindow() != RESULT_OK) + return RESULT_FAIL; + + game.camera.target = (Vector2){0, 0}; + game.camera.offset = (Vector2){400, 300}; + game.camera.zoom = 1.0f; + + SetTargetFPS(60); + + int id = AddEntity(); + InitPlayer(id, entities, positions, velocities, inputs, + sprites, WIDTH / 2, HEIGHT / 2); + + return RESULT_OK; +} + +int AddEntity(void) { + int id = entityCount; + + entities = realloc(entities, sizeof(Entity) * (entityCount + 1)); + inputs = realloc(inputs, sizeof(InputComponent) * (entityCount + 1)); + positions = realloc(positions, sizeof(PositionComponent) * (entityCount + 1)); + velocities = realloc(velocities, sizeof(VelocityComponent) * (entityCount + 1)); + intents = realloc(intents, sizeof(MovementIntent) * (entityCount + 1)); + sprites = realloc(sprites, sizeof(SpriteComponent) * (entityCount + 1)); + + entities[id].id = id; + entities[id].components = 0; + + inputs[id].id = id; inputs[id].input = (Input){0}; + positions[id].id = id; positions[id].position = (Vector2){0,0}; + velocities[id].id = id; velocities[id].velocity = (Vector2){0,0}; + intents[id].direction = (Vector2){0,0}; intents[id].running = false; + + entityCount++; + return id; +} + +void UpdateGame(float dt) +{ + HandleWindowEvents(); + + InputSystemUpdate(entities, inputs, entityCount); + IntentSystemUpdate(entities, inputs, intents, entityCount); + MovementSystemUpdate(entities, positions, velocities, intents, entityCount, dt); + AnimationSystemUpdate(entities, sprites, intents, entityCount, dt); +} + +void DrawGame(void) +{ + BeginDrawing(); + ClearBackground(RAYWHITE); + RenderSystemDraw(entities, positions, sprites, entityCount); + EndDrawing(); +} + +void UnloadGame(void) { + for (int i = 0; i < entityCount; i++) { + if (entities[i].components & COMP_RENDERABLE) { + SpriteComponent *s = &sprites[i]; + for (int a = 0; a < s->animationCount; a++) + UnloadTexture(s->animations[a].texture); + UnloadTexture(s->mirroredAnimations[i].texture); + free(s->animations); + free(s->mirroredAnimations); + } + } + free(entities); + free(inputs); + free(positions); + free(velocities); + free(intents); + free(sprites); +} \ No newline at end of file diff --git a/src/core/game.h b/src/core/game.h new file mode 100644 index 0000000..816224a --- /dev/null +++ b/src/core/game.h @@ -0,0 +1,28 @@ +#ifndef GAME_H +#define GAME_H + +#include "raylib.h" + +#include + +#include "window.h" +#include "result.h" +#include "entity.h" +#include "player.h" +#include "input.h" +#include "movement.h" +#include "sprite.h" + +#include "input_system.h" +#include "intent_system.h" +#include "movement_system.h" +#include "animation_system.h" +#include "render_system.h" + +Result InitGame(void); +int AddEntity(void); +void UpdateGame(float dt); +void DrawGame(void); +void UnloadGame(void); + +#endif \ No newline at end of file diff --git a/src/core/result.h b/src/core/result.h new file mode 100644 index 0000000..3678380 --- /dev/null +++ b/src/core/result.h @@ -0,0 +1,12 @@ +#ifndef RESULT_H +#define RESULT_H + +typedef enum { + RESULT_OK = 0, + RESULT_FAIL, + RESULT_INVALID_ARGUMENT, + RESULT_INIT_FAILED, + RESULT_NOT_FOUND +} Result; + +#endif \ No newline at end of file diff --git a/src/core/window.c b/src/core/window.c new file mode 100644 index 0000000..53fb4a1 --- /dev/null +++ b/src/core/window.c @@ -0,0 +1,83 @@ +#include "window.h" + +const char *TITLE = "Punk n' Spray"; +const int WIDTH = 900; +const int HEIGHT = 600; + +Result InitGameWindow(void) +{ + SetConfigFlags(FLAG_WINDOW_HIGHDPI); + + InitWindow(WIDTH, HEIGHT, TITLE); + + if (!IsWindowReady()) + return RESULT_INIT_FAILED; + + return RESULT_OK; +} + +void HandleWindowEvents() +{ + if (IsKeyPressed(KEY_F11)) + { + int display = GetCurrentMonitor(); + + if (IsWindowFullscreen()) + { + SetWindowSize(WIDTH, HEIGHT); + } + else + { + SetWindowSize(GetMonitorWidth(display), GetMonitorHeight(display)); + } + + ToggleFullscreen(); + } +} + +void ShowSplashScreen(void) +{ + Image logoImg = LoadImage("resources/images/PunkNSpray.png"); + Image miarmaImg = LoadImage("resources/images/Miarma.png"); + ImageResize(&miarmaImg, 64, 64); + + Texture2D logo = LoadTextureFromImage(logoImg); + Texture2D miarma = LoadTextureFromImage(miarmaImg); + UnloadImage(logoImg); + UnloadImage(miarmaImg); + + Font font = LoadFontEx("resources/fonts/CyberpunkRegular.ttf", 24, NULL, 0); + + float timer = 0.0f; + const float duration = 3.0f; + + while (timer < duration && !WindowShouldClose()) { + BeginDrawing(); + ClearBackground(WHITE); + + // logo juego centrado + int logoX = (WIDTH - logo.width) / 2; + int logoY = (HEIGHT - logo.height) / 2 - 40; + DrawTexture(logo, logoX, logoY, WHITE); + + // texto centrado encima del logo + const char *text = "Desarrollado por"; + int textWidth = MeasureText(text, 24); + int textX = (WIDTH - textWidth) / 2 - 20; + int textY = logoY + logo.height - 30; + DrawTextEx(font, text, (Vector2){(float)textX, (float)textY}, + (float)font.baseSize, 2, BLACK); + + // logo miarma centrado debajo del texto + int miarmaX = (WIDTH - miarma.width) / 2; + int miarmaY = textY + 20; + DrawTexture(miarma, miarmaX, miarmaY, WHITE); + + timer += GetFrameTime(); + EndDrawing(); + } + + UnloadTexture(logo); + UnloadTexture(miarma); + UnloadFont(font); +} \ No newline at end of file diff --git a/src/core/window.h b/src/core/window.h new file mode 100644 index 0000000..3a474fa --- /dev/null +++ b/src/core/window.h @@ -0,0 +1,16 @@ +#ifndef WINDOW_H +#define WINDOW_H + +#include "result.h" +#include "raylib.h" +#include + +extern const char *TITLE; +extern const int WIDTH; +extern const int HEIGHT; + +Result InitGameWindow(void); +void HandleWindowEvents(void); +void ShowSplashScreen(void); + +#endif \ No newline at end of file diff --git a/src/entities/entity.c b/src/entities/entity.c new file mode 100644 index 0000000..e69de29 diff --git a/src/entities/entity.h b/src/entities/entity.h new file mode 100644 index 0000000..00af815 --- /dev/null +++ b/src/entities/entity.h @@ -0,0 +1,19 @@ +#ifndef ENTITY_H +#define ENTITY_H + +#include + +typedef int EntityId; + +typedef struct { + EntityId id; + uint32_t components; +} Entity; + +#define COMP_POSITION 0x01 +#define COMP_VELOCITY 0x02 +#define COMP_INPUT 0x03 +#define COMP_COLLIDER 0x04 +#define COMP_RENDERABLE 0x05 + +#endif \ No newline at end of file diff --git a/src/entities/player.c b/src/entities/player.c new file mode 100644 index 0000000..49e633d --- /dev/null +++ b/src/entities/player.c @@ -0,0 +1,54 @@ +#include "player.h" + +void InitPlayer(int id, Entity *entities, PositionComponent *positions, + VelocityComponent *velocities, InputComponent *inputs, + SpriteComponent *sprites, float x, float y) + { + Entity *player = &entities[id]; + + positions[id].position = (Vector2){x, y}; + velocities[id].velocity = (Vector2){0,0}; + inputs[id].input = (Input){0}; + + SpriteComponent *s = &sprites[id]; + s->animationCount = 3; + s->currentAnimation = 0; + s->animations = malloc(sizeof(Animation) * s->animationCount); + + // idle + s->animations[0].texture = LoadTexture("resources/textures/idle_48x48.png"); + s->animations[0].frameCount = 10; + s->animations[0].currentFrame = 0; + s->animations[0].frameTime = 0.15f; + s->animations[0].elapsedTime = 0; + s->animations[0].source = (Rectangle){0, 0, s->animations[0].texture.width / s->animations[0].frameCount, s->animations[0].texture.height}; + s->animations[0].origin = (Vector2){s->animations[0].source.width / 2, s->animations[0].source.height / 2}; + s->animations[0].rotation = 0; + s->animations[0].scale = 1.0f; + + // walk + s->animations[1].texture = LoadTexture("resources/textures/walk_48x48.png"); + s->animations[1].frameCount = 8; + s->animations[1].currentFrame = 0; + s->animations[1].frameTime = 0.1f; + s->animations[1].elapsedTime = 0; + s->animations[1].source = (Rectangle){0, 0, s->animations[1].texture.width / s->animations[1].frameCount, s->animations[1].texture.height}; + s->animations[1].origin = (Vector2){s->animations[1].source.width / 2, s->animations[1].source.height / 2}; + s->animations[1].rotation = 0; + s->animations[1].scale = 1.0f; + + // run + s->animations[2].texture = LoadTexture("resources/textures/run_48x48.png"); + s->animations[2].frameCount = 8; + s->animations[2].currentFrame = 0; + s->animations[2].frameTime = 0.08f; + s->animations[2].elapsedTime = 0; + s->animations[2].source = (Rectangle){0, 0, s->animations[2].texture.width / s->animations[2].frameCount, s->animations[2].texture.height}; + s->animations[2].origin = (Vector2){s->animations[2].source.width / 2, s->animations[2].source.height / 2}; + s->animations[2].rotation = 0; + s->animations[2].scale = 1.0f; + + s->mirroredAnimations = MirrorAnimations(s->animations, s->animationCount); + + player->components = COMP_POSITION | COMP_VELOCITY | COMP_INPUT | COMP_RENDERABLE; +} \ No newline at end of file diff --git a/src/entities/player.h b/src/entities/player.h new file mode 100644 index 0000000..524896d --- /dev/null +++ b/src/entities/player.h @@ -0,0 +1,17 @@ +#ifndef PLAYER_H +#define PLAYER_H + +#include "position.h" +#include "velocity.h" +#include "raylib.h" +#include "input.h" +#include "entity.h" +#include "sprite.h" +#include "stdlib.h" +#include "animation_util.h" + +void InitPlayer(int id, Entity *entities, PositionComponent *positions, + VelocityComponent *velocities, InputComponent *inputs, + SpriteComponent *sprites, float x, float y); + +#endif \ No newline at end of file diff --git a/src/level/level.c b/src/level/level.c new file mode 100644 index 0000000..e69de29 diff --git a/src/level/level.h b/src/level/level.h new file mode 100644 index 0000000..54e0de3 --- /dev/null +++ b/src/level/level.h @@ -0,0 +1,4 @@ +#ifndef LEVEL_H +#define LEVEL_H + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..ec88e5f --- /dev/null +++ b/src/main.c @@ -0,0 +1,21 @@ +#include "core/result.h" +#include "raylib.h" +#include "core/game.h" + +int main() +{ + InitGame(); + ShowSplashScreen(); + + while (!WindowShouldClose()) + { + float dt = GetFrameTime(); + UpdateGame(dt); + DrawGame(); + } + + UnloadGame(); + CloseWindow(); + + return RESULT_OK; +} \ No newline at end of file diff --git a/src/math/vector.c b/src/math/vector.c new file mode 100644 index 0000000..6cb3db2 --- /dev/null +++ b/src/math/vector.c @@ -0,0 +1,10 @@ +#include "vector.h" + +void NormalizeVector(Vector2 *vector) +{ + float m = sqrtf(vector->x * vector->x + vector->y * vector->y); + if (m > 0.0001f) + *vector = (Vector2){ vector->x / m, vector->y / m }; + else + *vector = (Vector2){ 0, 0 }; +} \ No newline at end of file diff --git a/src/math/vector.h b/src/math/vector.h new file mode 100644 index 0000000..f613cc9 --- /dev/null +++ b/src/math/vector.h @@ -0,0 +1,9 @@ +#ifndef VECTOR_H +#define VECTOR_H + +#include "raylib.h" +#include "math.h" + +void NormalizeVector(Vector2 *vector); + +#endif \ No newline at end of file diff --git a/src/systems/animation_system.c b/src/systems/animation_system.c new file mode 100644 index 0000000..d9c590b --- /dev/null +++ b/src/systems/animation_system.c @@ -0,0 +1,47 @@ +#include "animation_system.h" + +void AnimationSystemUpdate(Entity *entities, + SpriteComponent *sprites, + MovementIntent *intents, + size_t count, + float dt) +{ + for (size_t i = 0; i < count; i++) + { + if (!(entities[i].components & COMP_RENDERABLE)) + continue; + + SpriteComponent *s = &sprites[i]; + + Animation *animToDraw = (intents[i].direction.x < 0) ? &s->mirroredAnimations[s->currentAnimation] : &s->animations[s->currentAnimation]; + + int newAnim = 0; + if (intents[i].direction.x != 0 || intents[i].direction.y != 0) + newAnim = intents[i].running ? 2 : 1; + + if (s->currentAnimation != newAnim) + { + s->currentAnimation = newAnim; + s->animations[newAnim].currentFrame = 0; + s->animations[newAnim].elapsedTime = 0; + s->mirroredAnimations[newAnim].currentFrame = 0; + s->mirroredAnimations[newAnim].elapsedTime = 0; + } + + // Actualizar frame + animToDraw->elapsedTime += dt; + if (animToDraw->elapsedTime >= animToDraw->frameTime) + { + animToDraw->currentFrame = (animToDraw->currentFrame + 1) % animToDraw->frameCount; + animToDraw->elapsedTime = 0; + } + + // Actualizar source rectangle + animToDraw->source.x = animToDraw->currentFrame * (animToDraw->texture.width / animToDraw->frameCount); + animToDraw->source.y = 0; + animToDraw->source.width = animToDraw->texture.width / animToDraw->frameCount; + animToDraw->source.height = animToDraw->texture.height; + + s->currentAnimationPtr = animToDraw; + } +} \ No newline at end of file diff --git a/src/systems/animation_system.h b/src/systems/animation_system.h new file mode 100644 index 0000000..f8bebf5 --- /dev/null +++ b/src/systems/animation_system.h @@ -0,0 +1,16 @@ +#ifndef ANIMATION_SYSTEM_H +#define ANIMATION_SYSTEM_H + +#include "raylib.h" +#include "sprite.h" +#include "entity.h" +#include "stdlib.h" +#include "movement.h" + +void AnimationSystemUpdate(Entity *entities, + SpriteComponent *sprites, + MovementIntent *intents, + size_t count, + float dt); + +#endif \ No newline at end of file diff --git a/src/systems/input_system.c b/src/systems/input_system.c new file mode 100644 index 0000000..eba3a40 --- /dev/null +++ b/src/systems/input_system.c @@ -0,0 +1,17 @@ +#include "input_system.h" + +void InputSystemUpdate(Entity *entities, + InputComponent *inputs, + size_t count) +{ + for (size_t i = 0; i < count; i++) + { + if (!(entities[i].components & COMP_INPUT)) + continue; + + inputs[i].input.up = IsKeyDown(KEY_W); + inputs[i].input.down = IsKeyDown(KEY_S); + inputs[i].input.left = IsKeyDown(KEY_A); + inputs[i].input.right = IsKeyDown(KEY_D); + } +} \ No newline at end of file diff --git a/src/systems/input_system.h b/src/systems/input_system.h new file mode 100644 index 0000000..de19972 --- /dev/null +++ b/src/systems/input_system.h @@ -0,0 +1,12 @@ +#ifndef INPUT_SYSTEM_H +#define INPUT_SYSTEM_H + +#include +#include "raylib.h" +#include "input.h" +#include "vector.h" +#include "entity.h" + +void InputSystemUpdate(Entity *entities, InputComponent *inputs, size_t count); + +#endif \ No newline at end of file diff --git a/src/systems/intent_system.c b/src/systems/intent_system.c new file mode 100644 index 0000000..96f1fe3 --- /dev/null +++ b/src/systems/intent_system.c @@ -0,0 +1,26 @@ +#include "intent_system.h" + +void IntentSystemUpdate(Entity *entities, + InputComponent *inputs, + MovementIntent *intents, + size_t count) +{ + for (size_t i = 0; i < count; i++) + { + if (!(entities[i].components & COMP_INPUT)) + continue; + + Vector2 dir = {0, 0}; + + if (inputs[i].input.up) dir.y -= 1; + if (inputs[i].input.down) dir.y += 1; + if (inputs[i].input.left) dir.x -= 1; + if (inputs[i].input.right) dir.x += 1; + + if (fabsf(dir.x) > 0.0001f || fabsf(dir.y) > 0.0001f) + NormalizeVector(&dir); + + intents[i].direction = dir; + intents[i].running = IsKeyDown(KEY_LEFT_SHIFT); + } +} \ No newline at end of file diff --git a/src/systems/intent_system.h b/src/systems/intent_system.h new file mode 100644 index 0000000..250fba4 --- /dev/null +++ b/src/systems/intent_system.h @@ -0,0 +1,14 @@ +#ifndef INTENT_SYSTEM_H +#define INTENT_SYSTEM_H + +#include "entity.h" +#include "input.h" +#include +#include "raylib.h" +#include "movement.h" +#include "math.h" +#include "vector.h" + +void IntentSystemUpdate(Entity *entities, InputComponent *inputs, MovementIntent *intents, size_t count); + +#endif \ No newline at end of file diff --git a/src/systems/movement_system.c b/src/systems/movement_system.c new file mode 100644 index 0000000..cf53f7b --- /dev/null +++ b/src/systems/movement_system.c @@ -0,0 +1,30 @@ +#include "movement_system.h" + +void MovementSystemUpdate(Entity *entities, + PositionComponent *positions, + VelocityComponent *velocities, + MovementIntent *intents, + size_t count, + float dt) +{ + const float baseSpeed = 200.0f; + const float runMultiplier = 1.5f; + + for (size_t i = 0; i < count; i++) + { + if (!(entities[i].components & COMP_POSITION) || + !(entities[i].components & COMP_VELOCITY)) + continue; + + Vector2 dir = intents[i].direction; + + float speed = baseSpeed * + (intents[i].running ? runMultiplier : 1.0f); + + velocities[i].velocity.x = dir.x * speed; + velocities[i].velocity.y = dir.y * speed; + + positions[i].position.x += velocities[i].velocity.x * dt; + positions[i].position.y += velocities[i].velocity.y * dt; + } +} \ No newline at end of file diff --git a/src/systems/movement_system.h b/src/systems/movement_system.h new file mode 100644 index 0000000..6ba1de7 --- /dev/null +++ b/src/systems/movement_system.h @@ -0,0 +1,14 @@ +#ifndef MOVEMENT_SYSTEM_H +#define MOVEMENT_SYSTEM_H + +#include +#include "raylib.h" +#include "position.h" +#include "velocity.h" +#include "movement.h" +#include "entity.h" + +void MovementSystemUpdate(Entity *entities, PositionComponent *positions, + VelocityComponent *velocities, MovementIntent *intents, size_t count, + float dt); +#endif \ No newline at end of file diff --git a/src/systems/physics_system.c b/src/systems/physics_system.c new file mode 100644 index 0000000..a035c24 --- /dev/null +++ b/src/systems/physics_system.c @@ -0,0 +1,10 @@ +#include "physics_system.h" + +void PhysicsSystemUpdate(Entity *entities, + size_t count, + float dt) +{ + for(size_t i = 0; i < count; i++) { + + } +} \ No newline at end of file diff --git a/src/systems/physics_system.h b/src/systems/physics_system.h new file mode 100644 index 0000000..be8fe2a --- /dev/null +++ b/src/systems/physics_system.h @@ -0,0 +1,10 @@ +#ifndef PHYSICS_SYSTEM_H +#define PHYSICS_SYSTEM_H + +#include "raylib.h" +#include "entity.h" +#include + +void PhysicsSystemUpdate(Entity *entities, size_t count, float dt); + +#endif \ No newline at end of file diff --git a/src/systems/render_system.c b/src/systems/render_system.c new file mode 100644 index 0000000..c35cf64 --- /dev/null +++ b/src/systems/render_system.c @@ -0,0 +1,27 @@ +#include "render_system.h" + +void RenderSystemDraw(Entity *entities, PositionComponent *positions, SpriteComponent *sprites, size_t count) +{ + for (size_t i = 0; i < count; i++) + { + if (!(entities[i].components & COMP_POSITION)) + continue; + + Vector2 pos = positions[i].position; + + if (entities[i].components & COMP_RENDERABLE) + { + SpriteComponent *s = &sprites[i]; + + DrawTextureRec( + s->currentAnimationPtr->texture, + s->currentAnimationPtr->source, + pos, + WHITE); + } + else + { + DrawRectangle(pos.x, pos.y, 32, 32, RED); + } + } +} \ No newline at end of file diff --git a/src/systems/render_system.h b/src/systems/render_system.h new file mode 100644 index 0000000..19d8df1 --- /dev/null +++ b/src/systems/render_system.h @@ -0,0 +1,12 @@ +#ifndef RENDER_SYSTEM_H +#define RENDER_SYSTEM_H + +#include +#include "raylib.h" +#include "position.h" +#include "entity.h" +#include "sprite.h" + +void RenderSystemDraw(Entity *entities, PositionComponent *positions, SpriteComponent *sprites, size_t count); + +#endif \ No newline at end of file diff --git a/src/util/animation_util.c b/src/util/animation_util.c new file mode 100644 index 0000000..668254b --- /dev/null +++ b/src/util/animation_util.c @@ -0,0 +1,24 @@ +#include "animation_util.h" + +Animation *MirrorAnimations(Animation *originalAnimations, int count) +{ + if (!originalAnimations || count <= 0) return NULL; + + Animation *mirrored = malloc(sizeof(Animation) * count); + if (!mirrored) return NULL; + + for (int i = 0; i < count; i++) + { + mirrored[i] = originalAnimations[i]; + mirrored[i].currentFrame = 0; + mirrored[i].elapsedTime = 0; + + // mirror + Image img = LoadImageFromTexture(originalAnimations[i].texture); + ImageFlipHorizontal(&img); + mirrored[i].texture = LoadTextureFromImage(img); + UnloadImage(img); + } + + return mirrored; +} \ No newline at end of file diff --git a/src/util/animation_util.h b/src/util/animation_util.h new file mode 100644 index 0000000..5cb569f --- /dev/null +++ b/src/util/animation_util.h @@ -0,0 +1,11 @@ +#ifndef ANIMATION_UTIL_H +#define ANIMATION_UTIL_H + +#include "sprite.h" +#include "raylib.h" +#include +#include + +Animation *MirrorAnimations(Animation *originalAnimations, int count); + +#endif \ No newline at end of file