From 9080d88f6f30164e84e08a1769f9e07ad930d2d6 Mon Sep 17 00:00:00 2001 From: Joseph Aquino Date: Mon, 29 Sep 2025 21:25:09 -0400 Subject: [PATCH] first commit --- .gitignore | 396 + Create-Solution.bat | 2 + LICENSE.txt | 21 + assets/fonts/ChakraPetch-Regular.ttf | Bin 0 -> 71556 bytes assets/fonts/OFL.txt | 93 + build-ninja.sh | 4 + build.sh | 4 + clean-ninja.sh | 7 + clean.sh | 7 + config/game-config.txt | 4 + ecc.sh | 7 + include/Color.h | 20 + include/Game.h | 75 + include/Math-util.h | 9 + include/Random.h | 74 + include/Util.h | 5 + premake5.lua | 154 + run.sh | 3 + src/Color.cpp | 27 + src/Game.cpp | 221 + src/main.cpp | 18 + vendor/SFML/include/SFML/Audio.hpp | 55 + .../SFML/include/SFML/Audio/AudioResource.hpp | 93 + vendor/SFML/include/SFML/Audio/Export.hpp | 44 + .../include/SFML/Audio/InputSoundFile.hpp | 336 + vendor/SFML/include/SFML/Audio/Listener.hpp | 234 + vendor/SFML/include/SFML/Audio/Music.hpp | 377 + .../include/SFML/Audio/OutputSoundFile.hpp | 147 + .../include/SFML/Audio/PlaybackDevice.hpp | 110 + vendor/SFML/include/SFML/Audio/Sound.hpp | 284 + .../SFML/include/SFML/Audio/SoundBuffer.hpp | 451 + .../SFML/Audio/SoundBufferRecorder.hpp | 149 + .../SFML/include/SFML/Audio/SoundChannel.hpp | 65 + .../include/SFML/Audio/SoundFileFactory.hpp | 200 + .../include/SFML/Audio/SoundFileFactory.inl | 96 + .../include/SFML/Audio/SoundFileReader.hpp | 167 + .../include/SFML/Audio/SoundFileWriter.hpp | 130 + .../SFML/include/SFML/Audio/SoundRecorder.hpp | 362 + .../SFML/include/SFML/Audio/SoundSource.hpp | 686 + .../SFML/include/SFML/Audio/SoundStream.hpp | 385 + vendor/SFML/include/SFML/Config.hpp | 164 + vendor/SFML/include/SFML/GpuPreference.hpp | 70 + vendor/SFML/include/SFML/Graphics.hpp | 67 + .../SFML/include/SFML/Graphics/BlendMode.hpp | 220 + .../include/SFML/Graphics/CircleShape.hpp | 165 + vendor/SFML/include/SFML/Graphics/Color.hpp | 274 + vendor/SFML/include/SFML/Graphics/Color.inl | 156 + .../include/SFML/Graphics/ConvexShape.hpp | 155 + .../include/SFML/Graphics/CoordinateType.hpp | 43 + .../SFML/include/SFML/Graphics/Drawable.hpp | 120 + vendor/SFML/include/SFML/Graphics/Export.hpp | 44 + vendor/SFML/include/SFML/Graphics/Font.hpp | 529 + vendor/SFML/include/SFML/Graphics/Glsl.hpp | 224 + vendor/SFML/include/SFML/Graphics/Glsl.inl | 177 + vendor/SFML/include/SFML/Graphics/Glyph.hpp | 67 + vendor/SFML/include/SFML/Graphics/Image.hpp | 417 + .../include/SFML/Graphics/PrimitiveType.hpp | 48 + vendor/SFML/include/SFML/Graphics/Rect.hpp | 203 + vendor/SFML/include/SFML/Graphics/Rect.inl | 130 + .../include/SFML/Graphics/RectangleShape.hpp | 143 + .../include/SFML/Graphics/RenderStates.hpp | 191 + .../include/SFML/Graphics/RenderTarget.hpp | 606 + .../include/SFML/Graphics/RenderTexture.hpp | 342 + .../include/SFML/Graphics/RenderWindow.hpp | 308 + vendor/SFML/include/SFML/Graphics/Shader.hpp | 1023 + vendor/SFML/include/SFML/Graphics/Shape.hpp | 357 + vendor/SFML/include/SFML/Graphics/Sprite.hpp | 278 + .../include/SFML/Graphics/StencilMode.hpp | 256 + vendor/SFML/include/SFML/Graphics/Text.hpp | 486 + vendor/SFML/include/SFML/Graphics/Texture.hpp | 874 + .../SFML/include/SFML/Graphics/Transform.hpp | 393 + .../SFML/include/SFML/Graphics/Transform.inl | 236 + .../include/SFML/Graphics/Transformable.hpp | 340 + vendor/SFML/include/SFML/Graphics/Vertex.hpp | 122 + .../include/SFML/Graphics/VertexArray.hpp | 221 + .../include/SFML/Graphics/VertexBuffer.hpp | 414 + vendor/SFML/include/SFML/Graphics/View.hpp | 357 + vendor/SFML/include/SFML/Main.hpp | 39 + vendor/SFML/include/SFML/Network.hpp | 51 + vendor/SFML/include/SFML/Network/Export.hpp | 44 + vendor/SFML/include/SFML/Network/Ftp.hpp | 629 + vendor/SFML/include/SFML/Network/Http.hpp | 480 + .../SFML/include/SFML/Network/IpAddress.hpp | 297 + vendor/SFML/include/SFML/Network/Packet.hpp | 552 + vendor/SFML/include/SFML/Network/Socket.hpp | 229 + .../include/SFML/Network/SocketHandle.hpp | 52 + .../include/SFML/Network/SocketSelector.hpp | 273 + .../SFML/include/SFML/Network/TcpListener.hpp | 166 + .../SFML/include/SFML/Network/TcpSocket.hpp | 317 + .../SFML/include/SFML/Network/UdpSocket.hpp | 293 + vendor/SFML/include/SFML/OpenGL.hpp | 78 + vendor/SFML/include/SFML/System.hpp | 55 + vendor/SFML/include/SFML/System/Angle.hpp | 511 + vendor/SFML/include/SFML/System/Angle.inl | 274 + vendor/SFML/include/SFML/System/Clock.hpp | 196 + vendor/SFML/include/SFML/System/Err.hpp | 77 + vendor/SFML/include/SFML/System/Exception.hpp | 46 + vendor/SFML/include/SFML/System/Export.hpp | 44 + .../include/SFML/System/FileInputStream.hpp | 212 + .../SFML/include/SFML/System/InputStream.hpp | 166 + .../include/SFML/System/MemoryInputStream.hpp | 139 + .../include/SFML/System/NativeActivity.hpp | 58 + vendor/SFML/include/SFML/System/Sleep.hpp | 57 + vendor/SFML/include/SFML/System/String.hpp | 700 + vendor/SFML/include/SFML/System/String.inl | 64 + .../include/SFML/System/SuspendAwareClock.hpp | 76 + vendor/SFML/include/SFML/System/Time.hpp | 500 + vendor/SFML/include/SFML/System/Time.inl | 284 + vendor/SFML/include/SFML/System/Utf.hpp | 764 + vendor/SFML/include/SFML/System/Utf.inl | 732 + vendor/SFML/include/SFML/System/Vector2.hpp | 435 + vendor/SFML/include/SFML/System/Vector2.inl | 217 + vendor/SFML/include/SFML/System/Vector3.hpp | 356 + vendor/SFML/include/SFML/System/Vector3.inl | 214 + vendor/SFML/include/SFML/Window.hpp | 55 + vendor/SFML/include/SFML/Window/Clipboard.hpp | 114 + vendor/SFML/include/SFML/Window/Context.hpp | 224 + .../include/SFML/Window/ContextSettings.hpp | 125 + vendor/SFML/include/SFML/Window/Cursor.hpp | 303 + vendor/SFML/include/SFML/Window/Event.hpp | 442 + vendor/SFML/include/SFML/Window/Event.inl | 78 + vendor/SFML/include/SFML/Window/Export.hpp | 44 + .../SFML/include/SFML/Window/GlResource.hpp | 122 + vendor/SFML/include/SFML/Window/Joystick.hpp | 213 + vendor/SFML/include/SFML/Window/Keyboard.hpp | 475 + vendor/SFML/include/SFML/Window/Mouse.hpp | 175 + vendor/SFML/include/SFML/Window/Sensor.hpp | 139 + vendor/SFML/include/SFML/Window/Touch.hpp | 131 + vendor/SFML/include/SFML/Window/VideoMode.hpp | 224 + vendor/SFML/include/SFML/Window/Vulkan.hpp | 112 + vendor/SFML/include/SFML/Window/Window.hpp | 422 + .../SFML/include/SFML/Window/WindowBase.hpp | 653 + .../SFML/include/SFML/Window/WindowBase.inl | 112 + .../SFML/include/SFML/Window/WindowEnums.hpp | 60 + .../SFML/include/SFML/Window/WindowHandle.hpp | 98 + vendor/SFML/lib/FLAC.lib | Bin 0 -> 738608 bytes vendor/SFML/lib/FLACd.lib | Bin 0 -> 1883358 bytes vendor/SFML/lib/freetype.lib | Bin 0 -> 1903438 bytes vendor/SFML/lib/freetyped.lib | Bin 0 -> 3694878 bytes vendor/SFML/lib/ogg.lib | Bin 0 -> 49622 bytes vendor/SFML/lib/oggd.lib | Bin 0 -> 80034 bytes vendor/SFML/lib/sfml-audio-s-d.lib | Bin 0 -> 18607622 bytes vendor/SFML/lib/sfml-audio-s.lib | Bin 0 -> 4730912 bytes vendor/SFML/lib/sfml-graphics-s-d.lib | Bin 0 -> 16132936 bytes vendor/SFML/lib/sfml-graphics-s.lib | Bin 0 -> 3646464 bytes vendor/SFML/lib/sfml-main-d.lib | Bin 0 -> 16422 bytes vendor/SFML/lib/sfml-main.lib | Bin 0 -> 1392 bytes vendor/SFML/lib/sfml-network-s-d.lib | Bin 0 -> 7211916 bytes vendor/SFML/lib/sfml-network-s.lib | Bin 0 -> 1996380 bytes vendor/SFML/lib/sfml-system-s-d.lib | Bin 0 -> 2683376 bytes vendor/SFML/lib/sfml-system-s.lib | Bin 0 -> 606082 bytes vendor/SFML/lib/sfml-window-s-d.lib | Bin 0 -> 11547774 bytes vendor/SFML/lib/sfml-window-s.lib | Bin 0 -> 2268398 bytes vendor/SFML/lib/vorbis.lib | Bin 0 -> 1062762 bytes vendor/SFML/lib/vorbisd.lib | Bin 0 -> 1415258 bytes vendor/SFML/lib/vorbisenc.lib | Bin 0 -> 696406 bytes vendor/SFML/lib/vorbisencd.lib | Bin 0 -> 855172 bytes vendor/SFML/lib/vorbisfile.lib | Bin 0 -> 65076 bytes vendor/SFML/lib/vorbisfiled.lib | Bin 0 -> 93846 bytes vendor/SFML/share/doc/SFML/license.md | 9 + vendor/SFML/share/doc/SFML/readme.md | 79 + vendor/imgui/LICENSE | 23 + vendor/imgui/LICENSE.txt | 21 + vendor/imgui/README.md | 284 + vendor/imgui/imconfig-SFML.h | 36 + vendor/imgui/imconfig.h | 144 + vendor/imgui/imgui-SFML.cpp | 1468 ++ vendor/imgui/imgui-SFML.h | 134 + vendor/imgui/imgui-SFML_export.h | 25 + vendor/imgui/imgui.cpp | 16839 ++++++++++++++++ vendor/imgui/imgui.h | 3724 ++++ vendor/imgui/imgui_demo.cpp | 10405 ++++++++++ vendor/imgui/imgui_draw.cpp | 4787 +++++ vendor/imgui/imgui_internal.h | 3585 ++++ vendor/imgui/imgui_tables.cpp | 4468 ++++ vendor/imgui/imgui_widgets.cpp | 10320 ++++++++++ vendor/imgui/imstb_rectpack.h | 627 + vendor/imgui/imstb_textedit.h | 1469 ++ vendor/imgui/imstb_truetype.h | 5085 +++++ vendor/imgui/misc/README.txt | 23 + vendor/imgui/misc/cpp/README.txt | 13 + vendor/imgui/misc/cpp/imgui_stdlib.cpp | 85 + vendor/imgui/misc/cpp/imgui_stdlib.h | 21 + vendor/imgui/misc/debuggers/README.txt | 16 + vendor/imgui/misc/debuggers/imgui.gdb | 12 + .../imgui/misc/debuggers/imgui.natstepfilter | 31 + vendor/imgui/misc/debuggers/imgui.natvis | 58 + vendor/imgui/misc/fonts/Cousine-Regular.ttf | Bin 0 -> 43912 bytes vendor/imgui/misc/fonts/DroidSans.ttf | Bin 0 -> 190044 bytes vendor/imgui/misc/fonts/Karla-Regular.ttf | Bin 0 -> 16848 bytes vendor/imgui/misc/fonts/ProggyClean.ttf | Bin 0 -> 41208 bytes vendor/imgui/misc/fonts/ProggyTiny.ttf | Bin 0 -> 35656 bytes vendor/imgui/misc/fonts/Roboto-Medium.ttf | Bin 0 -> 162588 bytes .../misc/fonts/binary_to_compressed_c.cpp | 424 + vendor/imgui/misc/freetype/README.md | 62 + vendor/imgui/misc/freetype/imgui_freetype.cpp | 969 + vendor/imgui/misc/freetype/imgui_freetype.h | 58 + .../misc/single_file/imgui_single_file.h | 29 + vendor/premake5/LICENSE.txt | 27 + vendor/premake5/ecc/LICENSE.md | 29 + vendor/premake5/ecc/README.md | 49 + vendor/premake5/ecc/_manifest.lua | 4 + vendor/premake5/ecc/_preload.lua | 35 + vendor/premake5/ecc/ecc.lua | 122 + vendor/premake5/ninja/LICENSE | 22 + vendor/premake5/ninja/README.md | 43 + vendor/premake5/ninja/_manifest.lua | 4 + vendor/premake5/ninja/_preload.lua | 60 + vendor/premake5/ninja/ninja.lua | 845 + vendor/premake5/premake5 | Bin 0 -> 2659760 bytes vendor/premake5/premake5.exe | Bin 0 -> 1312256 bytes 211 files changed, 96313 insertions(+) create mode 100644 .gitignore create mode 100644 Create-Solution.bat create mode 100644 LICENSE.txt create mode 100644 assets/fonts/ChakraPetch-Regular.ttf create mode 100644 assets/fonts/OFL.txt create mode 100755 build-ninja.sh create mode 100755 build.sh create mode 100755 clean-ninja.sh create mode 100755 clean.sh create mode 100644 config/game-config.txt create mode 100755 ecc.sh create mode 100644 include/Color.h create mode 100644 include/Game.h create mode 100644 include/Math-util.h create mode 100644 include/Random.h create mode 100644 include/Util.h create mode 100644 premake5.lua create mode 100755 run.sh create mode 100644 src/Color.cpp create mode 100644 src/Game.cpp create mode 100644 src/main.cpp create mode 100644 vendor/SFML/include/SFML/Audio.hpp create mode 100644 vendor/SFML/include/SFML/Audio/AudioResource.hpp create mode 100644 vendor/SFML/include/SFML/Audio/Export.hpp create mode 100644 vendor/SFML/include/SFML/Audio/InputSoundFile.hpp create mode 100644 vendor/SFML/include/SFML/Audio/Listener.hpp create mode 100644 vendor/SFML/include/SFML/Audio/Music.hpp create mode 100644 vendor/SFML/include/SFML/Audio/OutputSoundFile.hpp create mode 100644 vendor/SFML/include/SFML/Audio/PlaybackDevice.hpp create mode 100644 vendor/SFML/include/SFML/Audio/Sound.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundBuffer.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundBufferRecorder.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundChannel.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundFileFactory.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundFileFactory.inl create mode 100644 vendor/SFML/include/SFML/Audio/SoundFileReader.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundFileWriter.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundRecorder.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundSource.hpp create mode 100644 vendor/SFML/include/SFML/Audio/SoundStream.hpp create mode 100644 vendor/SFML/include/SFML/Config.hpp create mode 100644 vendor/SFML/include/SFML/GpuPreference.hpp create mode 100644 vendor/SFML/include/SFML/Graphics.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/BlendMode.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/CircleShape.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Color.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Color.inl create mode 100644 vendor/SFML/include/SFML/Graphics/ConvexShape.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/CoordinateType.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Drawable.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Export.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Font.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Glsl.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Glsl.inl create mode 100644 vendor/SFML/include/SFML/Graphics/Glyph.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Image.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/PrimitiveType.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Rect.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Rect.inl create mode 100644 vendor/SFML/include/SFML/Graphics/RectangleShape.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/RenderStates.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/RenderTarget.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/RenderTexture.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/RenderWindow.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Shader.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Shape.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Sprite.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/StencilMode.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Text.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Texture.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Transform.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Transform.inl create mode 100644 vendor/SFML/include/SFML/Graphics/Transformable.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/Vertex.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/VertexArray.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/VertexBuffer.hpp create mode 100644 vendor/SFML/include/SFML/Graphics/View.hpp create mode 100644 vendor/SFML/include/SFML/Main.hpp create mode 100644 vendor/SFML/include/SFML/Network.hpp create mode 100644 vendor/SFML/include/SFML/Network/Export.hpp create mode 100644 vendor/SFML/include/SFML/Network/Ftp.hpp create mode 100644 vendor/SFML/include/SFML/Network/Http.hpp create mode 100644 vendor/SFML/include/SFML/Network/IpAddress.hpp create mode 100644 vendor/SFML/include/SFML/Network/Packet.hpp create mode 100644 vendor/SFML/include/SFML/Network/Socket.hpp create mode 100644 vendor/SFML/include/SFML/Network/SocketHandle.hpp create mode 100644 vendor/SFML/include/SFML/Network/SocketSelector.hpp create mode 100644 vendor/SFML/include/SFML/Network/TcpListener.hpp create mode 100644 vendor/SFML/include/SFML/Network/TcpSocket.hpp create mode 100644 vendor/SFML/include/SFML/Network/UdpSocket.hpp create mode 100644 vendor/SFML/include/SFML/OpenGL.hpp create mode 100644 vendor/SFML/include/SFML/System.hpp create mode 100644 vendor/SFML/include/SFML/System/Angle.hpp create mode 100644 vendor/SFML/include/SFML/System/Angle.inl create mode 100644 vendor/SFML/include/SFML/System/Clock.hpp create mode 100644 vendor/SFML/include/SFML/System/Err.hpp create mode 100644 vendor/SFML/include/SFML/System/Exception.hpp create mode 100644 vendor/SFML/include/SFML/System/Export.hpp create mode 100644 vendor/SFML/include/SFML/System/FileInputStream.hpp create mode 100644 vendor/SFML/include/SFML/System/InputStream.hpp create mode 100644 vendor/SFML/include/SFML/System/MemoryInputStream.hpp create mode 100644 vendor/SFML/include/SFML/System/NativeActivity.hpp create mode 100644 vendor/SFML/include/SFML/System/Sleep.hpp create mode 100644 vendor/SFML/include/SFML/System/String.hpp create mode 100644 vendor/SFML/include/SFML/System/String.inl create mode 100644 vendor/SFML/include/SFML/System/SuspendAwareClock.hpp create mode 100644 vendor/SFML/include/SFML/System/Time.hpp create mode 100644 vendor/SFML/include/SFML/System/Time.inl create mode 100644 vendor/SFML/include/SFML/System/Utf.hpp create mode 100644 vendor/SFML/include/SFML/System/Utf.inl create mode 100644 vendor/SFML/include/SFML/System/Vector2.hpp create mode 100644 vendor/SFML/include/SFML/System/Vector2.inl create mode 100644 vendor/SFML/include/SFML/System/Vector3.hpp create mode 100644 vendor/SFML/include/SFML/System/Vector3.inl create mode 100644 vendor/SFML/include/SFML/Window.hpp create mode 100644 vendor/SFML/include/SFML/Window/Clipboard.hpp create mode 100644 vendor/SFML/include/SFML/Window/Context.hpp create mode 100644 vendor/SFML/include/SFML/Window/ContextSettings.hpp create mode 100644 vendor/SFML/include/SFML/Window/Cursor.hpp create mode 100644 vendor/SFML/include/SFML/Window/Event.hpp create mode 100644 vendor/SFML/include/SFML/Window/Event.inl create mode 100644 vendor/SFML/include/SFML/Window/Export.hpp create mode 100644 vendor/SFML/include/SFML/Window/GlResource.hpp create mode 100644 vendor/SFML/include/SFML/Window/Joystick.hpp create mode 100644 vendor/SFML/include/SFML/Window/Keyboard.hpp create mode 100644 vendor/SFML/include/SFML/Window/Mouse.hpp create mode 100644 vendor/SFML/include/SFML/Window/Sensor.hpp create mode 100644 vendor/SFML/include/SFML/Window/Touch.hpp create mode 100644 vendor/SFML/include/SFML/Window/VideoMode.hpp create mode 100644 vendor/SFML/include/SFML/Window/Vulkan.hpp create mode 100644 vendor/SFML/include/SFML/Window/Window.hpp create mode 100644 vendor/SFML/include/SFML/Window/WindowBase.hpp create mode 100644 vendor/SFML/include/SFML/Window/WindowBase.inl create mode 100644 vendor/SFML/include/SFML/Window/WindowEnums.hpp create mode 100644 vendor/SFML/include/SFML/Window/WindowHandle.hpp create mode 100644 vendor/SFML/lib/FLAC.lib create mode 100644 vendor/SFML/lib/FLACd.lib create mode 100644 vendor/SFML/lib/freetype.lib create mode 100644 vendor/SFML/lib/freetyped.lib create mode 100644 vendor/SFML/lib/ogg.lib create mode 100644 vendor/SFML/lib/oggd.lib create mode 100644 vendor/SFML/lib/sfml-audio-s-d.lib create mode 100644 vendor/SFML/lib/sfml-audio-s.lib create mode 100644 vendor/SFML/lib/sfml-graphics-s-d.lib create mode 100644 vendor/SFML/lib/sfml-graphics-s.lib create mode 100644 vendor/SFML/lib/sfml-main-d.lib create mode 100644 vendor/SFML/lib/sfml-main.lib create mode 100644 vendor/SFML/lib/sfml-network-s-d.lib create mode 100644 vendor/SFML/lib/sfml-network-s.lib create mode 100644 vendor/SFML/lib/sfml-system-s-d.lib create mode 100644 vendor/SFML/lib/sfml-system-s.lib create mode 100644 vendor/SFML/lib/sfml-window-s-d.lib create mode 100644 vendor/SFML/lib/sfml-window-s.lib create mode 100644 vendor/SFML/lib/vorbis.lib create mode 100644 vendor/SFML/lib/vorbisd.lib create mode 100644 vendor/SFML/lib/vorbisenc.lib create mode 100644 vendor/SFML/lib/vorbisencd.lib create mode 100644 vendor/SFML/lib/vorbisfile.lib create mode 100644 vendor/SFML/lib/vorbisfiled.lib create mode 100644 vendor/SFML/share/doc/SFML/license.md create mode 100644 vendor/SFML/share/doc/SFML/readme.md create mode 100644 vendor/imgui/LICENSE create mode 100644 vendor/imgui/LICENSE.txt create mode 100644 vendor/imgui/README.md create mode 100644 vendor/imgui/imconfig-SFML.h create mode 100644 vendor/imgui/imconfig.h create mode 100644 vendor/imgui/imgui-SFML.cpp create mode 100644 vendor/imgui/imgui-SFML.h create mode 100644 vendor/imgui/imgui-SFML_export.h create mode 100644 vendor/imgui/imgui.cpp create mode 100644 vendor/imgui/imgui.h create mode 100644 vendor/imgui/imgui_demo.cpp create mode 100644 vendor/imgui/imgui_draw.cpp create mode 100644 vendor/imgui/imgui_internal.h create mode 100644 vendor/imgui/imgui_tables.cpp create mode 100644 vendor/imgui/imgui_widgets.cpp create mode 100644 vendor/imgui/imstb_rectpack.h create mode 100644 vendor/imgui/imstb_textedit.h create mode 100644 vendor/imgui/imstb_truetype.h create mode 100644 vendor/imgui/misc/README.txt create mode 100644 vendor/imgui/misc/cpp/README.txt create mode 100644 vendor/imgui/misc/cpp/imgui_stdlib.cpp create mode 100644 vendor/imgui/misc/cpp/imgui_stdlib.h create mode 100644 vendor/imgui/misc/debuggers/README.txt create mode 100644 vendor/imgui/misc/debuggers/imgui.gdb create mode 100644 vendor/imgui/misc/debuggers/imgui.natstepfilter create mode 100644 vendor/imgui/misc/debuggers/imgui.natvis create mode 100644 vendor/imgui/misc/fonts/Cousine-Regular.ttf create mode 100644 vendor/imgui/misc/fonts/DroidSans.ttf create mode 100644 vendor/imgui/misc/fonts/Karla-Regular.ttf create mode 100644 vendor/imgui/misc/fonts/ProggyClean.ttf create mode 100644 vendor/imgui/misc/fonts/ProggyTiny.ttf create mode 100644 vendor/imgui/misc/fonts/Roboto-Medium.ttf create mode 100644 vendor/imgui/misc/fonts/binary_to_compressed_c.cpp create mode 100644 vendor/imgui/misc/freetype/README.md create mode 100644 vendor/imgui/misc/freetype/imgui_freetype.cpp create mode 100644 vendor/imgui/misc/freetype/imgui_freetype.h create mode 100644 vendor/imgui/misc/single_file/imgui_single_file.h create mode 100644 vendor/premake5/LICENSE.txt create mode 100644 vendor/premake5/ecc/LICENSE.md create mode 100644 vendor/premake5/ecc/README.md create mode 100644 vendor/premake5/ecc/_manifest.lua create mode 100644 vendor/premake5/ecc/_preload.lua create mode 100644 vendor/premake5/ecc/ecc.lua create mode 100644 vendor/premake5/ninja/LICENSE create mode 100644 vendor/premake5/ninja/README.md create mode 100644 vendor/premake5/ninja/_manifest.lua create mode 100644 vendor/premake5/ninja/_preload.lua create mode 100644 vendor/premake5/ninja/ninja.lua create mode 100755 vendor/premake5/premake5 create mode 100644 vendor/premake5/premake5.exe diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4ef6152 --- /dev/null +++ b/.gitignore @@ -0,0 +1,396 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +#[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +intermediate-files/ + +.cache/ +.vscode/ +*.json +*.make +Makefile +*.sublime-* + +*.vcxproj + +*.sln + +*.vcxproj.filters + +*.code-workspace + +*.o + +*.d + +*.ninja* + +.idea/ + +Engine-Core/lib +Engine-Core/intermediate-files +Editor/bin +Editor/intermediate-files +Game/bin + +imgui.ini \ No newline at end of file diff --git a/Create-Solution.bat b/Create-Solution.bat new file mode 100644 index 0000000..2cd4d72 --- /dev/null +++ b/Create-Solution.bat @@ -0,0 +1,2 @@ +.\vendor\premake5\premake5.exe vs2022 +PAUSE \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..3da13a2 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Joseph Aquino + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/assets/fonts/ChakraPetch-Regular.ttf b/assets/fonts/ChakraPetch-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..245df022c86aab4a8cc15718076bcd546444c6de GIT binary patch literal 71556 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 V;-AgS8&E!+q(mwIoZx6Q{}00xA+G=c literal 0 HcmV?d00001 diff --git a/assets/fonts/OFL.txt b/assets/fonts/OFL.txt new file mode 100644 index 0000000..7bd926c --- /dev/null +++ b/assets/fonts/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Chakra Petch Project Authors (https://github.com/m4rc1e/Chakra-Petch.git) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/build-ninja.sh b/build-ninja.sh new file mode 100755 index 0000000..c4a2877 --- /dev/null +++ b/build-ninja.sh @@ -0,0 +1,4 @@ +#! /bin/bash + +./vendor/premake5/premake5 ninja +ninja $1 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..8b3a4e6 --- /dev/null +++ b/build.sh @@ -0,0 +1,4 @@ +#! /bin/bash + +./vendor/premake5/premake5 gmake +make config=$1 diff --git a/clean-ninja.sh b/clean-ninja.sh new file mode 100755 index 0000000..f01a203 --- /dev/null +++ b/clean-ninja.sh @@ -0,0 +1,7 @@ +#! /bin/bash +if [ -z "$1" ] || [ $# -eq 0 ] + then + ninja -t clean + else + ninja -t clean $1 +fi \ No newline at end of file diff --git a/clean.sh b/clean.sh new file mode 100755 index 0000000..d726eae --- /dev/null +++ b/clean.sh @@ -0,0 +1,7 @@ +#! /bin/bash +if [ -z "$1" ] || [ $# -eq 0 ] + then + make config=Debug clean && make config=Release clean + else + make config=$1 clean +fi \ No newline at end of file diff --git a/config/game-config.txt b/config/game-config.txt new file mode 100644 index 0000000..3953675 --- /dev/null +++ b/config/game-config.txt @@ -0,0 +1,4 @@ +framerate 60 + +playerColor 1 1 1 + diff --git a/ecc.sh b/ecc.sh new file mode 100755 index 0000000..323e448 --- /dev/null +++ b/ecc.sh @@ -0,0 +1,7 @@ +#! /bin/bash +if [ -z "$1" ] || [ $# -eq 0 ] + then + ./vendor/premake5/premake5 --config=Debug ecc + else + ./vendor/premake5/premake5 --config=$1 ecc +fi \ No newline at end of file diff --git a/include/Color.h b/include/Color.h new file mode 100644 index 0000000..fa80187 --- /dev/null +++ b/include/Color.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +struct Color +{ + Color() = default; + Color(float r_in, float g_in, float b_in, float a_in); + + Color(sf::Color color_in); + + sf::Color sfml(); + + float* imgui(); + + float r{}; + float g{}; + float b{}; + float a{1.f}; +}; \ No newline at end of file diff --git a/include/Game.h b/include/Game.h new file mode 100644 index 0000000..d8c6142 --- /dev/null +++ b/include/Game.h @@ -0,0 +1,75 @@ +#pragma once + +#include + +#include + +#include +#include +#include +#include + + +class SnakeNode +{ + +}; + +struct Player +{ + Player() = default; + Player(sf::Vector2i gridPos_in); + + sf::Vector2i gridPos{}; + sf::Vector2i previousGridPos{}; + sf::Vector2f windowPos{}; + int score{}; + int lives{3}; + bool left{false}; + bool right{false}; + bool up{false}; + bool down{false}; +}; + +class Game +{ +public: + Game(bool useImgui_in); + + void run(); + +private: + void imgui(); + + void render(); + + void input(); + + void collision(); + + void movement(); + + void resetGame(); + + bool parseConfigFile(); + + void soundSystem(); + + void scoreSystem(); + + +private: + sf::Clock clock; + sf::RenderWindow window; + sf::Font font; + sf::Text lives; + sf::Text score; + + Player player; + + // mostly used for imgui + int framerate{}; + float volume{}; + bool useImgui; + static constexpr unsigned int numPhysicsUpdates{4}; +}; \ No newline at end of file diff --git a/include/Math-util.h b/include/Math-util.h new file mode 100644 index 0000000..01dcb1a --- /dev/null +++ b/include/Math-util.h @@ -0,0 +1,9 @@ + +namespace Math +{ + template + inline T max(U first, V second) + { + return static_cast(static_cast(first) >= static_cast(second) ? first : second); + } +} \ No newline at end of file diff --git a/include/Random.h b/include/Random.h new file mode 100644 index 0000000..28c2beb --- /dev/null +++ b/include/Random.h @@ -0,0 +1,74 @@ +#pragma once + +#ifndef RANDOM_MT_H +#define RANDOM_MT_H + +#include +#include + +// This header-only Random namespace implements a self-seeding Mersenne Twister. +// Requires C++17 or newer. +// It can be #included into as many code files as needed (The inline keyword avoids ODR violations) +// Freely redistributable, courtesy of learncpp.com (https://www.learncpp.com/cpp-tutorial/global-random-numbers-random-h/) +namespace Random +{ + // Returns a seeded Mersenne Twister + // Note: we'd prefer to return a std::seed_seq (to initialize a std::mt19937), but std::seed can't be copied, so it can't be returned by value. + // Instead, we'll create a std::mt19937, seed it, and then return the std::mt19937 (which can be copied). + inline std::mt19937 generate() + { + std::random_device rd{}; + + // Create seed_seq with clock and 7 random numbers from std::random_device + std::seed_seq ss{ + static_cast(std::chrono::steady_clock::now().time_since_epoch().count()), + rd(), rd(), rd(), rd(), rd(), rd(), rd() }; + + return std::mt19937{ ss }; + } + + // Here's our global std::mt19937 object. + // The inline keyword means we only have one global instance for our whole program. + inline std::mt19937 mt{ generate() }; // generates a seeded std::mt19937 and copies it into our global object + + // Generate a random int between [min, max] (inclusive) + // * also handles cases where the two arguments have different types but can be converted to int + inline int get(int min, int max) + { + return std::uniform_int_distribution{min, max}(mt); + } + + // The following function templates can be used to generate random numbers in other cases + + // See https://www.learncpp.com/cpp-tutorial/function-template-instantiation/ + // You can ignore these if you don't understand them + + // Generate a random value between [min, max] (inclusive) + // * min and max must have the same type + // * return value has same type as min and max + // * Supported types: + // * short, int, long, long long + // * unsigned short, unsigned int, unsigned long, or unsigned long long + // Sample call: Random::get(1L, 6L); // returns long + // Sample call: Random::get(1u, 6u); // returns unsigned int + template + T get(T min, T max) + { + return std::uniform_int_distribution{min, max}(mt); + } + + // Generate a random value between [min, max] (inclusive) + // * min and max can have different types + // * return type must be explicitly specified as a template argument + // * min and max will be converted to the return type + // Sample call: Random::get(0, 6); // returns std::size_t + // Sample call: Random::get(0, 6u); // returns std::size_t + // Sample call: Random::get(0, 6u); // returns int + template + R get(S min, T max) + { + return get(static_cast(min), static_cast(max)); + } +} + +#endif \ No newline at end of file diff --git a/include/Util.h b/include/Util.h new file mode 100644 index 0000000..53ba3ae --- /dev/null +++ b/include/Util.h @@ -0,0 +1,5 @@ +#pragma once + +#include +#include +#include \ No newline at end of file diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 0000000..f497dbb --- /dev/null +++ b/premake5.lua @@ -0,0 +1,154 @@ +require "ecc/ecc" +require "ninja/ninja" + +workspace "snake" + architecture "x64" + + output_dir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" + vs_intdir = "!$(SolutionDir)intermediate-files/" .. output_dir + intdir = "%{wks.location}/intermediate-files/" .. output_dir + vs_bindir = "$(SolutionDir)bin/" .. output_dir + bindir = "%{wks.location}/bin/" .. output_dir + vs_coreinclude_dir = "$(SolutionDir)include" + vs_sfmldir = "$(SolutionDir)vendor/SFML" + sfmldir = "%{wks.location}/vendor/SFML" + vs_imguidir = "$(SolutionDir)vendor/imgui" + imguidir = "%{wks.location}/vendor/imgui" + vs_include_dir = "$(SolutionDir)include" + include_dir = "%{wks.location}/include" + + configurations + { + "Debug", + "Release" + } + + project "snake" + language "C++" + cppdialect "C++20" + systemversion "latest" + kind "WindowedApp" + targetname "snake" + + files + { + "src/**.cpp", + "include/**.h", + "include/**.hpp", + "vendor/imgui/imgui.cpp", + "vendor/imgui/imgui_draw.cpp", + "vendor/imgui/imgui_tables.cpp", + "vendor/imgui/imgui_widgets.cpp", + "vendor/imgui/imgui-SFML.cpp" + } + + --visual studio-- + filter {"action:vs*", "system:windows"} + targetdir (vs_bindir) + objdir (vs_intdir) + debugdir "$(SolutionDir)" + includedirs + { + "src", + vs_include_dir, + vs_sfmldir .. "/include", + vs_imguidir + } + + libdirs {vs_sfmldir .."/lib"} + + --not visual studio -- + filter {"not action:vs*", "system:windows"} + targetdir (bindir) + objdir (intdir) + debugdir "%{wks.location}" + includedirs + { + "src", + include_dir, + sfmldir .. "/include", + imguidir + } + + libdirs {sfmldir .."/lib"} + + --windows specific settings-- + filter{"system:windows"} + defines {"PLATFORM_WINDOWS", "SFML_STATIC"} + staticruntime "on" + + filter {"system:windows", "configurations:debug"} + defines{"_DEBUG", "_CONSOLE"} + links + { + "sfml-main-d", + "sfml-graphics-s-d", + "sfml-window-s-d", + "opengl32", + "gdi32", + "freetyped", + "sfml-audio-s-d", + "flacd", + "vorbisfiled", + "vorbisd", + "oggd", + "sfml-system-s-d", + "winmm" + } + + filter {"system:windows", "configurations:release"} + defines{"NDEBUG"} + links + { + "sfml-main", + "sfml-graphics-s", + "sfml-window-s", + "opengl32", + "gdi32", + "freetype", + "sfml-audio-s", + "flac", + "vorbisfile", + "vorbis", + "ogg", + "sfml-system-s", + "winmm" + } + + + --linux specific settings-- + filter {"system:linux"} + defines {"PLATFORM_LINUX"} + targetdir (bindir) + objdir (intdir) + debugdir "%{wks.location}" + includedirs + { + "src", + include_dir, + imguidir + } + + links + { + "sfml-graphics", + "sfml-window", + "sfml-audio", + "sfml-system", + "OpenGL", + } + + + --config settings-- + filter "configurations:debug" + defines {"LOG_ENABLE", "GAME_DEBUG"} + symbols "on" + runtime "Debug" + warnings "Extra" + + filter "configurations:release" + defines {"GAME_RELEASE"} + optimize "Speed" + inlining "Auto" + symbols "off" + runtime "Release" \ No newline at end of file diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..3da1e02 --- /dev/null +++ b/run.sh @@ -0,0 +1,3 @@ +#! /bin/bash + +./bin/$1-linux-x86_64/breakout \ No newline at end of file diff --git a/src/Color.cpp b/src/Color.cpp new file mode 100644 index 0000000..09a461e --- /dev/null +++ b/src/Color.cpp @@ -0,0 +1,27 @@ +#include + +#include + +Color::Color(float r_in, float g_in, float b_in, float a_in = 1.0f) + : r(r_in) + , g(g_in) + , b(b_in) + , a(a_in) +{ } + +Color::Color(sf::Color color_in) + : r(color_in.r / 255.f) + , g(color_in.g / 255.f) + , b(color_in.b / 255.f) + , a(color_in.a / 255.f) +{ } + +sf::Color Color::sfml() +{ + return sf::Color{uint8_t(r * 255), uint8_t(g * 255), uint8_t(b * 255), uint8_t(a * 255)}; +} + +float* Color::imgui() +{ + return &r; +} diff --git a/src/Game.cpp b/src/Game.cpp new file mode 100644 index 0000000..e678188 --- /dev/null +++ b/src/Game.cpp @@ -0,0 +1,221 @@ +#include +#include + +#include + +#include +#include +#include + +#include +#include + + +Game::Game(bool useImgui_in) + : window({sf::VideoMode({ 1920u, 1080u }), "project-breakout"}) + , font("assets/fonts/ChakraPetch-Regular.ttf") + , lives(font) + , score(font) + , volume(10) + , useImgui(useImgui_in) +{ + + if (!ImGui::SFML::Init(window)) return; + + if (!parseConfigFile()) return; + + lives.setPosition({10, static_cast(window.getSize().y - 40)}); + score.setPosition({10, static_cast(window.getSize().y - 80)}); + + window.setFramerateLimit(framerate); + +} + +bool Game::parseConfigFile() +{ + std::ifstream configFile{"config/game-config.txt"}; + + if(!configFile) + { + std::cerr << "ERROR: CANNOT OPEN 'game-config.txt'\n"; + return false; + } + + std::string inputBuff; + while(configFile >> inputBuff) + { + + } + + return true; +} + +void Game::input() +{ + while (const std::optional event = window.pollEvent()) + { + ImGui::SFML::ProcessEvent(window, *event); + + if (event->is()) + { + window.close(); + } + + if (const auto* keyPressed = event->getIf()) + { + switch (keyPressed->scancode) + { + case sf::Keyboard::Scan::Escape: + window.close(); + break; + + case sf::Keyboard::Scan::Left: + case sf::Keyboard::Scan::A: + player.left = true; + break; + + case sf::Keyboard::Scan::Right: + case sf::Keyboard::Scan::D: + player.right = true; + break; + + case sf::Keyboard::Scan::Up: + case sf::Keyboard::Scan::W: + player.up = true; + break; + + case sf::Keyboard::Scan::Down: + case sf::Keyboard::Scan::S: + player.down = true; + break; + + case sf::Keyboard::Scan::R: + resetGame(); + break; + + default: + break; + } + } + + if (const auto* keyReleased = event->getIf()) + { + switch (keyReleased->scancode) + { + case sf::Keyboard::Scan::Left: + case sf::Keyboard::Scan::A: + player.left = false; + break; + + case sf::Keyboard::Scan::Right: + case sf::Keyboard::Scan::D: + player.right = false; + break; + + case sf::Keyboard::Scan::Up: + case sf::Keyboard::Scan::W: + player.up = false; + break; + + case sf::Keyboard::Scan::Down: + case sf::Keyboard::Scan::S: + player.down = false; + break; + + default: + break; + } + } + } +} + +void Game::collision() +{ + + +} + +void Game::movement() +{ + +} + +void Game::imgui() +{ + ImGui::SetNextWindowCollapsed(false, ImGuiCond_Once); + ImGui::SetNextWindowSize({490,375}, ImGuiCond_Once); + ImGui::SetNextWindowPos({26,29}, ImGuiCond_Once); + if(!ImGui::Begin("menu")) + { + ImGui::End(); + return; + } + ImGui::Text("Controls:"); + ImGui::Indent(); + ImGui::Text("A/D or arrow keys: move left and right"); + ImGui::Text("R: reset game"); + ImGui::Unindent(); + + if (ImGui::SliderFloat("Game Volume", &volume, 0, 100, "%.1f")) + { + + } + + + ImGui::End(); +} + +void Game::render() +{ + window.clear(); + + lives.setString("Lives: " + std::to_string(player.lives)); + score.setString("Score: " + std::to_string(player.score)); + + window.draw(lives); + window.draw(score); + + ImGui::SFML::Render(window); + + window.display(); +} + +void Game::soundSystem() +{ + +} + +void Game::scoreSystem() +{ + +} + +void Game::resetGame() +{ + +} + +void Game::run() +{ + while(window.isOpen()) + { + ImGui::SFML::Update(window, clock.restart()); + + input(); + + movement(); + + collision(); + + soundSystem(); + + scoreSystem(); + + imgui(); + + render(); + + } + + ImGui::SFML::Shutdown(); +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..bea0c7d --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,18 @@ +#include + +int main(int argc, char* argv[]) +{ + // parse command-line arguments + bool useImgui{true}; + for (int i = 0; i < argc; i++) + { + if (!strcmp(argv[i], "--noImgui")) + { + useImgui = false; + } + } + + Game game(useImgui); + + game.run(); +} \ No newline at end of file diff --git a/vendor/SFML/include/SFML/Audio.hpp b/vendor/SFML/include/SFML/Audio.hpp new file mode 100644 index 0000000..50668fd --- /dev/null +++ b/vendor/SFML/include/SFML/Audio.hpp @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +//////////////////////////////////////////////////////////// +/// \defgroup audio Audio module +/// +/// Sounds, streaming (musics or custom sources), recording, +/// spatialization. +/// +//////////////////////////////////////////////////////////// diff --git a/vendor/SFML/include/SFML/Audio/AudioResource.hpp b/vendor/SFML/include/SFML/Audio/AudioResource.hpp new file mode 100644 index 0000000..b75840c --- /dev/null +++ b/vendor/SFML/include/SFML/Audio/AudioResource.hpp @@ -0,0 +1,93 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#include + + +namespace sf +{ +//////////////////////////////////////////////////////////// +/// \brief Base class for classes that require an audio device +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API AudioResource +{ +public: + //////////////////////////////////////////////////////////// + /// \brief Copy constructor + /// + //////////////////////////////////////////////////////////// + AudioResource(const AudioResource&) = default; + + //////////////////////////////////////////////////////////// + /// \brief Copy assignment + /// + //////////////////////////////////////////////////////////// + AudioResource& operator=(const AudioResource&) = default; + + //////////////////////////////////////////////////////////// + /// \brief Move constructor + /// + //////////////////////////////////////////////////////////// + AudioResource(AudioResource&&) noexcept = default; + + //////////////////////////////////////////////////////////// + /// \brief Move assignment + /// + //////////////////////////////////////////////////////////// + AudioResource& operator=(AudioResource&&) noexcept = default; + +protected: + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + //////////////////////////////////////////////////////////// + AudioResource(); + +private: + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::shared_ptr m_device; //!< Sound device +}; + +} // namespace sf + + +//////////////////////////////////////////////////////////// +/// \class sf::AudioResource +/// \ingroup audio +/// +/// This class is for internal use only, it must be the base +/// of every class that requires a valid audio device in +/// order to work. +/// +//////////////////////////////////////////////////////////// diff --git a/vendor/SFML/include/SFML/Audio/Export.hpp b/vendor/SFML/include/SFML/Audio/Export.hpp new file mode 100644 index 0000000..4cf99c1 --- /dev/null +++ b/vendor/SFML/include/SFML/Audio/Export.hpp @@ -0,0 +1,44 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + + +//////////////////////////////////////////////////////////// +// Portable import / export macros +//////////////////////////////////////////////////////////// +#if defined(SFML_AUDIO_EXPORTS) + +#define SFML_AUDIO_API SFML_API_EXPORT + +#else + +#define SFML_AUDIO_API SFML_API_IMPORT + +#endif diff --git a/vendor/SFML/include/SFML/Audio/InputSoundFile.hpp b/vendor/SFML/include/SFML/Audio/InputSoundFile.hpp new file mode 100644 index 0000000..253ed63 --- /dev/null +++ b/vendor/SFML/include/SFML/Audio/InputSoundFile.hpp @@ -0,0 +1,336 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#include + +#include +#include +#include + +#include +#include + + +namespace sf +{ +class Time; +class InputStream; + +//////////////////////////////////////////////////////////// +/// \brief Provide read access to sound files +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API InputSoundFile +{ +public: + //////////////////////////////////////////////////////////// + /// \brief Default constructor + /// + /// Construct an input sound file that is not associated + /// with a file to read. + /// + //////////////////////////////////////////////////////////// + InputSoundFile() = default; + + //////////////////////////////////////////////////////////// + /// \brief Construct a sound file from the disk for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag, + /// it may not be properly removed, tag data will be treated as MP3 data + /// and there is a low chance of garbage decoded at the end of file. + /// See also: https://github.com/lieff/minimp3 + /// + /// \param filename Path of the sound file to load + /// + /// \throws sf::Exception if opening the file was unsuccessful + /// + //////////////////////////////////////////////////////////// + explicit InputSoundFile(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Construct a sound file in memory for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \throws sf::Exception if opening the file was unsuccessful + /// + //////////////////////////////////////////////////////////// + InputSoundFile(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Construct a sound file from a custom stream for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// \param stream Source stream to read from + /// + /// \throws sf::Exception if opening the file was unsuccessful + /// + //////////////////////////////////////////////////////////// + explicit InputSoundFile(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Open a sound file from the disk for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC, MP3. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// Because of minimp3_ex limitation, for MP3 files with big (>16kb) APEv2 tag, + /// it may not be properly removed, tag data will be treated as MP3 data + /// and there is a low chance of garbage decoded at the end of file. + /// See also: https://github.com/lieff/minimp3 + /// + /// \param filename Path of the sound file to load + /// + /// \return `true` if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] bool openFromFile(const std::filesystem::path& filename); + + //////////////////////////////////////////////////////////// + /// \brief Open a sound file in memory for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// \param data Pointer to the file data in memory + /// \param sizeInBytes Size of the data to load, in bytes + /// + /// \return `true` if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] bool openFromMemory(const void* data, std::size_t sizeInBytes); + + //////////////////////////////////////////////////////////// + /// \brief Open a sound file from a custom stream for reading + /// + /// The supported audio formats are: WAV (PCM only), OGG/Vorbis, FLAC. + /// The supported sample sizes for FLAC and WAV are 8, 16, 24 and 32 bit. + /// + /// \param stream Source stream to read from + /// + /// \return `true` if the file was successfully opened + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] bool openFromStream(InputStream& stream); + + //////////////////////////////////////////////////////////// + /// \brief Get the total number of audio samples in the file + /// + /// \return Number of samples + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] std::uint64_t getSampleCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the number of channels used by the sound + /// + /// \return Number of channels (1 = mono, 2 = stereo) + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] unsigned int getChannelCount() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the sample rate of the sound + /// + /// \return Sample rate, in samples per second + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] unsigned int getSampleRate() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the map of position in sample frame to sound channel + /// + /// This is used to map a sample in the sample stream to a + /// position during spatialization. + /// + /// \return Map of position in sample frame to sound channel + /// + /// \see `getSampleRate`, `getChannelCount`, `getDuration` + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] const std::vector& getChannelMap() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the total duration of the sound file + /// + /// This function is provided for convenience, the duration is + /// deduced from the other sound file attributes. + /// + /// \return Duration of the sound file + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] Time getDuration() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the read offset of the file in time + /// + /// \return Time position + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] Time getTimeOffset() const; + + //////////////////////////////////////////////////////////// + /// \brief Get the read offset of the file in samples + /// + /// \return Sample position + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] std::uint64_t getSampleOffset() const; + + //////////////////////////////////////////////////////////// + /// \brief Change the current read position to the given sample offset + /// + /// This function takes a sample offset to provide maximum + /// precision. If you need to jump to a given time, use the + /// other overload. + /// + /// The sample offset takes the channels into account. + /// If you have a time offset instead, you can easily find + /// the corresponding sample offset with the following formula: + /// `timeInSeconds * sampleRate * channelCount` + /// If the given offset exceeds to total number of samples, + /// this function jumps to the end of the sound file. + /// + /// \param sampleOffset Index of the sample to jump to, relative to the beginning + /// + //////////////////////////////////////////////////////////// + void seek(std::uint64_t sampleOffset); + + //////////////////////////////////////////////////////////// + /// \brief Change the current read position to the given time offset + /// + /// Using a time offset is handy but imprecise. If you need an accurate + /// result, consider using the overload which takes a sample offset. + /// + /// If the given time exceeds to total duration, this function jumps + /// to the end of the sound file. + /// + /// \param timeOffset Time to jump to, relative to the beginning + /// + //////////////////////////////////////////////////////////// + void seek(Time timeOffset); + + //////////////////////////////////////////////////////////// + /// \brief Read audio samples from the open file + /// + /// \param samples Pointer to the sample array to fill + /// \param maxCount Maximum number of samples to read + /// + /// \return Number of samples actually read (may be less than \a maxCount) + /// + //////////////////////////////////////////////////////////// + [[nodiscard]] std::uint64_t read(std::int16_t* samples, std::uint64_t maxCount); + + //////////////////////////////////////////////////////////// + /// \brief Close the current file + /// + //////////////////////////////////////////////////////////// + void close(); + +private: + //////////////////////////////////////////////////////////// + /// \brief Deleter for input streams that only conditionally deletes + /// + //////////////////////////////////////////////////////////// + struct SFML_AUDIO_API StreamDeleter + { + StreamDeleter(bool theOwned); + + // To accept ownership transfer from usual std::unique_ptr + template + StreamDeleter(const std::default_delete&); + + void operator()(InputStream* ptr) const; + + bool owned{true}; + }; + + //////////////////////////////////////////////////////////// + // Member data + //////////////////////////////////////////////////////////// + std::unique_ptr m_reader; //!< Reader that handles I/O on the file's format + std::unique_ptr m_stream{nullptr, false}; //!< Input stream used to access the file's data + std::uint64_t m_sampleOffset{}; //!< Sample Read Position + std::uint64_t m_sampleCount{}; //!< Total number of samples in the file + unsigned int m_sampleRate{}; //!< Number of samples per second + std::vector m_channelMap; //!< The map of position in sample frame to sound channel +}; + +} // namespace sf + + +//////////////////////////////////////////////////////////// +/// \class sf::InputSoundFile +/// \ingroup audio +/// +/// This class decodes audio samples from a sound file. It is +/// used internally by higher-level classes such as `sf::SoundBuffer` +/// and `sf::Music`, but can also be useful if you want to process +/// or analyze audio files without playing them, or if you want to +/// implement your own version of `sf::Music` with more specific +/// features. +/// +/// Usage example: +/// \code +/// // Open a sound file +/// sf::InputSoundFile file("music.ogg"); +/// +/// // Print the sound attributes +/// std::cout << "duration: " << file.getDuration().asSeconds() << '\n' +/// << "channels: " << file.getChannelCount() << '\n' +/// << "sample rate: " << file.getSampleRate() << '\n' +/// << "sample count: " << file.getSampleCount() << std::endl; +/// +/// // Read and process batches of samples until the end of file is reached +/// std::array samples; +/// std::uint64_t count; +/// do +/// { +/// count = file.read(samples.data(), samples.size()); +/// +/// // process, analyze, play, convert, or whatever +/// // you want to do with the samples... +/// } +/// while (count > 0); +/// \endcode +/// +/// \see `sf::SoundFileReader`, `sf::OutputSoundFile` +/// +//////////////////////////////////////////////////////////// diff --git a/vendor/SFML/include/SFML/Audio/Listener.hpp b/vendor/SFML/include/SFML/Audio/Listener.hpp new file mode 100644 index 0000000..475b366 --- /dev/null +++ b/vendor/SFML/include/SFML/Audio/Listener.hpp @@ -0,0 +1,234 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#include +#include + + +//////////////////////////////////////////////////////////// +/// \brief The audio listener is the point in the scene +/// from where all the sounds are heard +/// +//////////////////////////////////////////////////////////// +namespace sf::Listener +{ +//////////////////////////////////////////////////////////// +/// \brief Structure defining the properties of a directional cone +/// +/// Sounds will play at gain 1 when they are positioned +/// within the inner angle of the cone. Sounds will play +/// at `outerGain` when they are positioned outside the +/// outer angle of the cone. The gain declines linearly +/// from 1 to `outerGain` as the sound moves from the inner +/// angle to the outer angle. +/// +//////////////////////////////////////////////////////////// +struct Cone +{ + Angle innerAngle; //!< Inner angle + Angle outerAngle; //!< Outer angle + float outerGain{}; //!< Outer gain +}; + +//////////////////////////////////////////////////////////// +/// \brief Change the global volume of all the sounds and musics +/// +/// `volume` is a number between 0 and 100; it is combined +/// with the individual volume of each sound / music. +/// The default value for the volume is 100 (maximum). +/// +/// \param volume New global volume, in the range [0, 100] +/// +/// \see `getGlobalVolume` +/// +//////////////////////////////////////////////////////////// +SFML_AUDIO_API void setGlobalVolume(float volume); + +//////////////////////////////////////////////////////////// +/// \brief Get the current value of the global volume +/// +/// \return Current global volume, in the range [0, 100] +/// +/// \see `setGlobalVolume` +/// +//////////////////////////////////////////////////////////// +[[nodiscard]] SFML_AUDIO_API float getGlobalVolume(); + +//////////////////////////////////////////////////////////// +/// \brief Set the position of the listener in the scene +/// +/// The default listener's position is (0, 0, 0). +/// +/// \param position New listener's position +/// +/// \see `getPosition`, `setDirection` +/// +//////////////////////////////////////////////////////////// +SFML_AUDIO_API void setPosition(const Vector3f& position); + +//////////////////////////////////////////////////////////// +/// \brief Get the current position of the listener in the scene +/// +/// \return Listener's position +/// +/// \see `setPosition` +/// +//////////////////////////////////////////////////////////// +[[nodiscard]] SFML_AUDIO_API Vector3f getPosition(); + +//////////////////////////////////////////////////////////// +/// \brief Set the forward vector of the listener in the scene +/// +/// The direction (also called "at vector") is the vector +/// pointing forward from the listener's perspective. Together +/// with the up vector, it defines the 3D orientation of the +/// listener in the scene. The direction vector doesn't +/// have to be normalized. +/// The default listener's direction is (0, 0, -1). +/// +/// \param direction New listener's direction +/// +/// \see `getDirection`, `setUpVector`, `setPosition` +/// +//////////////////////////////////////////////////////////// +SFML_AUDIO_API void setDirection(const Vector3f& direction); + +//////////////////////////////////////////////////////////// +/// \brief Get the current forward vector of the listener in the scene +/// +/// \return Listener's forward vector (not normalized) +/// +/// \see `setDirection` +/// +//////////////////////////////////////////////////////////// +[[nodiscard]] SFML_AUDIO_API Vector3f getDirection(); + +//////////////////////////////////////////////////////////// +/// \brief Set the velocity of the listener in the scene +/// +/// The default listener's velocity is (0, 0, -1). +/// +/// \param velocity New listener's velocity +/// +/// \see `getVelocity`, `getDirection`, `setUpVector`, `setPosition` +/// +//////////////////////////////////////////////////////////// +SFML_AUDIO_API void setVelocity(const Vector3f& velocity); + +//////////////////////////////////////////////////////////// +/// \brief Get the current forward vector of the listener in the scene +/// +/// \return Listener's velocity +/// +/// \see `setVelocity` +/// +//////////////////////////////////////////////////////////// +[[nodiscard]] SFML_AUDIO_API Vector3f getVelocity(); + +//////////////////////////////////////////////////////////// +/// \brief Set the cone properties of the listener in the audio scene +/// +/// The cone defines how directional attenuation is applied. +/// The default cone of a sound is (2 * PI, 2 * PI, 1). +/// +/// \param cone Cone properties of the listener in the scene +/// +/// \see `getCone` +/// +//////////////////////////////////////////////////////////// +SFML_AUDIO_API void setCone(const Listener::Cone& cone); + +//////////////////////////////////////////////////////////// +/// \brief Get the cone properties of the listener in the audio scene +/// +/// \return Cone properties of the listener +/// +/// \see `setCone` +/// +//////////////////////////////////////////////////////////// +[[nodiscard]] SFML_AUDIO_API Listener::Cone getCone(); + +//////////////////////////////////////////////////////////// +/// \brief Set the upward vector of the listener in the scene +/// +/// The up vector is the vector that points upward from the +/// listener's perspective. Together with the direction, it +/// defines the 3D orientation of the listener in the scene. +/// The up vector doesn't have to be normalized. +/// The default listener's up vector is (0, 1, 0). It is usually +/// not necessary to change it, especially in 2D scenarios. +/// +/// \param upVector New listener's up vector +/// +/// \see `getUpVector`, `setDirection`, `setPosition` +/// +//////////////////////////////////////////////////////////// +SFML_AUDIO_API void setUpVector(const Vector3f& upVector); + +//////////////////////////////////////////////////////////// +/// \brief Get the current upward vector of the listener in the scene +/// +/// \return Listener's upward vector (not normalized) +/// +/// \see `setUpVector` +/// +//////////////////////////////////////////////////////////// +[[nodiscard]] SFML_AUDIO_API Vector3f getUpVector(); +} // namespace sf::Listener + + +//////////////////////////////////////////////////////////// +/// \namespace sf::Listener +/// \ingroup audio +/// +/// The audio listener defines the global properties of the +/// audio environment, it defines where and how sounds and musics +/// are heard. If `sf::View` is the eyes of the user, then +/// `sf::Listener` are their ears (by the way, they are often linked +/// together -- same position, orientation, etc.). +/// +/// `sf::Listener` is a simple interface, which allows to setup the +/// listener in the 3D audio environment (position, direction and +/// up vector), and to adjust the global volume. +/// +/// Usage example: +/// \code +/// // Move the listener to the position (1, 0, -5) +/// sf::Listener::setPosition({1, 0, -5}); +/// +/// // Make it face the right axis (1, 0, 0) +/// sf::Listener::setDirection({1, 0, 0}); +/// +/// // Reduce the global volume +/// sf::Listener::setGlobalVolume(50); +/// \endcode +/// +//////////////////////////////////////////////////////////// diff --git a/vendor/SFML/include/SFML/Audio/Music.hpp b/vendor/SFML/include/SFML/Audio/Music.hpp new file mode 100644 index 0000000..c60acda --- /dev/null +++ b/vendor/SFML/include/SFML/Audio/Music.hpp @@ -0,0 +1,377 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2025 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include + +#include + +#include +#include +#include + +#include +#include + + +namespace sf +{ +class Time; +class InputStream; +class InputSoundFile; + +//////////////////////////////////////////////////////////// +/// \brief Streamed music played from an audio file +/// +//////////////////////////////////////////////////////////// +class SFML_AUDIO_API Music : public SoundStream +{ +public: + //////////////////////////////////////////////////////////// + /// \brief Structure defining a time range using the template type + /// + //////////////////////////////////////////////////////////// + template + struct Span + { + T offset{}; //!< The beginning offset of the time range + T length{}; //!< The length of the time range + }; + + // Associated `Span` type + using TimeSpan = Span