├── .gitignore ├── .vscode └── settings.json ├── AssignmentCppCheck.cppcheck ├── Engine ├── Engine.vcxproj ├── Engine.vcxproj.filters ├── General │ ├── Actor.cpp │ ├── Actor.h │ ├── Components │ │ ├── BoxCollider.h │ │ ├── CircleCollider.h │ │ ├── Follow.h │ │ ├── IActorComponent.h │ │ └── Physics.h │ ├── Systems │ │ ├── CollisionSystem.cpp │ │ ├── CollisionSystem.h │ │ ├── Input.cpp │ │ └── Input.h │ ├── World.cpp │ └── World.h ├── Jobs │ ├── Console │ │ ├── ConsolePrint.Win32.cpp │ │ └── ConsolePrint.h │ ├── HashedString │ │ ├── HashedString-inl.h │ │ ├── HashedString.cpp │ │ └── HashedString.h │ ├── JobSystem │ │ ├── IJob.cpp │ │ ├── IJob.h │ │ ├── INamed.h │ │ ├── JobRunner.cpp │ │ ├── JobRunner.h │ │ ├── JobSystem.cpp │ │ ├── JobSystem.h │ │ ├── SharedJobQueue-inl.h │ │ ├── SharedJobQueue.cpp │ │ └── SharedJobQueue.h │ └── Syncronization │ │ ├── Events.cpp │ │ ├── Events.h │ │ ├── Mutex.cpp │ │ ├── Mutex.h │ │ ├── ScopeLock.h │ │ ├── Semaphore.cpp │ │ ├── Semaphore.h │ │ ├── SingleWriterMultipleReader.h │ │ └── WaitableObject.h ├── Math │ ├── Math.h │ ├── Matrix3.h │ ├── Matrix4.h │ ├── Vector.h │ ├── Vector3.h │ ├── Vector4.h │ └── pchMath.h ├── Memory │ ├── BitArray.cpp │ ├── BitArray.h │ ├── FixedSizeAllocator.cpp │ ├── FixedSizeAllocator.h │ ├── MemorySystem.cpp │ ├── MemorySystem.h │ ├── PoolAllocator.cpp │ ├── PoolAllocator.h │ └── SmartPointer │ │ ├── RefCount.h │ │ ├── SmartPtr.h │ │ ├── SmartPtrConversion.h │ │ └── WeakPtr.h ├── Render │ └── GLibHelper.h └── String │ ├── String.cpp │ └── String.h ├── EnginePlusPong.sln ├── Exports ├── GLib │ ├── BasicTypes.h │ ├── GLib.h │ └── GLib.lib └── json.hpp ├── FixedSizeAllocator.png ├── LICENSE.md ├── MemoryPoolAllocator.png ├── Pong ├── Assets │ ├── BrickGreen.dds │ ├── BrickRed.dds │ ├── Circle.dds │ ├── LeftPaddle.dds │ ├── RightPaddle.dds │ ├── Square.dds │ └── WhiteSquareArrow.dds ├── Pong.cpp ├── Pong.vcxproj ├── Pong.vcxproj.filters └── Saved │ ├── Ball.json │ ├── EditorState2.json │ ├── EditorStatePong.json │ ├── LeftPaddle.json │ └── RightPaddle.json ├── README.md └── ReadMe.txt /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "string": "cpp" 4 | } 5 | } -------------------------------------------------------------------------------- /AssignmentCppCheck.cppcheck: -------------------------------------------------------------------------------- 1 | 2 | 3 | AssignmentCppCheck-cppcheck-build-dir 4 | Unspecified 5 | CppAssignments.sln 6 | false 7 | true 8 | false 9 | 10 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | constParameter 19 | 20 | 21 | -------------------------------------------------------------------------------- /Engine/Engine.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 15.0 86 | {D32EC244-7D50-4AFE-97D6-21816808F479} 87 | Win32Proj 88 | Engine 89 | 10.0.17763.0 90 | 91 | 92 | 93 | StaticLibrary 94 | true 95 | v141 96 | MultiByte 97 | 98 | 99 | StaticLibrary 100 | false 101 | v141 102 | true 103 | MultiByte 104 | 105 | 106 | StaticLibrary 107 | true 108 | v141 109 | MultiByte 110 | 111 | 112 | StaticLibrary 113 | false 114 | v141 115 | true 116 | MultiByte 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | true 138 | $(SolutionDir)JobSystem;$(SolutionDir)Exports;$(IncludePath) 139 | 140 | 141 | true 142 | $(SolutionDir)JobSystem;$(SolutionDir)Exports;$(IncludePath) 143 | 144 | 145 | false 146 | $(SolutionDir)JobSystem;$(SolutionDir)Exports;$(IncludePath) 147 | 148 | 149 | false 150 | $(SolutionDir)JobSystem;$(SolutionDir)Exports;$(IncludePath) 151 | 152 | 153 | 154 | NotUsing 155 | Level3 156 | Disabled 157 | true 158 | _DEBUG;_LIB;%(PreprocessorDefinitions);CLASSIC_MAIN 159 | true 160 | Math/pchMath.h 161 | 162 | 163 | Windows 164 | true 165 | 166 | 167 | 168 | 169 | NotUsing 170 | Level3 171 | Disabled 172 | true 173 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions);CLASSIC_MAIN 174 | true 175 | Math/pchMath.h 176 | 177 | 178 | Windows 179 | true 180 | 181 | 182 | 183 | 184 | NotUsing 185 | Level3 186 | MaxSpeed 187 | true 188 | true 189 | true 190 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);CLASSIC_MAIN 191 | true 192 | Math/pchMath.h 193 | 194 | 195 | Windows 196 | true 197 | true 198 | true 199 | 200 | 201 | 202 | 203 | NotUsing 204 | Level3 205 | MaxSpeed 206 | true 207 | true 208 | true 209 | NDEBUG;_LIB;%(PreprocessorDefinitions);CLASSIC_MAIN 210 | true 211 | Math/pchMath.h 212 | 213 | 214 | Windows 215 | true 216 | true 217 | true 218 | 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /Engine/Engine.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {401731cb-8649-479f-b29d-26c81aa6ae83} 18 | 19 | 20 | {baa1cc17-1aa6-4114-a4ea-bef45b9888ba} 21 | 22 | 23 | {6655fc5f-ca76-44f6-8cc1-dc9a91ad469e} 24 | 25 | 26 | {a284184a-fa02-4af6-a0ea-50155c336f2c} 27 | 28 | 29 | {0ccd3b9d-fb96-49af-89b5-d9bba84bfb61} 30 | 31 | 32 | {9941a002-288c-4ed6-a21e-89924901b540} 33 | 34 | 35 | {b2812732-c0ae-44c8-b650-1c60a3715597} 36 | 37 | 38 | {46187728-5eaf-43e2-97b3-2493b6c52b40} 39 | 40 | 41 | {d0d2b6da-2530-4b50-b7a0-55e11c8b6c80} 42 | 43 | 44 | {2df2c4d2-8cdb-4afd-9512-ad61f1eb6bf2} 45 | 46 | 47 | {cfe56c9f-1c35-47e3-b83e-5c853b4679d6} 48 | 49 | 50 | {e8c37ceb-cf9f-4421-9bbd-efbeaf68f010} 51 | 52 | 53 | {773000ef-7957-4076-ae22-41996235a762} 54 | 55 | 56 | {706ff25c-9d59-4a1b-98eb-364b95b3041b} 57 | 58 | 59 | {50d06f3a-5623-4453-bb4c-94a5b0f29d0d} 60 | 61 | 62 | {633621b2-1a2d-4594-b951-4f4aff6031e6} 63 | 64 | 65 | {f019dabf-989a-41bf-9c14-f622a17e3675} 66 | 67 | 68 | {c9421643-e2f4-43d4-a560-2e10ecc52ebf} 69 | 70 | 71 | {e66f519e-c8a4-4e23-947d-e2ff517243d9} 72 | 73 | 74 | {4b5b03a2-45c7-43db-a111-88e1b4bfd757} 75 | 76 | 77 | {3cb6d948-4e87-47ba-b4fd-38e809e12433} 78 | 79 | 80 | {29eead44-427f-4d69-abcb-97e50fb484ce} 81 | 82 | 83 | 84 | 85 | Header Files\General 86 | 87 | 88 | Header Files\Math 89 | 90 | 91 | Header Files\Math 92 | 93 | 94 | Header Files\General 95 | 96 | 97 | Header Files\String 98 | 99 | 100 | Header Files\Memory 101 | 102 | 103 | Header Files\Memory 104 | 105 | 106 | Header Files\Memory 107 | 108 | 109 | Header Files\Memory 110 | 111 | 112 | Header Files\General\Components 113 | 114 | 115 | Header Files\General\Components 116 | 117 | 118 | Header Files\General\Components 119 | 120 | 121 | Header Files\Memory\SmartPointer 122 | 123 | 124 | Header Files\Memory\SmartPointer 125 | 126 | 127 | Header Files\Memory\SmartPointer 128 | 129 | 130 | Header Files\General\Components 131 | 132 | 133 | Header Files\Jobs\Console 134 | 135 | 136 | Header Files\Jobs\HashedString 137 | 138 | 139 | Header Files\Jobs\HashedString 140 | 141 | 142 | Header Files\Jobs\JobSystem 143 | 144 | 145 | Header Files\Jobs\JobSystem 146 | 147 | 148 | Header Files\Jobs\JobSystem 149 | 150 | 151 | Header Files\Jobs\JobSystem 152 | 153 | 154 | Header Files\Jobs\JobSystem 155 | 156 | 157 | Header Files\Jobs\JobSystem 158 | 159 | 160 | Header Files\Jobs\Synchronization 161 | 162 | 163 | Header Files\Jobs\Synchronization 164 | 165 | 166 | Header Files\Jobs\Synchronization 167 | 168 | 169 | Header Files\Jobs\Synchronization 170 | 171 | 172 | Header Files\Jobs\Synchronization 173 | 174 | 175 | Header Files\Jobs\Synchronization 176 | 177 | 178 | Header Files\Math 179 | 180 | 181 | Header Files\General\Components 182 | 183 | 184 | Header Files\Math 185 | 186 | 187 | Header Files\Math 188 | 189 | 190 | Header Files\Math 191 | 192 | 193 | Header Files\Render 194 | 195 | 196 | Header Files\Math 197 | 198 | 199 | Header Files\Memory\SmartPointer 200 | 201 | 202 | Header Files\General\Systems 203 | 204 | 205 | Header Files\General\Systems 206 | 207 | 208 | 209 | 210 | Source Files\General 211 | 212 | 213 | Source Files\General 214 | 215 | 216 | Source Files\String 217 | 218 | 219 | Source Files\Memory 220 | 221 | 222 | Source Files\Memory 223 | 224 | 225 | Source Files\Memory 226 | 227 | 228 | Source Files\Memory 229 | 230 | 231 | Source Files\Jobs\Console 232 | 233 | 234 | Source Files\Jobs\HashedString 235 | 236 | 237 | Source Files\Jobs\JobSystem 238 | 239 | 240 | Source Files\Jobs\JobSystem 241 | 242 | 243 | Source Files\Jobs\JobSystem 244 | 245 | 246 | Source Files\Jobs\JobSystem 247 | 248 | 249 | Source Files\Jobs\Synchronization 250 | 251 | 252 | Source Files\Jobs\Synchronization 253 | 254 | 255 | Source Files\Jobs\Synchronization 256 | 257 | 258 | Source Files\General\Systems 259 | 260 | 261 | Source Files\General\Systems 262 | 263 | 264 | -------------------------------------------------------------------------------- /Engine/General/Actor.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Actor.h" 4 | #include "../Math/Math.h" 5 | #include "Components/IActorComponent.h" 6 | #include "World.h" 7 | #include "Components/Physics.h" 8 | 9 | 10 | 11 | 12 | ////////////////////////////////////////////////////////////////////// Constructors and Destructors 13 | Actor::Actor(World* world, const std::string name, Vector2 position) 14 | { 15 | this->name = name; 16 | this->position = position; 17 | this->world_ = world; 18 | } 19 | Actor::~Actor() 20 | { 21 | for (IActorComponent* component : mComponents) 22 | { 23 | delete component; 24 | } 25 | } 26 | Actor &Actor::operator = (const Actor &other) 27 | { 28 | this->name = other.name; 29 | this->position = other.position; 30 | this->world_ = other.world_; 31 | return *this; 32 | } 33 | ////////////////////////////////////////////////////////////////////// Constructors and Destructors 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ////////////////////////////////////////////////////////////////////// BeginPlay & Tick 46 | void Actor::BeginPlay() 47 | { 48 | const size_t nComponents = mComponents.size(); 49 | for (size_t i = 0; i < nComponents; i++) 50 | { 51 | if (mComponents[i]) 52 | { 53 | mComponents[i]->BeginPlay(); 54 | } 55 | } 56 | } 57 | void Actor::Tick(const float DeltaSeconds) 58 | { 59 | const size_t nComponents = mComponents.size(); 60 | for (size_t i = 0; i < nComponents; i++) 61 | { 62 | if (mComponents[i]) 63 | { 64 | mComponents[i]->Tick(DeltaSeconds); 65 | } 66 | } 67 | } 68 | ////////////////////////////////////////////////////////////////////// BeginPlay & Tick 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | ////////////////////////////////////////////////////////////////////// Components 81 | void Actor::AddComponent(IActorComponent* actorComponent) 82 | { 83 | if (actorComponent) 84 | mComponents.push_back(actorComponent); 85 | } 86 | ////////////////////////////////////////////////////////////////////// Components 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ////////////////////////////////////////////////////////////////////// Components 102 | void Actor::OnCollisionStay(SmartPtr & otherActor) 103 | { 104 | if (otherActor == world_->GetPlayerActor() || world_->GetPlayerActor() == this) 105 | { 106 | PhysicsComponent * otherComp = otherActor->GetComponent(); 107 | PhysicsComponent * myComp = GetComponent(); 108 | 109 | if (otherComp && myComp) 110 | { 111 | myComp->AddForce((position - otherActor->position).getNormalized() * 10.0f, true); 112 | } 113 | } 114 | } 115 | 116 | void Actor::OnHit(SmartPtr & otherActor) 117 | { 118 | 119 | } 120 | ////////////////////////////////////////////////////////////////////// Components -------------------------------------------------------------------------------- /Engine/General/Actor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../Math/pchMath.h" 5 | #include 6 | #include "../Memory/SmartPointer/SmartPtr.h" 7 | 8 | 9 | namespace GLib { 10 | namespace Sprites { 11 | struct Sprite; 12 | } 13 | } 14 | 15 | class IActorComponent; 16 | class World; 17 | 18 | enum EMobility 19 | { 20 | Static, 21 | Moveable 22 | }; 23 | 24 | class Actor { 25 | public: 26 | Actor(World* world, const std::string name, Vector2 position); 27 | virtual ~Actor(); 28 | Actor &operator = (const Actor &other); 29 | 30 | 31 | virtual void BeginPlay(); 32 | virtual void Tick(const float DeltaSeconds); 33 | 34 | 35 | void AddComponent(IActorComponent* actorComponent); 36 | template T* GetComponent() 37 | { 38 | for (auto& component : mComponents) 39 | { 40 | T* ptr = dynamic_cast(component); 41 | if (ptr != nullptr) 42 | return ptr; 43 | } 44 | return nullptr; 45 | } 46 | 47 | virtual void OnHit(SmartPtr & otherActor); 48 | virtual void OnCollisionStay(SmartPtr & otherActor); 49 | 50 | 51 | 52 | 53 | inline Vector2 GetVelocity() const { return velocity; } 54 | inline void SetVelocity(const Vector2 i_velocity) { velocity = i_velocity; } 55 | 56 | inline EMobility GetMobility() const { return mobility; } 57 | inline void SetMobility(const EMobility i_mobility) { mobility = i_mobility; } 58 | 59 | 60 | 61 | 62 | public: 63 | std::string name; 64 | GLib::Sprites::Sprite * sprite; 65 | Vector2 position = Vector2{ 0,0 }; 66 | float zRotation; 67 | World * world_; 68 | bool bDebugTrigger = false; 69 | bool bDestroyedOnHit = false; 70 | 71 | private: 72 | std::vector mComponents; 73 | EMobility mobility = Moveable; 74 | Vector2 velocity; 75 | }; 76 | 77 | 78 | -------------------------------------------------------------------------------- /Engine/General/Components/BoxCollider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IActorComponent.h" 4 | #include "../Actor.h" 5 | #include "../../Math/Vector3.h" 6 | 7 | struct AABB 8 | { 9 | Vector3 Center; 10 | Vector3 Extents; 11 | 12 | AABB(const Vector3 i_center, const Vector3 i_extents) : Center(i_center), Extents(i_extents) 13 | {} 14 | }; 15 | 16 | class BoxColliderComponent : public IActorComponent 17 | { 18 | public: 19 | BoxColliderComponent(SmartPtr & actorRef, const Vector3 i_center, const Vector3 i_extents) : IActorComponent(actorRef), aabb(i_center, i_extents) {} 20 | 21 | void SetBounds(const Vector3 i_center, const Vector3 i_extents) 22 | { 23 | aabb.Center = i_center; 24 | aabb.Extents = i_extents; 25 | } 26 | 27 | AABB getBounds() const 28 | { 29 | return aabb; 30 | } 31 | 32 | private: 33 | AABB aabb; 34 | }; 35 | -------------------------------------------------------------------------------- /Engine/General/Components/CircleCollider.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IActorComponent.h" 4 | #include "../Actor.h" 5 | 6 | class CircleColliderComponent : public IActorComponent 7 | { 8 | public: 9 | CircleColliderComponent(SmartPtr & actorRef, float r) : IActorComponent(actorRef), radius(r) {} 10 | 11 | void SetRadius(float r) 12 | { 13 | radius = r; 14 | } 15 | 16 | float GetRadius() const 17 | { 18 | return radius; 19 | } 20 | 21 | private: 22 | float radius = 1.f; 23 | }; 24 | -------------------------------------------------------------------------------- /Engine/General/Components/Follow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Actor.h" 4 | #include "IActorComponent.h" 5 | #include "../World.h" 6 | #include "Physics.h" 7 | 8 | 9 | class FollowComponent : public IActorComponent 10 | { 11 | public: 12 | // Fixed Arguments 13 | FollowComponent(SmartPtr & actorRef, WeakPtr i_targetActorRef, const bool i_bShouldFollow = true, const float i_followForce = 1.0f) 14 | : IActorComponent(actorRef), targetActorRef(i_targetActorRef), bShouldFollow(i_bShouldFollow), followForce(i_followForce) 15 | {} 16 | 17 | // Variable Arguments 18 | FollowComponent(SmartPtr & actorRef) : IActorComponent(actorRef) 19 | {} 20 | 21 | void BeginPlay() override 22 | { 23 | SmartPtr actor; 24 | this->actor.acquire(actor); 25 | 26 | physicsComp = actor->GetComponent(); 27 | } 28 | 29 | void Tick(const float DeltaSeconds) override 30 | { 31 | SmartPtr actor; 32 | this->actor.acquire(actor); 33 | 34 | SmartPtr targetActor; 35 | this->targetActorRef.acquire(targetActor); 36 | 37 | 38 | if (!physicsComp) 39 | physicsComp = actor->GetComponent(); 40 | 41 | 42 | if (targetActor && physicsComp && bShouldFollow) 43 | { 44 | const Vector2 direction = (targetActor->position - actor->position).getNormalized(); 45 | physicsComp->AddForce(direction * followForce); 46 | } 47 | } 48 | 49 | void SetFollow(WeakPtr & i_targetActorRef, const bool i_bShouldFollow) 50 | { 51 | targetActorRef = i_targetActorRef; 52 | bShouldFollow = i_bShouldFollow; 53 | } 54 | 55 | public: 56 | WeakPtr targetActorRef; 57 | bool bShouldFollow = false; 58 | float followForce = 1.0f; 59 | 60 | private: 61 | PhysicsComponent * physicsComp = nullptr; 62 | }; 63 | -------------------------------------------------------------------------------- /Engine/General/Components/IActorComponent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Actor.h" 4 | #include "../../Memory/SmartPointer/WeakPtr.h" 5 | 6 | class IActorComponent 7 | { 8 | protected: 9 | WeakPtr actor; 10 | 11 | public: 12 | IActorComponent(SmartPtr & actorRef) : actor(actorRef) {}; 13 | virtual ~IActorComponent() = default; 14 | virtual void BeginPlay() {} 15 | virtual void Tick(const float DeltaSeconds) {} 16 | }; -------------------------------------------------------------------------------- /Engine/General/Components/Physics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Actor.h" 4 | #include "IActorComponent.h" 5 | #include "../World.h" 6 | #include 7 | 8 | 9 | class PhysicsComponent : public IActorComponent 10 | { 11 | public: 12 | // Fixed Arguments 13 | PhysicsComponent(SmartPtr & actorRef, const float i_mass = 1.f, const float i_gravityScale = 1.f, const float i_linearDrag = 0.0001f) 14 | : IActorComponent(actorRef), mass(i_mass <= 0.f ? 0.0001f : i_mass), gravityScale(i_gravityScale), linearDrag(i_linearDrag) 15 | {} 16 | 17 | // Variable Arguments 18 | PhysicsComponent(SmartPtr & actorRef, const size_t n ...) : IActorComponent(actorRef) 19 | { 20 | if (n < 3) 21 | { 22 | printf("NOT ENOUGH PARAMETERS FOUND! | %s @ %d\n", __FILE__, __LINE__); 23 | } 24 | else 25 | { 26 | va_list varList; 27 | va_start(varList, n); 28 | const float i_mass = static_cast(va_arg(varList, double)); 29 | mass = i_mass < 0.0001f ? 0.0001f : i_mass; 30 | gravityScale = static_cast(va_arg(varList, double)); 31 | linearDrag = static_cast(va_arg(varList, double)); 32 | va_end(varList); 33 | } 34 | } 35 | 36 | void Tick(const float DeltaSeconds) override 37 | { 38 | if (DeltaSeconds > 0.5f) return; 39 | SmartPtr actor; 40 | this->actor.acquire(actor); 41 | if (!actor) 42 | { 43 | netForce = Vector2::Zero(); 44 | netImpulse = Vector2::Zero(); 45 | } 46 | 47 | AddForce(Vector2::Down() * gravityScale); 48 | 49 | if (linearDrag < 0.0f) linearDrag = 0.0f; 50 | const Vector2 currentVelocity = actor->GetVelocity(); 51 | AddForce(currentVelocity * currentVelocity.getMagnitude() * -1 * linearDrag * DeltaSeconds); 52 | 53 | const float deltaSeconds = actor->world_->GetDeltaSeconds(); 54 | const Vector2 accelFromForce = netForce * 1000.f / mass; 55 | const Vector2 accelFromImpulse = netImpulse / mass; 56 | const Vector2 newVelocity = currentVelocity + (accelFromForce * deltaSeconds) + accelFromImpulse; 57 | 58 | const Vector2 displacement = (currentVelocity + newVelocity) / 2.f * deltaSeconds; 59 | if (!xConstraint) 60 | actor->position.x += displacement.x; 61 | if (!yConstraint) 62 | actor->position.y += displacement.y; 63 | 64 | actor->SetVelocity(newVelocity); 65 | netForce = Vector2::Zero(); 66 | netImpulse = Vector2::Zero(); 67 | } 68 | 69 | void AddForce(const Vector2 input, const bool isImpulse = false) 70 | { 71 | isImpulse ? netImpulse += input : netForce += input; 72 | } 73 | 74 | void SetConstraints(const bool x, const bool y) 75 | { 76 | xConstraint = x; 77 | yConstraint = y; 78 | } 79 | 80 | 81 | 82 | private: 83 | // Config 84 | float mass = 1.f; 85 | float gravityScale = 1.f; 86 | float linearDrag = 0.0001f; 87 | 88 | bool xConstraint = false; 89 | bool yConstraint = false; 90 | 91 | // Intermediates 92 | Vector2 netForce; 93 | Vector2 netImpulse; 94 | }; 95 | -------------------------------------------------------------------------------- /Engine/General/Systems/CollisionSystem.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "CollisionSystem.h" 4 | #include "../Components/BoxCollider.h" 5 | #include "../Components/Physics.h" 6 | #include "../Actor.h" 7 | 8 | 9 | CollisionSystem::CollisionSystem(World * _world) 10 | { 11 | this->world = _world; 12 | } 13 | 14 | void CollisionSystem::operator()(int milliseconds) 15 | { 16 | while (!world->GetIsGameOver()) 17 | { 18 | if (world->GetGameTime() < 1.0f) continue; 19 | //RunCheck(); 20 | } 21 | } 22 | 23 | void CollisionSystem::Run() 24 | { 25 | // -------------------------------------------------- DETECTION 26 | collisionDataArray.clear(); 27 | 28 | if (!world->GetIsGamePaused()) 29 | { 30 | std::vector> & tempActors = world->GetAllWeakActorRefs(); 31 | //world->CurrentActorsMutex.lock(); 32 | /*for (auto actor : tempActors) 33 | { 34 | if (!actor) 35 | printf("Viper"); 36 | 37 | SmartPtr smartRef; 38 | actor.acquire(smartRef); 39 | actor.acquire(smartRef); 40 | if (actor.acquire(smartRef)) 41 | printf("Viper"); 42 | if (!smartRef) 43 | printf("Viper"); 44 | }*/ 45 | //world->CurrentActorsMutex.unlock(); 46 | //return; // TESTING 47 | //world->CurrentActorsMutex.lock(); 48 | const float DeltaSeconds = world->GetDeltaSeconds(); 49 | std::vector> & actors = world->GetAllWeakActorRefs(); 50 | const size_t actorsLen = actors.size(); 51 | /*if (actorsLen < 1) 52 | continue;*/ 53 | 54 | for (unsigned int i = 0; i < actorsLen - 1; i++) 55 | { 56 | SmartPtr myActor; 57 | actors[i].acquire(myActor); 58 | if (!myActor) continue; 59 | const BoxColliderComponent * myCollider = myActor->GetComponent(); 60 | if (!myCollider) continue; 61 | 62 | for (int j = i + 1; j < actorsLen; j++) 63 | { 64 | SmartPtr otherActor; 65 | actors[j].acquire(otherActor); 66 | if (!otherActor || otherActor == myActor) continue; 67 | 68 | const BoxColliderComponent * otherCollider = otherActor->GetComponent(); 69 | if (!otherCollider) continue; 70 | 71 | 72 | 73 | 74 | // COLLISION LOGIC 75 | float tMyEnter = 9999; 76 | float tOtherEnter = 9999; 77 | float tMyExit = 9999; 78 | float tOtherExit = 9999; 79 | 80 | const AABB myBounds = myCollider->getBounds(); 81 | const AABB otherBounds = otherCollider->getBounds(); 82 | 83 | 84 | const Matrix4 mOtherRot = Matrix4::ZRotation(otherActor->zRotation); 85 | const Matrix4 mOtherTrans = Matrix4::Translation(otherActor->position); 86 | const Matrix4 mOtherToWorld = mOtherTrans * mOtherRot; 87 | const Matrix4 mWorldToOther = mOtherToWorld.inverse(); 88 | 89 | const Matrix4 mMyRot = Matrix4::ZRotation(myActor->zRotation); 90 | const Matrix4 mMyTrans = Matrix4::Translation(myActor->position); 91 | const Matrix4 mMyToWorld = mMyTrans * mMyRot; 92 | const Matrix4 mWorldToMy = mMyToWorld.inverse(); 93 | 94 | 95 | const Matrix4 mOtherToMy = mWorldToMy * mOtherToWorld; 96 | const Matrix4 mMyToOther = mWorldToOther * mMyToWorld; 97 | 98 | const Vector4 myVelocity = myActor->GetVelocity(); 99 | const Vector4 otherVelocity = otherActor->GetVelocity(); 100 | const Vector4 myWorldRelativeVelocity = myVelocity - otherVelocity; 101 | const Vector4 otherWorldRelativeVelocity = myWorldRelativeVelocity.getInverse(); 102 | 103 | 104 | 105 | 106 | //////////////////////////////////////////////////////////////////////////////////////////////////// MY TEST 107 | const Vector4 otherCenterInMy = mOtherToMy * Vector4(otherBounds.Center, 1.f); 108 | 109 | const Vector4 otherExtentsXInMy = mOtherToMy * Vector4(otherBounds.Extents.x / 2, 0, 0, 0); 110 | const Vector4 otherExtentsYInMy = mOtherToMy * Vector4(0, otherBounds.Extents.y / 2, 0, 0); 111 | 112 | const float otherProjectionXOntoMyEnd = fabs(otherExtentsXInMy.x) + fabs(otherExtentsYInMy.x); 113 | const float otherProjectionYOntoMyEnd = fabs(otherExtentsXInMy.y) + fabs(otherExtentsYInMy.y); 114 | 115 | 116 | // Velocity Based Detection 117 | const Vector4 otherLocalRelativeVelocity = mMyRot * otherWorldRelativeVelocity; 118 | 119 | Vector4 myHitNormal; 120 | float myNormalTime = 0.f; 121 | 122 | 123 | float tMyH0 = -1; 124 | float tMyH1 = -1; 125 | bool bMyHSkip = false; 126 | if (Math::IsNearlyZero(otherLocalRelativeVelocity.x)) 127 | bMyHSkip = true; 128 | else 129 | { 130 | const float tR = ((myBounds.Center.x - (myBounds.Extents.x / 2)) - (otherCenterInMy.x + otherProjectionXOntoMyEnd)) / otherLocalRelativeVelocity.x; 131 | const float tL = ((myBounds.Center.x + (myBounds.Extents.x / 2)) - (otherCenterInMy.x - otherProjectionXOntoMyEnd)) / otherLocalRelativeVelocity.x; 132 | if (tR < tL) 133 | { 134 | myHitNormal = Vector2::Right(); 135 | myNormalTime = tR; 136 | } 137 | else 138 | { 139 | myHitNormal = Vector2::Left(); 140 | myNormalTime = tR; 141 | } 142 | tMyH0 = min(tR, tL); 143 | tMyH1 = max(tR, tL); 144 | } 145 | 146 | 147 | float tMyV0 = -1; 148 | float tMyV1 = -1; 149 | bool bMyVSkip = false; 150 | if (Math::IsNearlyZero(otherLocalRelativeVelocity.y)) 151 | bMyVSkip = true; 152 | else 153 | { 154 | const float tU = ((myBounds.Center.y - (myBounds.Extents.y / 2)) - (otherCenterInMy.y + otherProjectionYOntoMyEnd)) / otherLocalRelativeVelocity.y; 155 | const float tD = ((myBounds.Center.y + (myBounds.Extents.y / 2)) - (otherCenterInMy.y - otherProjectionYOntoMyEnd)) / otherLocalRelativeVelocity.y; 156 | if (tU < tD && tU < myNormalTime) 157 | { 158 | myHitNormal = Vector2::Up(); 159 | myNormalTime = tU; 160 | } 161 | if (tD < tU && tD < myNormalTime) 162 | { 163 | myHitNormal = Vector2::Down(); 164 | myNormalTime = tD; 165 | } 166 | tMyV0 = min(tU, tD); 167 | tMyV1 = max(tU, tD); 168 | } 169 | 170 | 171 | 172 | 173 | float tMyInMax = -1; 174 | float tMyOutMin = -1; 175 | int tMyModeIndicator = -1; 176 | bool bMySkip = false; 177 | 178 | if (!bMyHSkip && !bMyVSkip) 179 | { 180 | tMyInMax = max(tMyH0, tMyV0); 181 | tMyOutMin = min(tMyH1, tMyV1); 182 | if (tMyInMax < tMyOutMin) 183 | { 184 | tMyEnter = tMyInMax; 185 | tMyExit = tMyOutMin; 186 | } 187 | tMyModeIndicator = 0; 188 | } 189 | if (!bMyHSkip/* && bH*/ && bMyVSkip) 190 | { 191 | tMyInMax = tMyH0; 192 | tMyOutMin = tMyH1; 193 | tMyEnter = tMyInMax; 194 | tMyExit = tMyOutMin; 195 | tMyModeIndicator = 1; 196 | } 197 | if (bMyHSkip && !bMyVSkip/* && bV*/) 198 | { 199 | tMyInMax = tMyV0; 200 | tMyOutMin = tMyV1; 201 | tMyEnter = tMyInMax; 202 | tMyExit = tMyOutMin; 203 | tMyModeIndicator = 2; 204 | } 205 | if (bMyHSkip && bMyVSkip) 206 | { 207 | bMySkip = true; 208 | } 209 | 210 | //myHitNormal = mMyToWorld * Vector4(myHitNormal); 211 | //////////////////////////////////////////////////////////////////////////////////////////////////// MY TEST 212 | 213 | 214 | 215 | 216 | 217 | //////////////////////////////////////////////////////////////////////////////////////////////////// OTHER TEST 218 | const Vector4 myCenterInOther = mMyToOther * Vector4(myBounds.Center, 1.f); 219 | 220 | const Vector4 myExtentsXInOther = mMyToOther * Vector4(myBounds.Extents.x / 2, 0, 0, 0); 221 | const Vector4 myExtentsYInOther = mMyToOther * Vector4(0, myBounds.Extents.y / 2, 0, 0); 222 | 223 | const float myProjectionXOntoOtherEnd = fabs(myExtentsXInOther.x) + fabs(myExtentsYInOther.x); 224 | const float myProjectionYOntoOtherEnd = fabs(myExtentsXInOther.y) + fabs(myExtentsYInOther.y); 225 | 226 | 227 | // Velocity Based Detection 228 | const Vector4 myLocalRelativeVelocity = mOtherRot * myWorldRelativeVelocity; 229 | 230 | float tOtherH0 = -1; 231 | float tOtherH1 = -1; 232 | bool bOtherHSkip = false; 233 | if (Math::IsNearlyZero(myLocalRelativeVelocity.x)) 234 | bOtherHSkip = true; 235 | else 236 | { 237 | const float tR = ((otherBounds.Center.x - (otherBounds.Extents.x / 2)) - (myCenterInOther.x + myProjectionXOntoOtherEnd)) / myLocalRelativeVelocity.x; 238 | const float tL = ((otherBounds.Center.x + (otherBounds.Extents.x / 2)) - (myCenterInOther.x - myProjectionXOntoOtherEnd)) / myLocalRelativeVelocity.x; 239 | tOtherH0 = min(tR, tL); 240 | tOtherH1 = max(tR, tL); 241 | } 242 | 243 | 244 | float tOtherV0 = -1; 245 | float tOtherV1 = -1; 246 | bool bOtherVSkip = false; 247 | if (Math::IsNearlyZero(myLocalRelativeVelocity.y)) 248 | bOtherVSkip = true; 249 | else 250 | { 251 | const float tU = ((otherBounds.Center.y - (otherBounds.Extents.y / 2)) - (myCenterInOther.y + myProjectionYOntoOtherEnd)) / myLocalRelativeVelocity.y; 252 | const float tD = ((otherBounds.Center.y + (otherBounds.Extents.y / 2)) - (myCenterInOther.y - myProjectionYOntoOtherEnd)) / myLocalRelativeVelocity.y; 253 | tOtherV0 = min(tU, tD); 254 | tOtherV1 = max(tU, tD); 255 | } 256 | 257 | 258 | 259 | 260 | float tOtherInMax = -1; 261 | float tOtherOutMin = -1; 262 | int tOtherModeIndicator = -1; 263 | bool bOtherSkip = false; 264 | 265 | if (!bOtherHSkip && !bOtherVSkip) 266 | { 267 | tOtherInMax = max(tOtherH0, tOtherV0); 268 | tOtherOutMin = min(tOtherH1, tOtherV1); 269 | if (tOtherInMax < tOtherOutMin) 270 | { 271 | tOtherEnter = tOtherInMax; 272 | tOtherExit = tOtherOutMin; 273 | } 274 | tOtherModeIndicator = 0; 275 | } 276 | if (!bOtherHSkip && bOtherVSkip) 277 | { 278 | tOtherInMax = tOtherH0; 279 | tOtherOutMin = tOtherH1; 280 | tOtherEnter = tOtherInMax; 281 | tOtherExit = tOtherOutMin; 282 | tOtherModeIndicator = 1; 283 | } 284 | if (bOtherHSkip && !bOtherVSkip) 285 | { 286 | tOtherInMax = tOtherV0; 287 | tOtherOutMin = tOtherV1; 288 | tOtherEnter = tOtherInMax; 289 | tOtherExit = tOtherOutMin; 290 | tOtherModeIndicator = 2; 291 | } 292 | if (bOtherHSkip && bOtherVSkip) 293 | { 294 | bOtherSkip = true; 295 | } 296 | //////////////////////////////////////////////////////////////////////////////////////////////////// OTHER TEST 297 | 298 | 299 | 300 | if (bMySkip && bOtherSkip) 301 | continue; 302 | 303 | if (myActor->bDebugTrigger) 304 | myActor->bDebugTrigger = false; 305 | 306 | 307 | // FINALIZE 308 | const float tFinalEnter = max(tMyEnter, tOtherEnter); 309 | const float tFinalExit = min(tMyExit, tOtherExit); 310 | if (tMyEnter < 0 && tMyExit > 0 && tOtherEnter < 0 && tOtherExit > 0) 311 | { 312 | if (myActor->GetMobility() == EMobility::Moveable) myActor->OnCollisionStay(otherActor); 313 | if (otherActor->GetMobility() == EMobility::Moveable) otherActor->OnCollisionStay(myActor); 314 | 315 | if (myActor->bDestroyedOnHit) world->DeleteActor(myActor); 316 | if (otherActor->bDestroyedOnHit) world->DeleteActor(otherActor); 317 | } 318 | 319 | if (tMyEnter > 0 && tMyEnter < DeltaSeconds && tMyExit > 0 && tOtherEnter > 0 && tOtherEnter < DeltaSeconds && tOtherExit > 0) 320 | { 321 | collisionDataArray.push_back(CollisionData{ myActor, otherActor, tFinalEnter }); 322 | } 323 | } 324 | } 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | // -------------------------------------------------- RESOLUTION 334 | float tLeftInFrame = DeltaSeconds; 335 | while (!collisionDataArray.empty() && tLeftInFrame > 0) 336 | { 337 | unsigned int dataIndex = 0; 338 | for (unsigned int i = 1; i < collisionDataArray.size(); i++) 339 | if (collisionDataArray[i].enterTime < collisionDataArray[dataIndex].enterTime) 340 | dataIndex = i; 341 | 342 | 343 | tLeftInFrame -= collisionDataArray[dataIndex].enterTime; 344 | for (auto weakRef : actors) 345 | { 346 | SmartPtr actor; 347 | weakRef.acquire(actor); 348 | if (actor->GetMobility() == EMobility::Moveable) actor->position += actor->GetVelocity() * collisionDataArray[dataIndex].enterTime; 349 | } 350 | 351 | 352 | SmartPtr actor1 = collisionDataArray[dataIndex].actor1; 353 | SmartPtr actor2 = collisionDataArray[dataIndex].actor2; 354 | 355 | const float actor1Speed = actor1->GetVelocity().getMagnitude(); 356 | const float actor2Speed = actor2->GetVelocity().getMagnitude(); 357 | if (actor1->GetMobility() == EMobility::Moveable) actor1->SetVelocity((actor1->position - actor2->position).getNormalized() * ((actor2Speed + actor1Speed) / 2)); 358 | if (actor2->GetMobility() == EMobility::Moveable) actor2->SetVelocity((actor2->position - actor1->position).getNormalized() * ((actor2Speed + actor1Speed) / 2)); 359 | 360 | if (actor1->bDestroyedOnHit) world->DeleteActor(actor1); 361 | if (actor2->bDestroyedOnHit) world->DeleteActor(actor2); 362 | 363 | collisionDataArray.erase(collisionDataArray.begin() + dataIndex); 364 | } 365 | //world->CurrentActorsMutex.unlock(); 366 | } 367 | } -------------------------------------------------------------------------------- /Engine/General/Systems/CollisionSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../World.h" 4 | 5 | struct CollisionData 6 | { 7 | SmartPtr actor1; 8 | SmartPtr actor2; 9 | float enterTime; 10 | 11 | CollisionData & operator = (const CollisionData & otherCollisionData) 12 | { 13 | if (this == &otherCollisionData) 14 | return *this; 15 | actor1 = otherCollisionData.actor1; 16 | actor2 = otherCollisionData.actor2; 17 | enterTime = otherCollisionData.enterTime; 18 | return *this; 19 | } 20 | }; 21 | 22 | 23 | 24 | class CollisionSystem 25 | { 26 | World * world; 27 | std::vector collisionDataArray; 28 | 29 | public: 30 | CollisionSystem(World * _world); 31 | void operator()(int milliseconds); 32 | 33 | void Run(); 34 | }; -------------------------------------------------------------------------------- /Engine/General/Systems/Input.cpp: -------------------------------------------------------------------------------- 1 | #include "Input.h" 2 | 3 | std::vector * Input::keysDown; 4 | 5 | Input::Input() 6 | { 7 | keysDown = new std::vector(); 8 | } 9 | 10 | Input::~Input() 11 | { 12 | delete keysDown; 13 | } 14 | 15 | 16 | void Input::Keyboard_KeyPress(unsigned int i_VKeyID, bool bWentDown) 17 | { 18 | if (bWentDown) 19 | keysDown->push_back(i_VKeyID); 20 | else 21 | { 22 | for (unsigned int i = 0; i < keysDown->size(); i++) 23 | { 24 | if ((*keysDown)[i] == i_VKeyID) 25 | { 26 | keysDown->erase(keysDown->begin() + i); 27 | } 28 | } 29 | } 30 | } 31 | 32 | bool Input::Keyboard_IsKeyDown(unsigned i_VKeyID) 33 | { 34 | for (unsigned int key : *keysDown) 35 | { 36 | if (key == i_VKeyID) 37 | return true; 38 | } 39 | return false; 40 | } -------------------------------------------------------------------------------- /Engine/General/Systems/Input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class Input 7 | { 8 | static std::vector * keysDown; 9 | 10 | public: 11 | Input(); 12 | ~Input(); 13 | static bool Keyboard_IsKeyDown(unsigned int i_VKeyID); 14 | static void Keyboard_KeyPress(unsigned int i_VKeyID, bool bWentDown); 15 | }; 16 | -------------------------------------------------------------------------------- /Engine/General/World.cpp: -------------------------------------------------------------------------------- 1 | #include "World.h" 2 | #include "Windows.h" 3 | #include "../Render/GLibHelper.h" 4 | #include "GLib/GLib.h" 5 | #include 6 | #include "Components/BoxCollider.h" 7 | #include "Systems/Input.h" 8 | #include "Components/Physics.h" 9 | #include "Components/Follow.h" 10 | #include "Systems/CollisionSystem.h" 11 | using json = nlohmann::json; 12 | 13 | 14 | //////////////////////////////////////////////////////////////////////////////////////////////////// INIT/EXIT 15 | World::World(HINSTANCE i_hinstance, int i_cmdShow) 16 | { 17 | collisionSystem = new CollisionSystem(this); 18 | inputSystem = new Input(); 19 | 20 | const bool bSuccess = GLib::Initialize(i_hinstance, i_cmdShow, "Viper Engine Output", -1, 800, 600); 21 | assert(bSuccess); 22 | 23 | GLib::SetKeyStateChangeCallback(Input::Keyboard_KeyPress); 24 | } 25 | 26 | 27 | World::~World() 28 | { 29 | delete collisionSystem; 30 | delete inputSystem; 31 | } 32 | //////////////////////////////////////////////////////////////////////////////////////////////////// INIT/EXIT 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | //////////////////////////////////////////////////////////////////////////////////////////////////// ACTORS 45 | std::vector> World::GetAllActors() const 46 | { 47 | return actors; 48 | } 49 | void World::SpawnActor(SmartPtr & ref, const std::string name, const Vector2 spawn_location) 50 | { 51 | CurrentActorsMutex.lock(); 52 | const SmartPtr actor(new Actor(this, name, spawn_location)); 53 | ref = actor; 54 | actors.push_back(actor); 55 | UpdateWeakActorRefs(); 56 | CurrentActorsMutex.unlock(); 57 | } 58 | 59 | void World::SpawnQueuedActors() 60 | { 61 | if (!actorsToAdd.empty()) 62 | { 63 | CurrentActorsMutex.lock(); 64 | for (SmartPtr queuedActor : actorsToAdd) 65 | { 66 | actors.push_back(queuedActor); 67 | } 68 | actorsToAdd.clear(); 69 | CurrentActorsMutex.unlock(); 70 | } 71 | } 72 | 73 | 74 | void World::QueueNewActor(SmartPtr& ref, const std::string name, Vector2 spawn_location) 75 | { 76 | NewActorsMutex.lock(); 77 | const SmartPtr actor(new Actor(this, name, spawn_location)); 78 | ref = actor; 79 | actorsToAdd.push_back(actor); 80 | NewActorsMutex.unlock(); 81 | } 82 | 83 | 84 | 85 | 86 | 87 | 88 | void World::LoadScene(const std::string filePath) 89 | { 90 | std::ifstream file(filePath, std::ios_base::in); 91 | std::string fileData( 92 | (std::istreambuf_iterator(file)), 93 | std::istreambuf_iterator() 94 | ); 95 | auto editorState = json::parse(fileData); 96 | 97 | for (const json & actorData : editorState["actors"]) 98 | { 99 | SmartPtr ref; 100 | SpawnActorFromJson(actorData, ref); 101 | } 102 | } 103 | 104 | void World::SpawnPrefab(SmartPtr & ref, const std::string filePath) 105 | { 106 | std::ifstream file(filePath, std::ios_base::in); 107 | std::string fileData( 108 | (std::istreambuf_iterator(file)), 109 | std::istreambuf_iterator() 110 | ); 111 | auto actorData = json::parse(fileData); 112 | SpawnActorFromJson(actorData, ref); 113 | } 114 | 115 | void World::SpawnActorFromJson(const nlohmann::json & actorData, SmartPtr & ref) 116 | { 117 | // Set Position 118 | Vector2 spawnPos = Vector2::Zero(); 119 | float spawnRot = 0.0f; 120 | Vector2 spawnVelocity = Vector2::Zero(); 121 | if (actorData.contains("initial-position")) 122 | { 123 | const json & posData = actorData["initial-position"]; 124 | spawnPos = { posData[0], posData[1] }; 125 | } 126 | 127 | if (actorData.contains("initial-rotation")) 128 | { 129 | const json & posData = actorData["initial-rotation"]; 130 | spawnRot = posData.get(); 131 | } 132 | 133 | if (actorData.contains("initial-velocity")) 134 | { 135 | const json & velData = actorData["initial-velocity"]; 136 | spawnVelocity = { velData[0], velData[1] }; 137 | } 138 | 139 | // Set Name 140 | std::string actorName; 141 | if (actorData.contains("name")) 142 | { 143 | const json jName = actorData["name"]; 144 | actorName = jName.get(); 145 | } 146 | 147 | ////////// Spawn Actor 148 | SpawnActor(ref, actorName, spawnPos); 149 | ref->zRotation = spawnRot * 3.14159265359f / 180.f; 150 | ref->SetVelocity(spawnVelocity); 151 | 152 | if (actorData.contains("mobility") && actorData["mobility"].get() == "static") 153 | ref->SetMobility(EMobility::Static); 154 | 155 | // Set Sprite 156 | if (actorData.contains("sprite-path")) 157 | { 158 | auto spritePath = actorData["sprite-path"].get(); 159 | ref->sprite = GLibHelper::CreateSprite(spritePath.data()); 160 | } 161 | 162 | // Set Components 163 | for (const json & comp : actorData["components"]) 164 | { 165 | auto componentType = comp["type"].get(); 166 | const size_t nParams = comp.size(); 167 | 168 | // Physics 169 | if (componentType == "PhysicsComponent") 170 | { 171 | const float mass = comp["mass"].get(); 172 | const float gravityScale = comp["gravity-scale"].get(); 173 | const float linearDrag = comp["linear-drag"].get(); 174 | PhysicsComponent * newPhysicsComp = new PhysicsComponent( 175 | ref, 176 | nParams, 177 | mass, 178 | gravityScale, 179 | linearDrag 180 | ); 181 | ref->AddComponent(newPhysicsComp); 182 | 183 | if (comp.contains("constraints")) 184 | { 185 | const json & constraints = comp["constraints"]; 186 | newPhysicsComp->SetConstraints(constraints[0].get(), constraints[1].get()); 187 | } 188 | } 189 | 190 | // BoxCollider 191 | if (componentType == "BoxColliderComponent") 192 | { 193 | const Vector3 boxExtents{ comp["size"][0], comp["size"][1], 0.f }; 194 | ref->AddComponent(new BoxColliderComponent(ref, Vector3::Zero(), boxExtents)); 195 | } 196 | 197 | // Follow 198 | if (componentType == "FollowComponent") 199 | { 200 | auto followComp = new FollowComponent(ref); 201 | if (playerActor) 202 | { 203 | followComp->targetActorRef = playerActor; 204 | followComp->bShouldFollow = comp["should-follow"].get(); 205 | followComp->followForce = comp["follow-force"].get(); 206 | } 207 | ref->AddComponent(followComp); 208 | } 209 | } 210 | 211 | // Set Player Actor 212 | if (actorData.contains("player-actor") && actorData["player-actor"].get()) 213 | playerActor = ref; 214 | } 215 | 216 | void World::DeleteActor(SmartPtr & actor) 217 | { 218 | for (size_t i = 0; i < actors.size(); i++) 219 | { 220 | SmartPtr & cmpActor = actors.at(i); 221 | if (cmpActor == actor) 222 | { 223 | //actors[i] = nullptr; 224 | const auto spriteRef = cmpActor->sprite; 225 | if (spriteRef) 226 | { 227 | GLib::Sprites::Release(spriteRef); 228 | cmpActor->sprite = nullptr; 229 | } 230 | actors.erase(actors.begin() + i); 231 | break; 232 | } 233 | } 234 | UpdateWeakActorRefs(); 235 | } 236 | 237 | void World::DeleteAllActors() 238 | { 239 | playerActor = nullptr; 240 | for (SmartPtr & ref : actors) 241 | { 242 | if (ref->sprite) 243 | GLib::Sprites::Release(ref->sprite); 244 | ref = nullptr; 245 | } 246 | actors.clear(); 247 | UpdateWeakActorRefs(); 248 | } 249 | 250 | 251 | // PlayerActor 252 | void World::SetPlayerActor(SmartPtr & actor) 253 | { 254 | playerActor = actor; 255 | } 256 | WeakPtr & World::GetPlayerActor() 257 | { 258 | return playerActor; 259 | } 260 | 261 | 262 | // WeakRefs 263 | void World::UpdateWeakActorRefs() 264 | { 265 | CurrentActorRefsMutex.lock(); 266 | actorRefs.clear(); 267 | for (SmartPtr & actor : GetAllActors()) 268 | actorRefs.emplace_back(actor); 269 | CurrentActorRefsMutex.unlock(); 270 | } 271 | std::vector>& World::GetAllWeakActorRefs() 272 | { 273 | return actorRefs; 274 | } 275 | //////////////////////////////////////////////////////////////////////////////////////////////////// ACTORS 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | //////////////////////////////////////////////////////////////////////////////////////////////////// RENDER 289 | bool World::RenderAllActors() 290 | { 291 | // Pre-Render 292 | bool serviceInput; 293 | GLib::Service(serviceInput); 294 | if (serviceInput) return false; 295 | 296 | GLib::BeginRendering(); 297 | GLib::Sprites::BeginRendering(); 298 | 299 | for (WeakPtr & weakRef : actorRefs) 300 | { 301 | SmartPtr actor; 302 | weakRef.acquire(actor); 303 | if (actor && actor->sprite) 304 | { 305 | GLib::Point2D Offset = { actor->position.x, actor->position.y }; 306 | RenderSprite(*actor->sprite, Offset, actor->zRotation); 307 | } 308 | } 309 | 310 | // Post-Render 311 | GLib::Sprites::EndRendering(); 312 | GLib::EndRendering(); 313 | return true; 314 | } 315 | //////////////////////////////////////////////////////////////////////////////////////////////////// RENDER 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | //////////////////////////////////////////////////////////////////////////////////////////////////// EVENTS 329 | void World::BeginPlayAll() 330 | { 331 | CurrentActorsMutex.lock(); 332 | for (WeakPtr & weakRef : actorRefs) 333 | { 334 | SmartPtr actor; 335 | weakRef.acquire(actor); 336 | if (actor) actor->BeginPlay(); 337 | } 338 | 339 | // Time keeping 340 | LARGE_INTEGER lgInt; 341 | QueryPerformanceCounter(&lgInt); 342 | lastTimePoint = lgInt.QuadPart; 343 | CurrentActorsMutex.unlock(); 344 | } 345 | void World::TickAll() 346 | { 347 | CurrentActorsMutex.lock(); 348 | for (WeakPtr & weakRef : actorRefs) 349 | { 350 | SmartPtr actor; 351 | weakRef.acquire(actor); 352 | if (actor) actor->Tick(deltaSeconds); 353 | } 354 | 355 | collisionSystem->Run(); 356 | 357 | // Time keeping 358 | LARGE_INTEGER lgInt; 359 | QueryPerformanceCounter(&lgInt); 360 | QueryPerformanceFrequency(&pcFrequency); 361 | deltaSeconds = float(lgInt.QuadPart - lastTimePoint) / float(pcFrequency.QuadPart); 362 | lastTimePoint = lgInt.QuadPart; 363 | totalSeconds += deltaSeconds; 364 | CurrentActorsMutex.unlock(); 365 | } 366 | void World::EndPlay() 367 | { 368 | isGameOver = true; 369 | } 370 | bool World::GetIsGameOver() const 371 | { 372 | return isGameOver; 373 | } 374 | bool World::GetIsGamePaused() const 375 | { 376 | return isGamePaused; 377 | } 378 | void World::PauseToggle() 379 | { 380 | isGamePaused = !isGamePaused; 381 | } 382 | 383 | 384 | float World::GetDeltaSeconds() const 385 | { 386 | return static_cast(deltaSeconds); 387 | } 388 | float World::GetGameTime() const 389 | { 390 | return totalSeconds; 391 | } 392 | void World::Shutdown() 393 | { 394 | DeleteAllActors(); 395 | GLib::Shutdown(); 396 | delete this; 397 | } 398 | //////////////////////////////////////////////////////////////////////////////////////////////////// EVENTS -------------------------------------------------------------------------------- /Engine/General/World.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Windows.h" 6 | #include "Actor.h" 7 | #include "../Memory/SmartPointer/WeakPtr.h" 8 | #include 9 | #include "json.hpp" 10 | 11 | class CollisionSystem; 12 | class Input; 13 | 14 | 15 | class World 16 | { 17 | public: 18 | World(HINSTANCE i_hinstance, int i_cmdShow); 19 | ~World(); 20 | 21 | std::vector> GetAllActors() const; 22 | void SpawnActor(SmartPtr & ref, const std::string name, Vector2 spawn_location); 23 | void SpawnPrefab(SmartPtr & ref, const std::string filePath); 24 | void SpawnActorFromJson(const nlohmann::json & actorData, SmartPtr & ref); 25 | void SpawnQueuedActors(); 26 | void QueueNewActor(SmartPtr & ref, const std::string name, Vector2 spawn_location); 27 | void LoadScene(const std::string filePath); 28 | bool RenderAllActors(); 29 | void DeleteActor(SmartPtr & actor); 30 | void DeleteAllActors(); 31 | void SetPlayerActor(SmartPtr & actor); 32 | WeakPtr & GetPlayerActor(); 33 | std::vector> & GetAllWeakActorRefs(); 34 | void UpdateWeakActorRefs(); 35 | 36 | void TickAll(); 37 | void BeginPlayAll(); 38 | void EndPlay(); 39 | void Shutdown(); 40 | bool GetIsGameOver() const; 41 | bool GetIsGamePaused() const; 42 | void PauseToggle(); 43 | float GetDeltaSeconds() const; 44 | float GetGameTime() const; 45 | 46 | 47 | std::mutex CurrentActorsMutex; 48 | std::mutex CurrentActorRefsMutex; 49 | 50 | private: 51 | std::vector> actors; 52 | std::vector> actorRefs; 53 | 54 | CollisionSystem * collisionSystem; 55 | Input * inputSystem; 56 | 57 | std::mutex NewActorsMutex; 58 | std::vector> actorsToAdd; 59 | 60 | 61 | 62 | 63 | WeakPtr playerActor; 64 | bool isGameOver = false; 65 | bool isGamePaused = false; 66 | __int64 lastTimePoint; 67 | LARGE_INTEGER pcFrequency; 68 | float deltaSeconds; 69 | float totalSeconds; 70 | }; -------------------------------------------------------------------------------- /Engine/Jobs/Console/ConsolePrint.Win32.cpp: -------------------------------------------------------------------------------- 1 | #include // for va_ 2 | #include // for vsprintf_s() 3 | #include // for OutputDebugStringA(). Uggh.. this pulls in a lot of Windows specific stuff 4 | 5 | namespace Engine 6 | { 7 | 8 | void ConsolePrint( const char * i_pFmt, const char * i_pFile, unsigned int i_Line, ... ) 9 | { 10 | const size_t lenTemp = 128; 11 | char strTemp[lenTemp] = "DEBUG: %s %u: "; 12 | 13 | strcat_s( strTemp, i_pFmt ); 14 | 15 | const size_t lenOutput = 256; 16 | char strOutput[lenOutput]; 17 | 18 | // define a variable argument list variable 19 | va_list args; 20 | 21 | // initialize it. second parameter is variable immediately 22 | // preceeding variable arguments 23 | va_start( args, i_pFmt ); 24 | 25 | // (safely) print our formatted string to a char buffer 26 | vsprintf_s( strOutput, lenOutput, strTemp, args ); 27 | 28 | va_end( args ); 29 | 30 | OutputDebugStringA( strOutput ); 31 | } 32 | 33 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/Console/ConsolePrint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace Engine 4 | { 5 | 6 | void ConsolePrint( const char * i_pFmt, const char * i_pFile, unsigned int i_Line, ... ); 7 | 8 | } // namespace Engine 9 | 10 | // This is how we handle variable argument pre-processor macros 11 | // This is only supported by compilers that support the C99 standard 12 | #if defined(_DEBUG) && !defined(DISABLE_DEBUG_PRINT) 13 | #define DEBUG_PRINT(fmt,...) Engine::ConsolePrint((fmt),__FILE__,__LINE__,__VA_ARGS__) 14 | #else 15 | // This is one way we create a do nothing (NO OP) macro that doesn't 16 | // generate a compiler warning or error 17 | #define DEBUG_PRINT(fmt,...) void(0) 18 | #endif 19 | -------------------------------------------------------------------------------- /Engine/Jobs/HashedString/HashedString-inl.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Engine 5 | { 6 | inline HashedString::HashedString( ) : 7 | m_Hash( Hash( "" ) ) 8 | { 9 | } 10 | 11 | inline HashedString::HashedString( const char * i_string ) : 12 | m_Hash( Hash( i_string ) ) 13 | #ifdef DEBUG_KEEP_STRING 14 | , m_pString( strdup( i_string ) ) 15 | #endif 16 | { 17 | } 18 | 19 | inline HashedString::HashedString( const HashedString & i_other ) : 20 | m_Hash( i_other.m_Hash ) 21 | #ifdef DEBUG_KEEP_STRING 22 | , m_pString( strdup( i_other.m_pString ) ) 23 | #endif 24 | { 25 | } 26 | 27 | inline HashedString::~HashedString() 28 | { 29 | #ifdef DEBUG_KEEP_STRING 30 | if( m_pString ) 31 | free( m_pString ) 32 | #endif 33 | 34 | } 35 | 36 | inline HashedString & HashedString::operator=( const HashedString & i_other ) 37 | { 38 | m_Hash = i_other.m_Hash; 39 | 40 | #ifdef DEBUG_KEEP_STRING 41 | if( m_pString ) 42 | free( m_pString ) 43 | 44 | m_pString = i_other.m_pString; 45 | #endif 46 | 47 | return *this; 48 | } 49 | 50 | inline unsigned int HashedString::Get( void ) const 51 | { 52 | return m_Hash; 53 | } 54 | 55 | inline bool HashedString::operator==( const HashedString & i_other ) const 56 | { 57 | return m_Hash == i_other.m_Hash; 58 | } 59 | 60 | inline bool HashedString::operator<( const HashedString & i_other ) const 61 | { 62 | return m_Hash < i_other.m_Hash; 63 | } 64 | } // namespace Engine 65 | -------------------------------------------------------------------------------- /Engine/Jobs/HashedString/HashedString.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "HashedString.h" 4 | 5 | namespace Engine 6 | { 7 | 8 | unsigned int HashedString::Hash( const char * i_string ) 9 | { 10 | assert( i_string ); 11 | 12 | return Hash( reinterpret_cast( const_cast( i_string ) ), strlen( i_string ) ); 13 | } 14 | 15 | unsigned int HashedString::Hash( const void * i_bytes, size_t i_bytecount ) 16 | { 17 | // FNV hash, http://isthe.com/chongo/tech/comp/fnv/ 18 | 19 | register const unsigned char * p = static_cast( i_bytes ); 20 | unsigned int hash = 2166136261; 21 | 22 | for( size_t i = 0; i < i_bytecount; ++i ) 23 | hash = 16777619 * (hash ^ p[i]); 24 | 25 | return hash ^ (hash >> 16); 26 | } ; 27 | 28 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/HashedString/HashedString.h: -------------------------------------------------------------------------------- 1 | #ifndef __HASHED_STRING_H 2 | #define __HASHED_STRING_H 3 | 4 | namespace Engine 5 | { 6 | 7 | class HashedString 8 | { 9 | public: 10 | HashedString(); 11 | ~HashedString(); 12 | 13 | HashedString( const char * i_string ); 14 | HashedString( const HashedString & i_other ); 15 | HashedString & operator=( const HashedString & i_other ); 16 | 17 | unsigned int Get() const; 18 | 19 | bool operator==( const HashedString & i_other ) const; 20 | bool operator<( const HashedString & i_other ) const; 21 | 22 | static unsigned int Hash( const char * i_string ); 23 | static unsigned int Hash( const void * i_bytes, size_t i_count ); 24 | private: 25 | unsigned int m_Hash; 26 | 27 | #ifdef DEBUG_KEEP_STRING 28 | const char * m_pString; 29 | #endif 30 | } ; 31 | 32 | } // namespace Engine 33 | 34 | #include "HashedString-inl.h" 35 | 36 | #endif // __HASHED_STRING_H -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/IJob.cpp: -------------------------------------------------------------------------------- 1 | #include "IJob.h" 2 | 3 | #include 4 | 5 | namespace Engine 6 | { 7 | namespace JobSystem 8 | { 9 | CRITICAL_SECTION IJob::m_Shutdown; 10 | bool IJob::m_bShutdown = false; 11 | 12 | void IJob::Shutdown() 13 | { 14 | static bool bInited = false; 15 | if (bInited == false) 16 | { 17 | InitializeCriticalSection(&m_Shutdown); 18 | bInited = true; 19 | } 20 | 21 | EnterCriticalSection(&m_Shutdown); 22 | m_bShutdown = true; 23 | LeaveCriticalSection(&m_Shutdown); 24 | } 25 | 26 | } // namespace JobSystem 27 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/IJob.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "INamed.h" 6 | 7 | namespace Engine 8 | { 9 | namespace JobSystem 10 | { 11 | class IJob 12 | #ifdef _DEBUG 13 | : public INamed 14 | #endif 15 | { 16 | public: 17 | IJob(const char* i_pName) : 18 | INamed(i_pName) 19 | {} 20 | 21 | virtual ~IJob() { } 22 | virtual void Run() = 0; 23 | 24 | static void Shutdown(); 25 | static bool ShutdownRequested(); 26 | private: 27 | static CRITICAL_SECTION m_Shutdown; 28 | static bool m_bShutdown; 29 | }; 30 | 31 | inline bool IJob::ShutdownRequested() 32 | { 33 | return m_bShutdown; 34 | } 35 | 36 | } // namespace JobSystem 37 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/INamed.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | namespace Engine 5 | { 6 | namespace JobSystem 7 | { 8 | class INamed 9 | { 10 | public: 11 | INamed(const char* i_pName = nullptr) : 12 | m_Name(i_pName ? i_pName : "") 13 | {} 14 | 15 | void SetName(const char* i_pName) 16 | { 17 | m_Name = i_pName; 18 | } 19 | const char* GetName(void) const 20 | { 21 | return m_Name.c_str(); 22 | } 23 | 24 | private: 25 | std::string m_Name; 26 | }; 27 | 28 | } // namespace JobSystem 29 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/JobRunner.cpp: -------------------------------------------------------------------------------- 1 | #include "JobRunner.h" 2 | 3 | #include 4 | 5 | #include "JobSystem.h" 6 | #include "../Console/ConsolePrint.h" 7 | 8 | namespace Engine 9 | { 10 | namespace JobSystem 11 | { 12 | 13 | DWORD WINAPI JobRunner(void* i_pThreadInput) 14 | { 15 | assert(i_pThreadInput); 16 | assert(((JobRunnerInput*)i_pThreadInput)->i_pQueue); 17 | 18 | JobRunnerInput* pInput = reinterpret_cast(i_pThreadInput); 19 | SharedJobQueue* pQueue = reinterpret_cast(pInput->i_pQueue); 20 | 21 | DEBUG_PRINT("JobRunner \"%s\": Starting Queue \"%s\".\n", pInput->m_ThreadName.c_str(), pQueue->GetName() ? pQueue->GetName() : "Unknown"); 22 | 23 | bool bDone = false; 24 | 25 | do 26 | { 27 | DEBUG_PRINT("JobRunner \"%s\": Acquiring Job.\n", pInput->m_ThreadName.c_str()); 28 | struct JobData* pJob = pQueue->GetWhenAvailable(); 29 | if (pJob) 30 | { 31 | DEBUG_PRINT("JobRunner \"%s\": Starting Job \"%s\" on Processor %d.\n", pInput->m_ThreadName.c_str(), pJob->Name.c_str(), GetCurrentProcessorNumber()); 32 | 33 | pJob->Function(); 34 | 35 | DEBUG_PRINT("JobRunner \"%s\": Finished Job \"%s\".\n", pInput->m_ThreadName.c_str(), pJob->Name.c_str()); 36 | delete pJob; 37 | pQueue->JobFinished(); 38 | bDone = ShutdownRequested(); 39 | } 40 | else 41 | bDone = ShutdownRequested(); 42 | 43 | } while (bDone == false); 44 | 45 | #ifdef _DEBUG 46 | DEBUG_PRINT("JobRunner \"%s\": Shutting down.\n", pInput->m_ThreadName.c_str()); 47 | #endif 48 | return 0; 49 | } 50 | 51 | } // namespace JobSystem 52 | } // namespace Engine 53 | -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/JobRunner.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SharedJobQueue.h" 4 | 5 | namespace Engine 6 | { 7 | namespace JobSystem 8 | { 9 | 10 | struct JobRunnerInput 11 | { 12 | SharedJobQueue* i_pQueue; 13 | #ifdef _DEBUG 14 | std::string m_ThreadName; 15 | #endif 16 | }; 17 | 18 | DWORD WINAPI JobRunner(void* i_pJobRunnerInput); 19 | 20 | } // namespace JobSystem 21 | } // namespace Engine 22 | -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/JobSystem.cpp: -------------------------------------------------------------------------------- 1 | #include "JobSystem.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "..\Console\ConsolePrint.h" 7 | #include "..\HashedString\HashedString.h" 8 | 9 | #include "JobRunner.h" 10 | #include "SharedJobQueue.h" 11 | 12 | namespace Engine 13 | { 14 | namespace JobSystem 15 | { 16 | struct JobRunnerData 17 | { 18 | HANDLE m_ThreadHandle; 19 | DWORD m_ThreadID; 20 | JobRunnerInput m_Input; 21 | }; 22 | 23 | struct JobQueueData 24 | { 25 | SharedJobQueue m_SharedQueue; 26 | std::vector m_Runners; 27 | }; 28 | 29 | bool bShutdownRequested = false; 30 | std::map Queues; 31 | 32 | void RequestShutdown() 33 | { 34 | DEBUG_PRINT("Job System: Shutting down.\n"); 35 | 36 | bShutdownRequested = true; 37 | 38 | std::vector AllThreads; 39 | 40 | std::map::iterator iter = Queues.begin(); 41 | while (iter != Queues.end()) 42 | { 43 | 44 | if (iter->second) 45 | { 46 | const size_t count = iter->second->m_Runners.size(); 47 | for (size_t i = 0; i < count; i++) 48 | { 49 | JobRunnerData* pRunner = iter->second->m_Runners[i]; 50 | if (pRunner && pRunner->m_ThreadHandle != NULL) 51 | AllThreads.push_back(pRunner->m_ThreadHandle); 52 | } 53 | } 54 | ++iter; 55 | } 56 | 57 | DEBUG_PRINT("Job System: Waiting for Queue runner threads to shut down.\n"); 58 | 59 | DWORD result = WaitForMultipleObjects(static_cast(AllThreads.size()), &AllThreads[0], TRUE, INFINITE); 60 | assert(result == WAIT_OBJECT_0); 61 | 62 | iter = Queues.begin(); 63 | while (iter != Queues.end()) 64 | { 65 | if (iter->second) 66 | { 67 | const size_t count = iter->second->m_Runners.size(); 68 | for (size_t i = 0; i < count; i++) 69 | { 70 | JobRunnerData* pRunner = iter->second->m_Runners[i]; 71 | if (pRunner) 72 | delete pRunner; 73 | } 74 | 75 | delete iter->second; 76 | } 77 | 78 | ++iter; 79 | } 80 | 81 | Queues.clear(); 82 | 83 | } 84 | 85 | bool ShutdownRequested() 86 | { 87 | return bShutdownRequested; 88 | } 89 | 90 | void AddRunner(JobQueueData& i_QueueData) 91 | { 92 | size_t runners = i_QueueData.m_Runners.size(); 93 | 94 | JobRunnerData* pNewRunner = new JobRunnerData; 95 | 96 | pNewRunner->m_Input.i_pQueue = &i_QueueData.m_SharedQueue; 97 | #ifdef _DEBUG 98 | const size_t sizeThreadName = 32; 99 | char ThreadName[sizeThreadName]; 100 | sprintf_s(ThreadName, sizeThreadName, "%s %d", i_QueueData.m_SharedQueue.GetName(), int(runners + 1)); 101 | pNewRunner->m_Input.m_ThreadName = ThreadName; 102 | #endif 103 | 104 | pNewRunner->m_ThreadHandle = CreateThread(NULL, 0, JobRunner, &pNewRunner->m_Input, CREATE_SUSPENDED, &pNewRunner->m_ThreadID); 105 | assert(pNewRunner->m_ThreadHandle != NULL); 106 | 107 | i_QueueData.m_Runners.push_back(pNewRunner); 108 | ResumeThread(pNewRunner->m_ThreadHandle); 109 | } 110 | 111 | void AddRunner(const HashedString& i_QueueName) 112 | { 113 | std::map::iterator existing = Queues.find(i_QueueName); 114 | assert(existing != Queues.end()); 115 | assert(existing->second); 116 | 117 | AddRunner(*existing->second); 118 | } 119 | 120 | void CreateQueue(const char* i_pName, unsigned int i_numRunners) 121 | { 122 | assert(i_pName); 123 | 124 | HashedString HashedName(i_pName); 125 | 126 | assert(Queues.find(HashedName) == Queues.end()); 127 | 128 | JobQueueData* pNewJobQueueData = new JobQueueData; 129 | pNewJobQueueData->m_SharedQueue.SetName(i_pName); 130 | 131 | Queues[HashedName] = pNewJobQueueData; 132 | 133 | for (unsigned int i = 0; i < i_numRunners; i++) 134 | AddRunner(*pNewJobQueueData); 135 | } 136 | 137 | bool HasJobs(const HashedString& i_QueueName) 138 | { 139 | std::map::iterator existing = Queues.find(i_QueueName); 140 | if (existing != Queues.end()) 141 | { 142 | if (existing->second) 143 | return existing->second->m_SharedQueue.HasJobs(); 144 | } 145 | 146 | return false; 147 | } 148 | 149 | void RunJob(const std::string& i_JobName, std::function i_JobFunction, const HashedString& i_QueueName) 150 | { 151 | std::map::iterator existing = Queues.find(i_QueueName); 152 | assert(existing != Queues.end()); 153 | assert(existing->second); 154 | 155 | DEBUG_PRINT("Job System: Adding Job to Queue \"%s\".\n", existing->second->m_SharedQueue.GetName()); 156 | existing->second->m_SharedQueue.Add(new JobData(i_JobName, i_JobFunction)); 157 | } 158 | 159 | } // namespace JobSystem 160 | } // namespace Engine 161 | 162 | -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/JobSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "..\HashedString\HashedString.h" 7 | 8 | namespace Engine 9 | { 10 | namespace JobSystem 11 | { 12 | struct JobData 13 | { 14 | std::string Name; 15 | std::function Function; 16 | 17 | JobData(const std::string& i_Name, std::function i_Function) : 18 | Name(i_Name), 19 | Function(i_Function) 20 | {} 21 | }; 22 | 23 | void CreateQueue(const char* i_pName, unsigned int i_numRunners); 24 | bool HasJobs(const HashedString& i_QueueName); 25 | void AddRunner(const HashedString& i_QueueName); 26 | 27 | void RunJob(const std::string& i_JobName, std::function i_JobFunction, const HashedString& i_QueueName); 28 | void RequestShutdown(); 29 | bool ShutdownRequested(); 30 | 31 | } // namespace JobSystem 32 | } // namespace Engine 33 | -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/SharedJobQueue-inl.h: -------------------------------------------------------------------------------- 1 | namespace Engine 2 | { 3 | namespace JobSystem 4 | { 5 | inline void SharedJobQueue::Shutdown() 6 | { 7 | EnterCriticalSection(&m_QueueAccess); 8 | m_ShutdownRequested = true; 9 | LeaveCriticalSection(&m_QueueAccess); 10 | 11 | WakeAllConditionVariable(&m_WakeAndCheck); 12 | } 13 | 14 | inline bool SharedJobQueue::ShutdownRequested() const 15 | { 16 | return m_ShutdownRequested; 17 | } 18 | 19 | } // namespace JobSystem 20 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/SharedJobQueue.cpp: -------------------------------------------------------------------------------- 1 | #include "SharedJobQueue.h" 2 | 3 | #include 4 | 5 | #include "..\Console\ConsolePrint.h" 6 | 7 | namespace Engine 8 | { 9 | namespace JobSystem 10 | { 11 | SharedJobQueue::SharedJobQueue() : 12 | m_ShutdownRequested(false) 13 | { 14 | InitializeConditionVariable(&m_WakeAndCheck); 15 | InitializeCriticalSection(&m_QueueAccess); 16 | } 17 | 18 | bool SharedJobQueue::Add(struct JobData* i_pJob) 19 | { 20 | assert(i_pJob); 21 | bool bAdded = false; 22 | 23 | EnterCriticalSection(&m_QueueAccess); 24 | if (m_ShutdownRequested == false) 25 | { 26 | m_Jobs.push(i_pJob); 27 | bAdded = true; 28 | } 29 | LeaveCriticalSection(&m_QueueAccess); 30 | 31 | if (bAdded) 32 | WakeConditionVariable(&m_WakeAndCheck); 33 | 34 | return bAdded; 35 | } 36 | 37 | bool SharedJobQueue::HasJobs() const 38 | { 39 | EnterCriticalSection(&m_QueueAccess); 40 | bool bFinished = m_Jobs.empty() && !m_bJobRunning; 41 | LeaveCriticalSection(&m_QueueAccess); 42 | 43 | return !bFinished; 44 | } 45 | 46 | void SharedJobQueue::JobFinished() 47 | { 48 | EnterCriticalSection(&m_QueueAccess); 49 | m_bJobRunning = false; 50 | LeaveCriticalSection(&m_QueueAccess); 51 | } 52 | 53 | struct JobData* SharedJobQueue::GetWhenAvailable() 54 | { 55 | EnterCriticalSection(&m_QueueAccess); 56 | 57 | if (m_Jobs.empty() && (m_ShutdownRequested == false)) 58 | { 59 | BOOL result = SleepConditionVariableCS(&m_WakeAndCheck, &m_QueueAccess, INFINITE); 60 | assert(result != 0); 61 | 62 | if (m_ShutdownRequested == true) 63 | { 64 | LeaveCriticalSection(&m_QueueAccess); 65 | return nullptr; 66 | } 67 | } 68 | 69 | struct JobData* pJob = nullptr; 70 | 71 | if (!m_Jobs.empty()) 72 | { 73 | pJob = m_Jobs.front(); 74 | m_Jobs.pop(); 75 | } 76 | 77 | m_bJobRunning = true; 78 | 79 | LeaveCriticalSection(&m_QueueAccess); 80 | return pJob; 81 | } 82 | 83 | } // namespace JobSystem 84 | } // namespace Engine 85 | -------------------------------------------------------------------------------- /Engine/Jobs/JobSystem/SharedJobQueue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "INamed.h" 7 | 8 | namespace Engine 9 | { 10 | namespace JobSystem 11 | { 12 | struct JobData; 13 | 14 | class SharedJobQueue 15 | #ifdef _DEBUG 16 | : public INamed 17 | #endif 18 | { 19 | public: 20 | SharedJobQueue(); 21 | 22 | bool Add(struct JobData* i_JobData); 23 | bool HasJobs() const; 24 | struct JobData* GetWhenAvailable(); 25 | void JobFinished(); 26 | private: 27 | SharedJobQueue(const SharedJobQueue&) = delete; 28 | SharedJobQueue& operator=(const SharedJobQueue&) = delete; 29 | 30 | std::queue m_Jobs; 31 | CONDITION_VARIABLE m_WakeAndCheck; 32 | mutable CRITICAL_SECTION m_QueueAccess; 33 | 34 | bool m_bJobRunning; 35 | bool m_ShutdownRequested; 36 | }; 37 | 38 | } // namespace JobSystem 39 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/Events.cpp: -------------------------------------------------------------------------------- 1 | #include "Events.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace Engine 7 | { 8 | 9 | ManualResetEvent::ManualResetEvent(bool i_bInitiallySignaled, const char* i_pName) 10 | { 11 | m_Handle = CreateEvent(NULL, TRUE, i_bInitiallySignaled, i_pName); 12 | assert(m_Handle != INVALID_HANDLE_VALUE); 13 | } 14 | 15 | ManualResetEvent::~ManualResetEvent() 16 | { 17 | CloseHandle(m_Handle); 18 | } 19 | 20 | void ManualResetEvent::Reset(void) 21 | { 22 | ResetEvent(m_Handle); 23 | } 24 | 25 | bool ManualResetEvent::Wait(wait_t i_WaitMilliseconds) 26 | { 27 | DWORD result = WaitForSingleObject(m_Handle, i_WaitMilliseconds); 28 | assert(((i_WaitMilliseconds == WaitInfinite) && (result == WAIT_OBJECT_0)) || (result == WAIT_TIMEOUT)); 29 | 30 | return result == WAIT_OBJECT_0; 31 | } 32 | 33 | void ManualResetEvent::Signal(void) 34 | { 35 | BOOL result = SetEvent(m_Handle); 36 | assert(result == TRUE); 37 | } 38 | 39 | AutoResetEvent::AutoResetEvent(bool i_bInitiallySignaled, const char* i_pName) 40 | { 41 | m_Handle = CreateEvent(NULL, FALSE, i_bInitiallySignaled, i_pName); 42 | assert(m_Handle != INVALID_HANDLE_VALUE); 43 | } 44 | 45 | AutoResetEvent::~AutoResetEvent() 46 | { 47 | CloseHandle(m_Handle); 48 | } 49 | 50 | bool AutoResetEvent::Wait(wait_t i_WaitMilliseconds) 51 | { 52 | DWORD result = WaitForSingleObject(m_Handle, i_WaitMilliseconds); 53 | assert(((i_WaitMilliseconds == WaitInfinite) && (result == WAIT_OBJECT_0)) || (result == WAIT_TIMEOUT)); 54 | 55 | return result == WAIT_OBJECT_0; 56 | } 57 | 58 | void AutoResetEvent::Signal(void) 59 | { 60 | BOOL result = SetEvent(m_Handle); 61 | assert(result == TRUE); 62 | } 63 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/Events.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "WaitableObject.h" 6 | 7 | namespace Engine 8 | { 9 | class Event : public WaitableObject 10 | { 11 | public: 12 | virtual bool Wait(wait_t i_WaitMilliseconds) = 0; 13 | virtual void Signal() = 0; 14 | 15 | }; 16 | 17 | class ManualResetEvent : public Event 18 | { 19 | public: 20 | ManualResetEvent(bool i_bInitiallySignaled = false, const char* i_pName = nullptr); 21 | ~ManualResetEvent(); 22 | 23 | void Reset(); 24 | 25 | bool Wait(wait_t i_WaitMilliseconds = INFINITE); 26 | void Signal(); 27 | private: 28 | ManualResetEvent(const ManualResetEvent&) = delete; 29 | ManualResetEvent& operator=(const ManualResetEvent&) = delete; 30 | }; 31 | 32 | class AutoResetEvent : public Event 33 | { 34 | public: 35 | AutoResetEvent(bool i_bInitiallySignaled = false, const char* i_pName = nullptr); 36 | ~AutoResetEvent(); 37 | 38 | bool Wait(wait_t i_WaitMilliseconds = INFINITE); 39 | void Signal(); 40 | private: 41 | AutoResetEvent(const AutoResetEvent&) = delete; 42 | AutoResetEvent& operator=(const AutoResetEvent&) = delete; 43 | }; 44 | 45 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/Mutex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Mutex.h" 5 | 6 | namespace Engine 7 | { 8 | 9 | Mutex::Mutex(bool i_bTakeOwnership, const char* i_pName) 10 | { 11 | m_Handle = CreateMutex(NULL, (BOOL)i_bTakeOwnership, i_pName); 12 | assert(m_Handle != NULL); 13 | } 14 | 15 | Mutex::~Mutex() 16 | { 17 | BOOL result = CloseHandle(m_Handle); 18 | assert(result == TRUE); 19 | } 20 | 21 | bool Mutex::TryAcquire(void) 22 | { 23 | DWORD result = WaitForSingleObject(m_Handle, 0); 24 | 25 | return result == WAIT_OBJECT_0; 26 | } 27 | 28 | void Mutex::Acquire(void) 29 | { 30 | DWORD result = WaitForSingleObject(m_Handle, INFINITE); 31 | assert(result == WAIT_OBJECT_0); 32 | 33 | } 34 | 35 | bool Mutex::Acquire(wait_t i_WaitMilliseconds) 36 | { 37 | DWORD result = WaitForSingleObject(m_Handle, i_WaitMilliseconds); 38 | assert(((i_WaitMilliseconds == WaitInfinite) && (result == WAIT_OBJECT_0)) || (result == WAIT_TIMEOUT)); 39 | 40 | return result == WAIT_OBJECT_0; 41 | } 42 | 43 | void Mutex::Release(void) 44 | { 45 | BOOL result = ReleaseMutex(m_Handle); 46 | assert(result == TRUE); 47 | } 48 | 49 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/Mutex.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "WaitableObject.h" 4 | 5 | namespace Engine 6 | { 7 | 8 | class Mutex : public WaitableObject 9 | { 10 | public: 11 | Mutex(bool i_bTakeOwnership = false, const char* i_pName = nullptr); 12 | ~Mutex(); 13 | 14 | bool TryAcquire(); 15 | void Acquire(); 16 | bool Acquire(wait_t i_WaitMilliseconds); 17 | void Release(); 18 | 19 | private: 20 | Mutex(const Mutex&) = delete; 21 | Mutex& operator=(const Mutex&) = delete; 22 | }; 23 | 24 | } // namespace Engine 25 | 26 | -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/ScopeLock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Mutex.h" 4 | 5 | namespace Engine 6 | { 7 | class ScopeLock 8 | { 9 | public: 10 | ScopeLock(Mutex& i_Mutex) : 11 | m_pMutex(&i_Mutex) 12 | { 13 | m_pMutex->Acquire(); 14 | } 15 | ~ScopeLock() 16 | { 17 | m_pMutex->Release(); 18 | } 19 | 20 | private: 21 | ScopeLock(const ScopeLock&) = delete; 22 | ScopeLock& operator=(const ScopeLock&) = delete; 23 | 24 | Mutex * m_pMutex; 25 | }; 26 | 27 | } // namespace Engine -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/Semaphore.cpp: -------------------------------------------------------------------------------- 1 | #include "Semaphore.h" 2 | 3 | #include 4 | #include 5 | 6 | namespace Engine 7 | { 8 | 9 | Semaphore::Semaphore(unsigned int i_initCount, unsigned int i_maxCount, const char* i_pName) 10 | { 11 | assert(i_initCount <= i_maxCount); 12 | 13 | m_Handle = CreateSemaphore(NULL, i_initCount, i_maxCount, i_pName); 14 | assert(m_Handle != NULL); 15 | } 16 | 17 | Semaphore::~Semaphore() 18 | { 19 | BOOL result = CloseHandle(m_Handle); 20 | assert(result == TRUE); 21 | } 22 | 23 | // should 24 | void Semaphore::Increment(unsigned int i_count) 25 | { 26 | BOOL result = ReleaseSemaphore(m_Handle, i_count, NULL); 27 | assert(result == TRUE); 28 | } 29 | 30 | void Semaphore::Decrement(void) 31 | { 32 | DWORD result = WaitForSingleObject(m_Handle, INFINITE); 33 | assert(result == WAIT_OBJECT_0); 34 | } 35 | 36 | bool Semaphore::Decrement(wait_t i_WaitMilliseconds) 37 | { 38 | DWORD result = WaitForSingleObject(m_Handle, i_WaitMilliseconds); 39 | assert(((i_WaitMilliseconds == WaitInfinite) && (result == WAIT_OBJECT_0)) || (result == WAIT_TIMEOUT)); 40 | 41 | return result == WAIT_OBJECT_0; 42 | } 43 | 44 | } // namespace Engine 45 | -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/Semaphore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "WaitableObject.h" 4 | 5 | namespace Engine 6 | { 7 | 8 | class Semaphore : public WaitableObject 9 | { 10 | public: 11 | Semaphore(unsigned int i_initCount, unsigned int i_maxCount, const char* i_pName = nullptr); 12 | ~Semaphore(); 13 | 14 | void Increment(unsigned int i_Count = 1); 15 | void Decrement(); 16 | bool Decrement(wait_t i_WaitMilliseconds); 17 | private: 18 | Semaphore(const Semaphore&) = delete; 19 | Semaphore& operator=(const Semaphore&) = delete; 20 | }; 21 | 22 | } // namespace Engine 23 | 24 | -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/SingleWriterMultipleReader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Engine 6 | { 7 | class SingleWriterMutipleReader 8 | { 9 | public: 10 | SingleWriterMutipleReader() 11 | { 12 | InitializeSRWLock(&m_RWLock); 13 | } 14 | 15 | void ReadLock() 16 | { 17 | AcquireSRWLockShared(&m_RWLock); 18 | } 19 | bool TryReadLock() 20 | { 21 | return TryAcquireSRWLockShared(&m_RWLock) == TRUE; 22 | } 23 | void ReleaseReadLock() 24 | { 25 | ReleaseSRWLockShared(&m_RWLock); 26 | } 27 | 28 | void WriteLock() 29 | { 30 | AcquireSRWLockExclusive(&m_RWLock); 31 | } 32 | bool TryWriteLock() 33 | { 34 | return TryAcquireSRWLockExclusive(&m_RWLock) == TRUE; 35 | } 36 | void ReleaseWriteLock() 37 | { 38 | ReleaseSRWLockShared(&m_RWLock); 39 | } 40 | 41 | private: 42 | SingleWriterMutipleReader(const SingleWriterMutipleReader&) = delete; 43 | SingleWriterMutipleReader& operator=(const SingleWriterMutipleReader&) = delete; 44 | 45 | SRWLOCK m_RWLock; 46 | }; 47 | 48 | } // namespace Engine 49 | 50 | -------------------------------------------------------------------------------- /Engine/Jobs/Syncronization/WaitableObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Engine 6 | { 7 | 8 | class WaitableObject 9 | { 10 | public: 11 | typedef DWORD wait_t; 12 | 13 | static const wait_t WaitInfinite = INFINITE; 14 | 15 | WaitableObject() : 16 | m_Handle(INVALID_HANDLE_VALUE) 17 | {} 18 | virtual ~WaitableObject() {} 19 | 20 | HANDLE GetHandle(void) { return m_Handle; } 21 | 22 | protected: 23 | HANDLE m_Handle; 24 | 25 | private: 26 | WaitableObject(const WaitableObject& i_other) = delete; 27 | WaitableObject& operator=(const WaitableObject& i_other) = delete; 28 | }; 29 | 30 | } // namespace Engine 31 | -------------------------------------------------------------------------------- /Engine/Math/Math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | class Math { 7 | public: 8 | 9 | 10 | static inline int random(const int min, const int max) { 11 | if (max < min) return -1; 12 | srand((unsigned)time(NULL)); 13 | return min + (rand() % (max - min)); 14 | } 15 | 16 | static inline bool IsNearlyEqual(const float a, const float b, const float minPrecision = 0.0001f) 17 | { 18 | const float diff = fabs(a - b); 19 | const float absA = fabs(a); 20 | const float absB = fabs(b); 21 | 22 | const float largest = (absB > absA) ? absB : absA; 23 | if (diff <= largest * minPrecision) 24 | return true; 25 | return false; 26 | } 27 | 28 | static inline bool IsNearlyZero(const float value, const float errorTolerance = 0.0001f) 29 | { 30 | return fabs(value) <= errorTolerance; 31 | } 32 | 33 | static inline bool IsNaN(const float value) 34 | { 35 | if (value != value) 36 | return true; 37 | return false; 38 | } 39 | 40 | static inline float clamp(const float input, const float min, const float max) 41 | { 42 | if (input < min) 43 | return min; 44 | if (input > max) 45 | return max; 46 | return input; 47 | } 48 | 49 | static inline bool clampRef(float & input, const float min, const float max) 50 | { 51 | if (input < min) 52 | { 53 | input = min; 54 | return true; 55 | } 56 | if (input > max) 57 | { 58 | input = max; 59 | return true; 60 | } 61 | return false; 62 | } 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /Engine/Math/Matrix3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Vector3.h" 4 | 5 | 6 | class Matrix3 { 7 | public: 8 | Matrix3() : mat{0} 9 | {} 10 | 11 | Matrix3(const float i_mat[3][3]) 12 | { 13 | for (int i = 0; i < 3; i++) 14 | for (int j = 0; j < 3; j++) 15 | mat[i][j] = i_mat[i][j]; 16 | } 17 | 18 | 19 | 20 | Vector3 row(const int i) 21 | { 22 | return Vector3{ mat[i][0], mat[i][1], mat[i][2] }; 23 | } 24 | 25 | Vector3 col(const int i) 26 | { 27 | return Vector3{ mat[0][i], mat[1][i], mat[2][i] }; 28 | } 29 | 30 | // OPERATIONS - WITH SCALAR 31 | Matrix3 operator + (const float i_scalar) 32 | { 33 | Matrix3 newMat; 34 | for (int i = 0; i < 3; ++i) 35 | for (int j = 0; j < 3; ++j) 36 | newMat.mat[i][j] = mat[i][j] + i_scalar; 37 | return newMat; 38 | } 39 | 40 | Matrix3 operator - (const float i_scalar) 41 | { 42 | Matrix3 newMat; 43 | for (int i = 0; i < 3; ++i) 44 | for (int j = 0; j < 3; ++j) 45 | newMat.mat[i][j] = mat[i][j] - i_scalar; 46 | return newMat; 47 | } 48 | 49 | Matrix3 operator * (const float i_scalar) 50 | { 51 | Matrix3 newMat; 52 | for (int i = 0; i < 3; ++i) 53 | for (int j = 0; j < 3; ++j) 54 | newMat.mat[i][j] = mat[i][j] * i_scalar; 55 | return newMat; 56 | } 57 | 58 | Matrix3 operator / (const float i_scalar) 59 | { 60 | Matrix3 newMat; 61 | for (int i = 0; i < 3; ++i) 62 | for (int j = 0; j < 3; ++j) 63 | newMat.mat[i][j] = mat[i][j] / i_scalar; 64 | return newMat; 65 | } 66 | 67 | 68 | // OPERATIONS - WITH OTHER MATRIX 69 | Matrix3 operator * (const Matrix3 other) 70 | { 71 | Matrix3 newMat; 72 | for (int i = 0; i < 3; ++i) 73 | for (int j = 0; j < 3; ++j) 74 | for (int k = 0; k < 3; ++k) 75 | { 76 | newMat.mat[i][j] += mat[i][k] * other.mat[k][j]; 77 | } 78 | return newMat; 79 | } 80 | 81 | Matrix3 operator + (const Matrix3 other) 82 | { 83 | Matrix3 newMat; 84 | for (int i = 0; i < 3; ++i) 85 | for (int j = 0; j < 3; ++j) 86 | newMat.mat[i][j] = mat[i][j] + other.mat[i][j]; 87 | return newMat; 88 | } 89 | 90 | Matrix3 operator - (const Matrix3 other) 91 | { 92 | Matrix3 newMat; 93 | for (int i = 0; i < 3; ++i) 94 | for (int j = 0; j < 3; ++j) 95 | newMat.mat[i][j] = mat[i][j] - other.mat[i][j]; 96 | return newMat; 97 | } 98 | 99 | 100 | 101 | // OPERATIONS - SELF 102 | Matrix3 transpose() const 103 | { 104 | float newMat[3][3]; 105 | for (int i = 0; i < 3; i++) 106 | { 107 | for (int j = 0; j < 3; j++) 108 | { 109 | newMat[i][j] = mat[j][i]; 110 | } 111 | } 112 | } 113 | 114 | Matrix3 inverse() const 115 | { 116 | 117 | } 118 | 119 | 120 | 121 | // CONSTANTS 122 | static const Matrix3 Zero() 123 | { 124 | const Matrix3 zero; 125 | return zero; 126 | } 127 | static const Matrix3 Unit() 128 | { 129 | Matrix3 temp; 130 | temp.mat[0][0] = 1; 131 | temp.mat[1][1] = 1; 132 | temp.mat[2][2] = 1; 133 | temp.mat[3][3] = 1; 134 | return temp; 135 | } 136 | 137 | 138 | 139 | // TRANSFORMS 140 | static const Matrix3 Translation(const Vector3 i_translationVector) 141 | { 142 | Matrix3 temp = Matrix3::Unit(); 143 | temp.mat[3][0] = i_translationVector.x; 144 | temp.mat[3][1] = i_translationVector.y; 145 | temp.mat[3][2] = i_translationVector.z; 146 | return temp; 147 | } 148 | 149 | static const Matrix3 Scale(const Vector3 i_scaleVector) 150 | { 151 | Matrix3 temp; 152 | temp.mat[0][0] = i_scaleVector.x; 153 | temp.mat[1][1] = i_scaleVector.y; 154 | temp.mat[2][2] = i_scaleVector.z; 155 | temp.mat[3][3] = 1; 156 | return temp; 157 | } 158 | 159 | static const Matrix3 ZRotation(const float i_zRotation) 160 | { 161 | Matrix3 temp = Matrix3::Unit(); 162 | temp.mat[0][0] = cos(i_zRotation); 163 | temp.mat[0][1] = -sin(i_zRotation); 164 | temp.mat[1][0] = sin(i_zRotation); 165 | temp.mat[1][1] = cos(i_zRotation); 166 | return temp; 167 | } 168 | 169 | 170 | private: 171 | float mat[3][3]; 172 | }; 173 | -------------------------------------------------------------------------------- /Engine/Math/Matrix4.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Vector4.h" 4 | 5 | class Matrix4 { 6 | public: 7 | Matrix4() : mat{0} 8 | {} 9 | 10 | Matrix4(const float i_mat[4][4]) 11 | { 12 | for (int i = 0; i < 4; i++) 13 | for (int j = 0; j < 4; j++) 14 | mat[i][j] = i_mat[i][j]; 15 | } 16 | 17 | 18 | 19 | // OPERATIONS - WITH SCALAR 20 | Matrix4 operator + (const float i_scalar) 21 | { 22 | Matrix4 newMat; 23 | for (int i = 0; i < 4; ++i) 24 | for (int j = 0; j < 4; ++j) 25 | newMat.mat[i][j] = mat[i][j] + i_scalar; 26 | return newMat; 27 | } 28 | 29 | Matrix4 operator - (const float i_scalar) 30 | { 31 | Matrix4 newMat; 32 | for (int i = 0; i < 4; ++i) 33 | for (int j = 0; j < 4; ++j) 34 | newMat.mat[i][j] = mat[i][j] - i_scalar; 35 | return newMat; 36 | } 37 | 38 | Matrix4 operator * (const float i_scalar) 39 | { 40 | Matrix4 newMat; 41 | for (int i = 0; i < 4; ++i) 42 | for (int j = 0; j < 4; ++j) 43 | newMat.mat[i][j] = mat[i][j] * i_scalar; 44 | return newMat; 45 | } 46 | 47 | Matrix4 operator / (const float i_scalar) 48 | { 49 | Matrix4 newMat; 50 | for (int i = 0; i < 4; ++i) 51 | for (int j = 0; j < 4; ++j) 52 | newMat.mat[i][j] = mat[i][j] / i_scalar; 53 | return newMat; 54 | } 55 | 56 | 57 | 58 | // OPERATIONS - SELF 59 | Matrix4 transpose() const 60 | { 61 | float newMat[4][4]; 62 | for (int i = 0; i < 4; i++) 63 | { 64 | for (int j = 0; j < 4; j++) 65 | { 66 | newMat[i][j] = mat[j][i]; 67 | } 68 | } 69 | } 70 | 71 | 72 | 73 | // CONSTANTS 74 | static const Matrix4 Zero() 75 | { 76 | const Matrix4 zero; 77 | return zero; 78 | } 79 | static const Matrix4 Unit() 80 | { 81 | Matrix4 temp; 82 | temp.mat[0][0] = 1; 83 | temp.mat[1][1] = 1; 84 | temp.mat[2][2] = 1; 85 | temp.mat[3][3] = 1; 86 | return temp; 87 | } 88 | 89 | 90 | 91 | // TRANSFORMS 92 | static const Matrix4 Translation(const Vector4 i_translationVector) 93 | { 94 | Matrix4 temp = Matrix4::Unit(); 95 | temp.mat[0][3] = i_translationVector.x; 96 | temp.mat[1][3] = i_translationVector.y; 97 | temp.mat[2][3] = i_translationVector.z; 98 | return temp; 99 | } 100 | 101 | static const Matrix4 Scale(const Vector4 i_scaleVector) 102 | { 103 | Matrix4 temp; 104 | temp.mat[0][0] = i_scaleVector.x; 105 | temp.mat[1][1] = i_scaleVector.y; 106 | temp.mat[2][2] = i_scaleVector.z; 107 | temp.mat[3][3] = 1; 108 | return temp; 109 | } 110 | 111 | static const Matrix4 ZRotation(const float i_zRotation) 112 | { 113 | Matrix4 temp = Matrix4::Unit(); 114 | const float ToDeg = 1; 115 | temp.mat[0][0] = cosf(i_zRotation * ToDeg); 116 | temp.mat[0][1] = -sinf(i_zRotation * ToDeg); 117 | temp.mat[1][0] = sinf(i_zRotation * ToDeg); 118 | temp.mat[1][1] = cosf(i_zRotation * ToDeg); 119 | return temp; 120 | } 121 | 122 | 123 | //private: 124 | float mat[4][4]; 125 | 126 | 127 | 128 | 129 | 130 | public: 131 | Matrix4 inverse() const 132 | { 133 | float m[16]; 134 | { 135 | int count = 0; 136 | for (int i = 0; i < 4; i++) 137 | for (int j = 0; j < 4; j++) 138 | m[count++] = mat[i][j]; 139 | } 140 | 141 | 142 | float inv[16]; 143 | int i = 0; 144 | 145 | inv[0] = m[5] * m[10] * m[15] - 146 | m[5] * m[11] * m[14] - 147 | m[9] * m[6] * m[15] + 148 | m[9] * m[7] * m[14] + 149 | m[13] * m[6] * m[11] - 150 | m[13] * m[7] * m[10]; 151 | 152 | inv[4] = -m[4] * m[10] * m[15] + 153 | m[4] * m[11] * m[14] + 154 | m[8] * m[6] * m[15] - 155 | m[8] * m[7] * m[14] - 156 | m[12] * m[6] * m[11] + 157 | m[12] * m[7] * m[10]; 158 | 159 | inv[8] = m[4] * m[9] * m[15] - 160 | m[4] * m[11] * m[13] - 161 | m[8] * m[5] * m[15] + 162 | m[8] * m[7] * m[13] + 163 | m[12] * m[5] * m[11] - 164 | m[12] * m[7] * m[9]; 165 | 166 | inv[12] = -m[4] * m[9] * m[14] + 167 | m[4] * m[10] * m[13] + 168 | m[8] * m[5] * m[14] - 169 | m[8] * m[6] * m[13] - 170 | m[12] * m[5] * m[10] + 171 | m[12] * m[6] * m[9]; 172 | 173 | inv[1] = -m[1] * m[10] * m[15] + 174 | m[1] * m[11] * m[14] + 175 | m[9] * m[2] * m[15] - 176 | m[9] * m[3] * m[14] - 177 | m[13] * m[2] * m[11] + 178 | m[13] * m[3] * m[10]; 179 | 180 | inv[5] = m[0] * m[10] * m[15] - 181 | m[0] * m[11] * m[14] - 182 | m[8] * m[2] * m[15] + 183 | m[8] * m[3] * m[14] + 184 | m[12] * m[2] * m[11] - 185 | m[12] * m[3] * m[10]; 186 | 187 | inv[9] = -m[0] * m[9] * m[15] + 188 | m[0] * m[11] * m[13] + 189 | m[8] * m[1] * m[15] - 190 | m[8] * m[3] * m[13] - 191 | m[12] * m[1] * m[11] + 192 | m[12] * m[3] * m[9]; 193 | 194 | inv[13] = m[0] * m[9] * m[14] - 195 | m[0] * m[10] * m[13] - 196 | m[8] * m[1] * m[14] + 197 | m[8] * m[2] * m[13] + 198 | m[12] * m[1] * m[10] - 199 | m[12] * m[2] * m[9]; 200 | 201 | inv[2] = m[1] * m[6] * m[15] - 202 | m[1] * m[7] * m[14] - 203 | m[5] * m[2] * m[15] + 204 | m[5] * m[3] * m[14] + 205 | m[13] * m[2] * m[7] - 206 | m[13] * m[3] * m[6]; 207 | 208 | inv[6] = -m[0] * m[6] * m[15] + 209 | m[0] * m[7] * m[14] + 210 | m[4] * m[2] * m[15] - 211 | m[4] * m[3] * m[14] - 212 | m[12] * m[2] * m[7] + 213 | m[12] * m[3] * m[6]; 214 | 215 | inv[10] = m[0] * m[5] * m[15] - 216 | m[0] * m[7] * m[13] - 217 | m[4] * m[1] * m[15] + 218 | m[4] * m[3] * m[13] + 219 | m[12] * m[1] * m[7] - 220 | m[12] * m[3] * m[5]; 221 | 222 | inv[14] = -m[0] * m[5] * m[14] + 223 | m[0] * m[6] * m[13] + 224 | m[4] * m[1] * m[14] - 225 | m[4] * m[2] * m[13] - 226 | m[12] * m[1] * m[6] + 227 | m[12] * m[2] * m[5]; 228 | 229 | inv[3] = -m[1] * m[6] * m[11] + 230 | m[1] * m[7] * m[10] + 231 | m[5] * m[2] * m[11] - 232 | m[5] * m[3] * m[10] - 233 | m[9] * m[2] * m[7] + 234 | m[9] * m[3] * m[6]; 235 | 236 | inv[7] = m[0] * m[6] * m[11] - 237 | m[0] * m[7] * m[10] - 238 | m[4] * m[2] * m[11] + 239 | m[4] * m[3] * m[10] + 240 | m[8] * m[2] * m[7] - 241 | m[8] * m[3] * m[6]; 242 | 243 | inv[11] = -m[0] * m[5] * m[11] + 244 | m[0] * m[7] * m[9] + 245 | m[4] * m[1] * m[11] - 246 | m[4] * m[3] * m[9] - 247 | m[8] * m[1] * m[7] + 248 | m[8] * m[3] * m[5]; 249 | 250 | inv[15] = m[0] * m[5] * m[10] - 251 | m[0] * m[6] * m[9] - 252 | m[4] * m[1] * m[10] + 253 | m[4] * m[2] * m[9] + 254 | m[8] * m[1] * m[6] - 255 | m[8] * m[2] * m[5]; 256 | 257 | float det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]; 258 | det = 1.f / det; 259 | Matrix4 output; 260 | { 261 | int count = 0; 262 | for (int i = 0; i < 4; i++) 263 | for (int j = 0; j < 4; j++) 264 | output.mat[i][j] = inv[count++] * det; 265 | } 266 | return output; 267 | } 268 | }; 269 | 270 | 271 | // OPERATIONS - WITH OTHER MATRIX 272 | inline Matrix4 operator * (const Matrix4 my, const Matrix4 other) 273 | { 274 | Matrix4 newMat; 275 | for (int i = 0; i < 4; ++i) 276 | for (int j = 0; j < 4; ++j) 277 | for (int k = 0; k < 4; ++k) 278 | { 279 | newMat.mat[i][j] += my.mat[i][k] * other.mat[k][j]; 280 | } 281 | return newMat; 282 | } 283 | 284 | inline Matrix4 operator + (const Matrix4 my, const Matrix4 other) 285 | { 286 | Matrix4 newMat; 287 | for (int i = 0; i < 4; ++i) 288 | for (int j = 0; j < 4; ++j) 289 | newMat.mat[i][j] = my.mat[i][j] + other.mat[i][j]; 290 | return newMat; 291 | } 292 | 293 | inline Matrix4 operator - (const Matrix4 my, const Matrix4 other) 294 | { 295 | Matrix4 newMat; 296 | for (int i = 0; i < 4; ++i) 297 | for (int j = 0; j < 4; ++j) 298 | newMat.mat[i][j] = my.mat[i][j] - other.mat[i][j]; 299 | return newMat; 300 | } 301 | 302 | 303 | // OPERATIONS - WITH VECTORS 304 | inline Vector4 operator * (const Matrix4 my, const Vector4 other) 305 | { 306 | Vector4 newVec; 307 | for (int i = 0; i < 4; i++) 308 | for (int j = 0; j < 4; j++) 309 | newVec.Set(i, newVec.Get(i) + (my.mat[i][j] * other.Get(j))); 310 | return newVec; 311 | } -------------------------------------------------------------------------------- /Engine/Math/Vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Vector2 { 4 | public: 5 | Vector2() { 6 | this->x = 0; 7 | this->y = 0; 8 | } 9 | 10 | Vector2(float x, float y) { 11 | this->x = x; 12 | this->y = y; 13 | } 14 | 15 | // BASIC 16 | inline Vector2 operator = (const Vector2 other) { 17 | x = other.x; 18 | y = other.y; 19 | return *this; 20 | } 21 | inline bool operator == (const Vector2 other) const { 22 | if (x == other.x && y == other.y) 23 | return true; 24 | else 25 | return false; 26 | } 27 | inline bool operator != (const Vector2 &other) const { 28 | return !(*this == other); 29 | } 30 | 31 | // MATH 32 | inline Vector2 getInverse() const 33 | { 34 | return Vector2{ -x, -y }; 35 | } 36 | inline float getMagnitude() const 37 | { 38 | return sqrt(x * x + y * y); 39 | } 40 | inline Vector2 getNormalized() const 41 | { 42 | const float mag = getMagnitude(); 43 | return Vector2{x / mag, y / mag}; 44 | } 45 | inline Vector2 operator - () const { 46 | return Vector2{-x, -y}; 47 | } 48 | inline Vector2 operator += (const Vector2 other) { 49 | x += other.x; 50 | y += other.y; 51 | return *this; 52 | } 53 | inline Vector2 operator -= (const Vector2 other) { 54 | x -= other.x; 55 | y -= other.y; 56 | return *this; 57 | } 58 | inline Vector2 operator *= (const Vector2 other) { 59 | x *= other.x; 60 | y *= other.y; 61 | return *this; 62 | } 63 | inline Vector2 operator /= (const Vector2 other) { 64 | x /= other.x; 65 | y /= other.y; 66 | return *this; 67 | } 68 | 69 | inline Vector2 operator *= (const float scalar) { 70 | x *= scalar; 71 | y *= scalar; 72 | return *this; 73 | } 74 | inline Vector2 operator /= (const float scalar) { 75 | x /= scalar; 76 | y /= scalar; 77 | return *this; 78 | } 79 | 80 | static float DistanceBetween(const Vector2 &v1, const Vector2 &v2) 81 | { 82 | const float dX = v2.x - v1.x; 83 | const float dY = v2.y - v1.y; 84 | return sqrt((dX * dX) + (dY * dY)); 85 | } 86 | 87 | float DistanceFrom(const Vector2 &v) const 88 | { 89 | const float dX = v.x - x; 90 | const float dY = v.y - y; 91 | return sqrt((dX * dX) + (dY * dY)); 92 | } 93 | 94 | 95 | // Need a const implementation 96 | static const Vector2 Zero() { 97 | return { 0, 0 }; 98 | } 99 | static const Vector2 One() { 100 | return { 1, 1 }; 101 | } 102 | static const Vector2 Up() { 103 | return { 0, 1 }; 104 | } 105 | static const Vector2 Down() { 106 | return { 0, -1 }; 107 | } 108 | static const Vector2 Left() { 109 | return { -1, 0 }; 110 | } 111 | static const Vector2 Right() { 112 | return { 1, 0 }; 113 | } 114 | 115 | 116 | public: 117 | float x; 118 | float y; 119 | }; 120 | 121 | inline Vector2 operator + (const Vector2 v1, const Vector2 v2) { 122 | return { v1.x + v2.x, v1.y + v2.y }; 123 | } 124 | inline Vector2 operator - (const Vector2 v1, const Vector2 v2) { 125 | return { v1.x - v2.x, v1.y - v2.y }; 126 | } 127 | inline Vector2 operator * (const Vector2 v1, const float scalar) { 128 | return Vector2{ v1.x * scalar, v1.y * scalar }; 129 | } 130 | inline Vector2 operator / (const Vector2 v1, const float scalar) { 131 | return Vector2{ v1.x / scalar, v1.y / scalar }; 132 | } -------------------------------------------------------------------------------- /Engine/Math/Vector3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Vector.h" 4 | 5 | class Vector3 { 6 | public: 7 | Vector3() { 8 | this->x = 0; 9 | this->y = 0; 10 | this->z = 0; 11 | } 12 | 13 | Vector3(const Vector2 input) 14 | { 15 | this->x = input.x; 16 | this->y = input.y; 17 | this->z = 0; 18 | } 19 | 20 | Vector3(float x, float y, float z) { 21 | this->x = x; 22 | this->y = y; 23 | this->z = z; 24 | } 25 | 26 | // BASIC 27 | inline Vector3 operator = (const Vector3 other) { 28 | x = other.x; 29 | y = other.y; 30 | z = other.z; 31 | return *this; 32 | } 33 | inline bool operator == (const Vector3 other) const { 34 | if (x == other.x && y == other.y && z == other.z) 35 | return true; 36 | else 37 | return false; 38 | } 39 | inline bool operator != (const Vector3 &other) const { 40 | return !(*this == other); 41 | } 42 | 43 | // MATH 44 | inline Vector3 getInverse() const 45 | { 46 | return Vector3{ -x, -y, -z }; 47 | } 48 | inline float getMagnitude() const 49 | { 50 | return sqrt((x * x) + (y * y) + (z * z)); 51 | } 52 | inline Vector3 getNormalized() const 53 | { 54 | const float mag = getMagnitude(); 55 | return Vector3{x / mag, y / mag, z / mag}; 56 | } 57 | inline Vector3 operator - () const { 58 | return Vector3{-x, -y, -z}; 59 | } 60 | inline Vector3 operator += (const Vector3 other) { 61 | x += other.x; 62 | y += other.y; 63 | z += other.z; 64 | return *this; 65 | } 66 | inline Vector3 operator -= (const Vector3 other) { 67 | x -= other.x; 68 | y -= other.y; 69 | z -= other.z; 70 | return *this; 71 | } 72 | inline Vector3 operator *= (const Vector3 other) { 73 | x *= other.x; 74 | y *= other.y; 75 | z *= other.z; 76 | return *this; 77 | } 78 | inline Vector3 operator /= (const Vector3 other) { 79 | x /= other.x; 80 | y /= other.y; 81 | z /= other.z; 82 | return *this; 83 | } 84 | 85 | inline Vector3 operator *= (const float scalar) { 86 | x *= scalar; 87 | y *= scalar; 88 | z *= scalar; 89 | return *this; 90 | } 91 | inline Vector3 operator /= (const float scalar) { 92 | x /= scalar; 93 | y /= scalar; 94 | z /= scalar; 95 | return *this; 96 | } 97 | 98 | 99 | // Need a const implementation 100 | static const Vector3 Zero() { 101 | return { 0, 0, 0 }; 102 | } 103 | static const Vector3 One() { 104 | return { 1, 1, 1 }; 105 | } 106 | 107 | 108 | public: 109 | float x; 110 | float y; 111 | float z; 112 | }; 113 | 114 | inline Vector3 operator + (const Vector3 v1, const Vector3 v2) { 115 | return { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; 116 | } 117 | inline Vector3 operator - (const Vector3 v1, const Vector3 v2) { 118 | return { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; 119 | } 120 | inline Vector3 operator * (const Vector3 v1, const float scalar) { 121 | return Vector3{ v1.x * scalar, v1.y * scalar, v1.z * scalar }; 122 | } 123 | inline Vector3 operator / (const Vector3 v1, const float scalar) { 124 | return Vector3{ v1.x / scalar, v1.y / scalar, v1.z / scalar }; 125 | } 126 | 127 | inline float dot(const Vector3& v1, const Vector3& v2) 128 | { 129 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 130 | } 131 | inline Vector3 cross(const Vector3& v1, const Vector3& v2) 132 | { 133 | return Vector3(v1.y * v2.z - v1.z * v2.y, 134 | v1.z * v2.x - v1.x * v2.z, 135 | v1.x * v2.y - v1.y * v2.x); 136 | } -------------------------------------------------------------------------------- /Engine/Math/Vector4.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Vector4 { 4 | public: 5 | Vector4() { 6 | this->x = 0; 7 | this->y = 0; 8 | this->z = 0; 9 | this->w = 0; 10 | } 11 | 12 | Vector4(const Vector3 input, const float i_w = 0) { 13 | this->x = input.x; 14 | this->y = input.y; 15 | this->z = input.z; 16 | this->w = i_w; 17 | } 18 | 19 | Vector4(const Vector2 input, const float i_z = 0, const float i_w = 0) { 20 | this->x = input.x; 21 | this->y = input.y; 22 | this->z = i_z; 23 | this->w = i_w; 24 | } 25 | 26 | Vector4(float x, float y, float z, float w) { 27 | this->x = x; 28 | this->y = y; 29 | this->z = z; 30 | this->w = w; 31 | } 32 | 33 | // BASIC 34 | inline Vector4 operator = (const Vector4 other) { 35 | x = other.x; 36 | y = other.y; 37 | z = other.z; 38 | w = other.w; 39 | return *this; 40 | } 41 | inline bool operator == (const Vector4 other) const { 42 | if (x == other.x && y == other.y && z == other.z && w == other.w) 43 | return true; 44 | else 45 | return false; 46 | } 47 | inline bool operator != (const Vector4 &other) const { 48 | return !(*this == other); 49 | } 50 | 51 | // MATH 52 | inline Vector4 getInverse() const 53 | { 54 | return Vector4{ -x, -y, -z, -w }; 55 | } 56 | inline float getMagnitude() const 57 | { 58 | return sqrt((x * x) + (y * y) + (z * z) + (w * w)); 59 | } 60 | inline Vector4 getNormalized() const 61 | { 62 | const float mag = getMagnitude(); 63 | return Vector4{x / mag, y / mag, z / mag, w / mag}; 64 | } 65 | inline Vector4 operator - () const { 66 | return Vector4{-x, -y, -z, -w}; 67 | } 68 | inline Vector4 operator += (const Vector4 other) { 69 | x += other.x; 70 | y += other.y; 71 | z += other.z; 72 | w += other.w; 73 | return *this; 74 | } 75 | inline Vector4 operator -= (const Vector4 other) { 76 | x -= other.x; 77 | y -= other.y; 78 | z -= other.z; 79 | w -= other.w; 80 | return *this; 81 | } 82 | inline Vector4 operator *= (const Vector4 other) { 83 | x *= other.x; 84 | y *= other.y; 85 | z *= other.z; 86 | w *= other.w; 87 | return *this; 88 | } 89 | inline Vector4 operator /= (const Vector4 other) { 90 | x /= other.x; 91 | y /= other.y; 92 | z /= other.z; 93 | w /= other.w; 94 | return *this; 95 | } 96 | 97 | inline Vector4 operator *= (const float scalar) { 98 | x *= scalar; 99 | y *= scalar; 100 | z *= scalar; 101 | w *= scalar; 102 | return *this; 103 | } 104 | inline Vector4 operator /= (const float scalar) { 105 | x /= scalar; 106 | y /= scalar; 107 | z /= scalar; 108 | w /= scalar; 109 | return *this; 110 | } 111 | 112 | 113 | // Need a const implementation 114 | static const Vector4 Zero() { 115 | return { 0, 0, 0, 0 }; 116 | } 117 | static const Vector4 One() { 118 | return { 1, 1, 1, 1 }; 119 | } 120 | 121 | inline float Get(const int i) const 122 | { 123 | switch (i) 124 | { 125 | case 0: 126 | return x; 127 | case 1: 128 | return y; 129 | case 2: 130 | return z; 131 | case 3: 132 | return w; 133 | default: 134 | return -9999; 135 | } 136 | } 137 | 138 | inline void Set(const int i, const float input) 139 | { 140 | switch (i) 141 | { 142 | case 0: 143 | x = input; 144 | return; 145 | case 1: 146 | y = input; 147 | return; 148 | case 2: 149 | z = input; 150 | return; 151 | case 3: 152 | w = input; 153 | return; 154 | default: 155 | return; 156 | } 157 | } 158 | 159 | 160 | public: 161 | float x; 162 | float y; 163 | float z; 164 | float w; 165 | }; 166 | 167 | inline Vector4 operator + (const Vector4 v1, const Vector4 v2) { 168 | return { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w }; 169 | } 170 | inline Vector4 operator - (const Vector4 v1, const Vector4 v2) { 171 | return { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w }; 172 | } 173 | inline Vector4 operator * (const Vector4 v1, const float scalar) { 174 | return Vector4{ v1.x * scalar, v1.y * scalar, v1.z * scalar, v1.w * scalar }; 175 | } 176 | inline Vector4 operator / (const Vector4 v1, const float scalar) { 177 | return Vector4{ v1.x / scalar, v1.y / scalar, v1.z / scalar, v1.w / scalar }; 178 | } -------------------------------------------------------------------------------- /Engine/Math/pchMath.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "Math.h" 7 | #include "Matrix3.h" 8 | #include "Matrix4.h" 9 | #include "Vector.h" 10 | #include "Vector3.h" 11 | #include "Vector4.h" -------------------------------------------------------------------------------- /Engine/Memory/BitArray.cpp: -------------------------------------------------------------------------------- 1 | #include "BitArray.h" 2 | #include 3 | 4 | 5 | // Init 6 | BitArray::BitArray(const size_t bits) : 7 | bits_(bits), 8 | array_length_((uint_bits_ + bits - 1) / uint_bits_), 9 | array_(reinterpret_cast(reinterpret_cast(this) + sizeof(BitArray))) 10 | { 11 | resetBits(1); 12 | } 13 | BitArray* BitArray::init(void*& placementPtr, const size_t bits) 14 | { 15 | auto _mapper = reinterpret_cast(placementPtr); 16 | _mapper->bits_ = bits; 17 | _mapper->array_length_ = (uint_bits_ + bits - 1) / uint_bits_; 18 | _mapper->array_ = reinterpret_cast(reinterpret_cast(placementPtr) + sizeof(BitArray)); 19 | _mapper->resetBits(0); 20 | 21 | return _mapper; 22 | } 23 | size_t BitArray::calcSpaceForArray(const size_t bits) 24 | { 25 | const size_t arrayLength = (uint_bits_ + bits - 1) / uint_bits_; 26 | return sizeof(uint_x) * arrayLength; 27 | } 28 | 29 | void BitArray::setAll(const size_t bits) 30 | { 31 | bits_ = bits; 32 | array_length_ = (uint_bits_ + bits - 1) / uint_bits_; 33 | array_ = reinterpret_cast(reinterpret_cast(this) + sizeof(BitArray)); 34 | resetBits(1); 35 | } 36 | 37 | void BitArray::resetBits(const bool value) 38 | { 39 | for (size_t i = 0; i < array_length_; i++) 40 | { 41 | array_[i] = value ? -1 : 0; 42 | } 43 | } 44 | size_t BitArray::getNBits() const 45 | { 46 | return bits_; 47 | } 48 | size_t BitArray::getArrayLength() const 49 | { 50 | return array_length_; 51 | } 52 | 53 | 54 | // Runtime 55 | void BitArray::set(size_t index, bool value) const 56 | { 57 | const uint_x i = index / uint_bits_; 58 | if (i > array_length_) throw std::out_of_range("Index out of range!"); 59 | const uint_x num = array_[i]; 60 | 61 | #ifdef WIN32 62 | const uint_x mask = 1u << (index % uint_bits_); 63 | #else 64 | const uint_x mask = 1ULL << (index % uint_bits_); 65 | #endif 66 | 67 | array_[i] = value ? num | mask : num & ~mask; 68 | } 69 | bool BitArray::get(size_t index) const 70 | { 71 | const uint_x i = index / uint_bits_; 72 | if (i > array_length_ - 1) throw std::out_of_range("Index out of range!"); 73 | const uint_x num = array_[i]; 74 | 75 | 76 | #ifdef WIN32 77 | const uint_x mask = 1u << (index % uint_bits_); 78 | #else 79 | const uint_x mask = 1ULL << (index % uint_bits_); 80 | #endif 81 | 82 | return num & mask; 83 | } 84 | bool BitArray::findFirstSetBit(unsigned long &index) const 85 | { 86 | unsigned long tempIndex = 0; 87 | for (unsigned long i = 0; i < array_length_; i++) 88 | { 89 | #ifdef WIN32 90 | const char isNonZero = _BitScanForward(&tempIndex, static_cast(array_[i])); 91 | #else 92 | const char isNonZero = _BitScanForward64(&tempIndex, static_cast(array_[i])); 93 | #endif 94 | if (isNonZero) 95 | { 96 | index = tempIndex + (static_cast(uint_bits_) * i); 97 | return true; 98 | } 99 | } 100 | return false; 101 | } 102 | 103 | -------------------------------------------------------------------------------- /Engine/Memory/BitArray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #ifdef WIN32 7 | typedef uint32_t uint_x; 8 | #else 9 | typedef uint64_t uint_x; 10 | #endif 11 | 12 | class BitArray 13 | { 14 | public: 15 | BitArray(const size_t bits); 16 | 17 | static BitArray* init(void* &placementPtr, const size_t bits); 18 | static size_t calcSpaceForArray(const size_t bits); 19 | void setAll(const size_t bits); 20 | void resetBits(const bool value); 21 | void set(size_t index, bool value) const; 22 | bool get(size_t index) const; 23 | bool findFirstSetBit(unsigned long &index) const; 24 | size_t getNBits() const; 25 | size_t getArrayLength() const; 26 | 27 | 28 | static const uint_x uint_bits_ = CHAR_BIT * sizeof(uint_x); 29 | 30 | private: 31 | size_t bits_ = 0; 32 | size_t array_length_ = 0; 33 | uint_x* array_ = nullptr; 34 | }; 35 | -------------------------------------------------------------------------------- /Engine/Memory/FixedSizeAllocator.cpp: -------------------------------------------------------------------------------- 1 | #include "FixedSizeAllocator.h" 2 | #include 3 | #include 4 | 5 | 6 | size_t FixedSizeAllocator::calcSpaceForManager(const size_t bits, const size_t blockSize) 7 | { 8 | return sizeof(FixedSizeAllocator) + BitArray::calcSpaceForArray(bits) + (blockSize * bits); 9 | } 10 | 11 | void* FixedSizeAllocator::_alloc() 12 | { 13 | unsigned long freeIndex = 0; 14 | const bool isFreeFound = bit_array_.findFirstSetBit(freeIndex); 15 | if (!isFreeFound) 16 | { 17 | printf("No free blocks found here!"); 18 | return nullptr; 19 | } 20 | bit_array_.set(freeIndex, 0); 21 | return reinterpret_cast(reinterpret_cast(start_) + block_size_ * freeIndex); 22 | } 23 | 24 | void FixedSizeAllocator::_free(void* ptr) 25 | { 26 | const size_t index = (reinterpret_cast(ptr) - reinterpret_cast(start_)) / block_size_; 27 | bit_array_.set(index, 1); 28 | } 29 | 30 | bool FixedSizeAllocator::_contains(const void* ptr) const 31 | { 32 | const uintptr_t ptrAddress = reinterpret_cast(ptr); 33 | const uintptr_t startAddress = reinterpret_cast(start_); 34 | const uintptr_t endAddress = reinterpret_cast(this) + heap_size_; 35 | if (ptrAddress > startAddress && ptrAddress < endAddress) 36 | return true; 37 | return false; 38 | } 39 | 40 | // PRINT / DEBUG 41 | void FixedSizeAllocator::ShowFreeBlocks(const FixedSizeAllocator* manager) 42 | { 43 | printf("\nPRINTING ALL FREE BLOCKS\n=========================\n"); 44 | /*for (unsigned int i = 0; i < manager->_nFreeDesc; i++) { 45 | if (manager->_freeDesc[i].offset != 0) { 46 | printf("Address => [%p] | From => [%d] | Size => [%d]\n", &manager->_freeDesc[i], manager->_freeDesc[i].offset, manager->_freeDesc[i].size); 47 | } 48 | }*/ 49 | } 50 | void FixedSizeAllocator::ShowOutstandingAllocations(const FixedSizeAllocator* manager) 51 | { 52 | printf("\nPRINTING ALL ALLOCATED BLOCKS\n=========================\n"); 53 | /*for (unsigned int i = 0; i < manager->_nUsedDesc; i++) { 54 | if (manager->_usedDesc[i].offset != 0) { 55 | printf("Address => [%p] | From => [%d] | Size => [%d]\n", &manager->_usedDesc[i], manager->_usedDesc[i].offset, manager->_usedDesc[i].size); 56 | } 57 | }*/ 58 | } -------------------------------------------------------------------------------- /Engine/Memory/FixedSizeAllocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "BitArray.h" 4 | 5 | // 1 => FREE 6 | // 0 => USED 7 | class FixedSizeAllocator 8 | { 9 | public: 10 | static FixedSizeAllocator* create(void* i_pHeapMemory, size_t i_HeapMemorySize, size_t i_blockSize, size_t i_bits) 11 | { 12 | FixedSizeAllocator* manager = static_cast(i_pHeapMemory); 13 | manager->block_size_ = i_blockSize; 14 | manager->heap_size_ = i_HeapMemorySize; 15 | manager->start_ = reinterpret_cast( 16 | reinterpret_cast(i_pHeapMemory) + 17 | sizeof(FixedSizeAllocator) + 18 | BitArray::calcSpaceForArray(i_bits) 19 | ); 20 | 21 | int* test = (int*)manager->start_; 22 | *test = 1911; 23 | 24 | manager->bit_array_.setAll(i_bits); 25 | 26 | return manager; 27 | } 28 | 29 | static size_t calcSpaceForManager(const size_t bits, const size_t blockSize); 30 | void* _alloc(); 31 | void _free(void* ptr); 32 | bool _contains(const void* ptr) const; 33 | 34 | 35 | void ShowFreeBlocks(const FixedSizeAllocator* i_pManager); 36 | void ShowOutstandingAllocations(const FixedSizeAllocator* i_pManager); 37 | 38 | private: 39 | size_t block_size_; 40 | void* start_; 41 | size_t heap_size_; 42 | BitArray bit_array_; // Always at the end 43 | }; -------------------------------------------------------------------------------- /Engine/Memory/MemorySystem.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PoolAllocator.h" 4 | #include "FixedSizeAllocator.h" 5 | #include "Windows.h" 6 | #include 7 | #include 8 | #include "malloc.h" 9 | 10 | #define LIMIT_1 16 11 | #define LIMIT_2 32 12 | #define LIMIT_3 96 13 | 14 | 15 | namespace HeapManagerProxy 16 | { 17 | static bool MsgsEnabled = true; 18 | void EnableDebugMessages(bool value) 19 | { 20 | MsgsEnabled = value; 21 | } 22 | 23 | 24 | static PoolAllocator* pool; 25 | static FixedSizeAllocator* fsa_1; 26 | static FixedSizeAllocator* fsa_2; 27 | static FixedSizeAllocator* fsa_3; 28 | 29 | 30 | void* GroupAlloc(size_t i_size) 31 | { 32 | // Alignment = 4 33 | if (i_size <= LIMIT_1) 34 | { 35 | return fsa_1->_alloc(); 36 | } 37 | if (i_size <= LIMIT_2) 38 | { 39 | return fsa_2->_alloc(); 40 | } 41 | if (i_size <= LIMIT_3) 42 | { 43 | return fsa_3->_alloc(); 44 | } 45 | return pool->_alloc(i_size, 4); 46 | } 47 | 48 | void GroupFree(void* i_ptr) 49 | { 50 | if (fsa_1->_contains(i_ptr)) 51 | { 52 | fsa_1->_free(i_ptr); 53 | } 54 | if (fsa_2->_contains(i_ptr)) 55 | { 56 | fsa_2->_free(i_ptr); 57 | } 58 | if (fsa_3->_contains(i_ptr)) 59 | { 60 | fsa_3->_free(i_ptr); 61 | } 62 | if (pool->Contains(i_ptr)) 63 | { 64 | pool->_free(i_ptr); 65 | } 66 | } 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | void InitializeMemorySystem() 81 | { 82 | // POOL ALLOCATOR INIT 83 | size_t heapSize = 1024 * 1024; 84 | const unsigned int numDescriptors = 2048; 85 | 86 | void* pHeapMemory = HeapAlloc(GetProcessHeap(), 0, heapSize); 87 | pool = PoolAllocator::create(pHeapMemory, heapSize, numDescriptors); 88 | 89 | // FIXED SIZE ALLOCATOR INIT 90 | size_t nBits = 100; 91 | size_t blockSize = 16; 92 | heapSize = FixedSizeAllocator::calcSpaceForManager(nBits, blockSize); 93 | pHeapMemory = HeapAlloc(GetProcessHeap(), 0, heapSize); 94 | fsa_1 = FixedSizeAllocator::create(pHeapMemory, heapSize, blockSize, nBits); 95 | 96 | nBits = 200; 97 | blockSize = 32; 98 | heapSize = FixedSizeAllocator::calcSpaceForManager(nBits, blockSize); 99 | pHeapMemory = HeapAlloc(GetProcessHeap(), 0, heapSize); 100 | fsa_2 = FixedSizeAllocator::create(pHeapMemory, heapSize, blockSize, nBits); 101 | 102 | nBits = 400; 103 | blockSize = 96; 104 | heapSize = FixedSizeAllocator::calcSpaceForManager(nBits, blockSize); 105 | pHeapMemory = HeapAlloc(GetProcessHeap(), 0, heapSize); 106 | fsa_3 = FixedSizeAllocator::create(pHeapMemory, heapSize, blockSize, nBits); 107 | } 108 | 109 | void Collect() 110 | { 111 | pool->collect(); 112 | } 113 | 114 | void DestroyMemorySystem() 115 | { 116 | HeapFree(GetProcessHeap(), 0, pool); 117 | HeapFree(GetProcessHeap(), 0, fsa_1); 118 | HeapFree(GetProcessHeap(), 0, fsa_2); 119 | HeapFree(GetProcessHeap(), 0, fsa_3); 120 | } 121 | 122 | 123 | 124 | 125 | // malloc/free 126 | void* _cdecl CustomMalloc(size_t i_size) 127 | { 128 | if (MsgsEnabled) printf("malloc %zu\n", i_size); 129 | return HeapManagerProxy::GroupAlloc(i_size); 130 | } 131 | void _cdecl CustomFree(void * i_ptr) 132 | { 133 | if (MsgsEnabled) printf("free 0x%" PRIXPTR "\n", reinterpret_cast(i_ptr)); 134 | return HeapManagerProxy::GroupFree(i_ptr); 135 | } 136 | } 137 | 138 | 139 | 140 | 141 | // Interface for allocation 142 | 143 | 144 | // new/delete 145 | //void * operator new(size_t i_size) 146 | //{ 147 | // if (HeapManagerProxy::MsgsEnabled) printf("new %zu\n", i_size); 148 | // return HeapManagerProxy::GroupAlloc(i_size); 149 | //} 150 | //void operator delete(void * i_ptr) 151 | //{ 152 | // if (HeapManagerProxy::MsgsEnabled) printf("delete 0x%" PRIXPTR "\n", reinterpret_cast(i_ptr)); 153 | // return HeapManagerProxy::GroupFree(i_ptr); 154 | //} 155 | // 156 | //// new[]/delete[] 157 | //void * operator new[](size_t i_size) 158 | //{ 159 | // if (HeapManagerProxy::MsgsEnabled) printf("new [] %zu\n", i_size); 160 | // return HeapManagerProxy::GroupAlloc(i_size); 161 | //} 162 | //void operator delete[](void * i_ptr) 163 | //{ 164 | // if (HeapManagerProxy::MsgsEnabled) printf("delete [] 0x%" PRIXPTR "\n", reinterpret_cast(i_ptr)); 165 | // return HeapManagerProxy::GroupFree(i_ptr); 166 | //} 167 | // 168 | //// custom new to force usage of PoolAllocator 169 | //void * operator new(size_t i_size, bool shouldForcePool) 170 | //{ 171 | // if (HeapManagerProxy::MsgsEnabled) printf("new %zu\n", i_size); 172 | // if (shouldForcePool) 173 | // return HeapManagerProxy::pool->_alloc(i_size, 4); 174 | // else 175 | // return HeapManagerProxy::GroupAlloc(i_size); 176 | //} -------------------------------------------------------------------------------- /Engine/Memory/MemorySystem.h: -------------------------------------------------------------------------------- 1 | namespace HeapManagerProxy 2 | { 3 | void EnableDebugMessages(bool value); 4 | 5 | void InitializeMemorySystem(); 6 | void Collect(); 7 | void DestroyMemorySystem(); 8 | void* GroupAlloc(size_t i_size); 9 | void GroupFree(void* i_ptr); 10 | 11 | void* CustomMalloc(size_t i_size); 12 | void CustomFree(void* i_ptr); 13 | } -------------------------------------------------------------------------------- /Engine/Memory/PoolAllocator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "PoolAllocator.h" 3 | 4 | 5 | void* PoolAllocator::_alloc(size_t i_bytes) 6 | { 7 | if (_nUsedDesc == _nMaxDesc) 8 | { 9 | printf("ERROR: Reached maximum number of ALLOC descriptors, free something to continue! %s @ %d", __FILE__, __LINE__); 10 | return nullptr; 11 | } 12 | for (size_t i = 0; i < _nFreeDesc; i++) 13 | { 14 | if (_freeDesc[i].size > i_bytes) 15 | { 16 | void* ptr = PoolAllocator::getPointerOffset(_start, static_cast(_freeDesc[i].offset + _freeDesc[i].size - i_bytes), false); 17 | 18 | if (writeUsedDescriptor(static_cast(_freeDesc[i].offset + _freeDesc[i].size - i_bytes), i_bytes)) 19 | { 20 | _freeDesc[i].size -= static_cast(i_bytes); 21 | } 22 | return ptr; 23 | } 24 | } 25 | return nullptr; 26 | } 27 | 28 | void* PoolAllocator::_alloc(size_t i_bytes, unsigned int i_alignment) 29 | { 30 | if (_nUsedDesc == _nMaxDesc) 31 | { 32 | printf("ERROR: Reached maximum number of ALLOC descriptors, free something to continue! %s @ %d", __FILE__, __LINE__); 33 | return nullptr; 34 | } 35 | for (size_t i = 0; i < _nFreeDesc; i++) 36 | { 37 | void* ptr = PoolAllocator::getPointerOffset(_start, static_cast(_freeDesc[i].offset + _freeDesc[i].size - i_bytes), false); 38 | unsigned int mod = reinterpret_cast(ptr) % i_alignment; 39 | if (_freeDesc[i].size > i_bytes + mod) 40 | { 41 | // Find an empty ALLOC descriptor to store data 42 | unsigned int allocIndex = int(UINT64_MAX); 43 | for (unsigned int j = 0; j < _nUsedDesc; j++) 44 | { 45 | if (_usedDesc[j].offset == 0) 46 | { 47 | allocIndex = j; 48 | break; 49 | } 50 | } 51 | if (_nUsedDesc == _nMaxDesc) 52 | { 53 | printf("ERROR: Reached maximum number of ALLOC descriptors, free something to continue! %s @ %d", __FILE__, __LINE__); 54 | return nullptr; 55 | } 56 | if (allocIndex > _nUsedDesc) 57 | { 58 | allocIndex = _nUsedDesc; 59 | _nUsedDesc++; 60 | } 61 | // USED metadata set 62 | _usedDesc[allocIndex].offset = static_cast(_freeDesc[i].offset + _freeDesc[i].size - i_bytes - mod); 63 | _usedDesc[allocIndex].size = static_cast(i_bytes + mod); 64 | // FREE metadata set 65 | _freeDesc[i].size -= static_cast(i_bytes + mod); 66 | ptr = PoolAllocator::getPointerOffset(ptr, mod, true); 67 | return ptr; 68 | } 69 | } 70 | return nullptr; 71 | } 72 | 73 | 74 | 75 | bool PoolAllocator::writeUsedDescriptor(unsigned int offset, size_t i_bytes) 76 | { 77 | // Find an empty descriptor to store data 78 | unsigned int allocIndex = int(UINT64_MAX); 79 | for (unsigned int j = 0; j < _nUsedDesc; j++) 80 | { 81 | if (_usedDesc[j].offset == 0) 82 | { 83 | allocIndex = j; 84 | break; 85 | } 86 | } 87 | if (allocIndex > _nUsedDesc) 88 | { 89 | allocIndex = _nUsedDesc; 90 | _nUsedDesc++; 91 | } 92 | _usedDesc[allocIndex].offset = static_cast(offset); 93 | _usedDesc[allocIndex].size = static_cast(i_bytes); 94 | 95 | return true; 96 | } 97 | 98 | bool PoolAllocator::_free(void * i_ptr) 99 | { 100 | unsigned int offset = static_cast(static_cast(i_ptr) - static_cast(_start)); 101 | for (unsigned int i = 0; i < _nUsedDesc; i++) 102 | { 103 | if (_usedDesc[i].offset == offset) 104 | { 105 | for (unsigned int j = 0; j < _nFreeDesc; j++) 106 | { 107 | if (_freeDesc[j].offset == 0) 108 | { 109 | _freeDesc[j].offset = _usedDesc[i].offset; 110 | _freeDesc[j].size = _usedDesc[i].size; 111 | _usedDesc[i].offset = 0; 112 | collect(); 113 | return true; 114 | } 115 | } 116 | if (_nFreeDesc == _nMaxDesc) 117 | { 118 | printf("\nERROR: Reached maximum number of FREE descriptors, defragmenting! %s @ %d", __FILE__, __LINE__); 119 | collect(); 120 | return false; 121 | } 122 | else 123 | { 124 | _freeDesc[_nFreeDesc].offset = _usedDesc[i].offset; 125 | _freeDesc[_nFreeDesc].size = _usedDesc[i].size; 126 | _usedDesc[i].offset = 0; 127 | _nFreeDesc++; 128 | collect(); 129 | return true; 130 | } 131 | } 132 | } 133 | return false; 134 | } 135 | 136 | void PoolAllocator::collect() 137 | { 138 | for (unsigned int i = 0; i < _nFreeDesc; i++) 139 | { 140 | if (_freeDesc[i].offset == 0) continue; 141 | for (unsigned int j = 0; j < _nFreeDesc; j++) 142 | { 143 | if (_freeDesc[j].offset == 0) continue; 144 | if (_freeDesc[i].offset + _freeDesc[i].size == _freeDesc[j].offset) 145 | { 146 | _freeDesc[i].size += _freeDesc[j].size; 147 | _freeDesc[j].offset = 0; 148 | _freeDesc[j].size = 0; 149 | } 150 | } 151 | } 152 | } 153 | 154 | size_t PoolAllocator::getLargestFreeBlock() 155 | { 156 | size_t largestFree = 0; 157 | for (unsigned int i = 0; i < _nFreeDesc; i++) 158 | { 159 | if (_freeDesc[i].size > largestFree) 160 | { 161 | largestFree = _freeDesc[i].size; 162 | } 163 | } 164 | return largestFree; 165 | } 166 | 167 | size_t PoolAllocator::getTotalFreeMemory() 168 | { 169 | size_t temp = 0; 170 | for (unsigned int i = 0; i < _nFreeDesc; i++) 171 | { 172 | if (_freeDesc[i].size != 0) 173 | { 174 | temp += _freeDesc[i].size; 175 | } 176 | } 177 | return temp; 178 | } 179 | 180 | bool PoolAllocator::Contains(const void * i_ptr) 181 | { 182 | if (i_ptr > _start && i_ptr < _end) 183 | { 184 | return true; 185 | } 186 | return false; 187 | } 188 | 189 | bool PoolAllocator::IsAllocated(const void * i_ptr) 190 | { 191 | size_t diff = reinterpret_cast(i_ptr) - reinterpret_cast(_start); 192 | for (unsigned int i = 0; i < _nUsedDesc; i++) 193 | { 194 | if (_usedDesc[i].offset == diff) 195 | { 196 | return true; 197 | } 198 | } 199 | return false; 200 | } 201 | 202 | BlockDesc* PoolAllocator::FindAllocated(const void* i_ptr) 203 | { 204 | size_t diff = (char*)i_ptr - (char*)_start; 205 | for (unsigned int i = 0; i < _nUsedDesc; i++) 206 | { 207 | if (_usedDesc[i].offset == diff) 208 | { 209 | return &_usedDesc[i]; 210 | } 211 | } 212 | return nullptr; 213 | } 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | // PRINT / DEBUG 222 | void PoolAllocator::ShowFreeBlocks() 223 | { 224 | printf("\nPRINTING ALL FREE BLOCKS\n=========================\n"); 225 | for (unsigned int i = 0; i < _nFreeDesc; i++) 226 | { 227 | if (_freeDesc[i].offset != 0) 228 | { 229 | printf("Address => [%p] | From => [%d] | Size => [%d]\n", &_freeDesc[i], _freeDesc[i].offset, _freeDesc[i].size); 230 | } 231 | } 232 | } 233 | void PoolAllocator::ShowOutstandingAllocations() 234 | { 235 | printf("\nPRINTING ALL ALLOCATED BLOCKS\n=========================\n"); 236 | for (unsigned int i = 0; i < _nUsedDesc; i++) 237 | { 238 | if (_usedDesc[i].offset != 0) 239 | { 240 | printf("Address => [%p] | From => [%d] | Size => [%d]\n", &_usedDesc[i], _usedDesc[i].offset, _usedDesc[i].size); 241 | } 242 | } 243 | } 244 | void PoolAllocator::clearBits(void* ptr, size_t size) 245 | { 246 | for (unsigned int i = 0; i < size; i++) 247 | { 248 | char* temp = (char*)ptr + i; 249 | *temp = '/'; 250 | } 251 | } 252 | 253 | // MATH HELPERS 254 | void* PoolAllocator::getPointerOffset(void* ptr, unsigned int offset, bool isReverse) 255 | { 256 | if (isReverse) 257 | { 258 | return reinterpret_cast((char*)ptr - offset); 259 | } 260 | else 261 | { 262 | return reinterpret_cast((char*)ptr + offset); 263 | } 264 | } -------------------------------------------------------------------------------- /Engine/Memory/PoolAllocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | 5 | // SIZE = 8 bytes 6 | struct BlockDesc 7 | { 8 | unsigned int offset; 9 | unsigned int size; 10 | }; 11 | 12 | class PoolAllocator 13 | { 14 | public: // Inaccessible when set to protected/private 15 | BlockDesc* _usedDesc; 16 | BlockDesc* _freeDesc; 17 | unsigned int _nMaxDesc = 0; 18 | unsigned int _nUsedDesc = 0; 19 | unsigned int _nFreeDesc = 0; 20 | size_t _heapSize = 0; 21 | size_t _memUsed = 0; 22 | void* _start; 23 | void* _end; 24 | 25 | 26 | 27 | 28 | 29 | 30 | static PoolAllocator* create(void* i_pHeapMemory, size_t i_HeapMemorySize, unsigned int i_numDescriptors) 31 | { 32 | PoolAllocator* manager = static_cast(i_pHeapMemory); 33 | manager->_start = static_cast((char*)manager + sizeof(PoolAllocator)); 34 | manager->_heapSize = i_HeapMemorySize; 35 | manager->_nMaxDesc = i_numDescriptors; 36 | manager->_memUsed = 0; 37 | manager->_end = (char*)manager->_start + manager->_heapSize - (static_cast(manager->_nMaxDesc) * 2 * sizeof(BlockDesc)) - sizeof(PoolAllocator); 38 | 39 | // Init Descriptors 40 | manager->_usedDesc = static_cast(manager->_end); 41 | manager->_nUsedDesc = 0; 42 | 43 | manager->_freeDesc = static_cast((void*)((char*)manager->_end + (manager->_nMaxDesc * sizeof(BlockDesc)))); 44 | manager->_nFreeDesc = 1; 45 | manager->_freeDesc[0].offset = 4; 46 | manager->_freeDesc[0].size = static_cast((char*)manager->_end - (char*)manager->_start); 47 | 48 | return manager; 49 | } 50 | void destroy() 51 | { 52 | 53 | } 54 | 55 | void* _alloc(size_t i_bytes); 56 | void* _alloc(size_t i_bytes, unsigned int i_alignment); 57 | bool _free(void* i_ptr); 58 | void collect(); 59 | size_t getLargestFreeBlock(); 60 | size_t getTotalFreeMemory(); 61 | bool Contains(const void * i_ptr); 62 | bool IsAllocated(const void* i_ptr); 63 | BlockDesc* FindAllocated(const void* i_ptr); 64 | void ShowFreeBlocks(); 65 | void ShowOutstandingAllocations(); 66 | void clearBits(void* ptr, size_t size); 67 | 68 | bool writeUsedDescriptor(unsigned int offset, size_t i_bytes); 69 | 70 | static void* getPointerOffset(void* ptr, unsigned int offset, bool isReverse); 71 | }; -------------------------------------------------------------------------------- /Engine/Memory/SmartPointer/RefCount.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct RefCount 4 | { 5 | int SmartPtrCount; 6 | int WeakPtrCount; 7 | 8 | RefCount(const int smartPtrCount, const int weakPtrCount) : 9 | SmartPtrCount(smartPtrCount), WeakPtrCount(weakPtrCount) 10 | {} 11 | }; -------------------------------------------------------------------------------- /Engine/Memory/SmartPointer/SmartPtr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RefCount.h" 4 | 5 | 6 | 7 | 8 | template 9 | class SmartPtr 10 | { 11 | template 12 | friend class WeakPtr; 13 | friend class SmartPtrConversion; 14 | 15 | RefCount * refCount; 16 | T * ptr; 17 | 18 | public: 19 | // Construct 20 | explicit SmartPtr(T * pointer = nullptr) : 21 | refCount(new RefCount(1, 0)), 22 | ptr(pointer) 23 | {} 24 | 25 | // Copy 26 | SmartPtr(const SmartPtr & other) : 27 | refCount(other.refCount), 28 | ptr(other.ptr) 29 | { 30 | if (ptr && refCount) 31 | refCount->SmartPtrCount++; 32 | } 33 | 34 | // SmartPtr(const WeakPtr & other); 35 | 36 | // Move 37 | SmartPtr(const SmartPtr && other) noexcept : 38 | refCount(other.refCount), 39 | ptr(other.ptr) 40 | { 41 | ++other.refCount->SmartPtrCount; 42 | } 43 | 44 | // Assign 45 | SmartPtr & operator = (const SmartPtr & other) 46 | { 47 | if (this->ptr == other.ptr) 48 | return *this; 49 | 50 | SafeRelease(); 51 | ptr = other.ptr; 52 | refCount = other.refCount; 53 | refCount->SmartPtrCount++; 54 | return *this; 55 | } 56 | SmartPtr & operator = (const SmartPtr && other) 57 | { 58 | return *this; 59 | } 60 | SmartPtr & operator = (std::nullptr_t other) 61 | { 62 | SafeRelease(); 63 | ptr = nullptr; 64 | refCount = nullptr; 65 | return *this; 66 | } 67 | 68 | // Destruct 69 | ~SmartPtr() 70 | { 71 | SafeRelease(); 72 | refCount = nullptr; 73 | ptr = nullptr; 74 | } 75 | 76 | int getSmartCount() const 77 | { 78 | return refCount->SmartPtrCount; 79 | } 80 | 81 | 82 | operator bool() const { return ptr ? true : false; } 83 | bool operator == (const T * t) { return (t == ptr) ? true : false; } 84 | bool operator == (const SmartPtr & other) { return (other.ptr == ptr) ? true : false; } 85 | T & operator * () { return *ptr; } 86 | T * operator -> () { return ptr; } 87 | 88 | 89 | 90 | private: 91 | SmartPtr(T * i_ptr, RefCount * i_refCount) : 92 | refCount(i_refCount), 93 | ptr(i_ptr) 94 | { 95 | if (ptr && refCount) 96 | refCount->SmartPtrCount++; 97 | } 98 | 99 | void SafeRelease() const 100 | { 101 | if (refCount) 102 | { 103 | refCount->SmartPtrCount--; 104 | if (refCount->SmartPtrCount <= 0) 105 | { 106 | delete ptr; 107 | delete refCount; 108 | } 109 | } 110 | } 111 | }; -------------------------------------------------------------------------------- /Engine/Memory/SmartPointer/SmartPtrConversion.h: -------------------------------------------------------------------------------- 1 | #include "SmartPtr.h" 2 | 3 | class SmartPtrConversion 4 | { 5 | public: 6 | template 7 | static SmartPtr SmartPtrCast(const SmartPtr & src) 8 | { 9 | SmartPtr destSmartPtr; 10 | destSmartPtr.ptr = static_cast(src.ptr); 11 | destSmartPtr.refCount = src.refCount; 12 | ++destSmartPtr.refCount->SmartPtrCount; 13 | return destSmartPtr; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Engine/Memory/SmartPointer/WeakPtr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SmartPtr.h" 4 | 5 | 6 | template 7 | class WeakPtr 8 | { 9 | friend SmartPtr; 10 | 11 | RefCount * refCount; 12 | T * ptr; 13 | 14 | public: 15 | // Construct 16 | WeakPtr() : 17 | refCount(nullptr), 18 | ptr(nullptr) 19 | {} 20 | 21 | // Copy 22 | WeakPtr(const WeakPtr & other) : 23 | refCount(other.refCount), 24 | ptr(other.ptr) 25 | { 26 | if (ptr && refCount) 27 | refCount->WeakPtrCount++; 28 | } 29 | WeakPtr(const SmartPtr & other) : 30 | refCount(other.refCount), 31 | ptr(other.ptr) 32 | { 33 | if (ptr && refCount) 34 | refCount->WeakPtrCount++; 35 | } 36 | 37 | // Move 38 | WeakPtr(const WeakPtr && other) noexcept : 39 | refCount(other.refCount), 40 | ptr(other.ptr) 41 | { 42 | ++other.refCount->WeakPtrCount; 43 | } 44 | 45 | // Assign 46 | WeakPtr & operator = (const SmartPtr & other) 47 | { 48 | if (ptr == other.ptr) 49 | return *this; 50 | 51 | SafeRelease(); 52 | ptr = other.ptr; 53 | refCount = other.refCount; 54 | refCount->WeakPtrCount++; 55 | return *this; 56 | } 57 | WeakPtr & operator = (const WeakPtr & other) 58 | { 59 | if (ptr == other.ptr) 60 | return *this; 61 | 62 | SafeRelease(); 63 | ptr = other.ptr; 64 | refCount = other.refCount; 65 | return *this; 66 | } 67 | WeakPtr & operator = (const WeakPtr && other) 68 | { 69 | //if (ptr == other.ptr) 70 | // return *this; 71 | 72 | //SafeRelease(); 73 | //ptr = other.ptr; 74 | //refCount = other.refCount; 75 | return *this; 76 | } 77 | WeakPtr & operator = (std::nullptr_t other) 78 | { 79 | SafeRelease(); 80 | ptr = nullptr; 81 | refCount = nullptr; 82 | return *this; 83 | } 84 | 85 | // Destruct 86 | ~WeakPtr() 87 | { 88 | if (ptr && refCount && refCount->SmartPtrCount > 0) SafeRelease(); 89 | } 90 | 91 | 92 | 93 | 94 | operator bool() const { return ptr ? true : false; } 95 | bool operator == (const T * t) { return (t == ptr) ? true : false; } 96 | bool operator == (const WeakPtr & other) { return (other.ptr == ptr) ? true : false; } 97 | bool operator == (const SmartPtr & other) { return (other.ptr == ptr) ? true : false; } 98 | 99 | 100 | bool acquire(SmartPtr & ref) 101 | { 102 | if (ptr && refCount && refCount->SmartPtrCount > 0) 103 | { 104 | SmartPtr toReturn(ptr, refCount); 105 | ref = toReturn; 106 | 107 | return true; 108 | } 109 | return false; 110 | } 111 | 112 | 113 | private: 114 | void SafeRelease() const 115 | { 116 | if (refCount) 117 | { 118 | refCount->WeakPtrCount--; 119 | if (refCount && refCount->SmartPtrCount <= 0) 120 | { 121 | delete ptr; 122 | delete refCount; 123 | } 124 | } 125 | } 126 | }; -------------------------------------------------------------------------------- /Engine/Render/GLibHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "GLib/GLib.h" 6 | 7 | 8 | namespace GLibHelper 9 | { 10 | void * LoadFile(const char * i_pFilename, size_t & o_sizeFile) 11 | { 12 | assert(i_pFilename != NULL); 13 | 14 | FILE * pFile = NULL; 15 | 16 | errno_t fopenError = fopen_s(&pFile, i_pFilename, "rb"); 17 | if (fopenError != 0) 18 | return NULL; 19 | 20 | assert(pFile != NULL); 21 | 22 | int FileIOError = fseek(pFile, 0, SEEK_END); 23 | assert(FileIOError == 0); 24 | 25 | long FileSize = ftell(pFile); 26 | assert(FileSize >= 0); 27 | 28 | FileIOError = fseek(pFile, 0, SEEK_SET); 29 | assert(FileIOError == 0); 30 | 31 | uint8_t * pBuffer = new uint8_t[FileSize]; 32 | assert(pBuffer); 33 | 34 | size_t FileRead = fread(pBuffer, 1, FileSize, pFile); 35 | assert(FileRead == FileSize); 36 | 37 | fclose(pFile); 38 | 39 | o_sizeFile = FileSize; 40 | 41 | return pBuffer; 42 | } 43 | 44 | GLib::Sprites::Sprite * CreateSprite(const char * i_pFilename) 45 | { 46 | assert(i_pFilename); 47 | 48 | size_t sizeTextureFile = 0; 49 | 50 | // Load the source file (texture data) 51 | void * pTextureFile = LoadFile(i_pFilename, sizeTextureFile); 52 | 53 | // Ask GLib to create a texture out of the data (assuming it was loaded successfully) 54 | GLib::Texture * pTexture = pTextureFile ? GLib::CreateTexture(pTextureFile, sizeTextureFile) : nullptr; 55 | 56 | // exit if something didn't work 57 | // probably need some debug logging in here!!!! 58 | if (pTextureFile) 59 | delete[] pTextureFile; 60 | 61 | if (pTexture == nullptr) 62 | return NULL; 63 | 64 | unsigned int width = 0; 65 | unsigned int height = 0; 66 | unsigned int depth = 0; 67 | 68 | // Get the dimensions of the texture. We'll use this to determine how big it is on screen 69 | bool result = GLib::GetDimensions(pTexture, width, height, depth); 70 | assert(result == true); 71 | assert((width > 0) && (height > 0)); 72 | 73 | // Define the sprite edges 74 | GLib::Sprites::SpriteEdges Edges = { -float(width / 2.0f), float(height / 2.0f), float(width / 2.0f), -float(height / 2.0f) }; 75 | GLib::Sprites::SpriteUVs UVs = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f } }; 76 | GLib::RGBA Color = { 255, 255, 255, 255 }; 77 | 78 | // Create the sprite 79 | GLib::Sprites::Sprite * pSprite = GLib::Sprites::CreateSprite(Edges, 0.1f, Color, UVs); 80 | if (pSprite == nullptr) 81 | { 82 | GLib::Release(pTexture); 83 | return nullptr; 84 | } 85 | 86 | // Bind the texture to sprite 87 | GLib::Sprites::SetTexture(*pSprite, *pTexture); 88 | 89 | return pSprite; 90 | } 91 | } -------------------------------------------------------------------------------- /Engine/String/String.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "String.h" 4 | 5 | bool String::ReadString(char* &str) 6 | { 7 | int size = 0; 8 | char c; 9 | 10 | while ((c = std::cin.get()) != '\n') 11 | { 12 | if (size > 0) 13 | { 14 | char* temp = new char[size]; 15 | StringCopy(str, temp, size); 16 | delete[] str; 17 | str = new char[++size + 1]; 18 | str[size - 1] = c; 19 | StringCopy(temp, str, size - 1); 20 | delete[] temp; 21 | } 22 | else 23 | { 24 | str[size++] = c; 25 | } 26 | } 27 | str[size] = '\0'; 28 | if (str == nullptr) 29 | return false; 30 | else 31 | return true; 32 | } 33 | 34 | bool String::StringCompare(const char* str1, const char* str2) 35 | { 36 | size_t i = 0; 37 | while (i < MAX_CHECK_LENGTH) 38 | { 39 | if (str1[i] == '\0' && str2[i] == '\0') 40 | return true; 41 | 42 | if (str1[i] == '\0' || str2[i] == '\0') 43 | return false; 44 | 45 | if (str1[i] != str2[i]) 46 | return false; 47 | i++; 48 | } 49 | return false; 50 | } 51 | 52 | size_t String::GetLength(const char* str) 53 | { 54 | size_t i = 0; 55 | while (i < MAX_CHECK_LENGTH && str[i] != '\0') 56 | { 57 | i++; 58 | } 59 | return i; 60 | } 61 | 62 | void String::StringCopy(const char* inStr, char* &outStr, size_t len) 63 | { 64 | for (size_t i = 0; i < len; i++) 65 | { 66 | outStr[i] = inStr[i]; 67 | } 68 | } -------------------------------------------------------------------------------- /Engine/String/String.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define MAX_CHECK_LENGTH 128 6 | 7 | class String 8 | { 9 | public: 10 | static bool ReadString(char* &str); 11 | static bool StringCompare(const char* str1, const char* str2); 12 | static size_t GetLength(const char* str); 13 | static void StringCopy(const char* inStr, char* &outStr, size_t len); 14 | }; -------------------------------------------------------------------------------- /EnginePlusPong.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.757 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Engine", "Engine\Engine.vcxproj", "{D32EC244-7D50-4AFE-97D6-21816808F479}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MemManager", "Pong\Pong.vcxproj", "{3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Debug|x64.ActiveCfg = Debug|x64 19 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Debug|x64.Build.0 = Debug|x64 20 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Debug|x86.ActiveCfg = Debug|Win32 21 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Debug|x86.Build.0 = Debug|Win32 22 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Release|x64.ActiveCfg = Release|x64 23 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Release|x64.Build.0 = Release|x64 24 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Release|x86.ActiveCfg = Release|Win32 25 | {D32EC244-7D50-4AFE-97D6-21816808F479}.Release|x86.Build.0 = Release|Win32 26 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Debug|x64.ActiveCfg = Debug|x64 27 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Debug|x64.Build.0 = Debug|x64 28 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Debug|x86.ActiveCfg = Debug|Win32 29 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Debug|x86.Build.0 = Debug|Win32 30 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Release|x64.ActiveCfg = Release|x64 31 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Release|x64.Build.0 = Release|x64 32 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Release|x86.ActiveCfg = Release|Win32 33 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {5393B636-A2DC-4017-9B61-B7291FBE85E0} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /Exports/GLib/BasicTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace GLib 6 | { 7 | typedef void(*KeyStateChange)(unsigned int i_VKeyID, bool i_bDown); 8 | 9 | struct Point2D 10 | { 11 | float x; 12 | float y; 13 | }; 14 | 15 | struct UV 16 | { 17 | float u, v; 18 | }; 19 | 20 | struct RGBA 21 | { 22 | uint8_t r, g, b, a; 23 | }; 24 | 25 | namespace Sprites 26 | { 27 | typedef struct _SpriteEdges 28 | { 29 | float Left; 30 | float Top; 31 | float Right; 32 | float Bottom; 33 | } SpriteEdges; 34 | 35 | typedef struct _SpriteUVs 36 | { 37 | UV TopLeft; 38 | UV TopRight; 39 | UV BottomLeft; 40 | UV BottomRight; 41 | } SpriteUVs; 42 | } // namespace Sprites 43 | } // namespace GLib -------------------------------------------------------------------------------- /Exports/GLib/GLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "BasicTypes.h" 6 | 7 | namespace GLib 8 | { 9 | bool Initialize( HINSTANCE i_hInstance, int i_CmdShow, const char * i_pWindowName, WORD i_IconID, unsigned int i_WindowWidth, unsigned int i_WindowHeight ); 10 | void Shutdown(); 11 | 12 | void Service( bool & o_bQuitRequested ); 13 | 14 | void SetKeyStateChangeCallback(KeyStateChange i_Callback); 15 | 16 | bool BeginRendering(); 17 | void EndRendering(); 18 | 19 | struct Texture; 20 | 21 | Texture * CreateTexture( void * i_pTextureData, size_t i_sizeTextureData ); 22 | void Release( Texture * i_pTexture ); 23 | 24 | bool GetDimensions( Texture * i_pTexture, unsigned int & o_Width, unsigned int & o_Height, unsigned int & o_Depth ); 25 | 26 | namespace Sprites 27 | { 28 | struct Sprite; 29 | 30 | bool Initialize(); 31 | void Shutdown(); 32 | 33 | bool BeginRendering(); 34 | void EndRendering(); 35 | 36 | Sprite * CreateSprite( const SpriteEdges & i_VertexOffsets, float i_Depth, const RGBA & i_Color, const SpriteUVs & i_UVs ); 37 | void SetTexture( Sprite & i_Sprite, Texture & i_Texture ); 38 | 39 | bool RenderSprite( const Sprite & i_Sprite, const Point2D & i_Offset, float i_zRotRadians ); 40 | 41 | void Release( Sprite * i_pSprite ); 42 | } // namespace Sprites 43 | } // namespace GLib -------------------------------------------------------------------------------- /Exports/GLib/GLib.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Exports/GLib/GLib.lib -------------------------------------------------------------------------------- /FixedSizeAllocator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/FixedSizeAllocator.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Vishal Naidu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MemoryPoolAllocator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/MemoryPoolAllocator.png -------------------------------------------------------------------------------- /Pong/Assets/BrickGreen.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/BrickGreen.dds -------------------------------------------------------------------------------- /Pong/Assets/BrickRed.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/BrickRed.dds -------------------------------------------------------------------------------- /Pong/Assets/Circle.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/Circle.dds -------------------------------------------------------------------------------- /Pong/Assets/LeftPaddle.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/LeftPaddle.dds -------------------------------------------------------------------------------- /Pong/Assets/RightPaddle.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/RightPaddle.dds -------------------------------------------------------------------------------- /Pong/Assets/Square.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/Square.dds -------------------------------------------------------------------------------- /Pong/Assets/WhiteSquareArrow.dds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vieper1/MemoryManager/e84551b9365c03a8dfa575ce2ebd4705f72aae72/Pong/Assets/WhiteSquareArrow.dds -------------------------------------------------------------------------------- /Pong/Pong.cpp: -------------------------------------------------------------------------------- 1 | #include "General/World.h" 2 | #include "General/Components/Physics.h" 3 | #include "General/Systems/Input.h" 4 | #include "Math/Math.h" 5 | 6 | 7 | //////////////////////////////////////////////////////////////////////////////////// Keyboard Input Event 8 | void Keyboard_HandleActionInput(World * world, PhysicsComponent * leftPhysics, PhysicsComponent * rightPhysics) 9 | { 10 | const float forceMultiplier = 1.f; 11 | const float rotationSpeed = -1.f; 12 | 13 | if (Input::Keyboard_IsKeyDown(87)) // UP 14 | leftPhysics->AddForce(Vector2::Up() * forceMultiplier); 15 | if (Input::Keyboard_IsKeyDown(83)) // DOWN 16 | leftPhysics->AddForce(Vector2::Down() * forceMultiplier); 17 | 18 | if (Input::Keyboard_IsKeyDown(73)) // UP 19 | rightPhysics->AddForce(Vector2::Up() * forceMultiplier); 20 | if (Input::Keyboard_IsKeyDown(75)) // DOWN 21 | rightPhysics->AddForce(Vector2::Down() * forceMultiplier); 22 | 23 | if (Input::Keyboard_IsKeyDown(27)) 24 | world->EndPlay(); 25 | //if (Keyboard_IsKeyDown(70)) // Debug Trigger 26 | // playerActor->bDebugTrigger = true; 27 | } 28 | //////////////////////////////////////////////////////////////////////////////////// Keyboard Input Event 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ////////////////////////////////////////////////////////////////////////////////////// Game Logic 43 | enum WinningPlayer 44 | { 45 | None, 46 | LeftPlayer, 47 | RightPlayer 48 | }; 49 | 50 | void EnforcePaddleBounds(SmartPtr & leftPaddle, SmartPtr & rightPaddle) 51 | { 52 | if (Math::clampRef(leftPaddle->position.y, -200, 220)) 53 | leftPaddle->SetVelocity(Vector2::Zero()); 54 | 55 | if (Math::clampRef(rightPaddle->position.y, -200, 220)) 56 | rightPaddle->SetVelocity(Vector2::Zero()); 57 | } 58 | 59 | WinningPlayer CheckScoreAndResetBall(World * world, SmartPtr & ball, int & leftScore, int & rightScore, const bool forceReset = false) 60 | { 61 | const float hVelocityMultiplier = 300.0f; 62 | 63 | const float ballX = ball->position.x; 64 | if (forceReset) 65 | { 66 | ball->position = Vector2::Zero(); 67 | ball->SetVelocity(Vector2(hVelocityMultiplier, 0.0f)); 68 | return WinningPlayer::None; 69 | } 70 | else 71 | { 72 | if (ballX > 400.f) 73 | { 74 | if (++leftScore == 3) 75 | { 76 | world->EndPlay(); 77 | return WinningPlayer::LeftPlayer; 78 | } 79 | ball->position = Vector2::Zero(); 80 | ball->SetVelocity(Vector2(hVelocityMultiplier, 0.0f)); 81 | } 82 | else if (ballX < -400.f) 83 | { 84 | if (++rightScore == 3) 85 | { 86 | world->EndPlay(); 87 | return WinningPlayer::RightPlayer; 88 | } 89 | ball->position = Vector2::Zero(); 90 | ball->SetVelocity(Vector2(-hVelocityMultiplier, 0.0f)); 91 | } 92 | return WinningPlayer::None; 93 | } 94 | } 95 | 96 | void EnforceBallConstantVelocity(SmartPtr & ball) 97 | { 98 | const float velocityMultiplier = 400.f; 99 | ball->SetVelocity(ball->GetVelocity().getNormalized() * velocityMultiplier); 100 | } 101 | 102 | int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) 103 | { 104 | { 105 | int LeftScore = 0; 106 | int RightScore = 0; 107 | WinningPlayer winner = WinningPlayer::None; 108 | 109 | auto world = new World(hInstance, nCmdShow); 110 | 111 | SmartPtr leftPaddle; 112 | world->SpawnPrefab(leftPaddle, "Saved\\LeftPaddle.json"); 113 | PhysicsComponent * leftPaddlePhysicsComp = leftPaddle->GetComponent(); 114 | 115 | SmartPtr rightPaddle; 116 | world->SpawnPrefab(rightPaddle, "Saved\\RightPaddle.json"); 117 | PhysicsComponent * rightPaddlePhysicsComp = rightPaddle->GetComponent(); 118 | 119 | SmartPtr ball; 120 | world->SpawnPrefab(ball, "Saved\\Ball.json"); 121 | 122 | 123 | 124 | world->LoadScene("Saved\\EditorStatePong.json"); 125 | 126 | 127 | world->BeginPlayAll(); 128 | CheckScoreAndResetBall(world, ball, LeftScore, RightScore, true); 129 | while (true) 130 | { 131 | if (world->GetIsGameOver()) break; 132 | if (world->GetIsGamePaused()) continue; 133 | 134 | // Tick 135 | world->TickAll(); 136 | EnforceBallConstantVelocity(ball); 137 | EnforcePaddleBounds(leftPaddle, rightPaddle); 138 | winner = CheckScoreAndResetBall(world, ball, LeftScore, RightScore); 139 | if (winner != WinningPlayer::None) 140 | break; 141 | 142 | // GLib 143 | Keyboard_HandleActionInput(world, leftPaddlePhysicsComp, rightPaddlePhysicsComp); 144 | if (!world->RenderAllActors()) 145 | break; 146 | } 147 | 148 | const size_t lenBuffer = 127; 149 | char Buffer[lenBuffer]; 150 | sprintf_s(Buffer, lenBuffer, "\n\n\n\n\n///// Winning Player = [%s]\n\n\n\n\n", winner == LeftPlayer ? "LEFT" : "RIGHT"); 151 | OutputDebugStringA(Buffer); 152 | 153 | world->Shutdown(); 154 | } 155 | 156 | #if defined(_DEBUG) 157 | _CrtDumpMemoryLeaks(); 158 | #endif // _DEBUG 159 | 160 | return 0; 161 | } 162 | //////////////////////////////////////////////////////////////////////////////////// Game Logic 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /Pong/Pong.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 15.0 29 | {3826FDBD-F04B-4A20-A3D0-3E1EDFA74FB4} 30 | Win32Proj 31 | CppAssignments 32 | 10.0.17763.0 33 | Pong 34 | 35 | 36 | 37 | Application 38 | true 39 | v141 40 | MultiByte 41 | 42 | 43 | Application 44 | false 45 | v141 46 | true 47 | MultiByte 48 | 49 | 50 | Application 51 | true 52 | v141 53 | MultiByte 54 | 55 | 56 | Application 57 | false 58 | v141 59 | true 60 | MultiByte 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | true 82 | $(SolutionDir)Engine;$(IncludePath) 83 | $(SolutionDir)Exports\GLib;$(LibraryPath) 84 | 85 | 86 | true 87 | $(SolutionDir)Engine;$(IncludePath) 88 | $(SolutionDir)Exports\GLib;$(LibraryPath) 89 | 90 | 91 | false 92 | $(SolutionDir)Engine;$(IncludePath) 93 | $(SolutionDir)Exports\GLib;$(LibraryPath) 94 | 95 | 96 | false 97 | $(SolutionDir)Engine;$(IncludePath) 98 | $(SolutionDir)Exports\GLib;$(LibraryPath) 99 | 100 | 101 | 102 | NotUsing 103 | Level3 104 | Disabled 105 | true 106 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | 109 | 110 | $(SolutionDir)Exports;%(AdditionalIncludeDirectories) 111 | 112 | 113 | 114 | 115 | Windows 116 | true 117 | C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64;$(SolutionDir)$(Configuration);$(SolutionDir)x64\$(Configuration);%(AdditionalLibraryDirectories) 118 | Engine.lib;D3d11.lib;GLib.lib;%(AdditionalDependencies) 119 | 120 | 121 | 122 | 123 | NotUsing 124 | Level3 125 | Disabled 126 | true 127 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 128 | true 129 | 130 | 131 | $(SolutionDir)Exports;%(AdditionalIncludeDirectories) 132 | 133 | 134 | 135 | 136 | Windows 137 | true 138 | C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64;$(SolutionDir)x64\$(Configuration);%(AdditionalLibraryDirectories) 139 | Engine.lib;D3d11.lib;GLib.lib;%(AdditionalDependencies) 140 | 141 | 142 | 143 | 144 | NotUsing 145 | Level3 146 | MaxSpeed 147 | true 148 | true 149 | true 150 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 151 | true 152 | 153 | 154 | $(SolutionDir)Exports;%(AdditionalIncludeDirectories) 155 | 156 | 157 | 158 | 159 | Windows 160 | true 161 | true 162 | true 163 | C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64;$(SolutionDir)$(Configuration);$(SolutionDir)x64\$(Configuration);%(AdditionalLibraryDirectories) 164 | Engine.lib;D3d11.lib;GLib.lib;%(AdditionalDependencies) 165 | 166 | 167 | 168 | 169 | NotUsing 170 | Level3 171 | MaxSpeed 172 | true 173 | true 174 | true 175 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 176 | true 177 | 178 | 179 | $(SolutionDir)Exports;%(AdditionalIncludeDirectories) 180 | 181 | 182 | 183 | 184 | Windows 185 | true 186 | true 187 | true 188 | C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64;$(SolutionDir)x64\$(Configuration);%(AdditionalLibraryDirectories) 189 | Engine.lib;D3d11.lib;GLib.lib;%(AdditionalDependencies) 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /Pong/Pong.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Resource Files 20 | 21 | 22 | 23 | 24 | Source Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pong/Saved/Ball.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ball", 3 | "sprite-path": "Assets\\Square.dds", 4 | "initial-position": [0.0, 0.0], 5 | "initial-velocity": [0.0, 0.0], 6 | "initial-rotation": 0.0, 7 | "components": [ 8 | { 9 | "type": "PhysicsComponent", 10 | "mass": 0.1, 11 | "gravity-scale": 0, 12 | "linear-drag": 0.0 13 | }, 14 | { 15 | "type": "BoxColliderComponent", 16 | "size": [100.0, 100.0] 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Pong/Saved/EditorStatePong.json: -------------------------------------------------------------------------------- 1 | { 2 | "actors": [ 3 | 4 | 5 | { 6 | "name": "WallT1", 7 | "sprite-path": "Assets\\Square.dds", 8 | "initial-position": [0.0, 320.0], 9 | "player-actor": false, 10 | "mobility": "static", 11 | "components": [ 12 | { 13 | "type": "PhysicsComponent", 14 | "mass": 1, 15 | "gravity-scale": 0, 16 | "linear-drag": 0.1 17 | }, 18 | { 19 | "type": "BoxColliderComponent", 20 | "size": [100.0, 100.0] 21 | } 22 | ] 23 | }, 24 | { 25 | "name": "WallT2", 26 | "sprite-path": "Assets\\Square.dds", 27 | "initial-position": [100.0, 320.0], 28 | "player-actor": false, 29 | "mobility": "static", 30 | "components": [ 31 | { 32 | "type": "PhysicsComponent", 33 | "mass": 1, 34 | "gravity-scale": 0, 35 | "linear-drag": 0.1 36 | }, 37 | { 38 | "type": "BoxColliderComponent", 39 | "size": [100.0, 100.0] 40 | } 41 | ] 42 | }, 43 | { 44 | "name": "WallT3", 45 | "sprite-path": "Assets\\Square.dds", 46 | "initial-position": [200.0, 320.0], 47 | "player-actor": false, 48 | "mobility": "static", 49 | "components": [ 50 | { 51 | "type": "PhysicsComponent", 52 | "mass": 1, 53 | "gravity-scale": 0, 54 | "linear-drag": 0.1 55 | }, 56 | { 57 | "type": "BoxColliderComponent", 58 | "size": [100.0, 100.0] 59 | } 60 | ] 61 | }, 62 | { 63 | "name": "WallT4", 64 | "sprite-path": "Assets\\Square.dds", 65 | "initial-position": [300.0, 320.0], 66 | "player-actor": false, 67 | "mobility": "static", 68 | "components": [ 69 | { 70 | "type": "PhysicsComponent", 71 | "mass": 1, 72 | "gravity-scale": 0, 73 | "linear-drag": 0.1 74 | }, 75 | { 76 | "type": "BoxColliderComponent", 77 | "size": [100.0, 100.0] 78 | } 79 | ] 80 | }, 81 | { 82 | "name": "WallT6", 83 | "sprite-path": "Assets\\Square.dds", 84 | "initial-position": [-100.0, 320.0], 85 | "player-actor": false, 86 | "mobility": "static", 87 | "components": [ 88 | { 89 | "type": "PhysicsComponent", 90 | "mass": 1, 91 | "gravity-scale": 0, 92 | "linear-drag": 0.1 93 | }, 94 | { 95 | "type": "BoxColliderComponent", 96 | "size": [100.0, 100.0] 97 | } 98 | ] 99 | }, 100 | { 101 | "name": "WallT7", 102 | "sprite-path": "Assets\\Square.dds", 103 | "initial-position": [-200.0, 320.0], 104 | "player-actor": false, 105 | "mobility": "static", 106 | "components": [ 107 | { 108 | "type": "PhysicsComponent", 109 | "mass": 1, 110 | "gravity-scale": 0, 111 | "linear-drag": 0.1 112 | }, 113 | { 114 | "type": "BoxColliderComponent", 115 | "size": [100.0, 100.0] 116 | } 117 | ] 118 | }, 119 | { 120 | "name": "WallT8", 121 | "sprite-path": "Assets\\Square.dds", 122 | "initial-position": [-300.0, 320.0], 123 | "player-actor": false, 124 | "mobility": "static", 125 | "components": [ 126 | { 127 | "type": "PhysicsComponent", 128 | "mass": 1, 129 | "gravity-scale": 0, 130 | "linear-drag": 0.1 131 | }, 132 | { 133 | "type": "BoxColliderComponent", 134 | "size": [100.0, 100.0] 135 | } 136 | ] 137 | }, 138 | { 139 | "name": "WallT9", 140 | "sprite-path": "Assets\\Square.dds", 141 | "initial-position": [400.0, 320.0], 142 | "player-actor": false, 143 | "mobility": "static", 144 | "components": [ 145 | { 146 | "type": "PhysicsComponent", 147 | "mass": 1, 148 | "gravity-scale": 0, 149 | "linear-drag": 0.1 150 | }, 151 | { 152 | "type": "BoxColliderComponent", 153 | "size": [100.0, 100.0] 154 | } 155 | ] 156 | }, 157 | { 158 | "name": "WallT10", 159 | "sprite-path": "Assets\\Square.dds", 160 | "initial-position": [-400.0, 320.0], 161 | "player-actor": false, 162 | "mobility": "static", 163 | "components": [ 164 | { 165 | "type": "PhysicsComponent", 166 | "mass": 1, 167 | "gravity-scale": 0, 168 | "linear-drag": 0.1 169 | }, 170 | { 171 | "type": "BoxColliderComponent", 172 | "size": [100.0, 100.0] 173 | } 174 | ] 175 | }, 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | { 185 | "name": "WallB1", 186 | "sprite-path": "Assets\\Square.dds", 187 | "initial-position": [0.0, -300.0], 188 | "player-actor": false, 189 | "mobility": "static", 190 | "components": [ 191 | { 192 | "type": "PhysicsComponent", 193 | "mass": 1, 194 | "gravity-scale": 0, 195 | "linear-drag": 0.1 196 | }, 197 | { 198 | "type": "BoxColliderComponent", 199 | "size": [100.0, 100.0] 200 | } 201 | ] 202 | }, 203 | { 204 | "name": "WallB2", 205 | "sprite-path": "Assets\\Square.dds", 206 | "initial-position": [100.0, -300.0], 207 | "player-actor": false, 208 | "mobility": "static", 209 | "components": [ 210 | { 211 | "type": "PhysicsComponent", 212 | "mass": 1, 213 | "gravity-scale": 0, 214 | "linear-drag": 0.1 215 | }, 216 | { 217 | "type": "BoxColliderComponent", 218 | "size": [100.0, 100.0] 219 | } 220 | ] 221 | }, 222 | { 223 | "name": "WallB3", 224 | "sprite-path": "Assets\\Square.dds", 225 | "initial-position": [200.0, -300.0], 226 | "player-actor": false, 227 | "mobility": "static", 228 | "components": [ 229 | { 230 | "type": "PhysicsComponent", 231 | "mass": 1, 232 | "gravity-scale": 0, 233 | "linear-drag": 0.1 234 | }, 235 | { 236 | "type": "BoxColliderComponent", 237 | "size": [100.0, 100.0] 238 | } 239 | ] 240 | }, 241 | { 242 | "name": "WallB4", 243 | "sprite-path": "Assets\\Square.dds", 244 | "initial-position": [300.0, -300.0], 245 | "player-actor": false, 246 | "mobility": "static", 247 | "components": [ 248 | { 249 | "type": "PhysicsComponent", 250 | "mass": 1, 251 | "gravity-scale": 0, 252 | "linear-drag": 0.1 253 | }, 254 | { 255 | "type": "BoxColliderComponent", 256 | "size": [100.0, 100.0] 257 | } 258 | ] 259 | }, 260 | { 261 | "name": "WallB6", 262 | "sprite-path": "Assets\\Square.dds", 263 | "initial-position": [-100.0, -300.0], 264 | "player-actor": false, 265 | "mobility": "static", 266 | "components": [ 267 | { 268 | "type": "PhysicsComponent", 269 | "mass": 1, 270 | "gravity-scale": 0, 271 | "linear-drag": 0.1 272 | }, 273 | { 274 | "type": "BoxColliderComponent", 275 | "size": [100.0, 100.0] 276 | } 277 | ] 278 | }, 279 | { 280 | "name": "WallB7", 281 | "sprite-path": "Assets\\Square.dds", 282 | "initial-position": [-200.0, -300.0], 283 | "player-actor": false, 284 | "mobility": "static", 285 | "components": [ 286 | { 287 | "type": "PhysicsComponent", 288 | "mass": 1, 289 | "gravity-scale": 0, 290 | "linear-drag": 0.1 291 | }, 292 | { 293 | "type": "BoxColliderComponent", 294 | "size": [100.0, 100.0] 295 | } 296 | ] 297 | }, 298 | { 299 | "name": "WallB8", 300 | "sprite-path": "Assets\\Square.dds", 301 | "initial-position": [-300.0, -300.0], 302 | "player-actor": false, 303 | "mobility": "static", 304 | "components": [ 305 | { 306 | "type": "PhysicsComponent", 307 | "mass": 1, 308 | "gravity-scale": 0, 309 | "linear-drag": 0.1 310 | }, 311 | { 312 | "type": "BoxColliderComponent", 313 | "size": [100.0, 100.0] 314 | } 315 | ] 316 | }, 317 | { 318 | "name": "WallB9", 319 | "sprite-path": "Assets\\Square.dds", 320 | "initial-position": [-400.0, -300.0], 321 | "player-actor": false, 322 | "mobility": "static", 323 | "components": [ 324 | { 325 | "type": "PhysicsComponent", 326 | "mass": 1, 327 | "gravity-scale": 0, 328 | "linear-drag": 0.1 329 | }, 330 | { 331 | "type": "BoxColliderComponent", 332 | "size": [100.0, 100.0] 333 | } 334 | ] 335 | }, 336 | { 337 | "name": "WallB10", 338 | "sprite-path": "Assets\\Square.dds", 339 | "initial-position": [400.0, -300.0], 340 | "player-actor": false, 341 | "mobility": "static", 342 | "components": [ 343 | { 344 | "type": "PhysicsComponent", 345 | "mass": 1, 346 | "gravity-scale": 0, 347 | "linear-drag": 0.1 348 | }, 349 | { 350 | "type": "BoxColliderComponent", 351 | "size": [100.0, 100.0] 352 | } 353 | ] 354 | } 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | ] 365 | } -------------------------------------------------------------------------------- /Pong/Saved/LeftPaddle.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Left Paddle", 3 | "sprite-path": "Assets\\LeftPaddle.dds", 4 | "player-actor": true, 5 | "initial-position": [-300.0, 0.0], 6 | "initial-velocity": [0.0, 0.0], 7 | "initial-rotation": 0.0, 8 | "components": [ 9 | { 10 | "type": "PhysicsComponent", 11 | "mass": 1, 12 | "gravity-scale": 0, 13 | "linear-drag": 0.0005, 14 | "constraints": [true, false] 15 | }, 16 | { 17 | "type": "BoxColliderComponent", 18 | "size": [100.0, 100.0] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /Pong/Saved/RightPaddle.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Right Paddle", 3 | "sprite-path": "Assets\\RightPaddle.dds", 4 | "player-actor": true, 5 | "initial-position": [300.0, 0.0], 6 | "initial-velocity": [0.0, 0.0], 7 | "initial-rotation": 0.0, 8 | "components": [ 9 | { 10 | "type": "PhysicsComponent", 11 | "mass": 1, 12 | "gravity-scale": 0, 13 | "linear-drag": 0.0005, 14 | "constraints": [true, false] 15 | }, 16 | { 17 | "type": "BoxColliderComponent", 18 | "size": [100.0, 100.0] 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Custom Game Engine 2 | This is a game engine I built from scratch on C++
3 | It includes the following systems:
4 | 1. A Linear Memory-Pool Allocator 5 | 2. A Fixed Size Allocator 6 | 3. A Custom Smart-Pointer System 7 | 4. A 2D-Physics Engine 8 | 5. A Box-2D Collision Engine 9 | 6. Unreal's Actor Hierarchy System (To build Player & NPC actors from) 10 | 7. Dynamic Component Attachment System (E.g. Keyboard Inputs, Box Collider, Circle Collider) 11 | 12 |
13 | 14 | NOTE: Git doesn't recognize changes to the solution's Default Project. So you'd have to select Pong as the Default Startup Project under the Solution's Properties in Visual Studio 15 | 16 |
17 | 18 | 19 | 20 | ## Memory Allocation System 21 | Here's a list of all the unique features the MemoryManager has: 22 | 23 | 1. Primary Allocator Unit => Created a Fixed Size Allocator (FSA) & included 3 instances of it to handle allocations of different sizes (100 - 16 byte blocks | 200 - 32 byte blocks | 400 - 96 byte blocks) 24 | - Header | C++ 25 | - The FSA is able to store anything less than its BLOCK SIZE to be stored in the first free block 26 | - This one's highly efficient because of the BIT-ARRAY State-Keeper 27 | 28 | ![Fixed Size Allocator](FixedSizeAllocator.png) 29 | 30 |
31 | 32 | 2. Backup Allocator => Pool Allocator 33 | - Header | C++ 34 | - The Memory-Pool style allocator allocates blocks linearly regardless of their size 35 | - There's a ratio of the TOTAL POOL SIZE that stores metadata for each of the allocated blocks 36 | 37 | ![Memory Pool Allocator](MemoryPoolAllocator.png) 38 | 39 |
40 | 41 | 42 | 3. The MemorySystem regulates the calls to the 3 FSAs or the Pool Allocator 43 | based on the size of the request 44 | - Header | C++ 45 | - This system receives the allocation calls and invokes the respective allocator 46 | 47 | 48 | 49 |

50 | 51 | 52 | ## Custom Smart-Pointer System 53 | Features: 54 | 1. Smart Pointer (reference) running a Reference Count book-keeping method to decide underlying pointer lifetime 55 | 2. Weak Pointer running the same book-keeping method, for systems that just want to watch the underlying pointer, or get a Ref to the SmartPtr 56 | 57 | 58 | 59 |

60 | 61 | 62 | ## 2D Physics Engine 63 | Features: 64 | 1. Config: [Mass], [Linear Damping], [Gravity], [Net Force] 65 | 2. Every object has Velocity 66 | 3. Acceleration is imparted based on the Mass, which in turn controls how fast the Velocity changes per frame 67 | 4. Linear Damping controls the acceleration resisting force 68 | 5. If you use the APPLY_FORCE(...) function, you'd change the NetForce value, which is applied each frame and cleared 69 | 70 | 71 |

72 | 73 | 74 | ## Box-2D Collision Engine 75 | Features: 76 | 1. Swept-Axis Collision Check formula to deflect off 2-objects with an Impending Collision that's Less Than 1-frame-time 77 | 2. Inter-Frame-Time-Forwarding to resolve more than 2 objects in collison sequentially 78 | 3. Object can register a callback to get notified when it's colliding with anything 79 | 80 | 81 | 82 |

83 | 84 | ## Unreal's Actor Hierarchy System 85 | Implemented a World class which handles 86 | 1. Actor Spawning (With and without JSON for prefab) 87 | 2. BeginPlay() 88 | 3. EventTick() 89 | 4. Pause 90 | 5. Quit 91 | 6. Cleanup 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |





101 | 102 | # GAME FEATURES 103 | 104 | How to play the game: 105 | 1. Move the LEFT paddle up/down using W/S 106 | 2. Move the RIGHT paddle up/down using I/K 107 | 3. If the Ball moves past the left paddle, the right player's score increases by 1 (And vice versa) 108 | 4. The first player to reach a score of 3 wins the game 109 | 5. The windows shuts itself down to close the game, printing the win-state in the output log 110 | 111 | NOTE: The walls comprise of white square bricks placed close to each other. Each reflect the ball in a random direction to give a sense of randomness to the game 112 | (Not really an interesting feature, but I just had in there since it makes it fun) 113 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | # README FILE | u1261299 | Vishal Naidu 2 | # GAME ENGINEERING - 1 3 | 4 | 5 | This file describes the Project, "Pong" 6 | That's part of the FinalExam 7 | 8 | 9 | 10 | 11 | 12 | ########################### 13 | # GAME FEATURES # 14 | ########################### 15 | 16 | How to play the game: 17 | 1. Move the LEFT paddle up/down using W/S 18 | 2. Move the RIGHT paddle up/down using I/K 19 | 3. If the Ball moves past the left paddle, the right player's score increases by 1 (And vice versa) 20 | 4. The first player to reach a score of 3 wins the game 21 | 5. The windows shuts itself down to close the game, printing the win-state in the output log 22 | 23 | NOTE: The walls comprise of white square bricks placed close to each other. Each reflect the ball in a random direction to give a sense of randomness to the game 24 | (Not really an interesting feature, but I just had in there since it makes it fun) 25 | 26 | 27 | 28 | The following is a list of features you'd find in my Pong game: 29 | 30 | 1. I noticed GLib's input handler gives you callbacks with each button press/release, so I used that to update a std::vector in Input.h every time there's a key callback 31 | This let me have a "Keyboard_IsKeyDown(uint Button_ID)" function similar to that in Unity 32 | 33 | - Engine/Systems/Input.h/cpp => key data handled here 34 | - CppAssignments/MonsterChase.cpp => usage of Keyboard_IsKeyDown(uint Button_ID) 35 | 36 | 37 | 2. Uses a SmartPtr/WeakPtr system 38 | - Only the property "std::vector> actors" in World holds references to the actors 39 | - There's a WeakPtr copy of the actors, which is used to distribute weak references to observer systems 40 | - Systems like Components (Physics, Box/CircleColliders, Follow), CollisionSystem, Input depend on the weak referernces and try to acquire full refs to work with 41 | 42 | 43 | 3. Implemented a World class which handles 44 | - Engine/General/World.h 45 | - Engine/General/World.cpp 46 | 47 | a. Actor Spawning (With and without JSON for prefab) 48 | b. BeginPlay() 49 | c. EventTick() 50 | d. Pause 51 | e. Quit 52 | f. Cleanup - Deleting all actors | Stop GLib Service 53 | 54 | 4. Physics Components 55 | - Each actor with an attached PhysicsComponent will have simulated motion with forces leading to linear acceleration 56 | - Drag forces included 57 | - X/Y constraints to lock movement in one/both axes 58 | - AddForce() function accumulates impending forces before applying them together in one Tick() 59 | 60 | 5. Math 61 | - Math.h provides some basic functionality like randomRange(), clamp(), isNearlyZero/Equal() 62 | - Vector classes for sizes 2, 3, 4 63 | - Matrix classes for sizes 3, 4 64 | - Matrix classes with transform matrices for translation, rotation and scaling 65 | 66 | 6. Collision 67 | - Uses the Swept-Axis collision check method to identify impending collisions 68 | - Calls on the actors' OnCollisionStay() and OnHit() functions when impending collision is found 69 | - Forwards all objects to the latest resolved impending collision time --------------------------------------------------------------------------------