diff --git a/.gitignore b/.gitignore
index 329b8ca..2ac2739 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,8 @@ BenchmarkDotNet.Artifacts/
project.lock.json
project.fragment.lock.json
artifacts/
+/sample/AnnetteWorld/
+/sample/random_stuff/
# StyleCop
StyleCopReport.xml
@@ -380,3 +382,4 @@ _deps
#clangd
.cache/
+TremblingFantasy/
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 41127c1..e7c5411 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,9 +11,12 @@ if(DOENGINE_COVERAGE)
endif()
# set(CMAKE_EXPORT_COMPILE_COMMANDS true)
-
+
+set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(FETCH_SDL_FROM_GIT true)
-set(DOENGINE_PREFERED_LANGUAGE 11)
+set(FETCH_GLM_FROM_GIT true)
+set(BUILD_SAMPLE_ACTIVE false)
+set(DOENGINE_PREFERED_LANGUAGE 17)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD ${DOENGINE_PREFERED_LANGUAGE})
@@ -23,11 +26,18 @@ set(SDL2_DISABLE_INSTALL OFF)
set(SDL2TTF_VENDORED TRUE)
if(FETCH_SDL_FROM_GIT)
- include(cmake-module/fetchSDLProjectFromSource.cmake)
+ include(cmake-module/fetchSDL3ProjectFromSource.cmake)
else()
message("WARNING: SDL Would the Machine Installed Version")
endif()
+if(FETCH_GLM_FROM_GIT)
+ include(cmake-module/fetchGLMProjectFromSource.cmake)
+ else()
+ message("WARNING: SDL Would the Machine Installed Version")
+endif()
+
+
set(ASSETS_DIR ${CMAKE_SOURCE_DIR}/assets)
if(DOENGINE_TESTS)
@@ -50,6 +60,10 @@ set(DOENGINE_SRC
src/Application/OpenglLoader.cpp
src/Application/Geometric.cpp
src/Application/Logger.cpp
+ src/Application/opengl_decls.cpp
+ src/Application/opengl_decls.h
+ src/Application/SDLOpenglWindow.cpp
+ src/Application/SDLOpenglRenderer.cpp
src/Application/SDLWindowManager.cpp
src/Application/WindowManager.cpp
src/Application/SDLWindowManager.h
@@ -57,31 +71,45 @@ set(DOENGINE_SRC
src/Application/SDLRenderer.h
src/Application/SDLTTFText.h
src/Application/SDLTTFText.cpp
+ src/Application/Timer.cpp
src/Application/Application.cpp
src/Application/StringUtils.cpp
src/Timer/FPSManager.cpp
src/GameState/GameStateManager.cpp
src/Timer/FPSManager.cpp
src/Tilemap/Tilemap.cpp
+ src/Tilemap/TileMapEditor.cpp
src/Texture/Texture.cpp
src/Event/SDLMouse.cpp
src/Event/SDLKeyboard.cpp
src/Music/SDLMusicHandler.cpp
- src/Music/SDLSoundHandler.cpp
- src/Event/SDLJoypad.cpp
- src/Music/SDLMusicHandler.cpp
- src/GameObject/GameObject.cpp
- src/Font/TTFText.cpp
- src/Event/Event.cpp
- src/Drawable/Gui.cpp
- src/Application/SDLTexture.cpp
- src/Application/SDLTexture.h
- includes/NativeStructs.h
- includes/Geometric.h
- includes/Color.h
- includes/defines.h
- includes/TTFText.h
- includes/Camera.h
+ src/Music/SDLSoundHandler.cpp
+ src/Event/SDLJoypad.cpp
+ src/Music/SDLMusicHandler.cpp
+ src/GameObject/GameObject.cpp
+ src/Font/TTFText.cpp
+ src/Font/FontCache.cpp
+ src/Event/Event.cpp
+ src/Event/EventHandler.cpp
+ src/Drawable/Gui.cpp
+ src/Drawable/UI.cpp
+ src/Drawable/TextField.cpp
+ src/Application/GameState.cpp
+ src/Application/Camera.cpp
+ src/Application/SDLTexture.cpp
+ src/Application/SDLTexture.h
+ src/Drawable/GameObject.cpp
+ src/Drawable/Draggable.cpp
+ src/Drawable/DraggableGameObject.cpp
+ src/Drawable/SelectionRect.cpp
+ src/Drawable/MessageBox.cpp
+ includes/NativeStructs.h
+ includes/Geometric.h
+ includes/Color.h
+ includes/defines.h
+ includes/TTFText.h
+ includes/FontCache.h
+ includes/Camera.h
includes/Event.h
includes/DOEngine.h
includes/DOEngine_SDL_includes.h
@@ -91,22 +119,30 @@ set(DOENGINE_SRC
includes/GameState.h
includes/GameStateManager.h
includes/Grids.h
- includes/LinkList.h
- includes/sort.h
- includes/Sprite.h
- includes/Utils.h
- includes/Texture.h
- includes/Tile.h
- includes/Tilemap.h
- includes/UDPPacket.h
- includes/Vector.h
- includes/Application.h
- includes/Mouse.h
- includes/Keyboard.h
- includes/Joypad.h
- includes/MusicHandler.h
- includes/SDLMusicHandler.h
- includes/SDLSoundHandler.h
+ includes/LinkList.h
+ includes/sort.h
+ includes/Sprite.h
+ includes/Utils.h
+ includes/Texture.h
+ includes/Tile.h
+ includes/Tilemap.h
+ includes/TileMapEditor.h
+ includes/UDPPacket.h
+ includes/Vector.h
+ includes/Application.h
+ includes/Mouse.h
+ includes/Keyboard.h
+ includes/Joypad.h
+ includes/MusicHandler.h
+ includes/SDLMusicHandler.h
+ includes/SDLSoundHandler.h
+ includes/UI.h
+ includes/Draggable.h
+ includes/DraggableGameObject.h
+ includes/SelectionRect.h
+ includes/SpriteOffset.h
+ includes/TextField.h
+ includes/MessageBox.h
)
add_library(${PROJECT_NAME}
@@ -116,11 +152,12 @@ add_library(${PROJECT_NAME}
set(DOENGINE_LIBRARIES )
if(FETCH_SDL_FROM_GIT)
set(DOENGINE_LIBRARIES ${DOENGINE_LIBRARIES}
- SDL2::SDL2
- SDL2::SDL2main
- SDL2_ttf
- SDL2_image
+ SDL3::SDL3
+ # SDL2::SDL2main
+ SDL3_ttf::SDL3_ttf
+ SDL3_image::SDL3_image
SDL2_mixer
+ GL
)
else()
set(DOENGINE_LIBRARIES ${DOENGINE_LIBRARIES}
@@ -135,6 +172,13 @@ endif()
target_link_libraries(${PROJECT_NAME} PRIVATE ${DOENGINE_LIBRARIES})
+message("Copying asssets to buils dir.")
+file(COPY ${ASSETS_DIR}
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
+# install(TARGETS ${PROJECT_NAME} DESTINATION /home/afl/Desktop/doengine )
+
+
+if(${BUILD_SAMPLE_ACTIVE})
#add_executable(${PROJECT_NAME}-sample
# sample/ignored_main.cpp
#)
@@ -153,7 +197,24 @@ add_executable(${PROJECT_NAME}-Tetris-sample
add_executable(${PROJECT_NAME}-MusicPlayer-sample
sample/MusicPlayer/MusicPlayer.cpp
)
+add_executable(BattleSpawn
+ sample/BattleSpawn/BattleSpawn.cpp
+)
+add_executable(PacmanClone
+ sample/Pacman/Pacman.cpp
+)
+
+add_executable(BattleCityRecreation
+ sample/BattleCityRecreation/BattleCityRecreation.cpp
+)
+
+add_executable(Tetris
+ sample/tetris/Tetris.cpp
+)
+add_executable(SideScroller
+ sample/SideScroller/SideScroller.cpp
+)
# to build sample needs
# Zip support, ubuntu sudo apt-get install libzip-dev
@@ -181,7 +242,31 @@ target_link_libraries(${PROJECT_NAME}-MusicPlayer-sample PRIVATE
${PROJECT_NAME}
${DOENGINE_LIBRARIES}
)
-message("Copying asssets to buils dir.")
-file(COPY ${ASSETS_DIR}
- DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-# install(TARGETS ${PROJECT_NAME} DESTINATION /home/afl/Desktop/doengine )
+
+target_link_libraries(BattleSpawn PRIVATE
+ ${PROJECT_NAME}
+ ${DOENGINE_LIBRARIES}
+)
+
+target_link_libraries(PacmanClone PRIVATE
+ ${PROJECT_NAME}
+ ${DOENGINE_LIBRARIES}
+)
+
+
+target_link_libraries(BattleCityRecreation PRIVATE
+ ${PROJECT_NAME}
+ ${DOENGINE_LIBRARIES}
+)
+
+target_link_libraries(Tetris PRIVATE
+ ${PROJECT_NAME}
+ ${DOENGINE_LIBRARIES}
+)
+
+
+target_link_libraries(SideScroller PRIVATE
+ ${PROJECT_NAME}
+ ${DOENGINE_LIBRARIES}
+)
+endif()
\ No newline at end of file
diff --git a/README.md b/README.md
index 98ae645..46b343a 100644
--- a/README.md
+++ b/README.md
@@ -1,25 +1,122 @@
# DOEngine
-another 2D game engine.
+
+another 2D game engine library base on SDL2 and Opengl.
#### What is it? why?
-##### Simple
-
-tileid
-rows
-colums
-tilesize
-src
-layercount
-cache
-tileset[]
-Data=[
- [
- x.x.x.x.x.x.x.x
- x.x.x.x.
- ],
- [],
- []
-]
-eventos
+this is a basically a gameengine library on top of SDL2 and opengl(next)
+there are tons of Game Engine, Frameworks, Tools and other Software that
+is use to create Games, is ok, we are not competing here. this library
+is create to see if we are able to run a Game without third party and by
+learning at our own pace.
+
+#### Authors
+
+- Aneury Perez -> https://github.com/aneury1 -> linkedin: https://www.linkedin.com/in/aneury-p-06902a3a/
+- Victor D. Montero -> https://github.com/victordmontero -> linkedin: https://www.linkedin.com/in/victor-d-montero-adames-888170144/
+
+feel free to contact us and feel to leave comments, bug reports and anything that can
+make it better. this software is suppose to be open source as now.
+
+#### Setup
+
+this is a C++ project, use CMake, there are some config for using installed SDL2(and sublibraries) Version
+or fetch from github.com please check CMakeLists.txt to see it. probably some would be listed bellow.
+
+#### Ussage.
+
+you can check the samples in the sample folders. but is basically setting up a State and add to the statemachine
+and work from it, using library common function for Drawing, Loading images, Loading fonts, Loading Music.
+
+please see in samples simplepong.cpp
+```cpp
+#include "Application.h"
+#include "GameObject.h"
+#include "Grids.h"
+#include "TTFText.h"
+
+struct Paddle : public GameObject
+{
+ ...
+ virtual void Update(float timer = 0)override{}
+ virtual void Render()override{}
+ virtual bool isColliding(GameObject* other)override{}
+};
+
+struct PongState : public GameState, public KeyDownEvent
+{
+ ...
+ virtual void OnKeydown(const Keyboard&) override{...}
+ virtual void OnEnter() override
+ {
+ ...
+ ///do setup
+ }
+ virtual void OnExit() override
+ {
+
+ ...
+ ///do a cleanup
+ }
+ virtual void Update(float elapsed)
+ {
+ ...
+ /// process Game State Action
+ }
+ virtual void Render()
+ {
+ ...
+ ///update Screen if necesary..
+ }
+};
+
+...
+enum StatesId{
+ Playstate = 1
+};
+
+
+int main(int argc, char* argv[])
+{
+ auto app = doengine::Application::getApplication();
+ doengine::Rect rect{1200, 900};
+ app->createWindow(rect);
+ auto pongState = new PongState();
+ app->addState(pongState, Playstate);
+ app->setState(Playstate);
+
+ while (app->IsRunning())
+ {
+ app->PollEvent();
+ app->Update();
+ app->Render();
+ }
+ app->Quit();
+ return 0;
+}
+
+
+```
+##### Issue when Compiling or running the samples.
+as this is on going you would have to issues compiling or running the project. if this is a compilation issue
+please head to CMake and check if you are fetch or using local installation probably clean up and do cmake ..
+would make it.
+
+if there are some issue running the samples, please check the path for assets, probably there would be missing
+some assets due to they are for privately use. in the future we would have own assets but by the time this
+is the state of it.
+
+##### WIP
+
+- Testing Android Setup(no yet ready)
+- Testing Opengl currently we have only SDL2 fallback
+- TileMap creating, font wrapping, blending, math, ...
+
+
+#### Docs.
+
+we dont have docs written, but we have a github project where you can see the status and board like kanban board
+we have samples and Test folders which its suppose to be very clear and explanatory in general, in addition of
+any doubts you can create and issue for letting us know that something is missing.
+Thanks for reach this place...
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..9ce2d5b
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,2 @@
+build-android/
+AndroidGame/
\ No newline at end of file
diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt
new file mode 100644
index 0000000..7746db1
--- /dev/null
+++ b/android/CMakeLists.txt
@@ -0,0 +1,349 @@
+cmake_minimum_required(VERSION 3.18.1)
+
+project(Doengine)
+
+# Set C/C++ standards
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Define paths relative to the Android folder
+set(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
+set(INCLUDES_DIR "${PROJECT_ROOT}/includes")
+set(SRC_DIR "${PROJECT_ROOT}/src")
+set(TEST_DIR "${SRC_DIR}/test")
+
+# Option to build as shared or static library
+option(BUILD_SHARED_LIBS "Build shared library instead of static" ON)
+option(BUILD_TESTS "Build test executable" FALSE)
+
+# Include FetchContent module for downloading dependencies
+include(FetchContent)
+
+# Set SDL2 build options - force shared libraries for all SDL components
+set(SDL_SHARED ON CACHE BOOL "" FORCE)
+set(SDL_STATIC OFF CACHE BOOL "" FORCE)
+set(SDL_TEST OFF CACHE BOOL "" FORCE)
+set(SDL_TESTS OFF CACHE BOOL "" FORCE)
+set(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
+
+# SDL2_image options
+set(SDL2IMAGE_INSTALL OFF CACHE BOOL "" FORCE)
+set(SDL2IMAGE_SAMPLES OFF CACHE BOOL "" FORCE)
+
+# SDL2_mixer options
+set(SDL2MIXER_INSTALL OFF CACHE BOOL "" FORCE)
+set(SDL2MIXER_SAMPLES OFF CACHE BOOL "" FORCE)
+
+# SDL2_ttf options
+set(SDL2TTF_INSTALL OFF CACHE BOOL "" FORCE)
+set(SDL2TTF_SAMPLES OFF CACHE BOOL "" FORCE)
+
+# SDL2_net options
+set(SDL2NET_INSTALL OFF CACHE BOOL "" FORCE)
+set(SDL2NET_SAMPLES OFF CACHE BOOL "" FORCE)
+
+# Fetch SDL2 from GitHub
+message(STATUS "Fetching SDL2 from GitHub...")
+FetchContent_Declare(
+ SDL2
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
+ GIT_TAG release-2.30.10
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_image from GitHub
+message(STATUS "Fetching SDL2_image from GitHub...")
+FetchContent_Declare(
+ SDL2_image
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_image.git
+ GIT_TAG release-2.8.4
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_mixer from GitHub
+message(STATUS "Fetching SDL2_mixer from GitHub...")
+FetchContent_Declare(
+ SDL2_mixer
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_mixer.git
+ GIT_TAG release-2.8.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_ttf from GitHub
+message(STATUS "Fetching SDL2_ttf from GitHub...")
+FetchContent_Declare(
+ SDL2_ttf
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_ttf.git
+ GIT_TAG release-2.22.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_net from GitHub
+message(STATUS "Fetching SDL2_net from GitHub...")
+FetchContent_Declare(
+ SDL2_net
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_net.git
+ GIT_TAG release-2.2.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch Google Test from GitHub
+message(STATUS "Fetching Google Test from GitHub...")
+FetchContent_Declare(
+ googletest
+ GIT_REPOSITORY https://github.com/google/googletest.git
+ GIT_TAG v1.14.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Disable Google Test installation and samples
+set(INSTALL_GTEST ON CACHE BOOL "" FORCE)
+set(BUILD_GMOCK ON CACHE BOOL "" FORCE)
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+# Make SDL2 and family available
+message(STATUS "Making SDL2 libraries available...")
+FetchContent_MakeAvailable(SDL2 SDL2_image SDL2_mixer SDL2_ttf SDL2_net googletest)
+
+# Collect all source files (excluding test directory)
+file(GLOB_RECURSE DOENGINE_SOURCES
+ "${SRC_DIR}/*.c"
+ "${SRC_DIR}/*.cpp"
+)
+
+# Remove test files from main library sources
+list(FILTER DOENGINE_SOURCES EXCLUDE REGEX "${TEST_DIR}/.*")
+
+# Collect all header files
+file(GLOB_RECURSE DOENGINE_HEADERS
+ "${INCLUDES_DIR}/*.h"
+ "${INCLUDES_DIR}/*.hpp"
+)
+
+# Collect test sources
+if(BUILD_TESTS)
+ file(GLOB_RECURSE TEST_SOURCES
+ "${TEST_DIR}/fixtures/*.c"
+ "${TEST_DIR}/fixtures/*.cpp"
+ "${TEST_DIR}/mocks/*.c"
+ "${TEST_DIR}/mocks/*.cpp"
+ "${TEST_DIR}/units/*.c"
+ "${TEST_DIR}/units/*.cpp"
+ )
+endif()
+
+# Create the library target
+if(BUILD_SHARED_LIBS)
+ add_library(${PROJECT_NAME} SHARED ${DOENGINE_SOURCES})
+ message(STATUS "Building LibDoengine as SHARED library")
+else()
+ add_library(${PROJECT_NAME} STATIC ${DOENGINE_SOURCES})
+ message(STATUS "Building LibDoengine as STATIC library")
+endif()
+
+# Include directories
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${INCLUDES_DIR}
+ PRIVATE
+ ${SRC_DIR}
+)
+
+# Link SDL2 libraries
+target_link_libraries(${PROJECT_NAME}
+ PUBLIC
+ SDL2::SDL2
+ SDL2_image::SDL2_image
+ SDL2_mixer::SDL2_mixer
+ SDL2_ttf::SDL2_ttf
+ SDL2_net::SDL2_net
+)
+
+# Link standard Android libraries
+find_library(LOG_LIBRARY log)
+find_library(ANDROID_LIBRARY android)
+find_library(GLESV2_LIBRARY GLESv2)
+find_library(EGL_LIBRARY EGL)
+
+target_link_libraries(${PROJECT_NAME}
+ PUBLIC
+ ${LOG_LIBRARY}
+ ${ANDROID_LIBRARY}
+ ${GLESV2_LIBRARY}
+ ${EGL_LIBRARY}
+)
+
+# Set compiler flags for Android
+target_compile_options(${PROJECT_NAME} PRIVATE
+ -Wall
+ -Wextra
+ -fPIC
+)
+
+# Define Android-specific macros
+target_compile_definitions(${PROJECT_NAME}
+ PRIVATE
+ ANDROID
+ __ANDROID__
+)
+
+# ========================================
+# Test Executable Configuration
+# ========================================
+if(BUILD_TESTS AND TEST_SOURCES)
+ message(STATUS "Building test executable...")
+
+ # Create test executable
+ add_executable(${PROJECT_NAME}_tests ${TEST_SOURCES})
+
+ # Include directories for tests
+ target_include_directories(${PROJECT_NAME}_tests
+ PRIVATE
+ ${INCLUDES_DIR}
+ ${SRC_DIR}
+ ${TEST_DIR}
+ ${TEST_DIR}/fixtures
+ ${TEST_DIR}/mocks
+ ${TEST_DIR}/units
+ ${googletest_SOURCE_DIR}/googletest/include
+ ${googletest_SOURCE_DIR}/googlemock/include
+ )
+
+ # Link libraries for tests
+ target_link_libraries(${PROJECT_NAME}_tests
+ PRIVATE
+ ${PROJECT_NAME}
+ gtest
+ gtest_main
+ gmock
+ gmock_main
+ )
+
+ # Set compiler flags for tests
+ target_compile_options(${PROJECT_NAME}_tests PRIVATE
+ -Wall
+ -Wextra
+ )
+
+ # Define Android-specific macros for tests
+ target_compile_definitions(${PROJECT_NAME}_tests
+ PRIVATE
+ ANDROID
+ __ANDROID__
+ )
+
+ # Set output directory for test executable
+ set_target_properties(${PROJECT_NAME}_tests PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_ABI}"
+ )
+
+ message(STATUS "Test executable will be built: ${PROJECT_NAME}_tests")
+else()
+ if(BUILD_TESTS)
+ message(STATUS "No test sources found in ${TEST_DIR}")
+ else()
+ message(STATUS "Test building disabled")
+ endif()
+endif()
+
+# Set output directory
+set_target_properties(${PROJECT_NAME} PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_ABI}"
+)
+
+# Set output directories for SDL2 libraries as well
+set_target_properties(SDL2 PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+)
+
+if(TARGET SDL2_image)
+ set_target_properties(SDL2_image PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ )
+endif()
+
+if(TARGET SDL2_mixer)
+ set_target_properties(SDL2_mixer PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ )
+endif()
+
+if(TARGET SDL2_ttf)
+ set_target_properties(SDL2_ttf PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ )
+endif()
+
+if(TARGET SDL2_net)
+ set_target_properties(SDL2_net PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ )
+endif()
+
+# Installation rules
+install(TARGETS ${PROJECT_NAME}
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ ARCHIVE DESTINATION lib/${ANDROID_ABI}
+)
+
+install(DIRECTORY ${INCLUDES_DIR}/
+ DESTINATION include
+ FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
+)
+
+# Install SDL2 shared libraries
+install(TARGETS SDL2
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ RUNTIME DESTINATION lib/${ANDROID_ABI}
+)
+
+if(TARGET SDL2_image)
+ install(TARGETS SDL2_image
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ RUNTIME DESTINATION lib/${ANDROID_ABI}
+ )
+endif()
+
+if(TARGET SDL2_mixer)
+ install(TARGETS SDL2_mixer
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ RUNTIME DESTINATION lib/${ANDROID_ABI}
+ )
+endif()
+
+if(TARGET SDL2_ttf)
+ install(TARGETS SDL2_ttf
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ RUNTIME DESTINATION lib/${ANDROID_ABI}
+ )
+endif()
+
+if(TARGET SDL2_net)
+ install(TARGETS SDL2_net
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ RUNTIME DESTINATION lib/${ANDROID_ABI}
+ )
+endif()
+
+# Print configuration summary
+message(STATUS "=== LibDoengine Build Configuration ===")
+message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
+message(STATUS "Android ABI: ${ANDROID_ABI}")
+message(STATUS "Android Platform: ${ANDROID_PLATFORM}")
+message(STATUS "Library Type: ${BUILD_SHARED_LIBS}")
+message(STATUS "Build Tests: ${BUILD_TESTS}")
+message(STATUS "Source Directory: ${SRC_DIR}")
+message(STATUS "Include Directory: ${INCLUDES_DIR}")
+message(STATUS "Test Directory: ${TEST_DIR}")
+message(STATUS "SDL2 Libraries: Fetched from GitHub")
+message(STATUS "Google Test: Fetched from GitHub (v1.14.0)")
+message(STATUS "========================================")
\ No newline at end of file
diff --git a/android/CMakeLists_prev.txt b/android/CMakeLists_prev.txt
new file mode 100644
index 0000000..256f446
--- /dev/null
+++ b/android/CMakeLists_prev.txt
@@ -0,0 +1,181 @@
+cmake_minimum_required(VERSION 3.18.1)
+
+project(LibDoengine)
+
+# Set C/C++ standards
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Define paths relative to the Android folder
+set(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
+set(INCLUDES_DIR "${PROJECT_ROOT}/includes")
+set(SRC_DIR "${PROJECT_ROOT}/src")
+
+# Option to build as shared or static library
+option(BUILD_SHARED_LIBS "Build shared library instead of static" ON)
+
+# Include FetchContent module for downloading dependencies
+include(FetchContent)
+
+# Set SDL2 build options - disable unnecessary features for mobile
+set(SDL_SHARED ON CACHE BOOL "" FORCE)
+set(SDL_STATIC OFF CACHE BOOL "" FORCE)
+set(SDL_TEST OFF CACHE BOOL "" FORCE)
+set(SDL_TESTS OFF CACHE BOOL "" FORCE)
+
+# Fetch SDL2 from GitHub
+message(STATUS "Fetching SDL2 from GitHub...")
+FetchContent_Declare(
+ SDL2
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
+ GIT_TAG release-2.30.10
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_image from GitHub
+message(STATUS "Fetching SDL2_image from GitHub...")
+FetchContent_Declare(
+ SDL2_image
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_image.git
+ GIT_TAG release-2.8.4
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_mixer from GitHub
+message(STATUS "Fetching SDL2_mixer from GitHub...")
+FetchContent_Declare(
+ SDL2_mixer
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_mixer.git
+ GIT_TAG release-2.8.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_ttf from GitHub
+message(STATUS "Fetching SDL2_ttf from GitHub...")
+FetchContent_Declare(
+ SDL2_ttf
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_ttf.git
+ GIT_TAG release-2.22.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Fetch SDL2_net from GitHub
+message(STATUS "Fetching SDL2_net from GitHub...")
+FetchContent_Declare(
+ SDL2_net
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_net.git
+ GIT_TAG release-2.2.0
+ GIT_SHALLOW TRUE
+ GIT_PROGRESS TRUE
+)
+
+# Make SDL2 and family available
+message(STATUS "Making SDL2 libraries available...")
+FetchContent_MakeAvailable(SDL2 SDL2_image SDL2_mixer SDL2_ttf SDL2_net)
+
+# Collect all source files
+file(GLOB_RECURSE DOENGINE_SOURCES
+ "${SRC_DIR}/*.c"
+ "${SRC_DIR}/*.cpp"
+)
+
+# Collect all header files
+file(GLOB_RECURSE DOENGINE_HEADERS
+ "${INCLUDES_DIR}/*.h"
+ "${INCLUDES_DIR}/*.hpp"
+)
+
+# Create the library target
+if(BUILD_SHARED_LIBS)
+ add_library(${PROJECT_NAME} SHARED ${DOENGINE_SOURCES})
+ message(STATUS "Building LibDoengine as SHARED library")
+else()
+ add_library(${PROJECT_NAME} STATIC ${DOENGINE_SOURCES})
+ message(STATUS "Building LibDoengine as STATIC library")
+endif()
+
+# Include directories
+target_include_directories(${PROJECT_NAME}
+ PUBLIC
+ ${INCLUDES_DIR}
+ PRIVATE
+ ${SRC_DIR}
+)
+
+# Link SDL2 libraries
+target_link_libraries(${PROJECT_NAME}
+ PUBLIC
+ SDL2::SDL2
+ SDL2_image::SDL2_image
+ SDL2_mixer::SDL2_mixer
+ SDL2_ttf::SDL2_ttf
+ SDL2_net::SDL2_net
+)
+
+# Link standard Android libraries
+find_library(LOG_LIBRARY log)
+find_library(ANDROID_LIBRARY android)
+find_library(GLESV2_LIBRARY GLESv2)
+find_library(EGL_LIBRARY EGL)
+
+target_link_libraries(${PROJECT_NAME}
+ PUBLIC
+ ${LOG_LIBRARY}
+ ${ANDROID_LIBRARY}
+ ${GLESV2_LIBRARY}
+ ${EGL_LIBRARY}
+)
+
+# Set compiler flags for Android
+target_compile_options(${PROJECT_NAME} PRIVATE
+ -Wall
+ -Wextra
+ -fPIC
+)
+
+# Define Android-specific macros
+target_compile_definitions(${PROJECT_NAME}
+ PRIVATE
+ ANDROID
+ __ANDROID__
+)
+
+# Set output directory
+set_target_properties(${PROJECT_NAME} PROPERTIES
+ ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/${ANDROID_ABI}"
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin/${ANDROID_ABI}"
+)
+
+# Installation rules
+install(TARGETS ${PROJECT_NAME}
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ ARCHIVE DESTINATION lib/${ANDROID_ABI}
+)
+
+install(DIRECTORY ${INCLUDES_DIR}/
+ DESTINATION include
+ FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp"
+)
+
+# Install SDL2 libraries as well
+install(TARGETS SDL2 SDL2_image SDL2_mixer SDL2_ttf SDL2_net
+ LIBRARY DESTINATION lib/${ANDROID_ABI}
+ ARCHIVE DESTINATION lib/${ANDROID_ABI}
+)
+
+# Print configuration summary
+message(STATUS "=== LibDoengine Build Configuration ===")
+message(STATUS "Build Type: ${CMAKE_BUILD_TYPE}")
+message(STATUS "Android ABI: ${ANDROID_ABI}")
+message(STATUS "Android Platform: ${ANDROID_PLATFORM}")
+message(STATUS "Library Type: ${BUILD_SHARED_LIBS}")
+message(STATUS "Source Directory: ${SRC_DIR}")
+message(STATUS "Include Directory: ${INCLUDES_DIR}")
+message(STATUS "SDL2 Libraries: Fetched from GitHub")
+message(STATUS "========================================")
\ No newline at end of file
diff --git a/android/boiler-plate-gen/generator.sh b/android/boiler-plate-gen/generator.sh
new file mode 100755
index 0000000..7ea8962
--- /dev/null
+++ b/android/boiler-plate-gen/generator.sh
@@ -0,0 +1,154 @@
+#!/bin/bash
+
+# Setup Android Project for DoEngine Game
+# This script creates the complete Android project structure
+
+set -e
+
+# Colors
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m'
+
+echo -e "${GREEN}=== DoEngine Android Project Setup ===${NC}"
+echo ""
+
+# Get script directory
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+DOENGINE_ROOT="$(dirname "$SCRIPT_DIR")"
+ANDROID_PROJECT="${DOENGINE_ROOT}/AndroidGame"
+
+# Configuration
+APP_NAME="DoEngineGame"
+PACKAGE_NAME="com.yourgame.doengine"
+
+echo -e "${BLUE}Project will be created at:${NC} ${ANDROID_PROJECT}"
+echo -e "${BLUE}DoEngine root:${NC} ${DOENGINE_ROOT}"
+echo ""
+
+# Create directory structure
+echo -e "${YELLOW}Creating project structure...${NC}"
+
+mkdir -p "${ANDROID_PROJECT}"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/java/com/yourgame/doengine"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/java/org/libsdl/app"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/cpp"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/values"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-hdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-mdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-xhdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-xxhdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-xxxhdpi"
+mkdir -p "${ANDROID_PROJECT}/app/libs/arm64-v8a"
+mkdir -p "${ANDROID_PROJECT}/app/libs/armeabi-v7a"
+
+echo -e "${GREEN}✓${NC} Directory structure created"
+
+# Create strings.xml
+cat > "${ANDROID_PROJECT}/app/src/main/res/values/strings.xml" << 'EOF'
+
+
+ DoEngine Game
+
+EOF
+
+echo -e "${GREEN}✓${NC} Created strings.xml"
+
+# Create settings.gradle
+cat > "${ANDROID_PROJECT}/settings.gradle" << 'EOF'
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ google()
+ mavenCentral()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "DoEngineGame"
+include ':app'
+EOF
+
+echo -e "${GREEN}✓${NC} Created settings.gradle"
+
+# Create gradle.properties
+cat > "${ANDROID_PROJECT}/gradle.properties" << 'EOF'
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+android.useAndroidX=true
+android.enableJetifier=true
+android.nonTransitiveRClass=false
+EOF
+
+echo -e "${GREEN}✓${NC} Created gradle.properties"
+
+# Create local.properties with SDK path
+if [ -n "$ANDROID_HOME" ]; then
+ cat > "${ANDROID_PROJECT}/local.properties" << EOF
+sdk.dir=${ANDROID_HOME}
+EOF
+ echo -e "${GREEN}✓${NC} Created local.properties with SDK path"
+else
+ echo -e "${YELLOW}⚠${NC} ANDROID_HOME not set, you'll need to set sdk.dir in local.properties manually"
+fi
+
+# Create .gitignore
+cat > "${ANDROID_PROJECT}/.gitignore" << 'EOF'
+*.iml
+.gradle
+/local.properties
+/.idea
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+*.apk
+*.ap_
+*.dex
+*.class
+bin/
+gen/
+out/
+EOF
+
+echo -e "${GREEN}✓${NC} Created .gitignore"
+
+# Create proguard-rules.pro
+cat > "${ANDROID_PROJECT}/app/proguard-rules.pro" << 'EOF'
+# Add project specific ProGuard rules here.
+-keep class org.libsdl.app.** { *; }
+EOF
+
+echo -e "${GREEN}✓${NC} Created proguard-rules.pro"
+
+echo ""
+echo -e "${GREEN}=== Project Structure Created ===${NC}"
+echo ""
+echo "Next steps:"
+echo "1. Copy the generated artifacts to the appropriate locations:"
+echo " - AndroidManifest.xml → ${ANDROID_PROJECT}/app/src/main/"
+echo " - build.gradle (app) → ${ANDROID_PROJECT}/app/"
+echo " - build.gradle (project) → ${ANDROID_PROJECT}/"
+echo " - MainActivity.java → ${ANDROID_PROJECT}/app/src/main/java/com/yourgame/doengine/"
+echo " - SDLActivity.java → ${ANDROID_PROJECT}/app/src/main/java/org/libsdl/app/"
+echo " - main.cpp → ${ANDROID_PROJECT}/app/src/main/cpp/"
+echo " - CMakeLists.txt (app) → ${ANDROID_PROJECT}/app/src/main/cpp/"
+echo ""
+echo "2. Build DoEngine libraries:"
+echo " cd ${DOENGINE_ROOT}/Android"
+echo " ./build-android.sh"
+echo ""
+echo "3. Copy DoEngine libraries to the Android project:"
+echo " cp ${DOENGINE_ROOT}/Android/build/libs/*/*.so ${ANDROID_PROJECT}/app/libs/"
+echo ""
+echo "4. Open project in Android Studio:"
+echo " studio ${ANDROID_PROJECT}"
+echo ""
+echo -e "${GREEN}Setup complete!${NC}"
\ No newline at end of file
diff --git a/android/boiler-plate-gen/selectable-gen.sh b/android/boiler-plate-gen/selectable-gen.sh
new file mode 100755
index 0000000..83ea90e
--- /dev/null
+++ b/android/boiler-plate-gen/selectable-gen.sh
@@ -0,0 +1,895 @@
+#!/bin/bash
+
+# Complete Android Project Generator for DoEngine
+# This script creates all necessary files and project structure
+
+set -e
+
+# Colors
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+CYAN='\033[0;36m'
+NC='\033[0m'
+
+# Banner
+echo -e "${CYAN}"
+echo "╔════════════════════════════════════════════════════════════╗"
+echo "║ ║"
+echo "║ DoEngine Android Project Generator ║"
+echo "║ Complete Boilerplate Creator ║"
+echo "║ ║"
+echo "╚════════════════════════════════════════════════════════════╝"
+echo -e "${NC}"
+echo ""
+
+# Get script directory
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# Default values
+DEFAULT_DOENGINE_PATH="$(dirname "$SCRIPT_DIR")"
+DEFAULT_PROJECT_NAME="DoEngineGame"
+DEFAULT_PACKAGE_NAME="com.yourgame.doengine"
+DEFAULT_APP_NAME="DoEngine Game"
+
+# Prompt for configuration
+echo -e "${BLUE}=== Project Configuration ===${NC}"
+echo ""
+
+# DoEngine path
+read -p "Enter DoEngine root path [${DEFAULT_DOENGINE_PATH}]: " DOENGINE_ROOT
+DOENGINE_ROOT=${DOENGINE_ROOT:-$DEFAULT_DOENGINE_PATH}
+
+# Validate DoEngine path
+if [ ! -d "$DOENGINE_ROOT" ]; then
+ echo -e "${RED}Error: DoEngine path does not exist: ${DOENGINE_ROOT}${NC}"
+ exit 1
+fi
+
+if [ ! -d "$DOENGINE_ROOT/includes" ] || [ ! -d "$DOENGINE_ROOT/src" ]; then
+ echo -e "${YELLOW}Warning: DoEngine path doesn't contain 'includes' and 'src' directories${NC}"
+ read -p "Continue anyway? (y/n): " CONTINUE
+ if [ "$CONTINUE" != "y" ]; then
+ exit 1
+ fi
+fi
+
+# Project name
+read -p "Enter project name [${DEFAULT_PROJECT_NAME}]: " PROJECT_NAME
+PROJECT_NAME=${PROJECT_NAME:-$DEFAULT_PROJECT_NAME}
+
+# Package name
+read -p "Enter package name (e.g., com.company.game) [${DEFAULT_PACKAGE_NAME}]: " PACKAGE_NAME
+PACKAGE_NAME=${PACKAGE_NAME:-$DEFAULT_PACKAGE_NAME}
+
+# Validate package name
+if ! [[ $PACKAGE_NAME =~ ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$ ]]; then
+ echo -e "${RED}Error: Invalid package name format. Use lowercase letters and dots (e.g., com.company.game)${NC}"
+ exit 1
+fi
+
+# App display name
+read -p "Enter app display name [${DEFAULT_APP_NAME}]: " APP_NAME
+APP_NAME=${APP_NAME:-$DEFAULT_APP_NAME}
+
+# Output directory
+read -p "Enter output directory for Android project [${DOENGINE_ROOT}/AndroidGame]: " ANDROID_PROJECT
+ANDROID_PROJECT=${ANDROID_PROJECT:-${DOENGINE_ROOT}/AndroidGame}
+
+# Convert package name to path
+PACKAGE_PATH=$(echo $PACKAGE_NAME | tr '.' '/')
+
+echo ""
+echo -e "${GREEN}=== Configuration Summary ===${NC}"
+echo -e "${CYAN}DoEngine Path:${NC} $DOENGINE_ROOT"
+echo -e "${CYAN}Project Name:${NC} $PROJECT_NAME"
+echo -e "${CYAN}Package Name:${NC} $PACKAGE_NAME"
+echo -e "${CYAN}App Name:${NC} $APP_NAME"
+echo -e "${CYAN}Output Directory:${NC} $ANDROID_PROJECT"
+echo ""
+read -p "Continue with this configuration? (y/n): " CONFIRM
+if [ "$CONFIRM" != "y" ]; then
+ echo "Cancelled."
+ exit 0
+fi
+
+echo ""
+echo -e "${YELLOW}Creating project structure...${NC}"
+
+# Create directory structure
+mkdir -p "${ANDROID_PROJECT}"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/java/${PACKAGE_PATH}"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/java/org/libsdl/app"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/cpp"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/values"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-hdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-mdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-xhdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-xxhdpi"
+mkdir -p "${ANDROID_PROJECT}/app/src/main/res/mipmap-xxxhdpi"
+mkdir -p "${ANDROID_PROJECT}/app/libs/arm64-v8a"
+mkdir -p "${ANDROID_PROJECT}/app/libs/armeabi-v7a"
+
+echo -e "${GREEN}✓${NC} Directory structure created"
+
+# Create AndroidManifest.xml
+echo -e "${YELLOW}Generating AndroidManifest.xml...${NC}"
+cat > "${ANDROID_PROJECT}/app/src/main/AndroidManifest.xml" << EOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+EOF
+echo -e "${GREEN}✓${NC} AndroidManifest.xml created"
+
+# Create MainActivity.java
+echo -e "${YELLOW}Generating MainActivity.java...${NC}"
+cat > "${ANDROID_PROJECT}/app/src/main/java/${PACKAGE_PATH}/MainActivity.java" << EOF
+package ${PACKAGE_NAME};
+
+import org.libsdl.app.SDLActivity;
+
+public class MainActivity extends SDLActivity {
+
+ /**
+ * This method is called by SDL before loading the native shared libraries.
+ * It can be overridden to provide names of shared libraries to be loaded.
+ * The default implementation returns the defaults. It never returns null.
+ * An array returned by a new implementation must at least contain "SDL2".
+ * Also keep in mind that the order the libraries are loaded may matter.
+ * @return names of shared libraries to be loaded (e.g. "SDL2", "main").
+ */
+ @Override
+ protected String[] getLibraries() {
+ return new String[] {
+ "SDL2",
+ "SDL2_image",
+ "SDL2_mixer",
+ "SDL2_ttf",
+ "SDL2_net",
+ "LibDoengine",
+ "${PROJECT_NAME}"
+ };
+ }
+
+ /**
+ * This method is called by SDL using JNI.
+ * @return the name of the main function to call from the native library
+ */
+ @Override
+ protected String getMainFunction() {
+ return "SDL_main";
+ }
+}
+EOF
+echo -e "${GREEN}✓${NC} MainActivity.java created"
+
+# Create SDLActivity.java
+echo -e "${YELLOW}Generating SDLActivity.java...${NC}"
+cat > "${ANDROID_PROJECT}/app/src/main/java/org/libsdl/app/SDLActivity.java" << 'EOF'
+package org.libsdl.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * SDL Activity - Base class for SDL applications on Android
+ * This is a minimal implementation. For production, use the full SDLActivity from SDL2.
+ */
+public class SDLActivity extends Activity {
+ private static final String TAG = "SDL";
+
+ // Main SDL surface
+ protected static SDLActivity mSingleton;
+ protected static SDLSurface mSurface;
+
+ // Load the .so files
+ public static void loadLibraries() {
+ for (String lib : mSingleton.getLibraries()) {
+ System.loadLibrary(lib);
+ }
+ }
+
+ /**
+ * This method returns the name of the shared library to be loaded
+ */
+ protected String[] getLibraries() {
+ return new String[] {
+ "SDL2",
+ "main"
+ };
+ }
+
+ /**
+ * This method returns the name of the main function
+ */
+ protected String getMainFunction() {
+ return "SDL_main";
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Keep singleton
+ mSingleton = this;
+
+ // Load libraries
+ loadLibraries();
+
+ // Set up the surface
+ mSurface = new SDLSurface(getApplication());
+ setContentView(mSurface);
+
+ // Keep screen on
+ mSurface.setKeepScreenOn(true);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ // Cleanup
+ nativeQuit();
+ }
+
+ // Native methods
+ public static native int nativeInit(Object arguments);
+ public static native void nativeQuit();
+ public static native void onNativeResize();
+ public static native void onNativeSurfaceChanged();
+ public static native void onNativeSurfaceDestroyed();
+
+ /**
+ * SDLSurface - Surface view for rendering
+ */
+ static class SDLSurface extends SurfaceView implements SurfaceHolder.Callback {
+
+ public SDLSurface(Context context) {
+ super(context);
+ getHolder().addCallback(this);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ // Start native thread
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ nativeInit(null);
+ }
+ }).start();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ onNativeResize();
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ onNativeSurfaceDestroyed();
+ }
+ }
+}
+EOF
+echo -e "${GREEN}✓${NC} SDLActivity.java created"
+
+# Create main.cpp
+echo -e "${YELLOW}Generating main.cpp...${NC}"
+cat > "${ANDROID_PROJECT}/app/src/main/cpp/main.cpp" << 'EOF'
+#include
+#include
+#include
+
+#define LOG_TAG "DoEngineGame"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
+// Screen dimensions
+const int SCREEN_WIDTH = 1280;
+const int SCREEN_HEIGHT = 720;
+
+// Game class using DoEngine (you'll implement this with your DoEngine)
+class Game {
+private:
+ SDL_Window* window;
+ SDL_Renderer* renderer;
+ bool isRunning;
+
+public:
+ Game() : window(nullptr), renderer(nullptr), isRunning(false) {}
+
+ bool initialize() {
+ LOGI("Initializing game...");
+
+ // Initialize SDL
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER) < 0) {
+ LOGE("SDL initialization failed: %s", SDL_GetError());
+ return false;
+ }
+
+ // Initialize SDL_image
+ int imgFlags = IMG_INIT_PNG | IMG_INIT_JPG;
+ if (!(IMG_Init(imgFlags) & imgFlags)) {
+ LOGE("SDL_image initialization failed: %s", IMG_GetError());
+ return false;
+ }
+
+ // Create window
+ window = SDL_CreateWindow(
+ "DoEngine Game",
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ SCREEN_WIDTH,
+ SCREEN_HEIGHT,
+ SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN
+ );
+
+ if (!window) {
+ LOGE("Window creation failed: %s", SDL_GetError());
+ return false;
+ }
+
+ // Create renderer
+ renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+ if (!renderer) {
+ LOGE("Renderer creation failed: %s", SDL_GetError());
+ return false;
+ }
+
+ SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
+
+ LOGI("Game initialized successfully!");
+ isRunning = true;
+ return true;
+ }
+
+ void handleEvents() {
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ isRunning = false;
+ break;
+
+ case SDL_FINGERDOWN:
+ LOGI("Touch down at: %f, %f", event.tfinger.x, event.tfinger.y);
+ break;
+
+ case SDL_FINGERUP:
+ LOGI("Touch up at: %f, %f", event.tfinger.x, event.tfinger.y);
+ break;
+
+ case SDL_APP_TERMINATING:
+ LOGI("App terminating");
+ isRunning = false;
+ break;
+
+ case SDL_APP_LOWMEMORY:
+ LOGI("Low memory warning");
+ break;
+
+ case SDL_APP_WILLENTERBACKGROUND:
+ LOGI("App will enter background");
+ break;
+
+ case SDL_APP_DIDENTERBACKGROUND:
+ LOGI("App entered background");
+ break;
+
+ case SDL_APP_WILLENTERFOREGROUND:
+ LOGI("App will enter foreground");
+ break;
+
+ case SDL_APP_DIDENTERFOREGROUND:
+ LOGI("App entered foreground");
+ break;
+ }
+ }
+ }
+
+ void update() {
+ // TODO: Update game logic using DoEngine
+ // This is where you'll use your DoEngine API
+ }
+
+ void render() {
+ // Clear screen
+ SDL_SetRenderDrawColor(renderer, 0x20, 0x20, 0x30, 0xFF);
+ SDL_RenderClear(renderer);
+
+ // TODO: Render game using DoEngine
+ // This is where you'll use your DoEngine rendering
+
+ // Example: Draw a colored rectangle
+ SDL_Rect fillRect = { SCREEN_WIDTH / 4, SCREEN_HEIGHT / 4,
+ SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 };
+ SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
+ SDL_RenderFillRect(renderer, &fillRect);
+
+ // Present
+ SDL_RenderPresent(renderer);
+ }
+
+ void run() {
+ LOGI("Starting game loop...");
+
+ const float targetFPS = 60.0f;
+ const float frameDelay = 1000.0f / targetFPS;
+
+ while (isRunning) {
+ Uint32 frameStart = SDL_GetTicks();
+
+ handleEvents();
+ update();
+ render();
+
+ Uint32 frameTime = SDL_GetTicks() - frameStart;
+ if (frameDelay > frameTime) {
+ SDL_Delay(frameDelay - frameTime);
+ }
+
+ // Calculate FPS (optional logging)
+ static int frameCount = 0;
+ static Uint32 fpsTimer = SDL_GetTicks();
+ frameCount++;
+ if (SDL_GetTicks() - fpsTimer > 1000) {
+ LOGI("FPS: %d", frameCount);
+ frameCount = 0;
+ fpsTimer = SDL_GetTicks();
+ }
+ }
+
+ LOGI("Game loop ended");
+ }
+
+ void cleanup() {
+ LOGI("Cleaning up...");
+
+ if (renderer) {
+ SDL_DestroyRenderer(renderer);
+ renderer = nullptr;
+ }
+
+ if (window) {
+ SDL_DestroyWindow(window);
+ window = nullptr;
+ }
+
+ IMG_Quit();
+ SDL_Quit();
+
+ LOGI("Cleanup complete");
+ }
+
+ ~Game() {
+ cleanup();
+ }
+};
+
+// Main entry point
+int main(int argc, char* argv[]) {
+ LOGI("DoEngine Game starting...");
+
+ Game game;
+
+ if (!game.initialize()) {
+ LOGE("Failed to initialize game!");
+ return 1;
+ }
+
+ game.run();
+
+ LOGI("DoEngine Game exiting normally");
+ return 0;
+}
+EOF
+echo -e "${GREEN}✓${NC} main.cpp created"
+
+# Create CMakeLists.txt
+echo -e "${YELLOW}Generating CMakeLists.txt...${NC}"
+cat > "${ANDROID_PROJECT}/app/src/main/cpp/CMakeLists.txt" << EOF
+cmake_minimum_required(VERSION 3.18.1)
+
+project(${PROJECT_NAME})
+
+# Set C/C++ standards
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Define paths
+set(DOENGINE_ROOT "${DOENGINE_ROOT}")
+set(DOENGINE_ANDROID "\${DOENGINE_ROOT}/Android")
+set(GAME_SRC_DIR "\${CMAKE_CURRENT_SOURCE_DIR}")
+
+# Add DoEngine library build
+add_subdirectory(\${DOENGINE_ANDROID} \${CMAKE_CURRENT_BINARY_DIR}/doengine)
+
+# Collect game source files
+file(GLOB_RECURSE GAME_SOURCES
+ "\${GAME_SRC_DIR}/*.c"
+ "\${GAME_SRC_DIR}/*.cpp"
+)
+
+# Create shared library for Android (required by SDL2)
+add_library(\${PROJECT_NAME} SHARED \${GAME_SOURCES})
+
+# Include directories
+target_include_directories(\${PROJECT_NAME}
+ PRIVATE
+ \${GAME_SRC_DIR}
+ \${DOENGINE_ROOT}/includes
+)
+
+# Link libraries
+target_link_libraries(\${PROJECT_NAME}
+ PRIVATE
+ LibDoengine
+ SDL2::SDL2main
+)
+
+# Set compiler flags
+target_compile_options(\${PROJECT_NAME} PRIVATE
+ -Wall
+ -Wextra
+)
+
+# Android-specific macros
+target_compile_definitions(\${PROJECT_NAME}
+ PRIVATE
+ ANDROID
+ __ANDROID__
+)
+
+# Export SDL_main for Android
+set_target_properties(\${PROJECT_NAME} PROPERTIES
+ LINK_FLAGS "-u Java_org_libsdl_app_SDLActivity_nativeInit"
+)
+
+message(STATUS "=== DoEngine Game Configuration ===")
+message(STATUS "Game Sources: \${GAME_SRC_DIR}")
+message(STATUS "DoEngine Path: \${DOENGINE_ROOT}")
+message(STATUS "==================================")
+EOF
+echo -e "${GREEN}✓${NC} CMakeLists.txt created"
+
+# Create build.gradle (app)
+echo -e "${YELLOW}Generating build.gradle (app)...${NC}"
+cat > "${ANDROID_PROJECT}/app/build.gradle" << EOF
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace '${PACKAGE_NAME}'
+ compileSdk 34
+
+ defaultConfig {
+ applicationId "${PACKAGE_NAME}"
+ minSdk 21
+ targetSdk 34
+ versionCode 1
+ versionName "1.0"
+
+ ndk {
+ abiFilters 'arm64-v8a', 'armeabi-v7a'
+ }
+
+ externalNativeBuild {
+ cmake {
+ arguments "-DANDROID_STL=c++_shared"
+ cppFlags "-std=c++17 -Wall -Wextra"
+ }
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ debug {
+ debuggable true
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path file('src/main/cpp/CMakeLists.txt')
+ version '3.18.1'
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['libs']
+ }
+ }
+}
+
+dependencies {
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.11.0'
+}
+EOF
+echo -e "${GREEN}✓${NC} build.gradle (app) created"
+
+# Create build.gradle (project)
+echo -e "${YELLOW}Generating build.gradle (project)...${NC}"
+cat > "${ANDROID_PROJECT}/build.gradle" << 'EOF'
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '8.2.0' apply false
+}
+EOF
+echo -e "${GREEN}✓${NC} build.gradle (project) created"
+
+# Create settings.gradle
+echo -e "${YELLOW}Generating settings.gradle...${NC}"
+cat > "${ANDROID_PROJECT}/settings.gradle" << EOF
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ google()
+ mavenCentral()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "${PROJECT_NAME}"
+include ':app'
+EOF
+echo -e "${GREEN}✓${NC} settings.gradle created"
+
+# Create gradle.properties
+echo -e "${YELLOW}Generating gradle.properties...${NC}"
+cat > "${ANDROID_PROJECT}/gradle.properties" << 'EOF'
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+android.useAndroidX=true
+android.enableJetifier=true
+android.nonTransitiveRClass=false
+EOF
+echo -e "${GREEN}✓${NC} gradle.properties created"
+
+# Create local.properties
+if [ -n "$ANDROID_HOME" ]; then
+ echo -e "${YELLOW}Generating local.properties...${NC}"
+ cat > "${ANDROID_PROJECT}/local.properties" << EOF
+sdk.dir=${ANDROID_HOME}
+EOF
+ echo -e "${GREEN}✓${NC} local.properties created with SDK path"
+else
+ echo -e "${YELLOW}⚠${NC} ANDROID_HOME not set, skipping local.properties"
+fi
+
+# Create strings.xml
+echo -e "${YELLOW}Generating strings.xml...${NC}"
+cat > "${ANDROID_PROJECT}/app/src/main/res/values/strings.xml" << EOF
+
+
+ ${APP_NAME}
+
+EOF
+echo -e "${GREEN}✓${NC} strings.xml created"
+
+# Create proguard-rules.pro
+echo -e "${YELLOW}Generating proguard-rules.pro...${NC}"
+cat > "${ANDROID_PROJECT}/app/proguard-rules.pro" << 'EOF'
+# Add project specific ProGuard rules here.
+-keep class org.libsdl.app.** { *; }
+EOF
+echo -e "${GREEN}✓${NC} proguard-rules.pro created"
+
+# Create .gitignore
+echo -e "${YELLOW}Generating .gitignore...${NC}"
+cat > "${ANDROID_PROJECT}/.gitignore" << 'EOF'
+*.iml
+.gradle
+/local.properties
+/.idea
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+*.apk
+*.ap_
+*.dex
+*.class
+bin/
+gen/
+out/
+app/libs/
+EOF
+echo -e "${GREEN}✓${NC} .gitignore created"
+
+# Create README
+echo -e "${YELLOW}Generating README.md...${NC}"
+cat > "${ANDROID_PROJECT}/README.md" << EOF
+# ${APP_NAME}
+
+Android game project using DoEngine and SDL2.
+
+## Project Information
+
+- **Package Name**: ${PACKAGE_NAME}
+- **Project Name**: ${PROJECT_NAME}
+- **DoEngine Path**: ${DOENGINE_ROOT}
+
+## Build Instructions
+
+### 1. Build DoEngine Libraries
+
+\`\`\`bash
+cd ${DOENGINE_ROOT}/Android
+./build-android.sh
+\`\`\`
+
+### 2. Copy Libraries to Android Project
+
+\`\`\`bash
+cp ${DOENGINE_ROOT}/Android/build/libs/arm64-v8a/*.so ${ANDROID_PROJECT}/app/libs/arm64-v8a/
+cp ${DOENGINE_ROOT}/Android/build/libs/armeabi-v7a/*.so ${ANDROID_PROJECT}/app/libs/armeabi-v7a/
+\`\`\`
+
+### 3. Open in Android Studio
+
+\`\`\`bash
+studio ${ANDROID_PROJECT}
+\`\`\`
+
+Or open Android Studio and select "Open an Existing Project", then navigate to:
+\`${ANDROID_PROJECT}\`
+
+### 4. Build and Run
+
+- Connect an Android device or start an emulator
+- Click the "Run" button in Android Studio
+
+## Project Structure
+
+\`\`\`
+${ANDROID_PROJECT}/
+├── app/
+│ ├── src/main/
+│ │ ├── java/${PACKAGE_PATH}/
+│ │ │ └── MainActivity.java
+│ │ ├── cpp/
+│ │ │ ├── main.cpp
+│ │ │ └── CMakeLists.txt
+│ │ ├── res/
+│ │ └── AndroidManifest.xml
+│ ├── libs/ (SDL2 & DoEngine .so files)
+│ └── build.gradle
+├── build.gradle
+└── settings.gradle
+\`\`\`
+
+## Development
+
+The main game code is in \`app/src/main/cpp/main.cpp\`. This is where you'll integrate your DoEngine API calls.
+
+## Troubleshooting
+
+### Libraries not found
+Make sure you've built DoEngine and copied the .so files to the \`app/libs/\` directory.
+
+### NDK not found
+Set the ANDROID_NDK_ROOT environment variable or update \`local.properties\`.
+
+### Build errors
+Clean and rebuild:
+\`\`\`bash
+./gradlew clean
+./gradlew build
+\`\`\`
+EOF
+echo -e "${GREEN}✓${NC} README.md created"
+
+# Create build helper script
+echo -e "${YELLOW}Generating build-and-deploy.sh...${NC}"
+cat > "${ANDROID_PROJECT}/build-and-deploy.sh" << EOF
+#!/bin/bash
+
+# Build and Deploy Script for ${APP_NAME}
+
+set -e
+
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+echo -e "\${GREEN}=== Building DoEngine Libraries ===\${NC}"
+cd "${DOENGINE_ROOT}/Android"
+./build-android.sh
+
+echo ""
+echo -e "\${GREEN}=== Copying Libraries to Android Project ===\${NC}"
+cp -v "${DOENGINE_ROOT}/Android/build/libs/arm64-v8a/"*.so "${ANDROID_PROJECT}/app/libs/arm64-v8a/"
+cp -v "${DOENGINE_ROOT}/Android/build/libs/armeabi-v7a/"*.so "${ANDROID_PROJECT}/app/libs/armeabi-v7a/"
+
+echo ""
+echo -e "\${GREEN}=== Libraries Deployed ===\${NC}"
+echo "You can now build the Android project in Android Studio"
+echo ""
+echo "To open in Android Studio:"
+echo " studio ${ANDROID_PROJECT}"
+EOF
+chmod +x "${ANDROID_PROJECT}/build-and-deploy.sh"
+echo -e "${GREEN}✓${NC} build-and-deploy.sh created"
+
+# Summary
+echo ""
+echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
+echo -e "${GREEN}║ ║${NC}"
+echo -e "${GREEN}║ Project Created Successfully! ║${NC}"
+echo -e "${GREEN}║ ║${NC}"
+echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
+echo ""
+echo -e "${CYAN}Project Location:${NC} ${ANDROID_PROJECT}"
+echo ""
+echo -e "${BLUE}=== Next Steps ===${NC}"
+echo ""
+echo -e "${YELLOW}1.${NC} Build DoEngine libraries:"
+echo -e " cd ${DOENGINE_ROOT}/Android"
+echo -e " ./build-android.sh"
+echo ""
+echo -e "${YELLOW}2.${NC} Deploy libraries to Android project:"
+echo -e " cd ${ANDROID_PROJECT}"
+echo -e " ./build-and-deploy.sh"
\ No newline at end of file
diff --git a/android/build-android-2.sh b/android/build-android-2.sh
new file mode 100644
index 0000000..8d838ef
--- /dev/null
+++ b/android/build-android-2.sh
@@ -0,0 +1,169 @@
+#!/bin/bash
+
+# Android Build Script for LibDoengine
+# This script builds the library for multiple Android ABIs
+
+set -e # Exit on error
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+# Configuration
+NDK_PATH="${ANDROID_NDK_ROOT:-$ANDROID_NDK}"
+
+# If NDK_PATH points to the ndk directory (not a specific version), find the latest version
+if [ -d "$NDK_PATH" ] && [ ! -f "$NDK_PATH/build/cmake/android.toolchain.cmake" ]; then
+ echo -e "${YELLOW}NDK path appears to be the base directory, searching for installed versions...${NC}"
+ # Find the latest NDK version
+ LATEST_NDK=$(ls -1 "$NDK_PATH" | grep -E '^[0-9]+\.' | sort -V | tail -n 1)
+ if [ -n "$LATEST_NDK" ]; then
+ NDK_PATH="$NDK_PATH/$LATEST_NDK"
+ echo -e "${GREEN}Found NDK version: ${NC}$LATEST_NDK"
+ fi
+fi
+
+MIN_SDK_VERSION=21
+TARGET_SDK_VERSION=33
+BUILD_TYPE="Release"
+LIBRARY_TYPE="SHARED" # Change to "STATIC" for static library
+
+# Android ABIs to build (uncomment the ones you need)
+ABIS=(
+ "arm64-v8a"
+ "armeabi-v7a"
+ # "x86"
+ # "x86_64"
+)
+
+# Get script directory
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
+BUILD_DIR="${SCRIPT_DIR}/build"
+
+echo -e "${GREEN}=== LibDoengine Android Build Script ===${NC}"
+echo ""
+
+# Check if NDK is set
+if [ -z "$NDK_PATH" ]; then
+ echo -e "${RED}Error: Android NDK not found!${NC}"
+ echo "Please set ANDROID_NDK_ROOT or ANDROID_NDK environment variable"
+ echo "Example: export ANDROID_NDK_ROOT=/path/to/android-ndk"
+ exit 1
+fi
+
+# Verify toolchain file exists
+if [ ! -f "$NDK_PATH/build/cmake/android.toolchain.cmake" ]; then
+ echo -e "${RED}Error: Android NDK toolchain not found at: $NDK_PATH${NC}"
+ echo "The NDK path should point to a complete NDK installation."
+ echo "Please check your NDK installation or set the correct path."
+ echo ""
+ echo "If your NDK is at /home/neonland/Android/Sdk/ndk, try:"
+ echo " export ANDROID_NDK_ROOT=/home/neonland/Android/Sdk/ndk/[version]"
+ echo ""
+ echo "Available NDK versions:"
+ if [ -d "$(dirname "$NDK_PATH")" ]; then
+ ls -1 "$(dirname "$NDK_PATH")" 2>/dev/null | grep -E '^[0-9]+\.' || echo " No NDK versions found"
+ fi
+ exit 1
+fi
+
+echo -e "${GREEN}NDK Path: ${NC}$NDK_PATH"
+echo -e "${GREEN}Min SDK: ${NC}$MIN_SDK_VERSION"
+echo -e "${GREEN}Target SDK: ${NC}$TARGET_SDK_VERSION"
+echo -e "${GREEN}Build Type: ${NC}$BUILD_TYPE"
+echo -e "${GREEN}Library Type: ${NC}$LIBRARY_TYPE"
+echo ""
+
+# Function to build for a specific ABI
+build_abi() {
+ local ABI=$1
+ echo -e "${YELLOW}Building for $ABI...${NC}"
+
+ local ABI_BUILD_DIR="${BUILD_DIR}/${ABI}"
+ mkdir -p "$ABI_BUILD_DIR"
+
+ cd "$ABI_BUILD_DIR"
+
+ # Configure with CMake
+ cmake "${SCRIPT_DIR}" \
+ -DCMAKE_TOOLCHAIN_FILE="${NDK_PATH}/build/cmake/android.toolchain.cmake" \
+ -DANDROID_ABI="${ABI}" \
+ -DANDROID_PLATFORM="android-${MIN_SDK_VERSION}" \
+ -DANDROID_STL=c++_shared \
+ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
+ -DBUILD_SHARED_LIBS=$([ "$LIBRARY_TYPE" = "SHARED" ] && echo "ON" || echo "OFF") \
+ -DCMAKE_INSTALL_PREFIX="${BUILD_DIR}/install/${ABI}"
+
+ # Build
+ cmake --build . --config ${BUILD_TYPE} -- -j$(nproc 2>/dev/null || echo 4)
+
+ # Install
+ cmake --install .
+
+ echo -e "${GREEN}✓ Successfully built for $ABI${NC}"
+ echo ""
+
+ cd "$SCRIPT_DIR"
+}
+
+# Clean build directory if requested
+if [ "$1" = "clean" ]; then
+ echo -e "${YELLOW}Cleaning build directory...${NC}"
+ rm -rf "$BUILD_DIR"
+ echo -e "${GREEN}✓ Clean complete${NC}"
+ exit 0
+fi
+
+# Create output directory
+mkdir -p "$BUILD_DIR"
+
+# Build for each ABI
+for ABI in "${ABIS[@]}"; do
+ build_abi "$ABI"
+done
+
+# Create a summary
+echo -e "${GREEN}=== Build Summary ===${NC}"
+echo ""
+echo "Libraries built for:"
+for ABI in "${ABIS[@]}"; do
+ LIB_PATH="${BUILD_DIR}/install/${ABI}/lib/${ABI}"
+ if [ -d "$LIB_PATH" ]; then
+ echo -e " ${GREEN}✓${NC} $ABI"
+ echo " Libraries:"
+ ls -lh "$LIB_PATH"/*.so 2>/dev/null | awk '{print " - " $9 " (" $5 ")"}' || true
+ ls -lh "$LIB_PATH"/*.a 2>/dev/null | awk '{print " - " $9 " (" $5 ")"}' || true
+ fi
+ echo ""
+done
+
+# Create a libs directory with all shared libraries organized by ABI
+LIBS_OUTPUT="${BUILD_DIR}/libs"
+mkdir -p "$LIBS_OUTPUT"
+
+echo -e "${YELLOW}Copying all shared libraries to: ${NC}${LIBS_OUTPUT}"
+for ABI in "${ABIS[@]}"; do
+ SRC_LIB_PATH="${BUILD_DIR}/install/${ABI}/lib/${ABI}"
+ DEST_ABI_PATH="${LIBS_OUTPUT}/${ABI}"
+
+ if [ -d "$SRC_LIB_PATH" ]; then
+ mkdir -p "$DEST_ABI_PATH"
+ cp -v "$SRC_LIB_PATH"/*.so "$DEST_ABI_PATH/" 2>/dev/null || true
+ echo -e " ${GREEN}✓${NC} Copied libraries for $ABI"
+ fi
+done
+
+echo ""
+echo -e "${GREEN}=== Build Complete ===${NC}"
+echo "Output directories:"
+echo " - Install dir: ${BUILD_DIR}/install"
+echo " - Libs dir: ${BUILD_DIR}/libs (organized by ABI)"
+echo ""
+echo "All shared libraries (.so files) including SDL2 and LibDoengine are in:"
+echo " ${BUILD_DIR}/libs/arm64-v8a/"
+echo " ${BUILD_DIR}/libs/armeabi-v7a/"
+echo ""
+echo "To clean build files, run: $0 clean"
\ No newline at end of file
diff --git a/android/build-android.sh b/android/build-android.sh
new file mode 100755
index 0000000..4ce3c37
--- /dev/null
+++ b/android/build-android.sh
@@ -0,0 +1,144 @@
+#!/bin/bash
+
+# Android Build Script for LibDoengine
+# This script builds the library for multiple Android ABIs
+
+set -e # Exit on error
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+# Configuration
+NDK_PATH="${ANDROID_NDK_ROOT:-$ANDROID_NDK}"
+
+# If NDK_PATH points to the ndk directory (not a specific version), find the latest version
+if [ -d "$NDK_PATH" ] && [ ! -f "$NDK_PATH/build/cmake/android.toolchain.cmake" ]; then
+ echo -e "${YELLOW}NDK path appears to be the base directory, searching for installed versions...${NC}"
+ # Find the latest NDK version
+ LATEST_NDK=$(ls -1 "$NDK_PATH" | grep -E '^[0-9]+\.' | sort -V | tail -n 1)
+ if [ -n "$LATEST_NDK" ]; then
+ NDK_PATH="$NDK_PATH/$LATEST_NDK"
+ echo -e "${GREEN}Found NDK version: ${NC}$LATEST_NDK"
+ fi
+fi
+
+MIN_SDK_VERSION=21
+TARGET_SDK_VERSION=33
+BUILD_TYPE="Release"
+LIBRARY_TYPE="SHARED" # Change to "STATIC" for static library
+
+# Android ABIs to build (uncomment the ones you need)
+ABIS=(
+ "arm64-v8a"
+ "armeabi-v7a"
+ # "x86"
+ # "x86_64"
+)
+
+# Get script directory
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
+BUILD_DIR="${SCRIPT_DIR}/build"
+
+echo -e "${GREEN}=== LibDoengine Android Build Script ===${NC}"
+echo ""
+
+# Check if NDK is set
+if [ -z "$NDK_PATH" ]; then
+ echo -e "${RED}Error: Android NDK not found!${NC}"
+ echo "Please set ANDROID_NDK_ROOT or ANDROID_NDK environment variable"
+ echo "Example: export ANDROID_NDK_ROOT=/path/to/android-ndk"
+ exit 1
+fi
+
+# Verify toolchain file exists
+if [ ! -f "$NDK_PATH/build/cmake/android.toolchain.cmake" ]; then
+ echo -e "${RED}Error: Android NDK toolchain not found at: $NDK_PATH${NC}"
+ echo "The NDK path should point to a complete NDK installation."
+ echo "Please check your NDK installation or set the correct path."
+ echo ""
+ echo "If your NDK is at /home/neonland/Android/Sdk/ndk, try:"
+ echo " export ANDROID_NDK_ROOT=/home/neonland/Android/Sdk/ndk/[version]"
+ echo ""
+ echo "Available NDK versions:"
+ if [ -d "$(dirname "$NDK_PATH")" ]; then
+ ls -1 "$(dirname "$NDK_PATH")" 2>/dev/null | grep -E '^[0-9]+\.' || echo " No NDK versions found"
+ fi
+ exit 1
+fi
+
+echo -e "${GREEN}NDK Path: ${NC}$NDK_PATH"
+echo -e "${GREEN}Min SDK: ${NC}$MIN_SDK_VERSION"
+echo -e "${GREEN}Target SDK: ${NC}$TARGET_SDK_VERSION"
+echo -e "${GREEN}Build Type: ${NC}$BUILD_TYPE"
+echo -e "${GREEN}Library Type: ${NC}$LIBRARY_TYPE"
+echo ""
+
+# Function to build for a specific ABI
+build_abi() {
+ local ABI=$1
+ echo -e "${YELLOW}Building for $ABI...${NC}"
+
+ local ABI_BUILD_DIR="${BUILD_DIR}/${ABI}"
+ mkdir -p "$ABI_BUILD_DIR"
+
+ cd "$ABI_BUILD_DIR"
+
+ # Configure with CMake
+ cmake "${SCRIPT_DIR}" \
+ -DCMAKE_TOOLCHAIN_FILE="${NDK_PATH}/build/cmake/android.toolchain.cmake" \
+ -DANDROID_ABI="${ABI}" \
+ -DANDROID_PLATFORM="android-${MIN_SDK_VERSION}" \
+ -DANDROID_STL=c++_shared \
+ -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
+ -DBUILD_SHARED_LIBS=$([ "$LIBRARY_TYPE" = "SHARED" ] && echo "ON" || echo "OFF") \
+ -DCMAKE_INSTALL_PREFIX="${BUILD_DIR}/install/${ABI}"
+
+ # Build
+ cmake --build . --config ${BUILD_TYPE} -- -j$(nproc 2>/dev/null || echo 4)
+
+ # Install
+ cmake --install .
+
+ echo -e "${GREEN}✓ Successfully built for $ABI${NC}"
+ echo ""
+
+ cd "$SCRIPT_DIR"
+}
+
+# Clean build directory if requested
+if [ "$1" = "clean" ]; then
+ echo -e "${YELLOW}Cleaning build directory...${NC}"
+ rm -rf "$BUILD_DIR"
+ echo -e "${GREEN}✓ Clean complete${NC}"
+ exit 0
+fi
+
+# Create output directory
+mkdir -p "$BUILD_DIR"
+
+# Build for each ABI
+for ABI in "${ABIS[@]}"; do
+ build_abi "$ABI"
+done
+
+# Create a summary
+echo -e "${GREEN}=== Build Summary ===${NC}"
+echo ""
+echo "Libraries built for:"
+for ABI in "${ABIS[@]}"; do
+ LIB_PATH="${BUILD_DIR}/install/${ABI}/lib/${ABI}"
+ if [ -d "$LIB_PATH" ]; then
+ echo -e " ${GREEN}✓${NC} $ABI"
+ ls -lh "$LIB_PATH"/*.so 2>/dev/null || ls -lh "$LIB_PATH"/*.a 2>/dev/null || true
+ fi
+done
+
+echo ""
+echo -e "${GREEN}=== Build Complete ===${NC}"
+echo "Output directory: ${BUILD_DIR}/install"
+echo ""
+echo "To clean build files, run: $0 clean"
\ No newline at end of file
diff --git a/assets/background/background_single.png b/assets/background/background_single.png
new file mode 100644
index 0000000..f08a0f2
Binary files /dev/null and b/assets/background/background_single.png differ
diff --git a/assets/background/full_map.png b/assets/background/full_map.png
new file mode 100644
index 0000000..6c59ad8
Binary files /dev/null and b/assets/background/full_map.png differ
diff --git a/assets/background/heaven1.png b/assets/background/heaven1.png
new file mode 100644
index 0000000..3b1db46
Binary files /dev/null and b/assets/background/heaven1.png differ
diff --git a/assets/background/heaven2.png b/assets/background/heaven2.png
new file mode 100644
index 0000000..9a032c6
Binary files /dev/null and b/assets/background/heaven2.png differ
diff --git a/assets/background/layer-1.png b/assets/background/layer-1.png
new file mode 100644
index 0000000..5fd0e49
Binary files /dev/null and b/assets/background/layer-1.png differ
diff --git a/assets/background/layer-2.png b/assets/background/layer-2.png
new file mode 100644
index 0000000..d8f225f
Binary files /dev/null and b/assets/background/layer-2.png differ
diff --git a/assets/background/layer-3.png b/assets/background/layer-3.png
new file mode 100644
index 0000000..0d864bd
Binary files /dev/null and b/assets/background/layer-3.png differ
diff --git a/assets/background/layer-4.png b/assets/background/layer-4.png
new file mode 100644
index 0000000..7a16cea
Binary files /dev/null and b/assets/background/layer-4.png differ
diff --git a/assets/background/layer-5.png b/assets/background/layer-5.png
new file mode 100644
index 0000000..67703eb
Binary files /dev/null and b/assets/background/layer-5.png differ
diff --git a/assets/gfx/Comida.bmp b/assets/gfx/Comida.bmp
new file mode 100644
index 0000000..7160daa
Binary files /dev/null and b/assets/gfx/Comida.bmp differ
diff --git a/assets/gfx/battle_city_tileset_1.png b/assets/gfx/battle_city_tileset_1.png
new file mode 100644
index 0000000..c505bae
Binary files /dev/null and b/assets/gfx/battle_city_tileset_1.png differ
diff --git a/assets/gfx/enemigo.bmp b/assets/gfx/enemigo.bmp
new file mode 100644
index 0000000..1d33fce
Binary files /dev/null and b/assets/gfx/enemigo.bmp differ
diff --git a/assets/gfx/muerte.bmp b/assets/gfx/muerte.bmp
new file mode 100644
index 0000000..aeb71c1
Binary files /dev/null and b/assets/gfx/muerte.bmp differ
diff --git a/assets/gfx/pacman.bmp b/assets/gfx/pacman.bmp
new file mode 100644
index 0000000..14f64a8
Binary files /dev/null and b/assets/gfx/pacman.bmp differ
diff --git a/assets/gfx/roca.bmp b/assets/gfx/roca.bmp
new file mode 100644
index 0000000..81c0708
Binary files /dev/null and b/assets/gfx/roca.bmp differ
diff --git a/assets/gfx/save.png b/assets/gfx/save.png
new file mode 100644
index 0000000..9623a04
Binary files /dev/null and b/assets/gfx/save.png differ
diff --git a/assets/gfx/shadow_dog.png b/assets/gfx/shadow_dog.png
new file mode 100644
index 0000000..220b7b7
Binary files /dev/null and b/assets/gfx/shadow_dog.png differ
diff --git a/assets/gfx/sprites/Resources.rar b/assets/gfx/sprites/Resources.rar
new file mode 100644
index 0000000..e96263c
Binary files /dev/null and b/assets/gfx/sprites/Resources.rar differ
diff --git a/assets/gfx/sprites/battle_city.jpg b/assets/gfx/sprites/battle_city.jpg
new file mode 100644
index 0000000..2798d14
Binary files /dev/null and b/assets/gfx/sprites/battle_city.jpg differ
diff --git a/assets/gfx/sprites/clouds_sprites.png b/assets/gfx/sprites/clouds_sprites.png
new file mode 100644
index 0000000..3b2623d
Binary files /dev/null and b/assets/gfx/sprites/clouds_sprites.png differ
diff --git a/assets/gfx/sprites/enemy_1.png b/assets/gfx/sprites/enemy_1.png
new file mode 100644
index 0000000..a18f0e1
Binary files /dev/null and b/assets/gfx/sprites/enemy_1.png differ
diff --git a/assets/gfx/sprites/map.png b/assets/gfx/sprites/map.png
new file mode 100644
index 0000000..bbfbc24
Binary files /dev/null and b/assets/gfx/sprites/map.png differ
diff --git a/assets/gfx/sprites/player.png b/assets/gfx/sprites/player.png
new file mode 100644
index 0000000..5a5eeba
Binary files /dev/null and b/assets/gfx/sprites/player.png differ
diff --git a/assets/gfx/sprites/playersprites.gif b/assets/gfx/sprites/playersprites.gif
new file mode 100644
index 0000000..0e38c49
Binary files /dev/null and b/assets/gfx/sprites/playersprites.gif differ
diff --git a/assets/gfx/sprites/snake.png b/assets/gfx/sprites/snake.png
new file mode 100644
index 0000000..2d982ba
Binary files /dev/null and b/assets/gfx/sprites/snake.png differ
diff --git a/assets/gfx/sprites/snake1b.png b/assets/gfx/sprites/snake1b.png
new file mode 100644
index 0000000..323eab9
Binary files /dev/null and b/assets/gfx/sprites/snake1b.png differ
diff --git a/assets/gfx/tileset/heaven_1.kra b/assets/gfx/tileset/heaven_1.kra
new file mode 100644
index 0000000..1abcd02
Binary files /dev/null and b/assets/gfx/tileset/heaven_1.kra differ
diff --git a/assets/gfx/tileset/heaven_1.png b/assets/gfx/tileset/heaven_1.png
new file mode 100644
index 0000000..a5d9795
Binary files /dev/null and b/assets/gfx/tileset/heaven_1.png differ
diff --git a/assets/gfx/tileset/platform_ts.png b/assets/gfx/tileset/platform_ts.png
new file mode 100644
index 0000000..b8bb982
Binary files /dev/null and b/assets/gfx/tileset/platform_ts.png differ
diff --git a/assets/gfx/tileset/project_ts.kra b/assets/gfx/tileset/project_ts.kra
new file mode 100644
index 0000000..ebfd23a
Binary files /dev/null and b/assets/gfx/tileset/project_ts.kra differ
diff --git a/assets/gfx/tileset/tilemap1.png b/assets/gfx/tileset/tilemap1.png
new file mode 100644
index 0000000..ca70f36
Binary files /dev/null and b/assets/gfx/tileset/tilemap1.png differ
diff --git a/assets/maps/testmap.map b/assets/maps/testmap.map
index 9813154..73ea13e 100644
--- a/assets/maps/testmap.map
+++ b/assets/maps/testmap.map
@@ -1,22 +1,17 @@
-20
-20
-1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
\ No newline at end of file
+60
+15
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+4 4 4 3 0 1 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
+2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
+2 2 2 2 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
\ No newline at end of file
diff --git a/assets/maps/testmap_2.map b/assets/maps/testmap_2.map
new file mode 100644
index 0000000..a35457e
--- /dev/null
+++ b/assets/maps/testmap_2.map
@@ -0,0 +1,33 @@
+30
+30
+48
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bgggggggggggggbbbbbbbbbbbbbbbb
+bgwwwwwwwwwwwgbbbbbbbbbbbbbbbb
+bgwbbbbbbbbwgbbbbbbbbbbbbbbbbb
+bgwbgttttgbwgbbbbbbbbbbbbbbbbb
+bgwbgttttgbwgbbbbbbbbbbbbbbbbb
+bgwbbbbbbbbwgbbbbbbbbbbbbbbbbb
+bgwwwwwwwwwwwgbbbbbbbbbbbbbbbb
+bgggggggggggggbbbbbbbbbbbbbbbb
+bbbbbbbBbbbbbbbbbbbbbbbbbbbbbb
+bgggggggggggggbbbbbbbbbbbbbbbb
+bgsssssssssssbgbbbbbbbbbbbbbbb
+bgsgggggggggsbgbbbbbbbbbbbbbbb
+bgsssssssssssbgbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+bgggggggggggggbbbbbbbbbbbbbbbb
+bgwwwwwwwwwwwgbbbbbbbbbbbbbbbb
+bgwbbbbbbbbwgbbbbbbbbbbbbbbbbb
+bgwbgttttgbwgbbbbbbbbbbbbbbbbb
+bgwbgttttgbwgbbbbbbbbbbbbbbbbb
+bgwbbbbbbbbwgbbbbbbbbbbbbbbbbb
+bgwwwwwwwwwwwgbbbbbbbbbbbbbbbb
+bgggggggggggggbbbbbbbbbbbbbbbb
+bbbbbbbBbbbbbbbbbbbbbbbbbbbbbb
+bgggggggggggggbbbbbbbbbbbbbbbb
+bgsssssssssssbgbbbbbbbbbbbbbbb
+bgsgggggggggsbgbbbbbbbbbbbbbbb
+bgsssssssssssbgbbbbbbbbbbbbbbb
+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
\ No newline at end of file
diff --git a/assets/settings/path.txt b/assets/settings/path.txt
new file mode 100644
index 0000000..7b652b6
--- /dev/null
+++ b/assets/settings/path.txt
@@ -0,0 +1,6 @@
+[images]
+
+[fonts]
+
+[sounds]
+
diff --git a/cmake-module/fetchGLMProjectFromSource.cmake b/cmake-module/fetchGLMProjectFromSource.cmake
new file mode 100644
index 0000000..ea258b5
--- /dev/null
+++ b/cmake-module/fetchGLMProjectFromSource.cmake
@@ -0,0 +1,19 @@
+
+include(FetchContent)
+message("Fecthing GLM Source code")
+# SDL2
+# SET(SDL_SHARED FALSE)
+FetchContent_Declare(
+ glm_lib
+ GIT_REPOSITORY https://github.com/g-truc/glm.git
+ GIT_TAG 1.0.3
+ GIT_SHALLOW TRUE
+)
+
+FetchContent_MakeAvailable(glm_lib)
+
+
+
+
+message("END Fecthing GLM Source code")
+
diff --git a/cmake-module/fetchSDL3ProjectFromSource.cmake b/cmake-module/fetchSDL3ProjectFromSource.cmake
new file mode 100644
index 0000000..f5cd2a0
--- /dev/null
+++ b/cmake-module/fetchSDL3ProjectFromSource.cmake
@@ -0,0 +1,44 @@
+
+include(FetchContent)
+message("Fecthing SDL Source code")
+# SDL2
+# SET(SDL_SHARED FALSE)
+FetchContent_Declare(
+ sdl_lib
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
+ GIT_TAG release-3.4.0
+)
+
+FetchContent_MakeAvailable(sdl_lib)
+
+# SDL2_image
+FetchContent_Declare(
+ sdl_image
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_image.git
+ GIT_SUBMODULES external/
+ GIT_TAG release-3.2.6
+)
+
+FetchContent_MakeAvailable(sdl_image)
+
+# SDL2_ttf
+FetchContent_Declare(
+ sdl_ttf
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_ttf.git
+ GIT_TAG release-3.2.2
+)
+
+FetchContent_MakeAvailable(sdl_ttf)
+
+# SDL2_mixer
+SET(SDL2MIXER_VENDORED TRUE)
+FetchContent_Declare(
+ sdl_mixer
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL_mixer.git
+ GIT_TAG release-2.6.3
+)
+
+FetchContent_MakeAvailable(sdl_mixer)
+
+message("END Fecthing SDL Source code")
+
diff --git a/sample/old_projects/CanvasTestState.h b/custom_project/CMakeLists.txt
similarity index 100%
rename from sample/old_projects/CanvasTestState.h
rename to custom_project/CMakeLists.txt
diff --git a/docs/ecs.md b/docs/ecs.md
new file mode 100644
index 0000000..2789be8
--- /dev/null
+++ b/docs/ecs.md
@@ -0,0 +1,1099 @@
+# DOEngine Experiment 101 - trying an Entity Component System (ECS)
+
+## Overview
+
+This is a lightweight **Entity Component System (ECS)** implementation for the `doengine` game engine. The ECS pattern is an architectural pattern commonly used in game development that favors composition over inheritance, allowing for flexible and scalable game object management.
+
+---
+
+## Table of Contents
+
+1. [Architecture Overview](#architecture-overview)
+2. [Core Components](#core-components)
+3. [Current Issues & Bugs](#current-issues--bugs)
+4. [API Reference](#api-reference)
+5. [Usage Examples](#usage-examples)
+6. [Improvements & Recommendations](#improvements--recommendations)
+
+---
+
+## Architecture Overview
+
+### What is ECS?
+
+The Entity Component System pattern separates:
+- **Entities**: Containers/IDs that group components together
+- **Components**: Pure data structures (position, velocity, sprite, etc.)
+- **Systems**: Logic that operates on entities with specific component combinations
+
+### Design Pattern
+
+```
+Entity (Container)
+ └── Component Array (Fast lookup by type)
+ └── Component Vector (Storage)
+ └── Bitset (Quick component presence checks)
+```
+
+---
+
+## Core Components
+
+### 1. Component Type System
+
+```cpp
+using ComponentId = int;
+
+inline ComponentId getNextComponentId()
+{
+ static ComponentId lastId = 0;
+ return ++lastId;
+}
+
+template
+inline ComponentId getComponentTypeId() noexcept
+{
+ static ComponentId typeID = getNextComponentId();
+ return typeID;
+}
+```
+
+**Purpose**: Assigns unique IDs to each component type at compile-time using template specialization.
+
+**How it works**: Each template instantiation creates a static variable with its own ID.
+
+---
+
+### 2. Component Base Class
+
+```cpp
+struct Component
+{
+ Entity *entity; // Back-reference to owning entity
+
+ virtual void init(){} // Called after component added
+ virtual void Update(){} // Per-frame logic
+ virtual void Render(){} // Rendering logic
+ virtual ~Component(){} // Virtual destructor for polymorphism
+};
+```
+
+**Purpose**: Base class that all components inherit from, providing common interface.
+
+---
+
+### 3. Entity Class
+
+```cpp
+struct Entity
+{
+ bool active = true;
+
+ std::vector> components; // Ownership
+ ComponentArray componentArray; // Fast lookup
+ ComponentBitset componentBitset; // Presence flags
+
+ // Methods: isActive, Update, Render, destroy
+ // addComponent, getComponent, hasComponent
+};
+```
+
+**Storage Strategy**:
+- **components vector**: Owns all components via shared_ptr
+- **componentArray**: Direct pointers indexed by component type ID (O(1) lookup)
+- **componentBitset**: Fast boolean checks for component presence
+
+---
+
+### 4. ECSManager
+
+```cpp
+struct ECSManager
+{
+ std::vector> entities;
+
+ void Update(); // Updates all entities
+ void Render(); // Renders all entities
+ void Refresh(); // Removes inactive entities
+ Entity& addEntity();
+};
+```
+
+**Purpose**: Central manager for all entities in the game world.
+
+---
+
+## Current Issues & Bugs
+
+### 🔴 Critical Bugs
+
+1. **Typo in `addComponent`**:
+ ```cpp
+ // WRONG:
+ T* c(new T(std::fordward(targs)...));
+
+ // CORRECT:
+ T* c(new T(std::forward(targs)...));
+ ```
+
+2. **Syntax Error in `getComponent`**:
+ ```cpp
+ // WRONG:
+ auto ptr[componentArray[getComponentTypeId()]];
+
+ // CORRECT:
+ auto ptr = componentArray[getComponentTypeId()];
+ ```
+
+3. **Missing `const` correctness in `getComponent`**:
+ - Method is marked `const` but accesses non-const array
+
+---
+
+### ⚠️ Design Issues
+
+1. **Memory Safety**:
+ - Raw pointer in `componentArray` alongside `shared_ptr` in `components`
+ - Potential dangling pointers if component is removed
+
+2. **No Component Removal**:
+ - No `removeComponent()` method
+
+3. **Thread Safety**:
+ - Not thread-safe (not suitable for multi-threaded game loops)
+
+4. **Limited Scalability**:
+ - `maxComponents = 32` is hardcoded
+ - No entity pooling/recycling
+
+5. **Unused Parameter**:
+ - `Entity::Update(float elapsed = 0)` doesn't use `elapsed`
+
+---
+
+## API Reference
+
+### Entity Methods
+
+#### `addComponent(Args...)`
+Adds a component of type T to the entity.
+
+**Parameters**: Constructor arguments for the component
+**Returns**: Reference to the created component
+**Example**:
+```cpp
+auto& pos = entity.addComponent(100, 200);
+```
+
+#### `getComponent()`
+Retrieves a component of type T.
+
+**Returns**: Reference to the component
+**Throws**: Undefined behavior if component doesn't exist
+**Example**:
+```cpp
+auto& pos = entity.getComponent();
+```
+
+#### `hasComponent()`
+Checks if entity has a component of type T.
+
+**Returns**: `bool`
+**Example**:
+```cpp
+if (entity.hasComponent()) { ... }
+```
+
+#### `destroy()`
+Marks entity as inactive (removed on next `Refresh()`).
+
+---
+
+### ECSManager Methods
+
+#### `addEntity()`
+Creates and registers a new entity.
+
+**Returns**: Reference to the new entity
+
+#### `Refresh()`
+Removes all inactive entities from the manager.
+
+**Important**: Call this after destroying entities to free memory.
+
+---
+
+## Usage Examples
+
+### Example 1: Basic Entity Creation
+
+```cpp
+#include "ECS.h"
+
+doengine::ECSManager manager;
+
+// Create entity
+doengine::Entity& player = manager.addEntity();
+
+// Add components
+auto& pos = player.addComponent();
+pos.setPosition({100, 100});
+
+// Game loop
+while (running) {
+ manager.Update();
+ manager.Render();
+ manager.Refresh();
+}
+```
+
+---
+
+### Example 2: Creating Custom Components
+
+```cpp
+// Velocity component
+struct VelocityComponent : public doengine::Component
+{
+ float vx = 0.0f;
+ float vy = 0.0f;
+
+ void init() override {
+ // Initialize velocity
+ }
+
+ void Update() override {
+ // Apply physics
+ auto& pos = entity->getComponent();
+ pos.point.x += static_cast(vx);
+ pos.point.y += static_cast(vy);
+ }
+};
+
+// Sprite component
+struct SpriteComponent : public doengine::Component
+{
+ std::string texturePath;
+ int width, height;
+
+ void init() override {
+ // Load texture
+ }
+
+ void Render() override {
+ auto& pos = entity->getComponent();
+ // Draw sprite at pos.X(), pos.Y()
+ }
+};
+```
+
+---
+
+### Example 3: Game Object with Multiple Components
+
+```cpp
+// Create player entity
+doengine::Entity& player = manager.addEntity();
+
+// Position
+auto& pos = player.addComponent();
+pos.setPosition({400, 300});
+
+// Velocity
+auto& vel = player.addComponent();
+vel.vx = 5.0f;
+vel.vy = 0.0f;
+
+// Sprite
+auto& sprite = player.addComponent();
+sprite.texturePath = "assets/player.png";
+sprite.width = 64;
+sprite.height = 64;
+
+// Input handling (outside ECS)
+void handleInput() {
+ if (entity.hasComponent()) {
+ auto& vel = entity.getComponent();
+ if (keyPressed(KEY_RIGHT)) vel.vx = 5.0f;
+ if (keyPressed(KEY_LEFT)) vel.vx = -5.0f;
+ }
+}
+```
+
+---
+
+### Example 4: Entity Destruction
+
+```cpp
+// Mark enemy as dead
+enemy.destroy();
+
+// Clean up inactive entities
+manager.Refresh(); // Enemy is now removed
+```
+
+---
+
+### Example 5: System-like Pattern
+
+```cpp
+// Physics System (updates all entities with position + velocity)
+void PhysicsSystem(doengine::ECSManager& manager)
+{
+ for (auto& entity : manager.entities) {
+ if (entity->hasComponent() &&
+ entity->hasComponent())
+ {
+ auto& pos = entity->getComponent();
+ auto& vel = entity->getComponent();
+
+ pos.point.x += static_cast(vel.vx);
+ pos.point.y += static_cast(vel.vy);
+ }
+ }
+}
+
+// Call in game loop
+PhysicsSystem(manager);
+```
+
+---
+
+### Example 6: Collision Detection System
+
+```cpp
+struct ColliderComponent : public doengine::Component
+{
+ int width, height;
+ bool isTrigger = false;
+
+ bool intersects(const ColliderComponent& other) {
+ auto& pos1 = entity->getComponent();
+ auto& pos2 = other.entity->getComponent();
+
+ return (pos1.X() < pos2.X() + other.width &&
+ pos1.X() + width > pos2.X() &&
+ pos1.Y() < pos2.Y() + other.height &&
+ pos1.Y() + height > pos2.Y());
+ }
+};
+
+// Collision System
+void CollisionSystem(doengine::ECSManager& manager)
+{
+ for (size_t i = 0; i < manager.entities.size(); ++i) {
+ if (!manager.entities[i]->hasComponent())
+ continue;
+
+ auto& col1 = manager.entities[i]->getComponent();
+
+ for (size_t j = i + 1; j < manager.entities.size(); ++j) {
+ if (!manager.entities[j]->hasComponent())
+ continue;
+
+ auto& col2 = manager.entities[j]->getComponent();
+
+ if (col1.intersects(col2)) {
+ // Handle collision
+ OnCollision(manager.entities[i], manager.entities[j]);
+ }
+ }
+ }
+}
+```
+
+---
+
+## Improvements & Recommendations
+
+### 1. Fix Critical Bugs
+
+```cpp
+// Fixed addComponent
+template
+T& addComponent(Targs&&... targs)
+{
+ T* c = new T(std::forward(targs)...); // FIX: forward
+ c->entity = this;
+ std::shared_ptr uPtr{c};
+ components.emplace_back(uPtr);
+
+ componentArray[getComponentTypeId()] = c;
+ componentBitset[getComponentTypeId()] = true;
+
+ c->init();
+ return *c;
+}
+
+// Fixed getComponent
+template
+T& getComponent() const
+{
+ auto ptr = componentArray[getComponentTypeId()]; // FIX: syntax
+ return *static_cast(ptr);
+}
+```
+
+---
+
+### 2. Add Component Removal
+
+```cpp
+template
+void removeComponent()
+{
+ if (!hasComponent()) return;
+
+ ComponentId id = getComponentTypeId();
+
+ // Remove from array
+ componentArray[id] = nullptr;
+ componentBitset[id] = false;
+
+ // Remove from vector
+ components.erase(
+ std::remove_if(components.begin(), components.end(),
+ [id](const std::shared_ptr& c) {
+ return dynamic_cast(c.get()) != nullptr;
+ }),
+ components.end()
+ );
+}
+```
+
+---
+
+### 3. Add Safety Checks
+
+```cpp
+template
+T& getComponent() const
+{
+ if (!hasComponent()) {
+ throw std::runtime_error("Component not found");
+ }
+ auto ptr = componentArray[getComponentTypeId()];
+ return *static_cast(ptr);
+}
+```
+
+---
+
+### 4. Use Delta Time
+
+```cpp
+struct Entity
+{
+ void Update(float deltaTime)
+ {
+ for(auto& it : components)
+ it->Update(deltaTime);
+ }
+};
+
+struct Component
+{
+ virtual void Update(float deltaTime) {}
+};
+```
+
+---
+
+### 5. Entity Pooling
+
+```cpp
+struct ECSManager
+{
+ std::vector> entities;
+ std::vector> entityPool;
+
+ Entity& addEntity()
+ {
+ std::shared_ptr p;
+
+ if (!entityPool.empty()) {
+ p = std::move(entityPool.back());
+ entityPool.pop_back();
+ p->active = true;
+ } else {
+ p = std::make_shared();
+ }
+
+ entities.emplace_back(p);
+ return *p;
+ }
+
+ void Refresh()
+ {
+ for (auto it = entities.begin(); it != entities.end();) {
+ if (!(*it)->isActive()) {
+ entityPool.push_back(*it);
+ it = entities.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+};
+```
+
+---
+
+### 6. Component Groups (Systems Pattern)
+
+```cpp
+template
+std::vector getEntitiesWith()
+{
+ std::vector result;
+
+ for (auto& entity : entities) {
+ if ((entity->hasComponent() && ...)) {
+ result.push_back(entity.get());
+ }
+ }
+
+ return result;
+}
+
+// Usage:
+auto movingEntities = manager.getEntitiesWith();
+```
+
+---
+
+### 7. Performance: Reserve Capacity
+
+```cpp
+ECSManager()
+{
+ entities.reserve(1000); // Pre-allocate
+}
+```
+
+---
+
+### 8. Better Memory Management
+
+```cpp
+// Use make_shared for better performance
+Entity& addEntity()
+{
+ entities.emplace_back(std::make_shared());
+ return *entities.back();
+}
+```
+
+---
+
+## Performance Considerations
+
+| Operation | Complexity | Notes |
+|-----------|-----------|-------|
+| Add Component | O(1) | Direct array indexing |
+| Get Component | O(1) | Array lookup by type ID |
+| Has Component | O(1) | Bitset check |
+| Remove Component | O(n) | Vector erase |
+| Iterate Entities | O(n) | Linear scan |
+| Refresh (cleanup) | O(n) | Erase-remove idiom |
+
+---
+
+## Best Practices
+
+1. **Always call `Refresh()`** after destroying entities to prevent memory leaks
+2. **Check `hasComponent()`** before `getComponent()` to avoid crashes
+3. **Use composition** over deep inheritance hierarchies
+4. **Keep components data-only** when possible
+5. **Implement Systems** as free functions operating on component groups
+6. **Profile before optimizing** - ECS is already quite fast for small-medium games
+
+---
+
+## Limitations
+
+- Maximum 32 component types (can be increased by changing `maxComponents`)
+- Not thread-safe
+- No built-in serialization
+- No component dependencies/requirements
+- No event system
+
+---
+
+## Conclusion
+
+This ECS implementation provides a solid foundation for a component-based game engine. With the suggested improvements, it would be production-ready for small to medium-sized games. For larger projects, consider libraries like EnTT or FLECS which offer more advanced features.
+
+---
+
+## Additional Resources
+
+- [Game Programming Patterns - Component Pattern](http://gameprogrammingpatterns.com/component.html)
+- [EnTT - Modern C++ ECS](https://github.com/skypjack/entt)
+- [Data-Oriented Design](https://www.dataorienteddesign.com/dodbook/)
+
+
+#### Sample Usage...
+
+```cpp
+
+
+#include "EntityComponentSystem.h"
+#include
+#include
+
+using namespace doengine;
+
+// ============================================================================
+// EXAMPLE 1: Basic Entity Creation and Component Management
+// ============================================================================
+
+void example1_basic_usage()
+{
+ std::cout << "=== Example 1: Basic Usage ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create a simple entity with position
+ Entity& player = manager.addEntity();
+ auto& pos = player.addComponent(100, 200);
+
+ std::cout << "Player position: (" << pos.X() << ", " << pos.Y() << ")" << std::endl;
+
+ // Move the player
+ pos.move(50, 30);
+ std::cout << "After move: (" << pos.X() << ", " << pos.Y() << ")" << std::endl;
+
+ // Check for components
+ if (player.hasComponent()) {
+ std::cout << "Player has PositionComponent" << std::endl;
+ }
+
+ // Game loop simulation
+ for (int frame = 0; frame < 3; ++frame) {
+ manager.Update(0.016f); // ~60 FPS
+ manager.Render();
+ }
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 2: Multiple Components - Moving Entity
+// ============================================================================
+
+void example2_moving_entity()
+{
+ std::cout << "=== Example 2: Moving Entity ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create entity with position and velocity
+ Entity& bullet = manager.addEntity();
+ bullet.addComponent(0, 0);
+ bullet.addComponent(100.0f, 50.0f); // pixels per second
+
+ // Simulate 5 frames
+ float deltaTime = 0.016f; // 60 FPS
+ for (int i = 0; i < 5; ++i) {
+ manager.Update(deltaTime);
+
+ auto& pos = bullet.getComponent();
+ std::cout << "Frame " << i << ": Position ("
+ << pos.X() << ", " << pos.Y() << ")" << std::endl;
+ }
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 3: Complete Game Entity (Player)
+// ============================================================================
+
+void example3_complete_player()
+{
+ std::cout << "=== Example 3: Complete Player Entity ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create player with all components
+ Entity& player = manager.addEntity();
+
+ auto& pos = player.addComponent(400, 300);
+ auto& vel = player.addComponent(0.0f, 0.0f);
+ auto& sprite = player.addComponent("assets/player.png", 64, 64);
+ auto& collider = player.addComponent(64, 64, "player");
+
+ std::cout << "Created player entity with:" << std::endl;
+ std::cout << " - Position: (" << pos.X() << ", " << pos.Y() << ")" << std::endl;
+ std::cout << " - Sprite: " << sprite.texturePath << std::endl;
+ std::cout << " - Collider: " << collider.width << "x" << collider.height << std::endl;
+
+ // Simulate player input (move right)
+ vel.vx = 200.0f; // Move right at 200 px/s
+
+ // Update a few frames
+ for (int i = 0; i < 3; ++i) {
+ manager.Update(0.016f);
+ auto& currentPos = player.getComponent();
+ std::cout << "Frame " << i << ": Player at ("
+ << currentPos.X() << ", " << currentPos.Y() << ")" << std::endl;
+ }
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 4: Component Removal
+// ============================================================================
+
+void example4_component_removal()
+{
+ std::cout << "=== Example 4: Component Removal ===" << std::endl;
+
+ ECSManager manager;
+ Entity& entity = manager.addEntity();
+
+ // Add components
+ entity.addComponent(10, 20);
+ entity.addComponent(5.0f, 5.0f);
+
+ std::cout << "Has Position: " << entity.hasComponent() << std::endl;
+ std::cout << "Has Velocity: " << entity.hasComponent() << std::endl;
+
+ // Remove velocity
+ entity.removeComponent();
+
+ std::cout << "After removing velocity:" << std::endl;
+ std::cout << "Has Position: " << entity.hasComponent() << std::endl;
+ std::cout << "Has Velocity: " << entity.hasComponent() << std::endl;
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 5: Entity Destruction and Cleanup
+// ============================================================================
+
+void example5_entity_lifecycle()
+{
+ std::cout << "=== Example 5: Entity Lifecycle ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create multiple entities
+ for (int i = 0; i < 5; ++i) {
+ Entity& ent = manager.addEntity();
+ ent.addComponent(i * 10, i * 10);
+ }
+
+ std::cout << "Created " << manager.getEntityCount() << " entities" << std::endl;
+
+ // Destroy some entities
+ manager.entities[1]->destroy();
+ manager.entities[3]->destroy();
+
+ std::cout << "Marked 2 entities for destruction" << std::endl;
+ std::cout << "Before refresh: " << manager.getEntityCount() << " entities" << std::endl;
+
+ // Clean up
+ manager.Refresh();
+
+ std::cout << "After refresh: " << manager.getEntityCount() << " entities" << std::endl;
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 6: Query Entities by Components (System Pattern)
+// ============================================================================
+
+void example6_entity_queries()
+{
+ std::cout << "=== Example 6: Entity Queries ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create different types of entities
+ // Static objects (position only)
+ for (int i = 0; i < 3; ++i) {
+ Entity& wall = manager.addEntity();
+ wall.addComponent(i * 100, 0);
+ }
+
+ // Moving objects (position + velocity)
+ for (int i = 0; i < 2; ++i) {
+ Entity& enemy = manager.addEntity();
+ enemy.addComponent(i * 50, 100);
+ enemy.addComponent(10.0f, 0.0f);
+ }
+
+ std::cout << "Total entities: " << manager.getEntityCount() << std::endl;
+
+ // Query entities with both position and velocity
+ auto movingEntities = manager.getEntitiesWith();
+ std::cout << "Moving entities (Position + Velocity): " << movingEntities.size() << std::endl;
+
+ // Process only moving entities
+ for (auto* entity : movingEntities) {
+ auto& pos = entity->getComponent();
+ auto& vel = entity->getComponent();
+ std::cout << " Moving entity at (" << pos.X() << ", " << pos.Y()
+ << ") with velocity (" << vel.vx << ", " << vel.vy << ")" << std::endl;
+ }
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 7: Collision Detection System
+// ============================================================================
+
+void example7_collision_system()
+{
+ std::cout << "=== Example 7: Collision Detection ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create player
+ Entity& player = manager.addEntity();
+ player.addComponent(100, 100);
+ player.addComponent(32, 32, "player");
+
+ // Create enemies
+ Entity& enemy1 = manager.addEntity();
+ enemy1.addComponent(120, 120); // Overlapping
+ enemy1.addComponent(32, 32, "enemy");
+
+ Entity& enemy2 = manager.addEntity();
+ enemy2.addComponent(300, 300); // Far away
+ enemy2.addComponent(32, 32, "enemy");
+
+ // Check collisions
+ auto collidables = manager.getEntitiesWith();
+
+ std::cout << "Checking collisions for " << collidables.size() << " entities" << std::endl;
+
+ for (size_t i = 0; i < collidables.size(); ++i) {
+ auto& col1 = collidables[i]->getComponent();
+
+ for (size_t j = i + 1; j < collidables.size(); ++j) {
+ auto& col2 = collidables[j]->getComponent();
+
+ if (col1.intersects(col2)) {
+ std::cout << "COLLISION: " << col1.tag << " hit " << col2.tag << std::endl;
+ }
+ }
+ }
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 8: Custom Physics System
+// ============================================================================
+
+// Custom component for gravity
+struct GravityComponent : public Component
+{
+ float gravity = 9.8f; // pixels per second squared
+
+ void Update(float deltaTime) override
+ {
+ if (entity->hasComponent()) {
+ auto& vel = entity->getComponent();
+ vel.vy += gravity * deltaTime;
+ }
+ }
+};
+
+void example8_physics_system()
+{
+ std::cout << "=== Example 8: Physics System ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create falling object
+ Entity& ball = manager.addEntity();
+ ball.addComponent(100, 0);
+ ball.addComponent(0.0f, 0.0f);
+ ball.addComponent();
+
+ std::cout << "Simulating falling ball:" << std::endl;
+
+ // Simulate 5 frames
+ for (int i = 0; i < 5; ++i) {
+ manager.Update(0.1f); // 10 FPS for visible effect
+
+ auto& pos = ball.getComponent();
+ auto& vel = ball.getComponent();
+
+ std::cout << "Frame " << i << ": Y=" << pos.Y()
+ << ", Velocity=" << vel.vy << std::endl;
+ }
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 9: Entity Pooling Performance
+// ============================================================================
+
+void example9_entity_pooling()
+{
+ std::cout << "=== Example 9: Entity Pooling ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create and destroy entities multiple times
+ std::cout << "Creating 100 entities..." << std::endl;
+ for (int i = 0; i < 100; ++i) {
+ Entity& ent = manager.addEntity();
+ ent.addComponent(i, i);
+ }
+ std::cout << "Active entities: " << manager.getEntityCount() << std::endl;
+
+ // Destroy half
+ std::cout << "Destroying 50 entities..." << std::endl;
+ for (size_t i = 0; i < 50; ++i) {
+ manager.entities[i]->destroy();
+ }
+ manager.Refresh();
+ std::cout << "Active entities after refresh: " << manager.getEntityCount() << std::endl;
+
+ // Create new entities (will reuse from pool)
+ std::cout << "Creating 50 new entities (from pool)..." << std::endl;
+ for (int i = 0; i < 50; ++i) {
+ Entity& ent = manager.addEntity();
+ ent.addComponent(i * 2, i * 2);
+ }
+ std::cout << "Active entities: " << manager.getEntityCount() << std::endl;
+
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// EXAMPLE 10: Complete Mini-Game
+// ============================================================================
+
+struct HealthComponent : public Component
+{
+ int health = 100;
+ int maxHealth = 100;
+
+ void takeDamage(int amount) {
+ health -= amount;
+ if (health <= 0) {
+ health = 0;
+ entity->destroy();
+ }
+ }
+};
+
+void example10_mini_game()
+{
+ std::cout << "=== Example 10: Mini Shooter Game ===" << std::endl;
+
+ ECSManager manager;
+
+ // Create player
+ Entity& player = manager.addEntity();
+ player.addComponent(400, 500);
+ player.addComponent(0.0f, 0.0f);
+ player.addComponent("player.png", 32, 32);
+ player.addComponent(32, 32, "player");
+ player.addComponent();
+
+ // Create enemies
+ for (int i = 0; i < 3; ++i) {
+ Entity& enemy = manager.addEntity();
+ enemy.addComponent(100 + i * 150, 100);
+ enemy.addComponent(0.0f, 50.0f); // Move down
+ enemy.addComponent("enemy.png", 32, 32);
+ enemy.addComponent(32, 32, "enemy");
+ auto& health = enemy.addComponent();
+ health.health = 50;
+ }
+
+ std::cout << "Game initialized with:" << std::endl;
+ std::cout << " - 1 Player" << std::endl;
+ std::cout << " - 3 Enemies" << std::endl;
+
+ // Simulate game loop
+ for (int frame = 0; frame < 10; ++frame) {
+ float deltaTime = 0.016f;
+
+ // Update all entities
+ manager.Update(deltaTime);
+
+ // Check collisions
+ auto collidables = manager.getEntitiesWith();
+ for (size_t i = 0; i < collidables.size(); ++i) {
+ for (size_t j = i + 1; j < collidables.size(); ++j) {
+ auto& col1 = collidables[i]->getComponent();
+ auto& col2 = collidables[j]->getComponent();
+
+ if (col1.intersects(col2)) {
+ // Handle collision
+ if (col1.tag == "player" && col2.tag == "enemy") {
+ std::cout << "Frame " << frame << ": Player hit by enemy!" << std::endl;
+
+ if (collidables[i]->hasComponent()) {
+ auto& health = collidables[i]->getComponent();
+ health.takeDamage(10);
+ std::cout << " Player health: " << health.health << std::endl;
+ }
+ }
+ }
+ }
+ }
+
+ // Clean up destroyed entities
+ manager.Refresh();
+ }
+
+ std::cout << "Game ended. Remaining entities: " << manager.getEntityCount() << std::endl;
+ std::cout << std::endl;
+}
+
+
+// ============================================================================
+// MAIN
+// ============================================================================
+
+int main()
+{
+ std::cout << "ECS System - Usage Examples" << std::endl;
+ std::cout << "======================================" << std::endl << std::endl;
+
+ try {
+ example1_basic_usage();
+ example2_moving_entity();
+ example3_complete_player();
+ example4_component_removal();
+ example5_entity_lifecycle();
+ example6_entity_queries();
+ example7_collision_system();
+ example8_physics_system();
+ example9_entity_pooling();
+ example10_mini_game();
+
+ std::cout << "All examples completed successfully!" << std::endl;
+ }
+ catch (const std::exception& e) {
+ std::cerr << "Error: " << e.what() << std::endl;
+ return 1;
+ }
+
+ return 0;
+}
+```
\ No newline at end of file
diff --git a/includes/AnimateGameObject.h b/includes/AnimateGameObject.h
new file mode 100644
index 0000000..4ea8722
--- /dev/null
+++ b/includes/AnimateGameObject.h
@@ -0,0 +1,40 @@
+#ifndef ANIMATED_GAMEOBJECT_H_DEFINED
+#define ANIMATED_GAMEOBJECT_H_DEFINED
+#include "GameObject.h"
+#include "Timer.h"
+namespace doengine
+{
+
+class AnimateGameObject : public GameObject
+{
+
+ public:
+
+ struct Animation
+ {
+ Timer timer;
+ int frameCount;
+
+ int getCurrentFrame()
+ {
+ return static_cast(timer.getTime() / timer.getLength() * frameCount);
+ }
+
+ void step(float fl)
+ {
+ timer.Update(fl);
+ }
+ };
+
+ AnimateGameObject();
+ virtual void Update(float elapsed) = 0;
+ virtual void Render() = 0;
+ void step(float elapsed); /// call it manually on Update...todo Put automatica on merge it GameState.
+};
+
+
+
+
+};
+
+#endif
\ No newline at end of file
diff --git a/includes/Application.h b/includes/Application.h
index 730be6b..b777aa3 100644
--- a/includes/Application.h
+++ b/includes/Application.h
@@ -8,7 +8,7 @@
namespace doengine
{
-
+class GameState;
class FpsManager;
class GameStateManager;
class WindowManager;
@@ -60,56 +60,18 @@ class Application
void Update();
void Render();
void Quit();
-
- long getElapsedTime()
- {
- return fps_handler->getElapsedTime();
- }
-
- uint32_t getDeltaTime()
- {
- return fps_handler->getDeltaTime();
- }
-
- void setW(int w)
- {
- window_rect.w = w;
- _internalResize();
- }
- void setH(int h)
- {
- window_rect.h = h;
- _internalResize();
- }
- void setSize(int w, int h)
- {
- window_rect.w = w;
- window_rect.h = h;
- _internalResize();
- }
- int getH()
- {
- return window_rect.h;
- }
- int getW()
- {
- return window_rect.w;
- }
-
+ long getElapsedTime();
+ uint32_t getDeltaTime();
+ void setW(int w);
+ void setH(int h);
+ void setSize(int w, int h);
+ int getH();
+ int getW();
+ Rect getDisplayMode(int m=0);
void SetWindowPencilColor(const Color& color);
-
void clearScreen(const Color& color);
-
- void addState(GameState* state, int id)
- {
- gsm->AddState(id, state);
- }
-
- void setState(int id)
- {
- gsm->SetState(id);
- }
-
+ void addState(GameState* state, int id);
+ void setState(int id);
private:
void destroy();
};
diff --git a/includes/Camera.h b/includes/Camera.h
index 3341bb9..f4010bc 100644
--- a/includes/Camera.h
+++ b/includes/Camera.h
@@ -1,25 +1,240 @@
#pragma once
-
+#include
#include "Camera.h"
+#include "Geometric.h"
namespace doengine
{
+
class Camera
{
- // Vector camera_pos;
-
- public:
- enum class CameraMovement : unsigned char
+public:
+ enum class CameraMovement
{
CameraUp,
CameraDown,
CameraLeft,
- CameraRight,
- CameraNotMovement
+ CameraRight
};
- virtual Camera* Update(CameraMovement where) = 0;
+private:
+ Point position; // Camera position (usually negative for scrolling)
+ Point targetPosition; // Target position for smooth following
+ int viewportWidth; // Screen width
+ int viewportHeight; // Screen height
+ int tileSize; // Size of each tile
+
+ // Bounds
+ bool boundsEnabled;
+ int minX, minY; // Minimum camera position (usually negative)
+ int maxX, maxY; // Maximum camera position (usually 0)
+
+ // Smoothing
+ float smoothingFactor; // Interpolation factor (0.0 - 1.0)
+ bool smoothingEnabled;
+
+ // Cached values for optimization
+ int rowOffset;
+ int colOffset;
+ int rowsToRender;
+ int colsToRender;
+
+public:
+ Camera(int viewportW, int viewportH, int tileSize, float smoothing = 0.1f)
+ : position(0, 0),
+ targetPosition(0, 0),
+ viewportWidth(viewportW),
+ viewportHeight(viewportH),
+ tileSize(tileSize),
+ boundsEnabled(false),
+ minX(0), minY(0),
+ maxX(0), maxY(0),
+ smoothingFactor(smoothing),
+ smoothingEnabled(true),
+ rowOffset(0),
+ colOffset(0),
+ rowsToRender(0),
+ colsToRender(0)
+ {
+ updateCachedValues();
+ }
+
+ void update(float deltaTime)
+ {
+ if (smoothingEnabled)
+ {
+ // Smooth interpolation towards target
+ float factor = std::min(1.0f, smoothingFactor * deltaTime * 60.0f); // Normalize for 60 FPS
+ position.x += (int)((targetPosition.x - position.x) * factor);
+ position.y += (int)((targetPosition.y - position.y) * factor);
+ }
+ else
+ {
+ // Instant movement
+ position = targetPosition;
+ }
+
+ // Apply bounds
+ if (boundsEnabled)
+ {
+ applyBounds();
+ }
+
+ // Update cached values
+ updateCachedValues();
+ }
+
+ void centerOn(const Point& worldPos)
+ {
+ // Center camera on a world position
+ targetPosition.x = -(worldPos.x - viewportWidth / 2);
+ targetPosition.y = -(worldPos.y - viewportHeight / 2);
+
+ if (boundsEnabled)
+ {
+ targetPosition.x = std::max(minX, std::min(maxX, targetPosition.x));
+ targetPosition.y = std::max(minY, std::min(maxY, targetPosition.y));
+ }
+ }
+
+ void centerOn(int worldX, int worldY)
+ {
+ centerOn(Point(worldX, worldY));
+ }
+
+ void moveCamera(CameraMovement direction, int speed)
+ {
+ switch (direction)
+ {
+ case CameraMovement::CameraUp:
+ targetPosition.y += speed;
+ break;
+ case CameraMovement::CameraDown:
+ targetPosition.y -= speed;
+ break;
+ case CameraMovement::CameraLeft:
+ targetPosition.x += speed;
+ break;
+ case CameraMovement::CameraRight:
+ targetPosition.x -= speed;
+ break;
+ }
+
+ if (boundsEnabled)
+ {
+ targetPosition.x = std::max(minX, std::min(maxX, targetPosition.x));
+ targetPosition.y = std::max(minY, std::min(maxY, targetPosition.y));
+ }
+ }
+
+ void setPosition(const Point& pos)
+ {
+ position = pos;
+ targetPosition = pos;
+
+ if (boundsEnabled)
+ {
+ applyBounds();
+ }
+
+ updateCachedValues();
+ }
+
+ void setPosition(int x, int y)
+ {
+ setPosition(Point(x, y));
+ }
+
+ Point getPosition() const
+ {
+ return position;
+ }
+
+ void setBounds(int minX, int minY, int maxX, int maxY)
+ {
+ this->minX = minX;
+ this->minY = minY;
+ this->maxX = maxX;
+ this->maxY = maxY;
+ }
+
+ void enableBounds(bool enabled)
+ {
+ boundsEnabled = enabled;
+ }
+
+ void setSmoothing(float factor)
+ {
+ smoothingFactor = std::max(0.0f, std::min(1.0f, factor));
+ }
+
+ void enableSmoothing(bool enabled)
+ {
+ smoothingEnabled = enabled;
+ }
+
+ // Get visible tile range
+ int getRowOffset() const { return rowOffset; }
+ int getColOffset() const { return colOffset; }
+ int getRowsToRender() const { return rowsToRender; }
+ int getColsToRender() const { return colsToRender; }
+
+ // Viewport dimensions
+ int getViewportWidth() const { return viewportWidth; }
+ int getViewportHeight() const { return viewportHeight; }
+
+ // Coordinate conversions
+ Point worldToScreen(int worldX, int worldY) const
+ {
+ return Point(worldX + position.x, worldY + position.y);
+ }
+
+ Point screenToWorld(int screenX, int screenY) const
+ {
+ return Point(screenX - position.x, screenY - position.y);
+ }
+
+ // Check if a world rectangle is visible
+ bool isVisible(int worldX, int worldY, int width, int height) const
+ {
+ Point screenPos = worldToScreen(worldX, worldY);
+ return !(screenPos.x + width < 0 ||
+ screenPos.x > viewportWidth ||
+ screenPos.y + height < 0 ||
+ screenPos.y > viewportHeight);
+ }
+
+ // Check if a tile is visible
+ bool isTileVisible(int tileRow, int tileCol) const
+ {
+ return tileCol >= colOffset &&
+ tileCol < colOffset + colsToRender &&
+ tileRow >= rowOffset &&
+ tileRow < rowOffset + rowsToRender;
+ }
+
+private:
+ void applyBounds()
+ {
+ position.x = std::max(minX, std::min(maxX, position.x));
+ position.y = std::max(minY, std::min(maxY, position.y));
+ targetPosition.x = std::max(minX, std::min(maxX, targetPosition.x));
+ targetPosition.y = std::max(minY, std::min(maxY, targetPosition.y));
+ }
+
+ void updateCachedValues()
+ {
+ // Calculate which tiles are visible
+ colOffset = std::max(0, -position.x / tileSize);
+ rowOffset = std::max(0, -position.y / tileSize);
+
+ // Add 2 extra tiles for safety (partial tiles at edges)
+ colsToRender = (viewportWidth / tileSize) + 2;
+ rowsToRender = (viewportHeight / tileSize) + 2;
+ }
};
+
+
} // namespace doengine
diff --git a/includes/Color.h b/includes/Color.h
index 03bbb38..66da962 100644
--- a/includes/Color.h
+++ b/includes/Color.h
@@ -19,21 +19,27 @@ struct Color
ColorT a;
};
-static const Color red(255, 0, 0, 255);
-static const Color white(255, 255, 255, 255);
-static const Color green(10, 255, 0, 255);
-static const Color blue(0, 0, 255, 255);
-static const Color yellow(243, 216, 64, 255);
-static const Color yellow1(100, 155, 0, 255);
-static const Color purple(0, 255, 244, 255);
-static const Color black(0, 0, 0, 255);
-static const Color gold(255, 215, 0, 255);
-static const Color gray(100, 100, 100, 255);
-static const Color blue5(19, 26, 50, 255);
-static const Color orange(226,116,17,255);
-static const Color cyan(21,204,209,255);
-static const Color skyBlue(77, 216, 255, 255);
-
+namespace Colors{
+ static const Color red(255, 0, 0, 255);
+ static const Color white(255, 255, 255, 255);
+ static const Color green(10, 255, 0, 255);
+ static const Color blue(0, 0, 255, 255);
+ static const Color yellow(243, 216, 64, 255);
+ static const Color yellow1(100, 155, 0, 255);
+ static const Color purple(0, 255, 244, 255);
+ static const Color purple1(166, 0, 247, 255);
+ static const Color black(0, 0, 0, 255);
+ static const Color black1(0x43, 0x43, 0x43, 255);
+ static const Color black2(0x60, 0x60, 0x60, 255);
+ static const Color black3(0x90, 0x90, 0x90, 255);
+ static const Color gold(255, 215, 0, 255);
+ static const Color gray(100, 100, 100, 255);
+ static const Color darkGrey(26, 31, 40, 255);
+ static const Color blue5(19, 26, 50, 255);
+ static const Color orange(226,116,17,255);
+ static const Color cyan(21,204,209,255);
+ static const Color skyBlue(77, 216, 255, 255);
+}
template
D toColor(const Color& o){
diff --git a/includes/CustomContainer.h b/includes/CustomContainer.h
new file mode 100644
index 0000000..0fd86e6
--- /dev/null
+++ b/includes/CustomContainer.h
@@ -0,0 +1,24 @@
+#ifndef CUSTOM_CONTAINER_H_DEFINED
+#define CUSTOM_CONTAINER_H_DEFINED
+#include
+namespace doengine
+{
+
+template
+class VectorBag
+{
+
+ public:
+ typedef const T traits_type;
+
+
+
+};
+
+
+
+};
+
+
+
+#endif CUSTOM_CONTAINER_H_DEFINED
\ No newline at end of file
diff --git a/includes/DOEngine_SDL_includes.h b/includes/DOEngine_SDL_includes.h
index 865c113..5e5225a 100644
--- a/includes/DOEngine_SDL_includes.h
+++ b/includes/DOEngine_SDL_includes.h
@@ -1,16 +1,33 @@
#ifndef DOENGINE_SDL_INCLUDES_HPP_DEFINED
#define DOENGINE_SDL_INCLUDES_HPP_DEFINED
-extern "C"
-{
+//#define FETCHED_CONTENT 0
+//#warning "Using fetched content"
+
+#ifndef FETCHED_CONTENT
+
#include
#include
#include
#include
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#else
+
+#include
+#include
+#include
+#include
+#include
#include
#include
#include
-}
+#include
+#endif
#endif
diff --git a/includes/Draggable.h b/includes/Draggable.h
new file mode 100644
index 0000000..81e19b4
--- /dev/null
+++ b/includes/Draggable.h
@@ -0,0 +1,17 @@
+#ifndef DRAGGABLE_H_DEFINED
+#define DRAGGABLE_H_DEFINED
+#include "Renderer.h"
+#include "Geometric.h"
+
+namespace doengine{
+
+struct Draggable{
+ virtual ~Draggable();
+ Draggable();
+ virtual void startDraggingPoint(const doengine::Rect& start)= 0;
+ virtual void updateCoords(const doengine::Rect& rect) = 0;
+ virtual void Render() = 0;
+};
+
+}
+#endif
diff --git a/includes/DraggableGameObject.h b/includes/DraggableGameObject.h
new file mode 100644
index 0000000..401f29a
--- /dev/null
+++ b/includes/DraggableGameObject.h
@@ -0,0 +1,77 @@
+#ifndef DRAGGABLE_GAMEOBJECT_H_DEFINED
+#define DRAGGABLE_GAMEOBJECT_H_DEFINED
+#include
+#include "Draggable.h"
+#include "Geometric.h"
+#include "Renderer.h"
+#include "Event.h"
+#include
+#include
+namespace doengine
+{
+
+
+class DraggableObject :
+ public Draggable,
+ public MouseEvent
+{
+
+ private:
+ std::vector> onSelectedHappened;
+ std::vector> onSelectedStopped;
+ std::vector> onMovementHappened;
+ std::vector> onMovementStopped;
+
+ protected:
+ virtual void startDraggingPoint(const doengine::Rect& start);
+ virtual void updateCoords(const doengine::Rect& rect);
+ virtual void render(doengine::Renderer *render);
+ virtual void MouseMove(const Mouse&);
+ virtual void MouseButtonDown(const Mouse&);
+ virtual void MouseButtonUp(const Mouse&);
+ virtual void MouseWheel(const Mouse&){}
+ void setSelected(bool selected);
+
+ Rect offset;
+ bool selected;
+
+
+ public:
+
+
+ void registerOnSelectedHappenedCallback(std::function fn);
+ void registerOnSelectedStoppedCallback(std::function fn);
+ void registerOnMovementHappenedCallback(std::function fn);
+ void registerOnMovementStoppedCallback(std::function fn);
+
+ Rect getDragablePosition();
+ void setObjectDimensionAndPosition(const doengine::Rect rect);
+ virtual ~DraggableObject() = default;
+ virtual void Update(float elapse) = 0;
+ virtual void Render() = 0;
+};
+
+class DraggableGameObject :
+ public Draggable
+{
+ bool selected;
+ int sprite;
+ int sprite_id;
+ int sprite_offset;
+ doengine::Rect offset;
+ std::unordered_map spriteOffsets;
+ public:
+ virtual ~DraggableGameObject();
+ DraggableGameObject();
+ DraggableGameObject(int x, int y);
+ DraggableGameObject(int x, int y, int spriteId, int spOffset);
+ void setSpriteOffset(std::unordered_map sprites);
+ void setSelectedIfCollided(const doengine::Rect& rect);
+ void setSelected(bool selected);
+ virtual void startDraggingPoint(const doengine::Rect& start);
+ virtual void updateCoords(const doengine::Rect& o);
+ virtual void render(doengine::Renderer *render);
+
+};
+}
+#endif
diff --git a/includes/EntityComponentSystem.h b/includes/EntityComponentSystem.h
new file mode 100644
index 0000000..27da553
--- /dev/null
+++ b/includes/EntityComponentSystem.h
@@ -0,0 +1,189 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/// Test Components....
+#include "Geometric.h"
+
+namespace doengine
+{
+
+using ComponentId = int;
+class Component;
+class Entity;
+
+inline ComponentId getNextComponentId()
+{
+ static ComponentId lastId = 0;
+ return ++lastId;
+}
+
+template inline ComponentId getComponentTypeId() noexcept
+{
+ static ComponentId typeID = getNextComponentId();
+ return typeID;
+}
+
+constexpr int maxComponents = 32;
+
+using ComponentBitset = std::bitset;
+using ComponentArray = std::array;
+
+
+struct Component
+{
+ public:
+ Entity *entity;
+
+ virtual void init(){}
+ virtual void Update(){}
+ virtual void Render(){}
+ virtual ~Component(){}
+};
+
+struct Entity
+{
+
+ bool active = true;
+
+ std::vector> components;
+ ComponentArray componentArray;
+ ComponentBitset componentBitset;
+
+ bool isActive()
+ {
+ return active;
+ }
+
+ void Update(float elapsed = 0)
+ {
+ for(auto it : components) it->Update();
+ }
+
+ void Render()
+ {
+ for(auto it : components) it->Render();
+ }
+
+ void destroy(){active = false;}
+
+ template bool hasComponent() const
+ {
+ return componentArray[getComponentTypeId];
+ }
+
+ template
+ T& addComponent(Targs&&... targs)
+ {
+ T* c(new T(std::forward(targs)...));
+ c->entity = this;
+ std::shared_ptr uPtr{c};
+ components.emplace_back(uPtr);
+
+ componentArray[getComponentTypeId()] = c;
+ componentBitset[getComponentTypeId()] = true;
+
+ c->init();
+
+ return *c;
+ }
+
+ template T& getComponent()const
+ {
+ auto ptr = componentArray[getComponentTypeId()];
+ return *static_cast(ptr);
+ }
+};
+
+
+struct ECSManager
+{
+ std::vector> entities;
+
+
+ static ECSManager* getECSManager()
+ {
+ static ECSManager* instance =nullptr;
+ if(instance == nullptr)
+ instance = new ECSManager();
+ return instance;
+ }
+
+ void Update()
+ {
+ for(auto it : entities)
+ {
+ it->Update();
+ }
+ }
+
+ void Render()
+ {
+ for(auto it : entities)
+ {
+ it->Render();
+ }
+ }
+
+ void Refresh()
+ {
+ entities.erase(
+ std::remove_if(
+ entities.begin(),
+ entities.end(),
+ [](const std::shared_ptr &ent){
+ return !ent->isActive();
+ })
+ );
+ }
+
+ Entity* addEntity()
+ {
+ Entity* ent = new Entity();
+ std::shared_ptr p{ent};
+ entities.emplace_back(std::move(p));
+ return ent;
+ }
+};
+
+
+
+struct PositionComponent : public Component
+{
+ Point point;
+
+ int X(){return point.x;}
+ int Y(){return point.y;}
+
+ Point getPosition()
+ {
+ return point;
+ }
+ void setPosition(Point p)
+ {
+ point.x = p.x;
+ point.y = p.y;
+ }
+ virtual void init() override{}
+ virtual void Update() override{}
+ virtual void Render() override{}
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/includes/Event.h b/includes/Event.h
index 7ce5df4..8eef04b 100644
--- a/includes/Event.h
+++ b/includes/Event.h
@@ -14,10 +14,13 @@ struct Event
static std::unordered_map keys_pressed;
static std::vector keydown;
static std::vector keyup;
+ static std::vector TextInputList;
static std::vector mouseEvent;
static std::vector joyButtonUpList;
static std::vector joyButtonDownList;
static std::vector joyButtonTriggerList;
+ static std::vector keyboardHandlingEventList;
+
static std::map joypadsConnected;
static int getMousePosition(int* x, int* y);
@@ -28,6 +31,7 @@ struct Event
static void PollEvent();
static void AddKeyPressEventListener(KeyUpEvent* ev);
static void AddKeyPressEventListener(KeyDownEvent* ev);
+ static void AddKeyboardEvent(KeyboardInputhandlingEvent* ev);
static void RemoveKeyPressEventListener(KeyUpEvent* ev);
static void RemoveKeyPressEventListener(KeyDownEvent* ev);
static void AddMouseEvent(MouseEvent* event);
@@ -38,5 +42,415 @@ struct Event
static void RemoveJoypadEventListener(JoyButtonUpEvent* ev);
static void RemoveJoypadEventListener(JoyButtonDownEvent* ev);
static void RemoveJoypadEventListener(JoyButtonTriggerEvent* ev);
+ static void RemoveKeyboardEvent(KeyboardInputhandlingEvent* ev);
+ static void AddTextInputEvent(TextInputEvent *event);
+ static void RemoveTextInputEvent(TextInputEvent *event);
};
+
+
+///Wrapper for Scancode
+typedef enum Scancode
+{
+ SCANCODE_UNKNOWN = 0,
+
+ /**
+ * \name Usage page 0x07
+ *
+ * These values are from usage page 0x07 (USB keyboard page).
+ */
+ /* @{ */
+
+ SCANCODE_A = 4,
+ SCANCODE_B = 5,
+ SCANCODE_C = 6,
+ SCANCODE_D = 7,
+ SCANCODE_E = 8,
+ SCANCODE_F = 9,
+ SCANCODE_G = 10,
+ SCANCODE_H = 11,
+ SCANCODE_I = 12,
+ SCANCODE_J = 13,
+ SCANCODE_K = 14,
+ SCANCODE_L = 15,
+ SCANCODE_M = 16,
+ SCANCODE_N = 17,
+ SCANCODE_O = 18,
+ SCANCODE_P = 19,
+ SCANCODE_Q = 20,
+ SCANCODE_R = 21,
+ SCANCODE_S = 22,
+ SCANCODE_T = 23,
+ SCANCODE_U = 24,
+ SCANCODE_V = 25,
+ SCANCODE_W = 26,
+ SCANCODE_X = 27,
+ SCANCODE_Y = 28,
+ SCANCODE_Z = 29,
+
+ SCANCODE_1 = 30,
+ SCANCODE_2 = 31,
+ SCANCODE_3 = 32,
+ SCANCODE_4 = 33,
+ SCANCODE_5 = 34,
+ SCANCODE_6 = 35,
+ SCANCODE_7 = 36,
+ SCANCODE_8 = 37,
+ SCANCODE_9 = 38,
+ SCANCODE_0 = 39,
+
+ SCANCODE_RETURN = 40,
+ SCANCODE_ESCAPE = 41,
+ SCANCODE_BACKSPACE = 42,
+ SCANCODE_TAB = 43,
+ SCANCODE_SPACE = 44,
+
+ SCANCODE_MINUS = 45,
+ SCANCODE_EQUALS = 46,
+ SCANCODE_LEFTBRACKET = 47,
+ SCANCODE_RIGHTBRACKET = 48,
+ SCANCODE_BACKSLASH = 49, /**< Located at the lower left of the return
+ * key on ISO keyboards and at the right end
+ * of the QWERTY row on ANSI keyboards.
+ * Produces REVERSE SOLIDUS (backslash) and
+ * VERTICAL LINE in a US layout, REVERSE
+ * SOLIDUS and VERTICAL LINE in a UK Mac
+ * layout, NUMBER SIGN and TILDE in a UK
+ * Windows layout, DOLLAR SIGN and POUND SIGN
+ * in a Swiss German layout, NUMBER SIGN and
+ * APOSTROPHE in a German layout, GRAVE
+ * ACCENT and POUND SIGN in a French Mac
+ * layout, and ASTERISK and MICRO SIGN in a
+ * French Windows layout.
+ */
+ SCANCODE_NONUSHASH = 50, /**< ISO USB keyboards actually use this code
+ * instead of 49 for the same key, but all
+ * OSes I've seen treat the two codes
+ * identically. So, as an implementor, unless
+ * your keyboard generates both of those
+ * codes and your OS treats them differently,
+ * you should generate SCANCODE_BACKSLASH
+ * instead of this code. As a user, you
+ * should not rely on this code because SDL
+ * will never generate it with most (all?)
+ * keyboards.
+ */
+ SCANCODE_SEMICOLON = 51,
+ SCANCODE_APOSTROPHE = 52,
+ SCANCODE_GRAVE = 53, /**< Located in the top left corner (on both ANSI
+ * and ISO keyboards). Produces GRAVE ACCENT and
+ * TILDE in a US Windows layout and in US and UK
+ * Mac layouts on ANSI keyboards, GRAVE ACCENT
+ * and NOT SIGN in a UK Windows layout, SECTION
+ * SIGN and PLUS-MINUS SIGN in US and UK Mac
+ * layouts on ISO keyboards, SECTION SIGN and
+ * DEGREE SIGN in a Swiss German layout (Mac:
+ * only on ISO keyboards), CIRCUMFLEX ACCENT and
+ * DEGREE SIGN in a German layout (Mac: only on
+ * ISO keyboards), SUPERSCRIPT TWO and TILDE in a
+ * French Windows layout, COMMERCIAL AT and
+ * NUMBER SIGN in a French Mac layout on ISO
+ * keyboards, and LESS-THAN SIGN and GREATER-THAN
+ * SIGN in a Swiss German, German, or French Mac
+ * layout on ANSI keyboards.
+ */
+ SCANCODE_COMMA = 54,
+ SCANCODE_PERIOD = 55,
+ SCANCODE_SLASH = 56,
+
+ SCANCODE_CAPSLOCK = 57,
+
+ SCANCODE_F1 = 58,
+ SCANCODE_F2 = 59,
+ SCANCODE_F3 = 60,
+ SCANCODE_F4 = 61,
+ SCANCODE_F5 = 62,
+ SCANCODE_F6 = 63,
+ SCANCODE_F7 = 64,
+ SCANCODE_F8 = 65,
+ SCANCODE_F9 = 66,
+ SCANCODE_F10 = 67,
+ SCANCODE_F11 = 68,
+ SCANCODE_F12 = 69,
+
+ SCANCODE_PRINTSCREEN = 70,
+ SCANCODE_SCROLLLOCK = 71,
+ SCANCODE_PAUSE = 72,
+ SCANCODE_INSERT = 73, /**< insert on PC, help on some Mac keyboards (but
+ does send code 73, not 117) */
+ SCANCODE_HOME = 74,
+ SCANCODE_PAGEUP = 75,
+ SCANCODE_DELETE = 76,
+ SCANCODE_END = 77,
+ SCANCODE_PAGEDOWN = 78,
+ SCANCODE_RIGHT = 79,
+ SCANCODE_LEFT = 80,
+ SCANCODE_DOWN = 81,
+ SCANCODE_UP = 82,
+
+ SCANCODE_NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards
+ */
+ SCANCODE_KP_DIVIDE = 84,
+ SCANCODE_KP_MULTIPLY = 85,
+ SCANCODE_KP_MINUS = 86,
+ SCANCODE_KP_PLUS = 87,
+ SCANCODE_KP_ENTER = 88,
+ SCANCODE_KP_1 = 89,
+ SCANCODE_KP_2 = 90,
+ SCANCODE_KP_3 = 91,
+ SCANCODE_KP_4 = 92,
+ SCANCODE_KP_5 = 93,
+ SCANCODE_KP_6 = 94,
+ SCANCODE_KP_7 = 95,
+ SCANCODE_KP_8 = 96,
+ SCANCODE_KP_9 = 97,
+ SCANCODE_KP_0 = 98,
+ SCANCODE_KP_PERIOD = 99,
+
+ SCANCODE_NONUSBACKSLASH = 100, /**< This is the additional key that ISO
+ * keyboards have over ANSI ones,
+ * located between left shift and Y.
+ * Produces GRAVE ACCENT and TILDE in a
+ * US or UK Mac layout, REVERSE SOLIDUS
+ * (backslash) and VERTICAL LINE in a
+ * US or UK Windows layout, and
+ * LESS-THAN SIGN and GREATER-THAN SIGN
+ * in a Swiss German, German, or French
+ * layout. */
+ SCANCODE_APPLICATION = 101, /**< windows contextual menu, compose */
+ SCANCODE_POWER = 102, /**< The USB document says this is a status flag,
+ * not a physical key - but some Mac keyboards
+ * do have a power key. */
+ SCANCODE_KP_EQUALS = 103,
+ SCANCODE_F13 = 104,
+ SCANCODE_F14 = 105,
+ SCANCODE_F15 = 106,
+ SCANCODE_F16 = 107,
+ SCANCODE_F17 = 108,
+ SCANCODE_F18 = 109,
+ SCANCODE_F19 = 110,
+ SCANCODE_F20 = 111,
+ SCANCODE_F21 = 112,
+ SCANCODE_F22 = 113,
+ SCANCODE_F23 = 114,
+ SCANCODE_F24 = 115,
+ SCANCODE_EXECUTE = 116,
+ SCANCODE_HELP = 117, /**< AL Integrated Help Center */
+ SCANCODE_MENU = 118, /**< Menu (show menu) */
+ SCANCODE_SELECT = 119,
+ SCANCODE_STOP = 120, /**< AC Stop */
+ SCANCODE_AGAIN = 121, /**< AC Redo/Repeat */
+ SCANCODE_UNDO = 122, /**< AC Undo */
+ SCANCODE_CUT = 123, /**< AC Cut */
+ SCANCODE_COPY = 124, /**< AC Copy */
+ SCANCODE_PASTE = 125, /**< AC Paste */
+ SCANCODE_FIND = 126, /**< AC Find */
+ SCANCODE_MUTE = 127,
+ SCANCODE_VOLUMEUP = 128,
+ SCANCODE_VOLUMEDOWN = 129,
+/* not sure whether there's a reason to enable these */
+/* SCANCODE_LOCKINGCAPSLOCK = 130, */
+/* SCANCODE_LOCKINGNUMLOCK = 131, */
+/* SCANCODE_LOCKINGSCROLLLOCK = 132, */
+ SCANCODE_KP_COMMA = 133,
+ SCANCODE_KP_EQUALSAS400 = 134,
+
+ SCANCODE_INTERNATIONAL1 = 135, /**< used on Asian keyboards, see
+ footnotes in USB doc */
+ SCANCODE_INTERNATIONAL2 = 136,
+ SCANCODE_INTERNATIONAL3 = 137, /**< Yen */
+ SCANCODE_INTERNATIONAL4 = 138,
+ SCANCODE_INTERNATIONAL5 = 139,
+ SCANCODE_INTERNATIONAL6 = 140,
+ SCANCODE_INTERNATIONAL7 = 141,
+ SCANCODE_INTERNATIONAL8 = 142,
+ SCANCODE_INTERNATIONAL9 = 143,
+ SCANCODE_LANG1 = 144, /**< Hangul/English toggle */
+ SCANCODE_LANG2 = 145, /**< Hanja conversion */
+ SCANCODE_LANG3 = 146, /**< Katakana */
+ SCANCODE_LANG4 = 147, /**< Hiragana */
+ SCANCODE_LANG5 = 148, /**< Zenkaku/Hankaku */
+ SCANCODE_LANG6 = 149, /**< reserved */
+ SCANCODE_LANG7 = 150, /**< reserved */
+ SCANCODE_LANG8 = 151, /**< reserved */
+ SCANCODE_LANG9 = 152, /**< reserved */
+
+ SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
+ SCANCODE_SYSREQ = 154,
+ SCANCODE_CANCEL = 155, /**< AC Cancel */
+ SCANCODE_CLEAR = 156,
+ SCANCODE_PRIOR = 157,
+ SCANCODE_RETURN2 = 158,
+ SCANCODE_SEPARATOR = 159,
+ SCANCODE_OUT = 160,
+ SCANCODE_OPER = 161,
+ SCANCODE_CLEARAGAIN = 162,
+ SCANCODE_CRSEL = 163,
+ SCANCODE_EXSEL = 164,
+
+ SCANCODE_KP_00 = 176,
+ SCANCODE_KP_000 = 177,
+ SCANCODE_THOUSANDSSEPARATOR = 178,
+ SCANCODE_DECIMALSEPARATOR = 179,
+ SCANCODE_CURRENCYUNIT = 180,
+ SCANCODE_CURRENCYSUBUNIT = 181,
+ SCANCODE_KP_LEFTPAREN = 182,
+ SCANCODE_KP_RIGHTPAREN = 183,
+ SCANCODE_KP_LEFTBRACE = 184,
+ SCANCODE_KP_RIGHTBRACE = 185,
+ SCANCODE_KP_TAB = 186,
+ SCANCODE_KP_BACKSPACE = 187,
+ SCANCODE_KP_A = 188,
+ SCANCODE_KP_B = 189,
+ SCANCODE_KP_C = 190,
+ SCANCODE_KP_D = 191,
+ SCANCODE_KP_E = 192,
+ SCANCODE_KP_F = 193,
+ SCANCODE_KP_XOR = 194,
+ SCANCODE_KP_POWER = 195,
+ SCANCODE_KP_PERCENT = 196,
+ SCANCODE_KP_LESS = 197,
+ SCANCODE_KP_GREATER = 198,
+ SCANCODE_KP_AMPERSAND = 199,
+ SCANCODE_KP_DBLAMPERSAND = 200,
+ SCANCODE_KP_VERTICALBAR = 201,
+ SCANCODE_KP_DBLVERTICALBAR = 202,
+ SCANCODE_KP_COLON = 203,
+ SCANCODE_KP_HASH = 204,
+ SCANCODE_KP_SPACE = 205,
+ SCANCODE_KP_AT = 206,
+ SCANCODE_KP_EXCLAM = 207,
+ SCANCODE_KP_MEMSTORE = 208,
+ SCANCODE_KP_MEMRECALL = 209,
+ SCANCODE_KP_MEMCLEAR = 210,
+ SCANCODE_KP_MEMADD = 211,
+ SCANCODE_KP_MEMSUBTRACT = 212,
+ SCANCODE_KP_MEMMULTIPLY = 213,
+ SCANCODE_KP_MEMDIVIDE = 214,
+ SCANCODE_KP_PLUSMINUS = 215,
+ SCANCODE_KP_CLEAR = 216,
+ SCANCODE_KP_CLEARENTRY = 217,
+ SCANCODE_KP_BINARY = 218,
+ SCANCODE_KP_OCTAL = 219,
+ SCANCODE_KP_DECIMAL = 220,
+ SCANCODE_KP_HEXADECIMAL = 221,
+
+ SCANCODE_LCTRL = 224,
+ SCANCODE_LSHIFT = 225,
+ SCANCODE_LALT = 226, /**< alt, option */
+ SCANCODE_LGUI = 227, /**< windows, command (apple), meta */
+ SCANCODE_RCTRL = 228,
+ SCANCODE_RSHIFT = 229,
+ SCANCODE_RALT = 230, /**< alt gr, option */
+ SCANCODE_RGUI = 231, /**< windows, command (apple), meta */
+
+ SCANCODE_MODE = 257, /**< I'm not sure if this is really not covered
+ * by any of the above, but since there's a
+ * special KMOD_MODE for it I'm adding it here
+ */
+
+ /* @} *//* Usage page 0x07 */
+
+ /**
+ * \name Usage page 0x0C
+ *
+ * These values are mapped from usage page 0x0C (USB consumer page).
+ * See https://usb.org/sites/default/files/hut1_2.pdf
+ *
+ * There are way more keys in the spec than we can represent in the
+ * current scancode range, so pick the ones that commonly come up in
+ * real world usage.
+ */
+ /* @{ */
+
+ SCANCODE_AUDIONEXT = 258,
+ SCANCODE_AUDIOPREV = 259,
+ SCANCODE_AUDIOSTOP = 260,
+ SCANCODE_AUDIOPLAY = 261,
+ SCANCODE_AUDIOMUTE = 262,
+ SCANCODE_MEDIASELECT = 263,
+ SCANCODE_WWW = 264, /**< AL Internet Browser */
+ SCANCODE_MAIL = 265,
+ SCANCODE_CALCULATOR = 266, /**< AL Calculator */
+ SCANCODE_COMPUTER = 267,
+ SCANCODE_AC_SEARCH = 268, /**< AC Search */
+ SCANCODE_AC_HOME = 269, /**< AC Home */
+ SCANCODE_AC_BACK = 270, /**< AC Back */
+ SCANCODE_AC_FORWARD = 271, /**< AC Forward */
+ SCANCODE_AC_STOP = 272, /**< AC Stop */
+ SCANCODE_AC_REFRESH = 273, /**< AC Refresh */
+ SCANCODE_AC_BOOKMARKS = 274, /**< AC Bookmarks */
+
+ /* @} *//* Usage page 0x0C */
+
+ /**
+ * \name Walther keys
+ *
+ * These are values that Christian Walther added (for mac keyboard?).
+ */
+ /* @{ */
+
+ SCANCODE_BRIGHTNESSDOWN = 275,
+ SCANCODE_BRIGHTNESSUP = 276,
+ SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display
+ switch, video mode switch */
+ SCANCODE_KBDILLUMTOGGLE = 278,
+ SCANCODE_KBDILLUMDOWN = 279,
+ SCANCODE_KBDILLUMUP = 280,
+ SCANCODE_EJECT = 281,
+ SCANCODE_SLEEP = 282, /**< SC System Sleep */
+
+ SCANCODE_APP1 = 283,
+ SCANCODE_APP2 = 284,
+
+ /* @} *//* Walther keys */
+
+ /**
+ * \name Usage page 0x0C (additional media keys)
+ *
+ * These values are mapped from usage page 0x0C (USB consumer page).
+ */
+ /* @{ */
+
+ SCANCODE_AUDIOREWIND = 285,
+ SCANCODE_AUDIOFASTFORWARD = 286,
+
+ /* @} *//* Usage page 0x0C (additional media keys) */
+
+ /**
+ * \name Mobile keys
+ *
+ * These are values that are often used on mobile phones.
+ */
+ /* @{ */
+
+ SCANCODE_SOFTLEFT = 287, /**< Usually situated below the display on phones and
+ used as a multi-function feature key for selecting
+ a software defined function shown on the bottom left
+ of the display. */
+ SCANCODE_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
+ used as a multi-function feature key for selecting
+ a software defined function shown on the bottom right
+ of the display. */
+ SCANCODE_CALL = 289, /**< Used for accepting phone calls. */
+ SCANCODE_ENDCALL = 290, /**< Used for rejecting phone calls. */
+
+ /* @} *//* Mobile keys */
+
+ /* Add any other keys here. */
+
+ NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes
+ for array bounds */
+} Scancode;
+
+
+
+
+
+
+
+
+
+
+
+
} // namespace doengine
\ No newline at end of file
diff --git a/includes/EventHandler.h b/includes/EventHandler.h
index ce737ed..84eedf1 100644
--- a/includes/EventHandler.h
+++ b/includes/EventHandler.h
@@ -11,6 +11,16 @@ using doengine::devices::Mouse;
namespace doengine
{
+
+struct KeyboardInputhandlingEvent
+{
+ KeyboardInputhandlingEvent();
+ virtual ~KeyboardInputhandlingEvent();
+ virtual void OnKeydown(const Keyboard&) = 0;
+ virtual void OnKeyup(const Keyboard&) = 0;
+};
+
+
class KeyDownEvent
{
public:
@@ -113,13 +123,22 @@ class OnMessageQueue
struct MouseEvent
{
- virtual ~MouseEvent()
- {
- }
-
+ virtual ~MouseEvent();
+ MouseEvent();
+ virtual void MouseWheel(const Mouse&) = 0;
virtual void MouseMove(const Mouse&) = 0;
virtual void MouseButtonDown(const Mouse&) = 0;
virtual void MouseButtonUp(const Mouse&) = 0;
};
+
+struct TextInputEvent
+{
+ virtual ~TextInputEvent();
+ TextInputEvent();
+ virtual void OnTextInput(const std::string& text) = 0;
+};
+
+
+
} // namespace doengine
\ No newline at end of file
diff --git a/includes/FPSManager.h b/includes/FPSManager.h
index 723e638..19a66e1 100644
--- a/includes/FPSManager.h
+++ b/includes/FPSManager.h
@@ -1,14 +1,18 @@
#pragma once
#include
+#include
+#include
+#include
namespace doengine
{
class FpsManager
{
- uint32_t start, elapsed, wait, fps;
-
+ uint32_t start, elapsed, wait, fps, last_elapsed;
+ uint64_t lastCounter;
+ uint64_t frequency;
public:
- FpsManager() : start(0L), elapsed(0L), fps(60L)
+ FpsManager() : start(0L), elapsed(0L), fps(60L), last_elapsed(0.0f)
{
}
@@ -21,6 +25,28 @@ class FpsManager
virtual void Handle();
virtual uint32_t getDeltaTime();
virtual float getElapsedTime();
+ virtual float getLastElapsedTime();
+ void beginFrame();
+ double endFrame();
+ static double getTicks();
};
+
+
+
+/*
+class TimerManager {
+public:
+ void update(float deltaSeconds);
+
+ Timer& addTimer(float seconds, Timer::Callback cb, bool repeat = false);
+ void clear();
+
+private:
+ std::vector> m_timers;
+};
+
+*/
+
+
} // namespace doengine
\ No newline at end of file
diff --git a/includes/FontCache.h b/includes/FontCache.h
new file mode 100644
index 0000000..b927788
--- /dev/null
+++ b/includes/FontCache.h
@@ -0,0 +1,28 @@
+#ifndef FONTCACHE_H_DEFINED
+#define FONTCACHE_H_DEFINED
+#include
+#include
+namespace doengine
+{
+
+constexpr const char *defaultGlyph =
+" !\"#$%&\'()*+\'-/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwyz{|}~";
+
+struct FontCache
+{
+ Texture *glyph_texture;
+
+ FontCache(const std::string& fontname);
+
+ void createGlyph();
+
+ void DrawText(int x, int y, int max_width);
+
+
+};
+
+
+
+}
+
+#endif
\ No newline at end of file
diff --git a/includes/GameObject.h b/includes/GameObject.h
index 1f370d3..f4b0a43 100644
--- a/includes/GameObject.h
+++ b/includes/GameObject.h
@@ -1,11 +1,40 @@
#pragma once
+#include "Application.h"
+#include "Geometric.h"
+#include "Renderer.h"
#include
+#include
namespace doengine
{
+
+class Renderer;
+
+enum ObjecType
+{
+ Player = 0,
+ Level,
+ Tile,
+ AnimateTile,
+ Npc,
+ Ui,
+ DebugObject,
+ UknownObject,
+ LastDefaultUnused
+};
+
+static unsigned long long id_pool = 0;
class GameObject
{
+ private:
+ long long id;
+
protected:
+ bool debuging_enable;
+
+ Rect position;
+ Renderer* renderer;
+
bool renderable;
bool solid;
int layer;
@@ -14,16 +43,17 @@ class GameObject
std::string texture_id;
public:
- GameObject()
- {
- }
+ GameObject();
+ virtual ~GameObject();
+ virtual void Update(float timer = 0) = 0;
+ virtual void Render() = 0;
+ Renderer* getRenderer();
+ Rect getPosition();
- virtual ~GameObject()
+ inline const int getId()
{
+ return id;
}
- virtual void Update(float timer = 0) = 0;
- virtual void Render() = 0;
- virtual bool isColliding(GameObject* other);
};
} // namespace doengine
\ No newline at end of file
diff --git a/includes/GameState.h b/includes/GameState.h
index c1b733a..aff87a2 100644
--- a/includes/GameState.h
+++ b/includes/GameState.h
@@ -1,9 +1,27 @@
#pragma once
+#include
+#include
+#include
+#include "Application.h"
+#include "Renderer.h"
+#include "GameObject.h"
namespace doengine
{
+
+class GameObject;
+typedef std::variant ArgValue;
+
class GameState
{
+ protected:
+ std::vector registered_game_object;
+ Renderer *renderer;
public:
+ GameState();
+ virtual ~GameState();
+ std::optional queryGameObject(long long id);
+ void registerGameObject(GameObject *object);
+ void unregisterGameObject(long long id);
virtual void OnEnter() = 0;
virtual void OnExit() = 0;
virtual void Update(float elapsed) = 0;
diff --git a/includes/GameStateManager.h b/includes/GameStateManager.h
index 7142bb5..0b7b2fe 100644
--- a/includes/GameStateManager.h
+++ b/includes/GameStateManager.h
@@ -5,6 +5,8 @@
#include
namespace doengine
{
+
+class GameState;
class GameStateManager
{
diff --git a/includes/Geometric.h b/includes/Geometric.h
index 780aaa6..33713b3 100644
--- a/includes/Geometric.h
+++ b/includes/Geometric.h
@@ -1,20 +1,141 @@
#pragma once
-
#include "Color.h"
+#include "Logger.h"
#include