From 1c321581424fc7b91a0e1390054e1a2bc08b4024 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 4 Feb 2026 10:16:16 -0600 Subject: [PATCH] DOlphin progress --- .ci/dolphin/Dockerfile | 5 ++ .ci/dolphin/build.sh | 11 +++ .gitignore | 4 +- CMakeLists.txt | 162 +++++++++++++++++++++++++++++++---- archive/ui/uiframe.c | 2 +- cmake/modules/Findcglm.cmake | 1 + src/CMakeLists.txt | 47 +++++----- src/asset/type/assetscript.h | 2 +- src/display/CMakeLists.txt | 10 +++ src/dusk.h | 5 ++ src/input/CMakeLists.txt | 6 ++ src/main.c | 1 - src/null.c | 9 ++ src/thread/CMakeLists.txt | 4 + src/time/CMakeLists.txt | 5 ++ src2/CMakeLists.txt | 27 ++++++ src2/main.cpp | 159 ++++++++++++++++++++++++++++++++++ src2/sdl_assets_loader.cpp | 71 +++++++++++++++ src2/sdl_assets_loader.h | 21 +++++ src2/sdl_starter.cpp | 48 +++++++++++ src2/sdl_starter.h | 8 ++ 21 files changed, 565 insertions(+), 43 deletions(-) create mode 100644 .ci/dolphin/Dockerfile create mode 100755 .ci/dolphin/build.sh create mode 100644 src/null.c create mode 100644 src2/CMakeLists.txt create mode 100644 src2/main.cpp create mode 100644 src2/sdl_assets_loader.cpp create mode 100644 src2/sdl_assets_loader.h create mode 100644 src2/sdl_starter.cpp create mode 100644 src2/sdl_starter.h diff --git a/.ci/dolphin/Dockerfile b/.ci/dolphin/Dockerfile new file mode 100644 index 0000000..0c8a1c4 --- /dev/null +++ b/.ci/dolphin/Dockerfile @@ -0,0 +1,5 @@ +FROM devkitpro/devkitppc + +RUN apt update && \ + apt install -y cmake git cmake python3 python3-pip python3-polib python3-pil python3-dotenv python3-pyqt5 python3-opengl && \ + dkp-pacman -S --needed --noconfirm gamecube-sdl2 ppc-liblzma ppc-libzip ppc-liblua51 \ No newline at end of file diff --git a/.ci/dolphin/build.sh b/.ci/dolphin/build.sh new file mode 100755 index 0000000..3a91224 --- /dev/null +++ b/.ci/dolphin/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +docker build -t myapp:latest -f .ci/dolphin/Dockerfile . +docker run -it -v ./:/workdir myapp:latest /bin/bash -c ' \ + cd /workdir && \ + rm -rf build2 && \ + mkdir -p build2 && \ + cd build2 && \ + cmake .. -DDUSK_TARGET_SYSTEM=gamecube -DCMAKE_C_COMPILER=$DEVKITPPC/bin/powerpc-eabi-gcc -DBUILD_SHARED_LIBS=OFF && \ + make VERBOSE=1 \ +' +# docker run -it -v ./:/workdir myapp:latest /bin/bash \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6db54e3..08c31ea 100644 --- a/.gitignore +++ b/.gitignore @@ -101,4 +101,6 @@ yarn-error.log yarn.lock .editor -.venv \ No newline at end of file +.venv + +/build2 \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 002737e..81746dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,13 +9,7 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) -option(ENABLE_TESTS "Enable tests" ON) - -# Set target system -if(NOT DEFINED DUSK_TARGET_SYSTEM) - set(DUSK_TARGET_SYSTEM "linux") - # set(DUSK_TARGET_SYSTEM "psp") -endif() +option(ENABLE_TESTS "Enable tests" OFF) # Prep cache set(DUSK_CACHE_TARGET "dusk-target") @@ -42,28 +36,47 @@ file(MAKE_DIRECTORY ${DUSK_GENERATED_HEADERS_DIR}) # Find packages find_package(Python3 COMPONENTS Interpreter REQUIRED) +# Set target system +# message(FATAL_ERROR "DISABLED FOR NOW2 ${DUSK_TARGET_SYSTEM}") + +if(NOT DEFINED DUSK_TARGET_SYSTEM) + set(DUSK_TARGET_SYSTEM "linux") +endif() + # Toolchains if(DUSK_TARGET_SYSTEM STREQUAL "psp") find_package(pspsdk REQUIRED) endif() +if(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + # Override to make library and binary be the same. + set(DUSK_LIBRARY_TARGET_NAME "${DUSK_LIBRARY_TARGET_NAME}.elf" CACHE INTERNAL ${DUSK_CACHE_TARGET}) +endif() + # Init Project. project(${DUSK_LIBRARY_TARGET_NAME} VERSION 1.0.0 - LANGUAGES C + LANGUAGES C CXX ) -# MainLibrary -add_library(${DUSK_LIBRARY_TARGET_NAME}) +# Either, create library and binary separately (used for tests), or make them +# one in the same so all code is in the binary. +if(ENABLE_TESTS) + # MainLibrary + add_library(${DUSK_LIBRARY_TARGET_NAME} STATIC) -# Binary Executable -add_executable(${DUSK_BINARY_TARGET_NAME}) + # Binary Executable + add_executable(${DUSK_BINARY_TARGET_NAME} ${DUSK_SOURCES_DIR}/null.c) -# Link library to binary and test -target_link_libraries(${DUSK_BINARY_TARGET_NAME} - PUBLIC - ${DUSK_LIBRARY_TARGET_NAME} -) + # Link library to binary + target_link_libraries(${DUSK_BINARY_TARGET_NAME} + PUBLIC + ${DUSK_LIBRARY_TARGET_NAME} + ) +else() + set(DUSK_BINARY_TARGET_NAME "${DUSK_LIBRARY_TARGET_NAME}" CACHE INTERNAL ${DUSK_CACHE_TARGET}) + add_executable(${DUSK_BINARY_TARGET_NAME} src2/main.cpp) +endif() # Add tools add_subdirectory(tools) @@ -77,8 +90,10 @@ if(DUSK_TARGET_SYSTEM STREQUAL "linux") find_package(OpenGL REQUIRED) target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC SDL2 + pthread OpenGL::GL GL + m ) elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") @@ -87,6 +102,7 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC ${SDL2_LIBRARIES} SDL2 + pthread OpenGL::GL zip bz2 @@ -94,18 +110,120 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") mbedtls mbedcrypto lzma + m ) target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE ${SDL2_INCLUDE_DIRS} ) +elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + if(NOT DEFINED ENV{DEVKITPPC}) + message(FATAL_ERROR "DEVKITPPC environment variable not set!") + endif() + set(DEVKITPPC $ENV{DEVKITPPC}) + if(NOT DEFINED ENV{DEVKITPRO}) + message(FATAL_ERROR "DEVKITPRO environment variable not set!") + endif() + set(DEVKITPRO $ENV{DEVKITPRO}) + + # set(CMAKE_C_COMPILER "${DEVKITPPC}/bin/powerpc-eabi-gcc") + # string(APPEND CMAKE_C_FLAGS "-g -O2 -mcpu=750 -meabi -mhard-float -Wall -mogc -DGEKKO") + + set(CMAKE_FIND_ROOT_PATH "${DEVKITPRO}" "${DEVKITPPC}") + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + set(CMAKE_SKIP_RPATH TRUE) + set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) + set(CMAKE_INSTALL_RPATH "") + + set(PORTLIBS_PATH "${DEVKITPRO}/portlibs") + + if(DUSK_TARGET_SYSTEM STREQUAL "gamecube") + set(_PORTLIBS_FLAVOR "gamecube") + set(_LIBOGC_LIBDIR "${DEVKITPRO}/libogc/lib/cube") + target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PRIVATE GEKKO HW_DOL GAMECUBE DOLPHIN) + set(_MACHDEP_OPTS -mogc -mcpu=750 -meabi -mhard-float) + else() + set(_PORTLIBS_FLAVOR "wii") + set(_LIBOGC_LIBDIR "${DEVKITPRO}/libogc/lib/wii") + target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PRIVATE GEKKO HW_RVL WII DOLPHIN) + set(_MACHDEP_OPTS -mrvll -mcpu=750 -meabi -mhard-float) + endif() + + target_compile_options(${DUSK_LIBRARY_TARGET_NAME} PRIVATE ${_MACHDEP_OPTS} -Wall -O2) + target_link_options(${DUSK_LIBRARY_TARGET_NAME} PRIVATE ${_MACHDEP_OPTS}) + + target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE + "${DEVKITPRO}/libogc/include" + "${PORTLIBS_PATH}/${_PORTLIBS_FLAVOR}/include" + "${PORTLIBS_PATH}/${_PORTLIBS_FLAVOR}/include/SDL2" + "${PORTLIBS_PATH}/ppc/include" + ) + + target_link_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE + "${_LIBOGC_LIBDIR}" + "${PORTLIBS_PATH}/${_PORTLIBS_FLAVOR}/lib" + "${PORTLIBS_PATH}/ppc/lib" + ) + + + set(Lua_FOUND TRUE) + set(libzip_FOUND TRUE) + + # Custom flags for cglm + set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE) + set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE) + find_package(cglm REQUIRED) + + # Compile lua + include(FetchContent) + FetchContent_Declare( + liblua + URL https://www.lua.org/ftp/lua-5.5.0.tar.gz + ) + FetchContent_MakeAvailable(liblua) + set(LUA_SRC_DIR "${liblua_SOURCE_DIR}/src") + set(LUA_C_FILES + lapi.c lauxlib.c lbaselib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c + ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c + loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c + lstrlib.c ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c lzio.c + ) + list(TRANSFORM LUA_C_FILES PREPEND "${LUA_SRC_DIR}/") + add_library(liblua STATIC ${LUA_C_FILES}) + target_include_directories(liblua PUBLIC "${LUA_SRC_DIR}") + target_compile_definitions(liblua PRIVATE LUA_USE_C89) + add_library(lua::lua ALIAS liblua) + + target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE + # cglm + # liblua + + # zip + # bz2 + # z + + SDL2 + SDL2_gfx + pthread + + aesnd + opengx + gxflux + + fat + ogc + m + opus + ) endif() # Force turn tests off for now set(ENABLE_TESTS OFF CACHE BOOL "Enable tests" FORCE) # Add code -add_subdirectory(src) +add_subdirectory(src2) # Handle tests if(ENABLE_TESTS) @@ -141,4 +259,12 @@ if(DUSK_TARGET_SYSTEM STREQUAL "psp") PSAR_PATH ${DUSK_BUILD_DIR}/dusk.dsk VERSION 01.00 ) +elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + set(DUSK_BINARY_TARGET_NAME_DOL "${DUSK_BUILD_DIR}/Dusk.dol") + add_custom_command(TARGET ${DUSK_BINARY_TARGET_NAME} POST_BUILD + COMMAND elf2dol + "$" + "${DUSK_BINARY_TARGET_NAME_DOL}" + COMMENT "Generating ${DUSK_BINARY_TARGET_NAME_DOL} from ${DUSK_BINARY_TARGET_NAME}" + ) endif() diff --git a/archive/ui/uiframe.c b/archive/ui/uiframe.c index d47509d..f3e32c6 100644 --- a/archive/ui/uiframe.c +++ b/archive/ui/uiframe.c @@ -8,7 +8,7 @@ #include "uiframe.h" #include "display/spritebatch.h" #include "assert/assert.h" -#include +#include "util/math.h" void uiFrameDraw( const float_t x, diff --git a/cmake/modules/Findcglm.cmake b/cmake/modules/Findcglm.cmake index b356a13..b6450e5 100644 --- a/cmake/modules/Findcglm.cmake +++ b/cmake/modules/Findcglm.cmake @@ -4,6 +4,7 @@ # https://opensource.org/licenses/MIT include(FetchContent) + FetchContent_Declare( cglm GIT_REPOSITORY https://github.com/recp/cglm.git diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7bc94a3..13db8e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,29 +3,31 @@ # This software is released under the MIT License. # https://opensource.org/licenses/MIT -find_package(cglm REQUIRED) -find_package(libzip REQUIRED) -find_package(Lua REQUIRED) +if(NOT cglm_FOUND) + find_package(cglm REQUIRED) + target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC cglm) +endif() -if(Lua_FOUND AND NOT TARGET Lua::Lua) - add_library(Lua::Lua INTERFACE IMPORTED) - set_target_properties( - Lua::Lua - PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}" - INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}" - ) +if(NOT libzip_FOUND) + find_package(libzip REQUIRED) + target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC zip) +endif() + +if(NOT Lua_FOUND) + find_package(Lua REQUIRED) + if(Lua_FOUND AND NOT TARGET Lua::Lua) + add_library(Lua::Lua INTERFACE IMPORTED) + set_target_properties( + Lua::Lua + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}" + ) + endif() + target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC Lua::Lua) endif() # Libs -target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} - PUBLIC - m - cglm - zip - pthread - Lua::Lua -) # Includes target_include_directories(${DUSK_LIBRARY_TARGET_NAME} @@ -63,7 +65,10 @@ add_subdirectory(map) add_subdirectory(scene) add_subdirectory(script) add_subdirectory(story) -add_subdirectory(thread) add_subdirectory(time) add_subdirectory(ui) -add_subdirectory(util) \ No newline at end of file +add_subdirectory(util) + +if(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "psp") + add_subdirectory(thread) +endif() \ No newline at end of file diff --git a/src/asset/type/assetscript.h b/src/asset/type/assetscript.h index 0a3a2d4..38b762a 100644 --- a/src/asset/type/assetscript.h +++ b/src/asset/type/assetscript.h @@ -9,7 +9,7 @@ #include "error/error.h" #include "duskdefs.h" #include -#include +#include "script/scriptcontext.h" #define ASSET_SCRIPT_BUFFER_SIZE 1024 diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt index de9d945..2284adc 100644 --- a/src/display/CMakeLists.txt +++ b/src/display/CMakeLists.txt @@ -38,6 +38,16 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") DISPLAY_HEIGHT=272 DISPLAY_SIZE_DYNAMIC=0 ) +elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + DISPLAY_SDL2=1 + DISPLAY_WINDOW_WIDTH_DEFAULT=640 + DISPLAY_WINDOW_HEIGHT_DEFAULT=480 + DISPLAY_WIDTH=640 + DISPLAY_HEIGHT=480 + DISPLAY_SIZE_DYNAMIC=0 + ) endif() dusk_run_python( diff --git a/src/dusk.h b/src/dusk.h index a794c2d..ea3b4df 100644 --- a/src/dusk.h +++ b/src/dusk.h @@ -29,6 +29,11 @@ #include #endif +#if DOLPHIN + #include + #include +#endif + typedef bool bool_t; typedef int int_t; typedef float float_t; diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index d03e53a..1db94a8 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -25,6 +25,12 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") INPUT_SDL2=1 INPUT_GAMEPAD=1 ) +elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + INPUT_SDL2=1 + INPUT_GAMEPAD=1 + ) endif() # CSV diff --git a/src/main.c b/src/main.c index 532b238..9c8f2eb 100644 --- a/src/main.c +++ b/src/main.c @@ -6,7 +6,6 @@ */ #include "engine/engine.h" -#include "asset/asset.h" #include "util/string.h" #include "input/input.h" diff --git a/src/null.c b/src/null.c new file mode 100644 index 0000000..3bf2e71 --- /dev/null +++ b/src/null.c @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +// Empty C file for annoying platforms. +#include "dusk.h" \ No newline at end of file diff --git a/src/thread/CMakeLists.txt b/src/thread/CMakeLists.txt index 258705b..160cedd 100644 --- a/src/thread/CMakeLists.txt +++ b/src/thread/CMakeLists.txt @@ -21,4 +21,8 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") PUBLIC THREAD_PTHREAD=1 ) +elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + ) endif() \ No newline at end of file diff --git a/src/time/CMakeLists.txt b/src/time/CMakeLists.txt index 803e9c9..69e9f48 100644 --- a/src/time/CMakeLists.txt +++ b/src/time/CMakeLists.txt @@ -21,4 +21,9 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp") PUBLIC TIME_FIXED=1 ) +elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii") + target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + TIME_FIXED=1 + ) endif() \ No newline at end of file diff --git a/src2/CMakeLists.txt b/src2/CMakeLists.txt new file mode 100644 index 0000000..a29ed81 --- /dev/null +++ b/src2/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (c) 2025 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Libs + +# Includes +target_include_directories(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) + +# Sources + +# Main Binary Source +target_sources(${DUSK_BINARY_TARGET_NAME} + PUBLIC + main.cpp + sdl_starter.cpp + sdl_assets_loader.cpp +) + +# Defs + + +# Subdirs diff --git a/src2/main.cpp b/src2/main.cpp new file mode 100644 index 0000000..1917184 --- /dev/null +++ b/src2/main.cpp @@ -0,0 +1,159 @@ +#include +#include "sdl_starter.h" +#include "sdl_assets_loader.h" + +SDL_Window *window = nullptr; +SDL_Renderer *renderer = nullptr; + +const int PLAYER_SPEED = 600; + +SDL_Rect player = {SCREEN_WIDTH / 2 - 64, SCREEN_HEIGHT / 2 - 64, 64, 64}; + +SDL_Rect ball = {SCREEN_WIDTH / 2 + 50, SCREEN_HEIGHT / 2, 32, 32}; + +int ballVelocityX = 400; +int ballVelocityY = 400; + +int colorIndex; + +SDL_Color colors[] = { + {128, 128, 128, 0}, // gray + {255, 255, 255, 0}, // white + {255, 0, 0, 0}, // red + {0, 255, 0, 0}, // green + {0, 0, 255, 0}, // blue + {255, 255, 0, 0}, // brown + {0, 255, 255, 0}, // cyan + {255, 0, 255, 0}, // purple +}; + +void quitGame() +{ + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); +} + +void handleEvents() +{ + SDL_Event event; + + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + quitGame(); + exit(0); + } + } +} + +int rand_range(int min, int max) +{ + return min + rand() / (RAND_MAX / (max - min + 1) + 1); +} + +void update(float deltaTime) +{ + // PAD_ButtonsDown tells us which buttons were pressed in this loop + // this is a "one shot" state which will not fire again until the button has been released + const u32 padDown = PAD_ButtonsDown(0); + + // PAD_ButtonsHeld tells us which buttons are keep pressing in this loop + const u32 padHeld = PAD_ButtonsHeld(0); + + // We return to the launcher application via exit + if (padDown & PAD_BUTTON_START) + exit(0); + + if (padHeld & PAD_BUTTON_LEFT && player.x > 0) + { + player.x -= PLAYER_SPEED * deltaTime; + } + + else if (padHeld & PAD_BUTTON_RIGHT && player.x < SCREEN_WIDTH - player.w) + { + player.x += PLAYER_SPEED * deltaTime; + } + + else if (padHeld & PAD_BUTTON_UP && player.y > 0) + { + player.y -= PLAYER_SPEED * deltaTime; + } + + else if (padHeld & PAD_BUTTON_DOWN && player.y < SCREEN_HEIGHT - player.h) + { + player.y += PLAYER_SPEED * deltaTime; + } + + if (ball.x < 0 || ball.x > SCREEN_WIDTH - ball.w) + { + ballVelocityX *= -1; + + colorIndex = rand_range(0, 5); + } + + else if (ball.y < 0 || ball.y > SCREEN_HEIGHT - ball.h) + { + ballVelocityY *= -1; + + colorIndex = rand_range(0, 5); + } + + else if (SDL_HasIntersection(&player, &ball)) + { + ballVelocityX *= -1; + ballVelocityY *= -1; + + colorIndex = rand_range(0, 5); + } + + ball.x += ballVelocityX * deltaTime; + ball.y += ballVelocityY * deltaTime; +} + +void render() +{ + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + + SDL_RenderFillRect(renderer, &player); + + SDL_SetRenderDrawColor(renderer, colors[colorIndex].r, colors[colorIndex].g, colors[colorIndex].b, 255); + + SDL_RenderFillRect(renderer, &ball); + + SDL_RenderPresent(renderer); +} + +int main(int argc, char **argv) +{ + window = SDL_CreateWindow("My Window", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + + if (startSDL(window, renderer) > 0) + { + return 1; + } + + Uint32 previousFrameTime = SDL_GetTicks(); + Uint32 currentFrameTime = previousFrameTime; + float deltaTime = 0.0f; + + PAD_Init(); + + while (true) + { + PAD_ScanPads(); + + currentFrameTime = SDL_GetTicks(); + deltaTime = (currentFrameTime - previousFrameTime) / 1000.0f; + previousFrameTime = currentFrameTime; + + handleEvents(); + update(deltaTime); + render(); + } +} \ No newline at end of file diff --git a/src2/sdl_assets_loader.cpp b/src2/sdl_assets_loader.cpp new file mode 100644 index 0000000..935d5a1 --- /dev/null +++ b/src2/sdl_assets_loader.cpp @@ -0,0 +1,71 @@ +#include "sdl_assets_loader.h" + +Sprite loadSprite(SDL_Renderer *renderer, const char *filePath, int positionX, int positionY) +{ + SDL_Rect textureBounds = {positionX, positionY, 0, 0}; + + SDL_Texture *texture = IMG_LoadTexture(renderer, filePath); + + if (texture != nullptr) + { + SDL_QueryTexture(texture, NULL, NULL, &textureBounds.w, &textureBounds.h); + } + + Sprite sprite = {texture, textureBounds}; + + return sprite; +} + +Mix_Chunk *loadSound(const char *filePath) +{ + Mix_Chunk *sound = nullptr; + + sound = Mix_LoadWAV(filePath); + if (sound == nullptr) + { + printf("Failed to load scratch sound effect! SDL_mixer Error: %s\n", Mix_GetError()); + } + + return sound; +} + +Mix_Music *loadMusic(const char *filePath) +{ + Mix_Music *music = nullptr; + + music = Mix_LoadMUS(filePath); + if (music == nullptr) + { + printf("Failed to load music! SDL_mixer Error: %s\n", Mix_GetError()); + } + + return music; +} + +void updateTextureText(SDL_Texture *&texture, const char *text, TTF_Font *&fontSquare, SDL_Renderer *renderer) +{ + SDL_Color fontColor = {255, 255, 255}; + + if (fontSquare == nullptr) + { + printf("TTF_OpenFont fontSquare: %s\n", TTF_GetError()); + } + + SDL_Surface *surface = TTF_RenderUTF8_Blended(fontSquare, text, fontColor); + if (surface == nullptr) + { + printf("TTF_OpenFont: %s\n", TTF_GetError()); + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Unable to create text surface! SDL Error: %s\n", SDL_GetError()); + exit(3); + } + + SDL_DestroyTexture(texture); + texture = SDL_CreateTextureFromSurface(renderer, surface); + if (texture == nullptr) + { + printf("TTF_OpenFont: %s\n", TTF_GetError()); + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Unable to create texture from surface! SDL Error: %s\n", SDL_GetError()); + } + + SDL_FreeSurface(surface); +} \ No newline at end of file diff --git a/src2/sdl_assets_loader.h b/src2/sdl_assets_loader.h new file mode 100644 index 0000000..4750d32 --- /dev/null +++ b/src2/sdl_assets_loader.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include +#include +#include + +typedef struct +{ + SDL_Texture *texture; + SDL_Rect textureBounds; +} Sprite; + +Sprite loadSprite(SDL_Renderer *renderer, const char *filePath, int positionX, int positionY); + +Mix_Chunk *loadSound(const char *filePath); + +Mix_Music *loadMusic(const char *filePath); + +void updateTextureText(SDL_Texture *&texture, const char *text, TTF_Font *&fontSquare, SDL_Renderer *renderer); \ No newline at end of file diff --git a/src2/sdl_starter.cpp b/src2/sdl_starter.cpp new file mode 100644 index 0000000..11857d6 --- /dev/null +++ b/src2/sdl_starter.cpp @@ -0,0 +1,48 @@ +#include "sdl_starter.h" +#include +#include +#include +#include + +int startSDL(SDL_Window *window, SDL_Renderer *renderer) { + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) + { + std::cout << "SDL crashed. Error: " << SDL_GetError(); + return 1; + } + + if (window == nullptr) + { + std::cerr << "Failed to create window: " << SDL_GetError() << std::endl; + SDL_Quit(); + return 1; + } + + if (renderer == nullptr) + { + std::cerr << "Failed to create renderer: " << SDL_GetError() << std::endl; + SDL_DestroyWindow(window); + SDL_Quit(); + return 1; + } + + if (!IMG_Init(IMG_INIT_PNG)) + { + std::cout << "SDL_image crashed. Error: " << SDL_GetError(); + return 1; + } + + if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0) + { + printf("SDL_mixer could not initialize! SDL_mixer Error: %s\n", Mix_GetError()); + return 1; + } + + if (TTF_Init() == -1) + { + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/src2/sdl_starter.h b/src2/sdl_starter.h new file mode 100644 index 0000000..9604e3f --- /dev/null +++ b/src2/sdl_starter.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +const int SCREEN_WIDTH = 640; +const int SCREEN_HEIGHT = 480; + +int startSDL(SDL_Window *window, SDL_Renderer *renderer);