Setup main game frame, initial assets and files.

main
sigonasr2 3 months ago
parent 278edfcb2b
commit e6ba1e88c7
  1. 5
      .gitignore
  2. 184
      ALL_BUILD.vcxproj
  3. 8
      ALL_BUILD.vcxproj.filters
  4. 343
      CMakeCache.txt
  5. 4
      CMakeLists.txt
  6. 178
      ZERO_CHECK.vcxproj
  7. 13
      ZERO_CHECK.vcxproj.filters
  8. BIN
      assets/border.png
  9. BIN
      assets/gametiles.png
  10. BIN
      assets/toybox32-1x.png
  11. 0
      bin/assets/.keepme
  12. BIN
      bin/hamster.exe
  13. BIN
      bin/hamster.pdb
  14. BIN
      border.png
  15. 44
      cmake_install.cmake
  16. BIN
      concept.png
  17. 623
      copy_data.vcxproj
  18. 29
      copy_data.vcxproj.filters
  19. 67
      hamster.sln
  20. 371
      hamster.vcxproj
  21. 62
      hamster.vcxproj.filters
  22. 4
      hamster.vcxproj.user
  23. 2
      src/CREDITS.txt
  24. 35
      src/HamsterGame.cpp
  25. 57
      src/HamsterGame.h
  26. 2
      src/TODO.txt
  27. 364
      src/main.cpp
  28. 0
      src/miniaudio.h
  29. 0
      src/olcPGEX_MiniAudio.h
  30. 722
      src/olcPGEX_ViewPort.h
  31. 4
      src/olcPixelGameEngine.cpp
  32. 13503
      src/olcPixelGameEngine.h
  33. 221
      src/olcUTIL_Animate2D.h
  34. 2535
      src/olcUTIL_Geometry2D.h

5
.gitignore vendored

@ -6,3 +6,8 @@ mingw-build
vs-build
.vscode
.cache
/.vs/hamster/v17
/.vs/hamster/FileContentIndex
/CMakeFiles
/hamster.dir/Debug
/x64/Debug

File diff suppressed because one or more lines are too long

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
</Project>

@ -0,0 +1,343 @@
# This is the CMakeCache file.
# For build in directory: c:/Users/sigon/source/repos/hamster
# It was generated by CMake: C:/Program Files/CMake/bin/cmake.exe
# You can edit this file to change values found and used by cmake.
# If you do not want to change any of the values, simply exit the editor.
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
# KEY is the name of a variable in the cache.
# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
########################
# EXTERNAL cache entries
########################
//Path to a program.
CMAKE_AR:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/bin/Hostx64/x64/lib.exe
//Semicolon separated list of supported configuration types, only
// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything
// else will be ignored.
CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo
//Flags used by the CXX compiler during all build types.
CMAKE_CXX_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 /GR /EHsc
//Flags used by the CXX compiler during DEBUG builds.
CMAKE_CXX_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1
//Flags used by the CXX compiler during MINSIZEREL builds.
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG
//Flags used by the CXX compiler during RELEASE builds.
CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG
//Flags used by the CXX compiler during RELWITHDEBINFO builds.
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG
//Libraries linked by default with all C++ applications.
CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
//Flags used by the C compiler during all build types.
CMAKE_C_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3
//Flags used by the C compiler during DEBUG builds.
CMAKE_C_FLAGS_DEBUG:STRING=/MDd /Zi /Ob0 /Od /RTC1
//Flags used by the C compiler during MINSIZEREL builds.
CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG
//Flags used by the C compiler during RELEASE builds.
CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DNDEBUG
//Flags used by the C compiler during RELWITHDEBINFO builds.
CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /Zi /O2 /Ob1 /DNDEBUG
//Libraries linked by default with all C applications.
CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib
//Flags used by the linker during all build types.
CMAKE_EXE_LINKER_FLAGS:STRING=/machine:x64
//Flags used by the linker during DEBUG builds.
CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
//Flags used by the linker during MINSIZEREL builds.
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
//Flags used by the linker during RELEASE builds.
CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
//Flags used by the linker during RELWITHDEBINFO builds.
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
//Value Computed by CMake.
CMAKE_FIND_PACKAGE_REDIRECTS_DIR:STATIC=C:/Users/sigon/source/repos/hamster/CMakeFiles/pkgRedirects
//Install path prefix, prepended onto install directories.
CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/hamster
//Path to a program.
CMAKE_LINKER:FILEPATH=C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/bin/Hostx64/x64/link.exe
//Flags used by the linker during the creation of modules during
// all build types.
CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:x64
//Flags used by the linker during the creation of modules during
// DEBUG builds.
CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
//Flags used by the linker during the creation of modules during
// MINSIZEREL builds.
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
//Flags used by the linker during the creation of modules during
// RELEASE builds.
CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
//Flags used by the linker during the creation of modules during
// RELWITHDEBINFO builds.
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
//Path to a program.
CMAKE_MT:FILEPATH=CMAKE_MT-NOTFOUND
//Value Computed by CMake
CMAKE_PROJECT_DESCRIPTION:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_HOMEPAGE_URL:STATIC=
//Value Computed by CMake
CMAKE_PROJECT_NAME:STATIC=hamster
//RC compiler
CMAKE_RC_COMPILER:FILEPATH=rc
//Flags for Windows Resource Compiler during all build types.
CMAKE_RC_FLAGS:STRING=-DWIN32
//Flags for Windows Resource Compiler during DEBUG builds.
CMAKE_RC_FLAGS_DEBUG:STRING=-D_DEBUG
//Flags for Windows Resource Compiler during MINSIZEREL builds.
CMAKE_RC_FLAGS_MINSIZEREL:STRING=
//Flags for Windows Resource Compiler during RELEASE builds.
CMAKE_RC_FLAGS_RELEASE:STRING=
//Flags for Windows Resource Compiler during RELWITHDEBINFO builds.
CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING=
//Flags used by the linker during the creation of shared libraries
// during all build types.
CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:x64
//Flags used by the linker during the creation of shared libraries
// during DEBUG builds.
CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING=/debug /INCREMENTAL
//Flags used by the linker during the creation of shared libraries
// during MINSIZEREL builds.
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO
//Flags used by the linker during the creation of shared libraries
// during RELEASE builds.
CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO
//Flags used by the linker during the creation of shared libraries
// during RELWITHDEBINFO builds.
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING=/debug /INCREMENTAL
//If set, runtime paths are not added when installing shared libraries,
// but are added when building.
CMAKE_SKIP_INSTALL_RPATH:BOOL=NO
//If set, runtime paths are not added when using shared libraries.
CMAKE_SKIP_RPATH:BOOL=NO
//Flags used by the linker during the creation of static libraries
// during all build types.
CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:x64
//Flags used by the linker during the creation of static libraries
// during DEBUG builds.
CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING=
//Flags used by the linker during the creation of static libraries
// during MINSIZEREL builds.
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING=
//Flags used by the linker during the creation of static libraries
// during RELEASE builds.
CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING=
//Flags used by the linker during the creation of static libraries
// during RELWITHDEBINFO builds.
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING=
//If this value is on, makefiles will be generated without the
// .SILENT directive, and all commands will be echoed to the console
// during the make. This is useful for debugging only. With Visual
// Studio IDE projects all commands are done without /nologo.
CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE
//Show a terminal window for STDOUT/STDERR
HAS_TERMINAL:BOOL=ON
//OpenGL library for win32
OPENGL_gl_LIBRARY:STRING=opengl32
//GLU library for win32
OPENGL_glu_LIBRARY:STRING=glu32
//Value Computed by CMake
hamster_BINARY_DIR:STATIC=C:/Users/sigon/source/repos/hamster
//Value Computed by CMake
hamster_IS_TOP_LEVEL:STATIC=ON
//Value Computed by CMake
hamster_SOURCE_DIR:STATIC=C:/Users/sigon/source/repos/hamster
########################
# INTERNAL cache entries
########################
//ADVANCED property for variable: CMAKE_AR
CMAKE_AR-ADVANCED:INTERNAL=1
//This is the directory where this CMakeCache.txt was created
CMAKE_CACHEFILE_DIR:INTERNAL=c:/Users/sigon/source/repos/hamster
//Major version of cmake used to create the current loaded cache
CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3
//Minor version of cmake used to create the current loaded cache
CMAKE_CACHE_MINOR_VERSION:INTERNAL=27
//Patch version of cmake used to create the current loaded cache
CMAKE_CACHE_PATCH_VERSION:INTERNAL=9
//Path to CMake executable.
CMAKE_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cmake.exe
//Path to cpack program executable.
CMAKE_CPACK_COMMAND:INTERNAL=C:/Program Files/CMake/bin/cpack.exe
//Path to ctest program executable.
CMAKE_CTEST_COMMAND:INTERNAL=C:/Program Files/CMake/bin/ctest.exe
//ADVANCED property for variable: CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES
CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS
CMAKE_C_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES
CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1
//Executable file format
CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG
CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL
CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE
CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//Name of external makefile project generator.
CMAKE_EXTRA_GENERATOR:INTERNAL=
//Name of generator.
CMAKE_GENERATOR:INTERNAL=Visual Studio 17 2022
//Generator instance identifier.
CMAKE_GENERATOR_INSTANCE:INTERNAL=C:/Program Files/Microsoft Visual Studio/2022/Community
//Name of generator platform.
CMAKE_GENERATOR_PLATFORM:INTERNAL=
//Name of generator toolset.
CMAKE_GENERATOR_TOOLSET:INTERNAL=
//Source directory with the top level CMakeLists.txt file for this
// project
CMAKE_HOME_DIRECTORY:INTERNAL=C:/Users/sigon/source/repos/hamster
//ADVANCED property for variable: CMAKE_LINKER
CMAKE_LINKER-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG
CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL
CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE
CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_MT
CMAKE_MT-ADVANCED:INTERNAL=1
//number of local generators
CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1
//Platform information initialized
CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1
//noop for ranlib
CMAKE_RANLIB:INTERNAL=:
//ADVANCED property for variable: CMAKE_RC_COMPILER
CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1
CMAKE_RC_COMPILER_WORKS:INTERNAL=1
//ADVANCED property for variable: CMAKE_RC_FLAGS
CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_RC_FLAGS_DEBUG
CMAKE_RC_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_RC_FLAGS_MINSIZEREL
CMAKE_RC_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_RC_FLAGS_RELEASE
CMAKE_RC_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_RC_FLAGS_RELWITHDEBINFO
CMAKE_RC_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//Path to CMake installation.
CMAKE_ROOT:INTERNAL=C:/Program Files/CMake/share/cmake-3.27
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL
CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE
CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH
CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_SKIP_RPATH
CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS
CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG
CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL
CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE
CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
//Details about finding OpenGL
FIND_PACKAGE_MESSAGE_DETAILS_OpenGL:INTERNAL=[opengl32][c ][v()]
//ADVANCED property for variable: OPENGL_gl_LIBRARY
OPENGL_gl_LIBRARY-ADVANCED:INTERNAL=1
//ADVANCED property for variable: OPENGL_glu_LIBRARY
OPENGL_glu_LIBRARY-ADVANCED:INTERNAL=1

@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.10)
#
# - dictates the output executable filename
#
project(TestApp)
project(hamster)
# Options you can set via command-line
option(HAS_TERMINAL "Show a terminal window for STDOUT/STDERR" ON)
@ -23,7 +23,7 @@ set(C_CXX_SOURCES_DIR "src")
#
# - the place where your C/C++ header files are located
#
set(C_CXX_HEADERS_DIR "include")
set(C_CXX_HEADERS_DIR "src")
#
# ASSETS_DIR

File diff suppressed because one or more lines are too long

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\CMakeFiles\842494a5b997e5d0cebd893a59fb5c26\generate.stamp.rule">
<Filter>CMake Rules</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Filter Include="CMake Rules">
<UniqueIdentifier>{DEE93F1C-04AD-3911-921D-46CA9A729E43}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

@ -0,0 +1,44 @@
# Install script for directory: C:/Users/sigon/source/repos/hamster
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/hamster")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "Release")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
if(CMAKE_INSTALL_COMPONENT)
set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt")
else()
set(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
endif()
string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT
"${CMAKE_INSTALL_MANIFEST_FILES}")
file(WRITE "C:/Users/sigon/source/repos/hamster/${CMAKE_INSTALL_MANIFEST}"
"${CMAKE_INSTALL_MANIFEST_CONTENT}")

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\.keepme" />
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\gfx\space.png">
<Filter>Resources</Filter>
</CustomBuild>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\sounds\Explosions1.wav" />
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\sounds\Laser_Shoot11.wav" />
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\sounds\bg-music.wav" />
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\sounds\lose9.wav" />
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\assets\sounds\thruster.wav" />
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\CMakeFiles\842494a5b997e5d0cebd893a59fb5c26\copy_data.rule">
<Filter>CMake Rules</Filter>
</CustomBuild>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<None Include="C:\Users\sigon\source\repos\hamster\CMakeFiles\copy_data" />
</ItemGroup>
<ItemGroup>
<Filter Include="CMake Rules">
<UniqueIdentifier>{DEE93F1C-04AD-3911-921D-46CA9A729E43}</UniqueIdentifier>
</Filter>
<Filter Include="Resources">
<UniqueIdentifier>{25EDBADE-2AB6-3C5C-A37D-62093F6FECF3}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

@ -0,0 +1,67 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hamster", "hamster.vcxproj", "{BE0D490D-4C46-3C09-AC76-396388C3D6FF}"
ProjectSection(ProjectDependencies) = postProject
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B} = {A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}
{CC963984-4384-3CCA-8B91-8A023E4392E9} = {CC963984-4384-3CCA-8B91-8A023E4392E9}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{78DD63E2-85EA-3547-BDC5-9E417448DDE3}"
ProjectSection(ProjectDependencies) = postProject
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B} = {A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}
{BE0D490D-4C46-3C09-AC76-396388C3D6FF} = {BE0D490D-4C46-3C09-AC76-396388C3D6FF}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "ZERO_CHECK.vcxproj", "{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "copy_data", "copy_data.vcxproj", "{CC963984-4384-3CCA-8B91-8A023E4392E9}"
ProjectSection(ProjectDependencies) = postProject
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B} = {A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
MinSizeRel|x64 = MinSizeRel|x64
RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.Debug|x64.ActiveCfg = Debug|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.Debug|x64.Build.0 = Debug|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.Release|x64.ActiveCfg = Release|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.Release|x64.Build.0 = Release|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{BE0D490D-4C46-3C09-AC76-396388C3D6FF}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{78DD63E2-85EA-3547-BDC5-9E417448DDE3}.Debug|x64.ActiveCfg = Debug|x64
{78DD63E2-85EA-3547-BDC5-9E417448DDE3}.Release|x64.ActiveCfg = Release|x64
{78DD63E2-85EA-3547-BDC5-9E417448DDE3}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{78DD63E2-85EA-3547-BDC5-9E417448DDE3}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.Debug|x64.ActiveCfg = Debug|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.Debug|x64.Build.0 = Debug|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.Release|x64.ActiveCfg = Release|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.Release|x64.Build.0 = Release|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{A1B2CDDF-E4C4-3CD3-ABD9-9EB877441F5B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.Debug|x64.ActiveCfg = Debug|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.Debug|x64.Build.0 = Debug|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.Release|x64.ActiveCfg = Release|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.Release|x64.Build.0 = Release|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{CC963984-4384-3CCA-8B91-8A023E4392E9}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FB9AF13F-7949-3C63-A714-F817C6CA15B9}
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

File diff suppressed because one or more lines are too long

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="17.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="src\HamsterGame.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="C:\Users\sigon\source\repos\hamster\src\olcPGEX_MiniAudio.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="C:\Users\sigon\source\repos\hamster\src\olcPixelGameEngine.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="C:\Users\sigon\source\repos\hamster\CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{6FA4D8BB-23B0-3494-9ED3-B7DCE970FEDF}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{7d02a2cb-d3b1-4576-813d-9a586e6aedd3}</UniqueIdentifier>
</Filter>
<Filter Include="Documentation">
<UniqueIdentifier>{ecbaa59b-6b75-4ab7-ab55-985bbd1e800c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\miniaudio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\olcPGEX_MiniAudio.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\olcPixelGameEngine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="olcUTIL_Geometry2D.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\olcPGEX_ViewPort.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\olcUTIL_Geometry2D.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\HamsterGame.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\olcUTIL_Animate2D.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="src\TODO.txt">
<Filter>Documentation</Filter>
</Text>
<Text Include="src\CREDITS.txt">
<Filter>Documentation</Filter>
</Text>
</ItemGroup>
</Project>

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

@ -0,0 +1,2 @@
Author:
Legend of Pocket Monsters - Chad Wolfe <https://opengameart.org/content/200-tileset-legend-of-pocket-monsters>

@ -0,0 +1,35 @@
#include "HamsterGame.h"
geom2d::rect<float>HamsterGame::SCREEN_FRAME{{96,0},{320,288}};
HamsterGame::HamsterGame()
{
sAppName = "Project Hamster";
}
bool HamsterGame::OnUserCreate(){
LoadAnimations();
return true;
}
bool HamsterGame::OnUserUpdate(float fElapsedTime){
DrawDecal({},
gameWindow.FillRectDecal({},{150.f,150.f},WHITE);
return true;
}
bool HamsterGame::OnUserDestroy(){
return true;
}
int main()
{
HamsterGame game;
if(game.Construct(512, 288, 2, 2))
game.Start();
return 0;
}

@ -0,0 +1,57 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
#include <unordered_map>
#include "olcUTIL_Geometry2D.h"
#include "olcUTIL_Animate2D.h"
#include "olcPGEX_ViewPort.h"
class HamsterGame : public olc::PixelGameEngine
{
public:
HamsterGame();
static geom2d::rect<float>SCREEN_FRAME;
static std::unordered_map<std::string,Animate2D::Animation<int>>ANIMATIONS;
const ViewPort gameWindow{{SCREEN_FRAME.pos,SCREEN_FRAME.pos+vf2d{0.f,SCREEN_FRAME.size.y},SCREEN_FRAME.pos+SCREEN_FRAME.size,SCREEN_FRAME.pos+vf2d{SCREEN_FRAME.size.x,0.f}},{96,0}};
public:
bool OnUserCreate()override final;
bool OnUserUpdate(float fElapsedTime)override final;
bool OnUserDestroy()override final;
private:
void LoadAnimations();
};

@ -0,0 +1,2 @@
olcPGEX_ViewPort - Submit a PR where the offset is subtracted instead of added to determine clip region cutoffs.

@ -1,364 +0,0 @@
#include "olcPixelGameEngine.h"
#include "olcPGEX_MiniAudio.h"
class OneLoneCoder_Asteroids : public olc::PixelGameEngine
{
public:
OneLoneCoder_Asteroids()
{
sAppName = "Asteroids";
}
private:
struct sSpaceObject
{
int nSize;
float x;
float y;
float dx;
float dy;
float angle;
};
std::vector<sSpaceObject> vecAsteroids;
std::vector<sSpaceObject> vecBullets;
sSpaceObject player;
bool bDead = false;
int nScore = 0;
std::vector<std::pair<float, float>> vecModelShip;
std::vector<std::pair<float, float>> vecModelAsteroid;
std::map<std::string, olc::Renderable*> gfx;
std::map<std::string, int> sfx;
olc::MiniAudio audio;
public:
bool OnUserCreate() override
{
auto loadGraphic = [&](const std::string& key, const std::string& filepath)
{
olc::Renderable* renderable = new olc::Renderable();
renderable->Load(filepath);
gfx[key] = renderable;
};
auto loadSound = [&](const std::string& key, const std::string& filepath)
{
sfx[key] = audio.LoadSound(filepath);
};
loadGraphic("background", "assets/gfx/space.png");
loadSound("bg-music", "assets/sounds/bg-music.wav");
loadSound("laser", "assets/sounds/Laser_Shoot11.wav");
loadSound("explosion", "assets/sounds/Explosions1.wav");
loadSound("lose", "assets/sounds/lose9.wav");
loadSound("thruster", "assets/sounds/thruster.wav");
vecModelShip =
{
{ 0.0f, -5.0f},
{-2.5f, +2.5f},
{+2.5f, +2.5f}
}; // A simple Isoceles Triangle
// Create a "jagged" circle for the asteroid. It's important it remains
// mostly circular, as we do a simple collision check against a perfect
// circle.
int verts = 20;
for (int i = 0; i < verts; i++)
{
float noise = (float)rand() / (float)RAND_MAX * 0.4f + 0.8f;
vecModelAsteroid.push_back(std::make_pair(noise * sinf(((float)i / (float)verts) * 6.28318f),
noise * cosf(((float)i / (float)verts) * 6.28318f)));
}
backgroundLayer = CreateLayer();
EnableLayer(backgroundLayer, true);
SetDrawTarget(backgroundLayer);
DrawSprite(0,0, gfx.at("background")->Sprite());
SetDrawTarget(nullptr);
ResetGame();
audio.Play(sfx.at("bg-music"), true);
return true;
}
bool OnUserDestroy() override
{
for(auto it = gfx.begin(); it != gfx.end(); ++it)
{
delete it->second;
}
return true;
}
int backgroundLayer = -1;
void ResetGame()
{
// Initialise Player Position
player.x = ScreenWidth() / 2.0f;
player.y = ScreenHeight() / 2.0f;
player.dx = 0.0f;
player.dy = 0.0f;
player.angle = 0.0f;
vecBullets.clear();
vecAsteroids.clear();
// Put in two asteroids
vecAsteroids.push_back({ (int)16, player.x - 80.0f, player.y, 10.0f, 40.0f, 0.0f });
vecAsteroids.push_back({ (int)16, player.x + 80.0f, player.y, -10.0f, -40.0f, 0.0f });
// Reset game
bDead = false;
nScore = false;
}
// Implements "wrap around" for various in-game sytems
void WrapCoordinates(float ix, float iy, float &ox, float &oy)
{
ox = ix;
oy = iy;
if (ix < 0.0f) ox = ix + (float)ScreenWidth();
if (ix >= (float)ScreenWidth()) ox = ix - (float)ScreenWidth();
if (iy < 0.0f) oy = iy + (float)ScreenHeight();
if (iy >= (float)ScreenHeight()) oy = iy - (float)ScreenHeight();
}
// Overriden to handle toroidal drawing routines
bool Draw(int x, int y, olc::Pixel col = olc::WHITE) override
{
float fx, fy;
WrapCoordinates(x, y, fx, fy);
return olc::PixelGameEngine::Draw(fx, fy, col);
}
bool IsPointInsideCircle(float cx, float cy, float radius, float x, float y)
{
return sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)) < radius;
}
// Called by olcConsoleGameEngine
bool OnUserUpdate(float fElapsedTime) override
{
if (bDead)
ResetGame();
// Clear Screen
Clear(olc::BLANK);
// Steer Ship
if (GetKey(olc::LEFT).bHeld)
player.angle -= 5.0f * fElapsedTime;
if (GetKey(olc::RIGHT).bHeld)
player.angle += 5.0f * fElapsedTime;
// Thrust? Apply ACCELERATION
if (GetKey(olc::UP).bHeld)
{
// ACCELERATION changes VELOCITY (with respect to time)
player.dx += sin(player.angle) * 20.0f * fElapsedTime;
player.dy += -cos(player.angle) * 20.0f * fElapsedTime;
}
if(GetKey(olc::UP).bPressed)
audio.Play(sfx.at("thruster"), true);
if(GetKey(olc::UP).bReleased)
audio.Stop(sfx.at("thruster"));
// VELOCITY changes POSITION (with respect to time)
player.x += player.dx * fElapsedTime;
player.y += player.dy * fElapsedTime;
// Keep ship in gamespace
WrapCoordinates(player.x, player.y, player.x, player.y);
// Check ship collision with asteroids
for (auto &a : vecAsteroids)
if (IsPointInsideCircle(a.x, a.y, a.nSize, player.x, player.y))
{
bDead = true; // Uh oh...
audio.Play(sfx.at("lose"));
}
// Fire Bullet in direction of player
if (GetKey(olc::SPACE).bReleased)
{
vecBullets.push_back({ 0, player.x, player.y, 150.0f * sinf(player.angle), -150.0f * cosf(player.angle), 100.0f });
audio.Play(sfx.at("laser"));
}
// Update and draw asteroids
for (auto &a : vecAsteroids)
{
// VELOCITY changes POSITION (with respect to time)
a.x += a.dx * fElapsedTime;
a.y += a.dy * fElapsedTime;
a.angle += 0.5f * fElapsedTime; // Add swanky rotation :)
// Asteroid coordinates are kept in game space (toroidal mapping)
WrapCoordinates(a.x, a.y, a.x, a.y);
// Draw Asteroids
DrawWireFrameModel(vecModelAsteroid, a.x, a.y, a.angle, (float)a.nSize, olc::YELLOW);
}
// Any new asteroids created after collision detection are stored
// in a temporary vector, so we don't interfere with the asteroids
// vector iterator in the for(auto)
std::vector<sSpaceObject> newAsteroids;
// Update Bullets
for (auto &b : vecBullets)
{
b.x += b.dx * fElapsedTime;
b.y += b.dy * fElapsedTime;
WrapCoordinates(b.x, b.y, b.x, b.y);
b.angle -= 1.0f * fElapsedTime;
// Check collision with asteroids
for (auto &a : vecAsteroids)
{
//if (IsPointInsideRectangle(a.x, a.y, a.x + a.nSize, a.y + a.nSize, b.x, b.y))
if(IsPointInsideCircle(a.x, a.y, a.nSize, b.x, b.y))
{
// Asteroid Hit - Remove bullet
// We've already updated the bullets, so force bullet to be offscreen
// so it is cleaned up by the removal algorithm.
b.x = -100;
// Create child asteroids
if (a.nSize > 4)
{
float angle1 = ((float)rand() / (float)RAND_MAX) * 6.283185f;
float angle2 = ((float)rand() / (float)RAND_MAX) * 6.283185f;
newAsteroids.push_back({ (int)a.nSize >> 1 ,a.x, a.y, 30.0f * sinf(angle1), 30.0f * cosf(angle1), 0.0f });
newAsteroids.push_back({ (int)a.nSize >> 1 ,a.x, a.y, 30.0f * sinf(angle2), 30.0f * cosf(angle2), 0.0f });
}
// Remove asteroid - Same approach as bullets
a.x = -100;
nScore += 100; // Small score increase for hitting asteroid
audio.Play(sfx.at("explosion"));
}
}
}
// Append new asteroids to existing vector
for(auto a:newAsteroids)
vecAsteroids.push_back(a);
// Clear up dead objects - They are out of game space
// Remove asteroids that have been blown up
if (vecAsteroids.size() > 0)
{
auto i = remove_if(vecAsteroids.begin(), vecAsteroids.end(), [&](sSpaceObject o) { return (o.x < 0); });
if (i != vecAsteroids.end())
vecAsteroids.erase(i);
}
if (vecAsteroids.empty()) // If no asteroids, level complete! :) - you win MORE asteroids!
{
// Level Clear
nScore += 1000; // Large score for level progression
vecAsteroids.clear();
vecBullets.clear();
// Add two new asteroids, but in a place where the player is not, we'll simply
// add them 90 degrees left and right to the player, their coordinates will
// be wrapped by th enext asteroid update
vecAsteroids.push_back({ (int)16, 80.0f * sinf(player.angle - 3.14159f/2.0f) + player.x,
80.0f * cosf(player.angle - 3.14159f/2.0f) + player.y,
60.0f * sinf(player.angle), 60.0f*cosf(player.angle), 0.0f });
vecAsteroids.push_back({ (int)16, 80.0f * sinf(player.angle + 3.14159f/2.0f) + player.x,
80.0f * cosf(player.angle + 3.14159f/2.0f) + player.y,
60.0f * sinf(-player.angle), 60.0f*cosf(-player.angle), 0.0f });
}
// Remove bullets that have gone off screen
if (vecBullets.size() > 0)
{
auto i = remove_if(vecBullets.begin(), vecBullets.end(), [&](sSpaceObject o) { return (o.x < 1 || o.y < 1 || o.x >= ScreenWidth() - 1 || o.y >= ScreenHeight() - 1); });
if (i != vecBullets.end())
vecBullets.erase(i);
}
// Draw Bullets
for (auto b : vecBullets)
Draw(b.x, b.y);
// Draw Ship
DrawWireFrameModel(vecModelShip, player.x, player.y, player.angle);
// Draw Score
DrawString(2, 2, "SCORE: " + std::to_string(nScore));
return !GetKey(olc::ESCAPE).bPressed;
}
void DrawWireFrameModel(const std::vector<std::pair<float, float>> &vecModelCoordinates, float x, float y, float r = 0.0f, float s = 1.0f, olc::Pixel col = olc::WHITE)
{
// pair.first = x coordinate
// pair.second = y coordinate
// Create translated model vector of coordinate pairs
std::vector<std::pair<float, float>> vecTransformedCoordinates;
int verts = vecModelCoordinates.size();
vecTransformedCoordinates.resize(verts);
// Rotate
for (int i = 0; i < verts; i++)
{
vecTransformedCoordinates[i].first = vecModelCoordinates[i].first * cosf(r) - vecModelCoordinates[i].second * sinf(r);
vecTransformedCoordinates[i].second = vecModelCoordinates[i].first * sinf(r) + vecModelCoordinates[i].second * cosf(r);
}
// Scale
for (int i = 0; i < verts; i++)
{
vecTransformedCoordinates[i].first = vecTransformedCoordinates[i].first * s;
vecTransformedCoordinates[i].second = vecTransformedCoordinates[i].second * s;
}
// Translate
for (int i = 0; i < verts; i++)
{
vecTransformedCoordinates[i].first = vecTransformedCoordinates[i].first + x;
vecTransformedCoordinates[i].second = vecTransformedCoordinates[i].second + y;
}
// Draw Closed Polygon
for (int i = 0; i < verts + 1; i++)
{
int j = (i + 1);
DrawLine(vecTransformedCoordinates[i % verts].first, vecTransformedCoordinates[i % verts].second,
vecTransformedCoordinates[j % verts].first, vecTransformedCoordinates[j % verts].second, col);
}
}
};
int main()
{
OneLoneCoder_Asteroids game;
if(game.Construct(320, 180, 4, 4))
game.Start();
return 0;
}

@ -0,0 +1,722 @@
#pragma once
#include "olcPixelGameEngine.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <vector>
// Declarations
namespace olc {
class ViewPort : public olc::PGEX {
public:
ViewPort();
//Define a set of vertices to construct this viewport with. Winding order is counter-clockwise.
ViewPort(std::vector<vf2d> vertices, vf2d offset = {0, 0});
virtual ~ViewPort();
void addPoint(vf2d point);
void clear();
void drawEdges();
void setOffset(vf2d offset);
static ViewPort rectViewPort(vf2d topLeft,
vf2d size,
olc::vf2d offset = {0, 0});
void DrawDecal(const olc::vf2d &pos,
olc::Decal *decal,
const olc::vf2d &scale = {1.0f, 1.0f},
const olc::Pixel &tint = olc::WHITE) const;
void DrawPartialDecal(const olc::vf2d &pos,
olc::Decal *decal,
const olc::vf2d &source_pos,
const olc::vf2d &source_size,
const olc::vf2d &scale = {1.0f, 1.0f},
const olc::Pixel &tint = olc::WHITE) const;
void DrawPartialDecal(const vf2d &pos,
const vf2d &size,
Decal *decal,
const vf2d source_pos,
const vf2d &source_size,
const Pixel &tint = olc::WHITE) const;
void DrawExplicitDecal(olc::Decal *decal,
const olc::vf2d *pos,
const olc::vf2d *uv,
const olc::Pixel *col,
uint32_t elements = 4) const;
void DrawWarpedDecal(Decal *decal,
const vf2d (&pos)[4],
const Pixel &tint = WHITE) const;
void DrawWarpedDecal(Decal *decal,
const vf2d *pos,
const Pixel &tint = WHITE) const;
void DrawWarpedDecal(Decal *decal,
const std::array<vf2d, 4> &pos,
const Pixel &tint = WHITE) const;
void DrawPartialWarpedDecal(Decal *decal,
const vf2d (&pos)[4],
const vf2d &source_pos,
const vf2d &source_size,
const Pixel &tint = WHITE) const;
void DrawPartialWarpedDecal(Decal *decal,
const vf2d *pos,
const vf2d &source_pos,
const vf2d &source_size,
const Pixel &tint = WHITE) const;
void DrawPartialWarpedDecal(Decal *decal,
const std::array<vf2d, 4> &pos,
const vf2d &source_pos,
const vf2d &source_size,
const Pixel &tint = WHITE) const;
void DrawRotatedDecal(const vf2d &pos,
Decal *decal,
const float fAngle,
const vf2d &center = {0.0f, 0.0f},
const vf2d &scale = {1.0f, 1.0f},
const Pixel &tint = WHITE) const;
void DrawPartialRotatedDecal(const vf2d &pos,
Decal *decal,
const float fAngle,
const vf2d &center,
const vf2d &source_pos,
const vf2d &source_size,
const vf2d &scale = {1.0f, 1.0f},
const Pixel &tint = WHITE) const;
void DrawRectDecal(const vf2d &pos,
const vf2d &size,
const Pixel col = WHITE) const;
void FillRectDecal(const vf2d &pos,
const vf2d &size,
const Pixel col = WHITE) const;
void GradientFillRectDecal(const vf2d &pos,
const vf2d &size,
const Pixel colTL,
const Pixel colBL,
const Pixel colBR,
const Pixel colTR) const;
void DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<vf2d> &uv,
const Pixel tint = WHITE) const;
void DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<float> &depth,
const std::vector<vf2d> &uv,
const Pixel tint = WHITE) const;
void DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<vf2d> &uv,
const std::vector<Pixel> &tint) const;
void DrawLineDecal(const vf2d &pos1,
const vf2d &pos2,
Pixel p = WHITE) const;
private:
void drawClippedDecal(Decal *decal,
const vf2d *points,
const vf2d *uvs,
const Pixel *col,
uint32_t elements = 0) const;
void drawClippedPolygonDecal(Decal *decal,
const vf2d *points,
const vf2d *uvs,
const float *depth,
const Pixel tint,
uint32_t elements = 0) const;
static bool ccw(vf2d A,vf2d B,vf2d C);
static bool intersect(vf2d A,vf2d B,vf2d C,vf2d D);
static float lineSegmentIntersect(vf2d lineA,
vf2d lineB,
vf2d segmentA,
vf2d segmentB);
static float directionFromLine(vf2d lineA, vf2d lineB, vf2d point);
std::vector<vf2d> clipVertices;
olc::vf2d offset;
};
} // namespace olc
// Definitions
#ifdef OLC_PGEX_VIEWPORT
#undef OLC_PGEX_VIEWPORT
olc::ViewPort::ViewPort() {
}
olc::ViewPort::~ViewPort() {
}
olc::ViewPort::ViewPort(std::vector<vf2d> vertices, olc::vf2d offset)
: clipVertices{vertices},
offset{offset} {
}
void olc::ViewPort::addPoint(vf2d point) {
clipVertices.push_back(point);
}
void olc::ViewPort::clear() {
clipVertices.clear();
}
void olc::ViewPort::drawEdges() {
for (auto i = 0u; i < clipVertices.size(); i++) {
auto current = clipVertices[i] + offset;
auto next = clipVertices[(i + 1) % clipVertices.size()] + offset;
pge->DrawLineDecal(current, next, olc::RED);
}
}
void olc::ViewPort::setOffset(vf2d offset) {
this->offset = offset;
}
olc::ViewPort
olc::ViewPort::rectViewPort(vf2d topLeft, vf2d size, olc::vf2d offset) {
return {{
topLeft,
{topLeft.x, topLeft.y + size.y},
topLeft + size,
{topLeft.x + size.x, topLeft.y},
},
offset};
}
void olc::ViewPort::DrawDecal(const olc::vf2d &pos,
olc::Decal *decal,
const olc::vf2d &scale,
const olc::Pixel &tint) const {
std::vector<olc::vf2d> points{
pos,
{pos.x, pos.y + decal->sprite->height * scale.y},
{pos.x + decal->sprite->width * scale.x,
pos.y + decal->sprite->height * scale.y},
{pos.x + decal->sprite->width * scale.x, pos.y},
};
DrawWarpedDecal(decal, points.data(), tint);
}
void olc::ViewPort::DrawPartialDecal(const olc::vf2d &pos,
olc::Decal *decal,
const olc::vf2d &source_pos,
const olc::vf2d &source_size,
const olc::vf2d &scale,
const olc::Pixel &tint) const {
DrawPartialDecal(pos, source_size * scale, decal, source_pos, source_size, tint);
}
void olc::ViewPort::DrawPartialDecal(const vf2d &pos,
const vf2d &size,
Decal *decal,
const vf2d source_pos,
const vf2d &source_size,
const Pixel &tint) const {
std::vector<vf2d> points{
pos,
{pos.x, pos.y + size.y},
pos + size,
{pos.x + size.x, pos.y},
};
DrawPartialWarpedDecal(decal, points.data(), source_pos, source_size, tint);
}
void olc::ViewPort::DrawExplicitDecal(olc::Decal *decal,
const olc::vf2d *pos,
const olc::vf2d *uv,
const olc::Pixel *col,
uint32_t elements) const {
drawClippedDecal(decal, pos, uv, col, elements);
}
void olc::ViewPort::DrawWarpedDecal(Decal *decal,
const vf2d (&pos)[4],
const Pixel &tint) const {
DrawWarpedDecal(decal, (const vf2d *)pos, tint);
}
void olc::ViewPort::DrawWarpedDecal(Decal *decal,
const vf2d *pos,
const Pixel &tint) const {
std::vector<float> w{ 1, 1, 1, 1 };
std::vector<olc::vf2d> newPos;
newPos.resize(4);
std::vector<vf2d> uvs{
{0, 0},
{0, 1},
{1, 1},
{1, 0},
};
std::vector<Pixel> cols{
tint,
tint,
tint,
tint,
};
olc::vf2d vInvScreenSize={ 1.0f / pge->GetScreenSize().x, 1.0f / pge->GetScreenSize().y };
olc::vf2d center;
float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y));
if (rd != 0)
{
rd = 1.0f / rd;
float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd;
float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd;
if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]);
float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag();
for (int i = 0; i < 4; i++)
{
float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3];
uvs[i] *= q; w[i] *= q;
}
drawClippedPolygonDecal(decal, pos, uvs.data(), w.data(), tint, 4);
}
}
void olc::ViewPort::DrawWarpedDecal(Decal *decal,
const std::array<vf2d, 4> &pos,
const Pixel &tint) const {
DrawWarpedDecal(decal, pos.data(), tint);
}
void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
const vf2d (&pos)[4],
const vf2d &source_pos,
const vf2d &source_size,
const Pixel &tint) const {
DrawPartialWarpedDecal(decal,
(const vf2d *)pos,
source_pos,
source_size,
tint);
}
void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
const vf2d *pos,
const vf2d &source_pos,
const vf2d &source_size,
const Pixel &tint) const {
olc::vf2d sourceUvPos =
source_pos
/ olc::vf2d{static_cast<float>(decal->sprite->width),
static_cast<float>(decal->sprite->height)};
olc::vf2d sourceUvSize =
source_size
/ olc::vf2d{static_cast<float>(decal->sprite->width),
static_cast<float>(decal->sprite->height)};
std::vector<vf2d> uvs{
sourceUvPos,
{sourceUvPos.x, sourceUvPos.y + sourceUvSize.y},
sourceUvPos + sourceUvSize,
{sourceUvPos.x + sourceUvSize.x, sourceUvPos.y},
};
std::vector<Pixel> cols{
tint,
tint,
tint,
tint,
};
std::vector<float>ws{1,1,1,1};
olc::vf2d center;
float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y));
if (rd != 0)
{
rd = 1.0f / rd;
float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd;
float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd;
if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]);
float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag();
for (int i = 0; i < 4; i++)
{
float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3];
uvs[i] *= q; ws[i] *= q;
}
drawClippedPolygonDecal(decal, pos, uvs.data(), ws.data(), tint, 4);
}
}
void olc::ViewPort::DrawPartialWarpedDecal(Decal *decal,
const std::array<vf2d, 4> &pos,
const vf2d &source_pos,
const vf2d &source_size,
const Pixel &tint) const {
DrawPartialWarpedDecal(decal, pos.data(), source_pos, source_size, tint);
}
void olc::ViewPort::DrawRotatedDecal(const vf2d &pos,
Decal *decal,
const float fAngle,
const vf2d &center,
const vf2d &scale,
const Pixel &tint) const {
auto sin = std::sin(fAngle);
auto cos = std::cos(fAngle);
std::vector<vf2d> points{
-center * scale,
olc::vf2d{-center.x, decal->sprite->height - center.y} * scale,
olc::vf2d{decal->sprite->width - center.x,
decal->sprite->height - center.y}
* scale,
olc::vf2d{decal->sprite->width - center.x, -center.y} * scale,
};
for (auto i = 0u; i < points.size(); i++) {
points[i] = pos
+ olc::vf2d{points[i].x * cos - points[i].y * sin,
points[i].x * sin + points[i].y * cos};
}
DrawWarpedDecal(decal, points.data(), tint);
}
void olc::ViewPort::DrawPartialRotatedDecal(const vf2d &pos,
Decal *decal,
const float fAngle,
const vf2d &center,
const vf2d &source_pos,
const vf2d &source_size,
const vf2d &scale,
const Pixel &tint) const {
auto sin = std::sin(fAngle);
auto cos = std::cos(fAngle);
std::vector<vf2d> points{
-center * scale,
olc::vf2d{-center.x, source_size.y - center.y} * scale,
(source_size - center) * scale,
olc::vf2d{source_size.x - center.x, -center.y} * scale,
};
for (auto i = 0u; i < points.size(); i++) {
points[i] = pos
+ olc::vf2d{points[i].x * cos - points[i].y * sin,
points[i].x * sin + points[i].y * cos};
}
DrawPartialWarpedDecal(decal, points.data(), source_pos, source_size, tint);
}
void olc::ViewPort::DrawRectDecal(const vf2d &pos,
const vf2d &size,
const Pixel col) const {
std::vector<vf2d> points{
pos,
{pos.x, pos.y + size.y},
pos + size,
{pos.x + size.x, pos.y},
};
// Ideally we use the wireframe mode just like the PGE,
// however we can't save the current decal mode which
// can impact some applications so instead we draw 4
// lines.
DrawLineDecal(points[0],points[1],col);
DrawLineDecal(points[1],points[2],col);
DrawLineDecal(points[2],points[3],col);
DrawLineDecal(points[3],points[0],col);
}
void olc::ViewPort::FillRectDecal(const vf2d &pos,
const vf2d &size,
const Pixel col) const {
std::vector<vf2d> points{
pos,
{pos.x, pos.y + size.y},
pos + size,
{pos.x + size.x, pos.y},
};
std::vector<vf2d> uvs{
{0, 0},
{0, 1},
{1, 1},
{1, 0},
};
DrawPolygonDecal(nullptr, points, uvs, col);
}
void olc::ViewPort::GradientFillRectDecal(const vf2d &pos,
const vf2d &size,
const Pixel colTL,
const Pixel colBL,
const Pixel colBR,
const Pixel colTR) const {
std::vector<vf2d> points{
pos,
{pos.x, pos.y + size.y},
pos + size,
{pos.x + size.x, pos.y},
};
std::vector<vf2d> uvs{
{0, 0},
{0, 1},
{1, 1},
{1, 0},
};
std::vector<Pixel> colors{
colTL,
colBL,
colBR,
colTR,
};
drawClippedDecal(nullptr, points.data(), uvs.data(), colors.data(), points.size());
}
void olc::ViewPort::DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<vf2d> &uv,
const Pixel tint) const {
std::vector<Pixel> colors;
colors.resize(pos.size());
for (auto i = 0u; i < colors.size(); i++) {
colors[i] = tint;
}
drawClippedDecal(decal, pos.data(), uv.data(), colors.data(), pos.size());
}
void olc::ViewPort::DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<float> &depth,
const std::vector<vf2d> &uv,
const Pixel tint) const {
drawClippedPolygonDecal(decal, pos.data(), uv.data(), depth.data(), tint, pos.size());
}
void olc::ViewPort::DrawPolygonDecal(Decal *decal,
const std::vector<vf2d> &pos,
const std::vector<vf2d> &uv,
const std::vector<Pixel> &tint) const {
drawClippedDecal(decal, pos.data(), uv.data(), tint.data(), pos.size());
}
void olc::ViewPort::DrawLineDecal(const vf2d &pos1,
const vf2d &pos2,
Pixel p) const {
vf2d posA = pos1 + offset;
vf2d posB = pos2 + offset;
for (auto i = 0u; i < clipVertices.size(); i++) {
auto clipA = clipVertices[i] - offset;
auto clipB = clipVertices[(i + 1) % clipVertices.size()] - offset;
auto intersection = lineSegmentIntersect(clipA, clipB, posA, posB);
if (intersection < 0 || intersection > 1) {
continue;
}
auto clipDirection = directionFromLine(clipA, clipB, posA);
auto intersectionPoint = posA + (posB - posA) * intersection;
if (clipDirection >= 0) {
posA = intersectionPoint;
} else {
posB = intersectionPoint;
}
}
// Inside check. Draw a ray to the edge of the screen and count the times
// it intersects. When odd, we are inside a shape, when even we are outside
// of it.
vf2d leftEdgeA = {0.f,posA.y};
vf2d leftEdgeB = {0.f,posB.y};
int leftEdgeIntersectionsA = 0;
int leftEdgeIntersectionsB = 0;
for (auto i = 0u; i < clipVertices.size(); i++) {
auto clipA = clipVertices[i] - offset;
auto clipB = clipVertices[(i + 1) % clipVertices.size()] - offset;
auto leftEdgeIntersectA = intersect(clipA, clipB, leftEdgeA, posA);
auto leftEdgeIntersectB = intersect(clipA, clipB, leftEdgeB, posB);
if (leftEdgeIntersectA) {
leftEdgeIntersectionsA++;
}
if (leftEdgeIntersectB) {
leftEdgeIntersectionsB++;
}
}
// If we found an intersection, we are drawing this line.
//
// Otherwise, if either count is odd, one point is at
// least inside the shape, so render it.
if (leftEdgeIntersectionsA % 2 == 1 || leftEdgeIntersectionsB % 2 == 1) {
pge->DrawLineDecal(posA, posB, p);
}
}
void olc::ViewPort::drawClippedDecal(Decal *decal,
const vf2d *points,
const vf2d *uvs,
const Pixel *col,
uint32_t elements) const {
std::vector<vf2d> outputList{points, points + elements};
std::vector<vf2d> outputUvs{uvs, uvs + elements};
std::vector<Pixel> outputCols{col, col + elements};
for (auto i = 0u; i < clipVertices.size(); i++) {
auto clipA = clipVertices[i] - offset;
auto clipB = clipVertices[(i + 1) % clipVertices.size()] - offset;
auto inputList{outputList};
auto inputUvs{outputUvs};
auto inputCols{outputCols};
outputList.clear();
outputUvs.clear();
outputCols.clear();
for (auto i = 0u; i < inputList.size(); i++) {
auto polygonA = inputList[i];
auto polygonB = inputList[(i + 1) % inputList.size()];
auto uvA = inputUvs[i];
auto uvB = inputUvs[(i + 1) % inputList.size()];
auto colA = inputCols[i];
auto colB = inputCols[(i + 1) % inputList.size()];
auto intersection =
lineSegmentIntersect(clipA, clipB, polygonA, polygonB);
auto intersectionPoint =
polygonA + (polygonB - polygonA) * intersection;
auto intersectionUv = uvA + (uvB - uvA) * intersection;
auto intersectionCol = PixelLerp(colA, colB, intersection);
float aDirection = directionFromLine(clipA, clipB, polygonA);
float bDirection = directionFromLine(clipA, clipB, polygonB);
if (bDirection <= 0) {
if (aDirection > 0) {
outputList.push_back(intersectionPoint);
outputUvs.push_back(intersectionUv);
outputCols.push_back(intersectionCol);
}
outputList.push_back(polygonB);
outputUvs.push_back(uvB);
outputCols.push_back(colB);
} else if (aDirection <= 0) {
outputList.push_back(intersectionPoint);
outputUvs.push_back(intersectionUv);
outputCols.push_back(intersectionCol);
}
}
}
if (outputList.size() == 0) {
return;
}
for (auto &point : outputList) {
point += offset;
}
pge->DrawExplicitDecal(decal,
outputList.data(),
outputUvs.data(),
outputCols.data(),
outputList.size());
}
void olc::ViewPort::drawClippedPolygonDecal(Decal *decal,
const vf2d *points,
const vf2d *uvs,
const float *depth,
const Pixel tint,
uint32_t elements) const {
std::vector<vf2d> outputList{points, points + elements};
std::vector<vf2d> outputUvs{uvs, uvs + elements};
std::vector<float> outputDepths{depth, depth + elements};
for (auto i = 0u; i < clipVertices.size(); i++) {
auto clipA = clipVertices[i] + offset;
auto clipB = clipVertices[(i + 1) % clipVertices.size()] + offset;
auto inputList{outputList};
auto inputUvs{outputUvs};
auto inputWs{outputDepths};
outputList.clear();
outputUvs.clear();
outputDepths.clear();
for (auto i = 0u; i < inputList.size(); i++) {
auto polygonA = inputList[i];
auto polygonB = inputList[(i + 1) % inputList.size()];
auto uvA = inputUvs[i];
auto uvB = inputUvs[(i + 1) % inputList.size()];
auto Wa = inputWs[i];
auto Wb = inputWs[(i + 1) % inputList.size()];
auto intersection =
lineSegmentIntersect(clipA, clipB, polygonA, polygonB);
auto intersectionPoint =
polygonA + (polygonB - polygonA) * intersection;
auto intersectionUv = uvA + (uvB - uvA) * intersection;
auto intersectionDepth = Wa + (Wb - Wa) * intersection;
float aDirection = directionFromLine(clipA, clipB, polygonA);
float bDirection = directionFromLine(clipA, clipB, polygonB);
if (bDirection <= 0) {
if (aDirection > 0) {
outputList.push_back(intersectionPoint);
outputUvs.push_back(intersectionUv);
outputDepths.push_back(intersectionDepth);
}
outputList.push_back(polygonB);
outputUvs.push_back(uvB);
outputDepths.push_back(Wb);
} else if (aDirection <= 0) {
outputList.push_back(intersectionPoint);
outputUvs.push_back(intersectionUv);
outputDepths.push_back(intersectionDepth);
}
}
}
for (auto &point : outputList) {
point += offset;
}
pge->DrawPolygonDecal(decal,
outputList,
outputDepths,
outputUvs,
tint);
}
bool olc::ViewPort::ccw(vf2d A,vf2d B,vf2d C) {
return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x);
}
bool olc::ViewPort::intersect(vf2d A,vf2d B,vf2d C,vf2d D) {
return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D);
}
float olc::ViewPort::lineSegmentIntersect(vf2d lineA,
vf2d lineB,
vf2d segmentA,
vf2d segmentB) {
return ((lineA.x - segmentA.x) * (lineA.y - lineB.y)
- (lineA.y - segmentA.y) * (lineA.x - lineB.x))
/ ((lineA.x - lineB.x) * (segmentA.y - segmentB.y)
- (lineA.y - lineB.y) * (segmentA.x - segmentB.x));
}
float olc::ViewPort::directionFromLine(vf2d lineA, vf2d lineB, vf2d point) {
return (lineB.x - lineA.x) * (point.y - lineA.y)
- (point.x - lineA.x) * (lineB.y - lineA.y);
}
#endif

@ -1,3 +1,5 @@
#include "olcUTIL_Geometry2D.h"
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
#define OLC_PGEX_VIEWPORT
#include "olcPGEX_ViewPort.h"

File diff suppressed because it is too large Load Diff

@ -0,0 +1,221 @@
/*
OneLoneCoder - Animate2D v1.01
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Handles animated Sprites efficiently
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2024 OneLoneCoder.com
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions or derivations of source code must retain the above
copyright notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce
the above copyright notice. This list of conditions and the following
disclaimer must be reproduced in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Links
~~~~~
YouTube: https://www.youtube.com/javidx9
Discord: https://discord.gg/WhwHUMV
Twitter: https://www.twitter.com/javidx9
Twitch: https://www.twitch.tv/javidx9
GitHub: https://www.github.com/onelonecoder
Homepage: https://www.onelonecoder.com
Author
~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022, 2023, 2024
Versions
~~~~~~~~
1.01 +PingPong Style Animation
*/
#pragma once
#include "olcPixelGameEngine.h"
#include "utilities/olcUTIL_Geometry2D.h"
#include <unordered_map>
namespace olc::utils::Animate2D
{
// This class rerpresents a valid "frame" of an animation. It could be from any image source, and
// any location withing that image source. Once it's constructed, it's advised not to change it, as
// this likely indicates a usage bug.
//
// "Sourceless" frames are valid too - this is useful if you have a particular animation set, but
// want to apply it to a variety of sources, for example sprite maps with common layouts.
class Frame
{
public:
inline Frame(const olc::Renderable* gfxSource, const geom2d::rect<int32_t>& rectSource = { {0,0},{0,0} })
: gfxImageSource(gfxSource), rectFrameSource(rectSource)
{
// If no source rectangle specified then use whole image source. Ignore in the event
// that a frame is set up as source-less
if(gfxSource && rectFrameSource.size.x == 0)
rectFrameSource.size = gfxSource->Sprite()->Size();
}
inline const olc::Renderable* GetSourceImage() const
{
return gfxImageSource;
}
inline const geom2d::rect<int32_t>& GetSourceRect() const
{
return rectFrameSource;
}
private:
const olc::Renderable* gfxImageSource;
geom2d::rect<int32_t> rectFrameSource;
};
// Animation styles decide how the frames should be traversed in time
enum class Style : uint8_t
{
Repeat, // Cycle through, go back to beginning
OneShot, // Play once and suspend on final frame
PingPong, // Traverse through forwards, then backwards
Reverse, // Cycle through sequence backwards
};
class FrameSequence
{
public:
// Constructs a sequence of frames with a duration and a traversal style
inline FrameSequence(const float fFrameDuration = 0.1f, const Style nStyle = Style::Repeat)
{
m_fFrameDuration = fFrameDuration;
m_fFrameRate = 1.0f / m_fFrameDuration;
m_nStyle = nStyle;
}
// Adds a frame to this sequence
inline void AddFrame(const Frame& frame)
{
m_vFrames.emplace_back(frame);
}
// Returns a Frame Object for a given time into an animation
inline const Frame& GetFrame(const float fTime) const
{
return m_vFrames[ConvertTimeToFrame(fTime)];
}
private:
Style m_nStyle;
std::vector<Frame> m_vFrames;
float m_fFrameDuration = 0.1f;
float m_fFrameRate = 10.0f;
inline const size_t ConvertTimeToFrame(const float fTime) const
{
switch (m_nStyle)
{
case Style::Repeat:
return size_t(fTime * m_fFrameRate) % m_vFrames.size();
break;
case Style::OneShot:
return std::clamp(size_t(fTime * m_fFrameRate), size_t(0), m_vFrames.size() - 1);
break;
case Style::PingPong:
{
// Thanks @sigonasr2 (discord)
size_t frame = size_t(m_fFrameRate * fTime) % (m_vFrames.size() * 2 - 1);
return frame >= m_vFrames.size() ? m_vFrames.size() - frame % m_vFrames.size() - 1 : frame;
}
break;
case Style::Reverse:
return (m_vFrames.size() - 1) - (size_t(fTime * m_fFrameRate) % m_vFrames.size());
break;
}
return 0;
}
};
// A Animate2D::State is a lightweight token that can be attached to things
// that are animated. Under normal circumstances, it is never updated manually
struct AnimationState
{
private:
size_t nIndex = 0;
float fTime = 0.0f;
template<typename StatesEnum>
friend class Animation;
};
// Animation object holds a group of frame sequences and can mutate an AnimationState token
template<typename StatesEnum>
class Animation
{
public:
Animation() = default;
// Change an animation state token to a new state
inline bool ChangeState(AnimationState& state, const StatesEnum& sStateName) const
{
size_t idx = m_mapStateIndices.at(sStateName);
if (state.nIndex != idx)
{
state.fTime = 0.0f;
state.nIndex = idx;
return true;
}
return false;
}
// Update an animation state token
inline void UpdateState(AnimationState& state, const float fElapsedTime) const
{
state.fTime += fElapsedTime;
}
public:
// Retrieve the frame information for a given animation state
inline const Frame& GetFrame(const AnimationState& state) const
{
return m_vSequences[state.nIndex].GetFrame(state.fTime);
}
public:
// Add a named Frame sequence as a state
inline void AddState(const StatesEnum& sStateName, const FrameSequence& sequence)
{
m_vSequences.emplace_back(sequence);
m_mapStateIndices[sStateName] = m_vSequences.size() - 1;
}
private:
std::vector<FrameSequence> m_vSequences;
std::unordered_map<StatesEnum, size_t> m_mapStateIndices;
};
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save