diff --git a/ConsoleEngine.sln b/ConsoleEngine.sln
index 76e8fb4..5dac93b 100644
--- a/ConsoleEngine.sln
+++ b/ConsoleEngine.sln
@@ -32,69 +32,194 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TerraForM.Tests", "Examples
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples.Tests", "Examples.Tests", "{106CCD57-88BD-4B0A-A67F-A5DA7D8FCA3C}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pong", "Examples\Pong\Pong.csproj", "{DE96766F-0853-439F-A054-A8B2EDC10DA6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleEngine.CrossPlatform", "Libs\ConsoleEngine.CrossPlatform\ConsoleEngine.CrossPlatform.csproj", "{F5F065A9-F0B1-45B6-B4BC-5912BAB09803}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|Any CPU.Build.0 = Release|Any CPU
- {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Release|x64.ActiveCfg = Release|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Release|x64.Build.0 = Release|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Release|x86.ActiveCfg = Release|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Release|x86.Build.0 = Release|Any CPU
{CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|Any CPU.Build.0 = Release|Any CPU
- {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|Any CPU.Build.0 = Release|Any CPU
- {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Debug|x64.Build.0 = Debug|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F}.Debug|x86.Build.0 = Debug|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|Any CPU.Build.0 = Release|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|x64.ActiveCfg = Release|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|x64.Build.0 = Release|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|x86.ActiveCfg = Release|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|x86.Build.0 = Release|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|x64.Build.0 = Debug|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|x86.Build.0 = Debug|Any CPU
{33AA545F-7515-406C-A749-EB0A02668F4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{33AA545F-7515-406C-A749-EB0A02668F4A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Release|x64.ActiveCfg = Release|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Release|x64.Build.0 = Release|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Release|x86.ActiveCfg = Release|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Release|x86.Build.0 = Release|Any CPU
{33AA545F-7515-406C-A749-EB0A02668F4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{33AA545F-7515-406C-A749-EB0A02668F4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Debug|x64.Build.0 = Debug|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {33AA545F-7515-406C-A749-EB0A02668F4A}.Debug|x86.Build.0 = Debug|Any CPU
{DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Release|x64.ActiveCfg = Release|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Release|x64.Build.0 = Release|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Release|x86.ActiveCfg = Release|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Release|x86.Build.0 = Release|Any CPU
{DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {99309207-1847-4EB9-A009-C7B92BC2CE64}.Release|Any CPU.Build.0 = Release|Any CPU
- {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {99309207-1847-4EB9-A009-C7B92BC2CE64}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|Any CPU.Build.0 = Release|Any CPU
- {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Debug|x64.Build.0 = Debug|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DE0311EB-079F-41B3-9D87-604AAB6F2F65}.Debug|x86.Build.0 = Debug|Any CPU
{BC3C7768-0401-47F4-931A-76BADFE6DC26}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BC3C7768-0401-47F4-931A-76BADFE6DC26}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Release|x64.ActiveCfg = Release|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Release|x64.Build.0 = Release|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Release|x86.ActiveCfg = Release|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Release|x86.Build.0 = Release|Any CPU
{BC3C7768-0401-47F4-931A-76BADFE6DC26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BC3C7768-0401-47F4-931A-76BADFE6DC26}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Debug|x64.Build.0 = Debug|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BC3C7768-0401-47F4-931A-76BADFE6DC26}.Debug|x86.Build.0 = Debug|Any CPU
{276379A8-897A-4703-A18D-9DB3A08A09AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{276379A8-897A-4703-A18D-9DB3A08A09AA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Release|x64.ActiveCfg = Release|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Release|x64.Build.0 = Release|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Release|x86.ActiveCfg = Release|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Release|x86.Build.0 = Release|Any CPU
{276379A8-897A-4703-A18D-9DB3A08A09AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{276379A8-897A-4703-A18D-9DB3A08A09AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Debug|x64.Build.0 = Debug|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {276379A8-897A-4703-A18D-9DB3A08A09AA}.Debug|x86.Build.0 = Debug|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|x64.ActiveCfg = Release|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|x64.Build.0 = Release|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|x86.ActiveCfg = Release|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Release|x86.Build.0 = Release|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|x64.Build.0 = Debug|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC}.Debug|x86.Build.0 = Debug|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|x64.ActiveCfg = Release|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|x64.Build.0 = Release|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|x86.ActiveCfg = Release|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Release|x86.Build.0 = Release|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|x64.Build.0 = Debug|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {A4209E56-1ECD-4616-BB13-DF77864F462C}.Debug|x86.Build.0 = Debug|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|x64.ActiveCfg = Release|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|x64.Build.0 = Release|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|x86.ActiveCfg = Release|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Release|x86.Build.0 = Release|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|x64.Build.0 = Debug|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F}.Debug|x86.Build.0 = Debug|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|x64.ActiveCfg = Release|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|x64.Build.0 = Release|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|x86.ActiveCfg = Release|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Release|x86.Build.0 = Release|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|x64.Build.0 = Debug|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0CDE38D4-12F4-426B-9252-E57820FF8D9B}.Debug|x86.Build.0 = Debug|Any CPU
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|x64.ActiveCfg = Release|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|x64.Build.0 = Release|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|x86.ActiveCfg = Release|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Release|x86.Build.0 = Release|Any CPU
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|x64.Build.0 = Debug|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA}.Debug|x86.Build.0 = Debug|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Release|x64.ActiveCfg = Release|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Release|x64.Build.0 = Release|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Release|x86.ActiveCfg = Release|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Release|x86.Build.0 = Release|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Debug|x64.Build.0 = Debug|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6}.Debug|x86.Build.0 = Debug|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|x64.ActiveCfg = Release|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|x64.Build.0 = Release|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|x86.ActiveCfg = Release|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Release|x86.Build.0 = Release|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|x64.Build.0 = Debug|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803}.Debug|x86.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
+ {CC763EA2-7C5E-45C2-948C-BA0279D3C04F} = {12D2B48F-E7F6-4BEC-8315-9EC8F41A059A}
{99309207-1847-4EB9-A009-C7B92BC2CE64} = {CA22425D-FB6C-45C6-A14C-561DF6D969B6}
+ {CA22425D-FB6C-45C6-A14C-561DF6D969B6} = {12D2B48F-E7F6-4BEC-8315-9EC8F41A059A}
{33AA545F-7515-406C-A749-EB0A02668F4A} = {CA22425D-FB6C-45C6-A14C-561DF6D969B6}
{DE0311EB-079F-41B3-9D87-604AAB6F2F65} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
{BC3C7768-0401-47F4-931A-76BADFE6DC26} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
{276379A8-897A-4703-A18D-9DB3A08A09AA} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
{4C3C2CB2-D212-4DBF-8247-C3C75A22D6EC} = {CA22425D-FB6C-45C6-A14C-561DF6D969B6}
- {87EB68ED-18DD-41C9-8A33-B305C4DF210F} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
- {CA22425D-FB6C-45C6-A14C-561DF6D969B6} = {12D2B48F-E7F6-4BEC-8315-9EC8F41A059A}
- {CC763EA2-7C5E-45C2-948C-BA0279D3C04F} = {12D2B48F-E7F6-4BEC-8315-9EC8F41A059A}
{A4209E56-1ECD-4616-BB13-DF77864F462C} = {12D2B48F-E7F6-4BEC-8315-9EC8F41A059A}
+ {87EB68ED-18DD-41C9-8A33-B305C4DF210F} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
{0CDE38D4-12F4-426B-9252-E57820FF8D9B} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
{58BE9E1E-1B58-423F-B2BF-9DB66E0CFACA} = {106CCD57-88BD-4B0A-A67F-A5DA7D8FCA3C}
+ {DE96766F-0853-439F-A054-A8B2EDC10DA6} = {028D7499-6A31-4A9F-868A-908AD53A8BD0}
+ {F5F065A9-F0B1-45B6-B4BC-5912BAB09803} = {CA22425D-FB6C-45C6-A14C-561DF6D969B6}
EndGlobalSection
EndGlobal
diff --git a/ConsoleEngine/ConsoleEngine.csproj b/ConsoleEngine/ConsoleEngine.csproj
index 4d61738..d0559d3 100644
--- a/ConsoleEngine/ConsoleEngine.csproj
+++ b/ConsoleEngine/ConsoleEngine.csproj
@@ -15,8 +15,12 @@
+
+
+ $(DefineConstants);WINDOWS_PLATFORM
+
diff --git a/ConsoleEngine/GameBase.cs b/ConsoleEngine/GameBase.cs
index 49de7e7..652e8e4 100644
--- a/ConsoleEngine/GameBase.cs
+++ b/ConsoleEngine/GameBase.cs
@@ -6,6 +6,7 @@
using ConsoleEngine.Infrastructure.Rendering;
using ConsoleEngine.Infrastructure.Scenery;
using ConsoleEngine.Native;
+using ConsoleEngine.CrossPlatform;
namespace ConsoleEngine;
@@ -32,7 +33,11 @@ protected GameBase(int width, int height, int fontWidth, int fontHeight)
protected GameBase(int width, int height, FontInfo fontInfo)
{
+#if WINDOWS_PLATFORM
_console = new RenderConsole(new ConsoleHandler(width, height, fontInfo));
+#else
+ _console = new RenderConsole(new CrossPlatformConsoleHandler(width, height, fontInfo));
+#endif
Name = "Game";
Scenes = new SceneManager(this);
}
diff --git a/ConsoleEngine/Infrastructure/Inputs/Input.cs b/ConsoleEngine/Infrastructure/Inputs/Input.cs
index b5a15bc..c36f917 100644
--- a/ConsoleEngine/Infrastructure/Inputs/Input.cs
+++ b/ConsoleEngine/Infrastructure/Inputs/Input.cs
@@ -3,6 +3,7 @@
using System.Linq;
using ConsoleEngine.Abstractions.Inputs;
using ConsoleEngine.Native;
+using ConsoleEngine.CrossPlatform;
namespace ConsoleEngine.Infrastructure.Inputs;
@@ -13,8 +14,13 @@ public class Input
//**********************************************************
public static readonly Input Instance = new();
+
+#if WINDOWS_PLATFORM
private static readonly IInputHandler Handler = new InputHandler();
-
+#else
+ private static readonly IInputHandler Handler = new CrossPlatformInputHandler();
+#endif
+
//**********************************************************
//** ctor:
//**********************************************************
diff --git a/Libs/ConsoleEngine.CrossPlatform/ConsoleEngine.CrossPlatform.csproj b/Libs/ConsoleEngine.CrossPlatform/ConsoleEngine.CrossPlatform.csproj
new file mode 100644
index 0000000..f41b3d3
--- /dev/null
+++ b/Libs/ConsoleEngine.CrossPlatform/ConsoleEngine.CrossPlatform.csproj
@@ -0,0 +1,18 @@
+
+
+
+ net8.0
+ 12
+ ConsoleEngine.CrossPlatform
+ Release;Debug
+ AnyCPU
+ True
+
+
+ $(DefineConstants);WINDOWS_PLATFORM
+
+
+
+
+
+
diff --git a/Libs/ConsoleEngine.CrossPlatform/CrossPlatformConsoleHandler.cs b/Libs/ConsoleEngine.CrossPlatform/CrossPlatformConsoleHandler.cs
new file mode 100644
index 0000000..26c272d
--- /dev/null
+++ b/Libs/ConsoleEngine.CrossPlatform/CrossPlatformConsoleHandler.cs
@@ -0,0 +1,68 @@
+using System;
+using ConsoleEngine.Abstractions.Rendering;
+
+namespace ConsoleEngine.CrossPlatform;
+
+public sealed class CrossPlatformConsoleHandler : IConsoleHandler
+{
+ private readonly FontInfo _fontInfo;
+ public CrossPlatformConsoleHandler(int width, int height, FontInfo fontInfo)
+ {
+ _fontInfo = fontInfo;
+ Width = width;
+ Height = height;
+ }
+
+ public int Width { get; }
+ public int Height { get; }
+
+ public void InitializeConsole()
+ {
+ Console.Clear();
+ SetFont(_fontInfo);
+ }
+
+ public void SetTitle(string title)
+ {
+ Console.Title = title;
+ }
+
+ public void SetCursorVisible(bool visible)
+ {
+ try { Console.CursorVisible = visible; } catch { }
+ }
+
+ public void Resizable(bool resizable)
+ {
+ // Not yet supported
+ }
+
+ public void SetFont(FontInfo fontInfo)
+ {
+ // Not yet supported
+ }
+
+ public void Render(Span pixels)
+ {
+ Console.SetCursorPosition(0, 0);
+ for (int y = 0; y < Height; y++)
+ {
+ for (int x = 0; x < Width; x++)
+ {
+ int i = y * Width + x;
+ if (i < pixels.Length)
+ Console.Write(pixels[i].Char);
+ else
+ Console.Write(' ');
+ }
+ Console.WriteLine();
+ }
+ }
+
+ public void Close()
+ {
+ // Not yet supported
+ }
+
+ private static ushort GetColorValue(ConsoleColor fg, ConsoleColor bg) => (ushort)((int)fg | ((int)bg<<4));
+}
\ No newline at end of file
diff --git a/Libs/ConsoleEngine.CrossPlatform/CrossPlatformInputHandler.cs b/Libs/ConsoleEngine.CrossPlatform/CrossPlatformInputHandler.cs
new file mode 100644
index 0000000..2fafa64
--- /dev/null
+++ b/Libs/ConsoleEngine.CrossPlatform/CrossPlatformInputHandler.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ConsoleEngine.Abstractions.Inputs;
+
+namespace ConsoleEngine.CrossPlatform;
+
+public class CrossPlatformInputHandler : IInputHandler
+{
+ private readonly int[] _previousState = new int[256];
+ private readonly int[] _newState = new int[256];
+ private readonly KeyState[] _keyStates = new KeyState[256];
+
+ public KeyState GetKey(int id)
+ {
+ return _keyStates[id];
+ }
+
+ public IEnumerable GetPressedKeyCodes() => _keyStates.Where(k => k.Pressed).Select(k => k.Index);
+
+ public void Update()
+ {
+ bool[] pressedThisFrame = new bool[_keyStates.Length];
+ while (Console.KeyAvailable)
+ {
+ var keyInfo = Console.ReadKey(true);
+ int key = (int)keyInfo.Key;
+ _keyStates[key].Pressed = true;
+ _keyStates[key].Held = true;
+ _keyStates[key].Index = key;
+ pressedThisFrame[key] = true;
+ }
+ for (int i = 0; i < _keyStates.Length; i++)
+ {
+ if (!pressedThisFrame[i])
+ {
+ if (_keyStates[i].Held)
+ {
+ _keyStates[i].Released = true;
+ }
+ else
+ {
+ _keyStates[i].Released = false;
+ }
+ _keyStates[i].Held = false;
+ _keyStates[i].Pressed = false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Libs/ConsoleEngine.Windows/ConsoleEngine.Windows.csproj b/Libs/ConsoleEngine.Windows/ConsoleEngine.Windows.csproj
index d2ff72f..7c4ebcb 100644
--- a/Libs/ConsoleEngine.Windows/ConsoleEngine.Windows.csproj
+++ b/Libs/ConsoleEngine.Windows/ConsoleEngine.Windows.csproj
@@ -8,8 +8,11 @@
AnyCPU
True
-
+
+ $(DefineConstants);WINDOWS_PLATFORM
+
+
diff --git a/Libs/ConsoleEngine.Windows/LowLevel/Kernel32.cs b/Libs/ConsoleEngine.Windows/LowLevel/Kernel32.cs
index cd347c0..1ee526a 100644
--- a/Libs/ConsoleEngine.Windows/LowLevel/Kernel32.cs
+++ b/Libs/ConsoleEngine.Windows/LowLevel/Kernel32.cs
@@ -11,6 +11,7 @@ namespace ConsoleEngine.Native.LowLevel;
///
internal static class Kernel32
{
+#if WINDOWS_PLATFORM
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr GetStdHandle(StdHandle nStdHandle);
@@ -67,4 +68,24 @@ internal static class Kernel32
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr hObject);
+#else
+ // Unix/macOS/Linux
+ // Can´t deal with Kernel32 calls, so void them
+ internal static IntPtr GetStdHandle(StdHandle nStdHandle) => IntPtr.Zero;
+ internal static bool SetConsoleActiveScreenBuffer(IntPtr hConsoleOutput) => false;
+ internal static IntPtr CreateConsoleScreenBuffer(GenericRights dwDesiredAccess, uint dwShareMode, IntPtr securityAttributes, uint flags, IntPtr screenBufferData) => IntPtr.Zero;
+ internal static bool WriteConsoleOutputCharacter(IntPtr screenBuffer, string characters, uint length, Coord writeCoord, out UInt32 numCharsWritten) { numCharsWritten = 0; return false; }
+ internal static bool WriteConsoleOutput(IntPtr hConsoleOutput, CharInfo[] lpBuffer, Coord dwBufferSize, Coord dwBufferCoord, ref SmallRect lpWriteRegion) => false;
+ internal static IntPtr GetConsoleWindow() => IntPtr.Zero;
+ internal static int SetCurrentConsoleFontEx(IntPtr consoleOutput, bool maximumWindow, ref ConsoleFontInfoEx consoleCurrentFontEx) => 0;
+ internal static bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, ref SmallRect lpConsoleWindow) => false;
+ internal static bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, Coord dwSize) => false;
+ internal static int GetAsyncKeyState(int vKeys) => 0;
+ internal static bool SetConsoleOutputCP(uint wCodePageID) => false;
+ internal static bool SetConsoleCP(uint wCodePageID) => false;
+ internal static bool SetConsoleTitle(char[] lpConsoleTitle) { try { Console.Title = new string(lpConsoleTitle); return true; } catch { return false; } }
+ internal static bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out ConsoleCursorInfo lpConsoleCursorInfo) { lpConsoleCursorInfo = default; return false; }
+ internal static bool SetConsoleCursorInfo(IntPtr hConsoleOutput, ref ConsoleCursorInfo lpConsoleCursorInfo) => false;
+ internal static bool CloseHandle(IntPtr hObject) => false;
+#endif
}
\ No newline at end of file