├── .gitignore
├── .vscode
├── launch.json
└── tasks.json
├── Contracts
├── Contracts.csproj
├── Faction.cs
└── TileData.cs
├── Engine
├── ActorManager.cs
├── CaveMapCreationStrategy.cs
├── CelluarAutomataTests.cs
├── CellularAutomata.cs
├── Engine.cs
├── Engine.csproj
├── EngineConstants.cs
├── EngineLogger.cs
├── Filters.cs
└── PlayerInput.cs
├── EntityComponentSystemCSharp
├── Components.cs
├── DuplicateComponentException.cs
├── EntityComponentSystemCSharp.csproj
├── EntityExtensions.cs
├── EntityManager.cs
├── MissingComponentException.cs
├── NotComponentException.cs
├── Orientation.cs
├── PointWrapper.cs
├── Systems
│ ├── CombatSystem.cs
│ ├── DemandSystem.cs
│ ├── EnergySystem.cs
│ ├── HealthSystem.cs
│ ├── IEngine.cs
│ ├── ISystem.cs
│ ├── MovementSystem.cs
│ ├── ProductionSystem.cs
│ ├── StackSystem.cs
│ ├── SystemBase.cs
│ └── WanderingMonsterSystem.cs
└── Test
│ ├── EntityManagerTests.cs
│ ├── EntityPrototypeTests.cs
│ ├── MockEngine.cs
│ ├── MockLogger.cs
│ ├── ProductionTests.MockMap.cs
│ └── ProductionTests.cs
├── EntityPrototypes.json
├── FeatureDetector
├── Detector.cs
├── DetectorTests.cs
├── FeatureDetector.csproj
└── FeatureFilters.cs
├── InventionHackGameplay.gif
├── InventionUiAndroid
├── InventionUiAndroid.csproj
├── MainActivity.cs
├── Properties
│ ├── AndroidManifest.xml
│ └── AssemblyInfo.cs
└── Resources
│ ├── Resource.designer.cs
│ ├── layout
│ └── activity_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── ic_launcher_background.xml
│ ├── strings.xml
│ └── styles.xml
├── InventionUiUwp
├── App.xaml
├── App.xaml.cs
├── Assets
│ ├── LockScreenLogo.scale-200.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── StoreLogo.png
│ └── Wide310x150Logo.scale-200.png
├── InventionUiUwp.csproj
├── MainPage.xaml
├── MainPage.xaml.cs
├── Package.appxmanifest
└── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── InventionUiWpf
├── InventionUiWpf.csproj
├── Program.cs
└── packages.config
├── InventionUiiOS
├── AppDelegate.cs
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon1024.png
│ │ ├── Icon120.png
│ │ ├── Icon152.png
│ │ ├── Icon167.png
│ │ ├── Icon180.png
│ │ ├── Icon20.png
│ │ ├── Icon29.png
│ │ ├── Icon40.png
│ │ ├── Icon58.png
│ │ ├── Icon60.png
│ │ ├── Icon76.png
│ │ ├── Icon80.png
│ │ └── Icon87.png
├── Entitlements.plist
├── Info.plist
├── InventionUiiOS.csproj
├── LaunchScreen.storyboard
├── Main.cs
├── Properties
│ └── AssemblyInfo.cs
├── Resources
│ └── LaunchScreen.xib
└── SceneDelegate.cs
├── LICENSE
├── MegaDungeon.sln
├── MegaDungeon.sln.Android
├── Portable
├── Cloth.cs
├── ColorPallete.cs
├── EntityData.cs
├── MegaDungeonUI.cs
├── MegaDungeonUIConstants.cs
├── Portable.csproj
├── Shell.cs
└── TileManager.cs
├── README.md
├── absurd64.bmp
├── nuget.exe
├── runtests.ps1
└── tiledata.json
/.gitignore:
--------------------------------------------------------------------------------
1 | *.txt
2 | *nh_progress.dat
3 | **/__pycache__/*
4 | *.mod
5 | **/cache/*
6 | **/*.ttyrec*
7 | **/*.h5
8 | **/*.hf5
9 | **/*.model
10 | **/rundata/*
11 | **/notes/*
12 |
13 |
14 | ## Ignore Visual Studio temporary files, build results, and
15 | ## files generated by popular Visual Studio add-ons.
16 | ##
17 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
18 |
19 | # User-specific files
20 | *.rsuser
21 | *.suo
22 | *.user
23 | *.userosscache
24 | *.sln.docstates
25 |
26 | #PerfView Traces
27 | PerfViewData.etl.zip
28 |
29 | # User-specific files (MonoDevelop/Xamarin Studio)
30 | *.userprefs
31 |
32 | # Build results
33 | [Dd]ebug/
34 | [Dd]ebugPublic/
35 | [Rr]elease/
36 | [Rr]eleases/
37 | x64/
38 | x86/
39 | [Aa][Rr][Mm]/
40 | [Aa][Rr][Mm]64/
41 | bld/
42 | [Bb]in/
43 | [Oo]bj/
44 | [Ll]og/
45 |
46 | # Visual Studio 2015/2017 cache/options directory
47 | .vs/
48 | # Uncomment if you have tasks that create the project's static files in wwwroot
49 | #wwwroot/
50 |
51 | # Visual Studio 2017 auto generated files
52 | Generated\ Files/
53 |
54 | # MSTest test Results
55 | [Tt]est[Rr]esult*/
56 | [Bb]uild[Ll]og.*
57 |
58 | # NUNIT
59 | *.VisualState.xml
60 | TestResult.xml
61 |
62 | # Build Results of an ATL Project
63 | [Dd]ebugPS/
64 | [Rr]eleasePS/
65 | dlldata.c
66 |
67 | # Benchmark Results
68 | BenchmarkDotNet.Artifacts/
69 |
70 | # .NET Core
71 | project.lock.json
72 | project.fragment.lock.json
73 | artifacts/
74 |
75 | # StyleCop
76 | StyleCopReport.xml
77 |
78 | # Files built by Visual Studio
79 | *_i.c
80 | *_p.c
81 | *_h.h
82 | *.ilk
83 | *.meta
84 | *.obj
85 | *.iobj
86 | *.pch
87 | *.pdb
88 | *.ipdb
89 | *.pgc
90 | *.pgd
91 | *.rsp
92 | *.sbr
93 | *.tlb
94 | *.tli
95 | *.tlh
96 | *.tmp
97 | *.tmp_proj
98 | *_wpftmp.csproj
99 | *.log
100 | *.vspscc
101 | *.vssscc
102 | .builds
103 | *.pidb
104 | *.svclog
105 | *.scc
106 |
107 | # Chutzpah Test files
108 | _Chutzpah*
109 |
110 | # Visual C++ cache files
111 | ipch/
112 | *.aps
113 | *.ncb
114 | *.opendb
115 | *.opensdf
116 | *.sdf
117 | *.cachefile
118 | *.VC.db
119 | *.VC.VC.opendb
120 |
121 | # Visual Studio profiler
122 | *.psess
123 | *.vsp
124 | *.vspx
125 | *.sap
126 |
127 | # Visual Studio Trace Files
128 | *.e2e
129 |
130 | # TFS 2012 Local Workspace
131 | $tf/
132 |
133 | # Guidance Automation Toolkit
134 | *.gpState
135 |
136 | # ReSharper is a .NET coding add-in
137 | _ReSharper*/
138 | *.[Rr]e[Ss]harper
139 | *.DotSettings.user
140 |
141 | # JustCode is a .NET coding add-in
142 | .JustCode
143 |
144 | # TeamCity is a build add-in
145 | _TeamCity*
146 |
147 | # DotCover is a Code Coverage Tool
148 | *.dotCover
149 |
150 | # AxoCover is a Code Coverage Tool
151 | .axoCover/*
152 | !.axoCover/settings.json
153 |
154 | # Visual Studio code coverage results
155 | *.coverage
156 | *.coveragexml
157 |
158 | # NCrunch
159 | _NCrunch_*
160 | .*crunch*.local.xml
161 | nCrunchTemp_*
162 |
163 | # MightyMoose
164 | *.mm.*
165 | AutoTest.Net/
166 |
167 | # Web workbench (sass)
168 | .sass-cache/
169 |
170 | # Installshield output folder
171 | [Ee]xpress/
172 |
173 | # DocProject is a documentation generator add-in
174 | DocProject/buildhelp/
175 | DocProject/Help/*.HxT
176 | DocProject/Help/*.HxC
177 | DocProject/Help/*.hhc
178 | DocProject/Help/*.hhk
179 | DocProject/Help/*.hhp
180 | DocProject/Help/Html2
181 | DocProject/Help/html
182 |
183 | # Click-Once directory
184 | publish/
185 |
186 | # Publish Web Output
187 | *.[Pp]ublish.xml
188 | *.azurePubxml
189 | # Note: Comment the next line if you want to checkin your web deploy settings,
190 | # but database connection strings (with potential passwords) will be unencrypted
191 | *.pubxml
192 | *.publishproj
193 |
194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
195 | # checkin your Azure Web App publish settings, but sensitive information contained
196 | # in these scripts will be unencrypted
197 | PublishScripts/
198 |
199 | # NuGet Packages
200 | *.nupkg
201 | # The packages folder can be ignored because of Package Restore
202 | **/[Pp]ackages/*
203 | # except build/, which is used as an MSBuild target.
204 | !**/[Pp]ackages/build/
205 | # Uncomment if necessary however generally it will be regenerated when needed
206 | #!**/[Pp]ackages/repositories.config
207 | # NuGet v3's project.json files produces more ignorable files
208 | *.nuget.props
209 | *.nuget.targets
210 |
211 | # Microsoft Azure Build Output
212 | csx/
213 | *.build.csdef
214 |
215 | # Microsoft Azure Emulator
216 | ecf/
217 | rcf/
218 |
219 | # Windows Store app package directories and files
220 | AppPackages/
221 | BundleArtifacts/
222 | Package.StoreAssociation.xml
223 | _pkginfo.txt
224 | *.appx
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 | # ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
251 | **/wwwroot/lib/
252 |
253 | # RIA/Silverlight projects
254 | Generated_Code/
255 |
256 | # Backup & report files from converting an old project file
257 | # to a newer Visual Studio version. Backup files are not needed,
258 | # because we have git ;-)
259 | _UpgradeReport_Files/
260 | Backup*/
261 | UpgradeLog*.XML
262 | UpgradeLog*.htm
263 | ServiceFabricBackup/
264 | *.rptproj.bak
265 |
266 | # SQL Server files
267 | *.mdf
268 | *.ldf
269 | *.ndf
270 |
271 | # Business Intelligence projects
272 | *.rdl.data
273 | *.bim.layout
274 | *.bim_*.settings
275 | *.rptproj.rsuser
276 | *- Backup*.rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # JetBrains Rider
313 | .idea/
314 | *.sln.iml
315 |
316 | # CodeRush personal settings
317 | .cr/personal
318 |
319 | # Python Tools for Visual Studio (PTVS)
320 | __pycache__/
321 | *.pyc
322 |
323 | # Cake - Uncomment if you are using it
324 | # tools/**
325 | # !tools/packages.config
326 |
327 | # Tabs Studio
328 | *.tss
329 |
330 | # Telerik's JustMock configuration file
331 | *.jmconfig
332 |
333 | # BizTalk build output
334 | *.btp.cs
335 | *.btm.cs
336 | *.odx.cs
337 | *.xsd.cs
338 |
339 | # OpenCover UI analysis results
340 | OpenCover/
341 |
342 | # Azure Stream Analytics local run output
343 | ASALocalRun/
344 |
345 | # MSBuild Binary and Structured Log
346 | *.binlog
347 |
348 | # NVidia Nsight GPU debugger configuration file
349 | *.nvuser
350 |
351 | # MFractors (Xamarin productivity tool) working folder
352 | .mfractor/
353 |
354 | # Local History for Visual Studio
355 | .localhistory/
356 |
357 | # BeatPulse healthcheck temp database
358 | healthchecksdb
359 |
360 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
361 | MigrationBackup/
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": ".NET Launch (console)",
9 | "type": "clr",
10 | "request": "launch",
11 | "preLaunchTask": "build",
12 | "program": "${workspaceFolder}/bin/Debug/InventionUiWpf/net461/InventionUiWpf.exe",
13 | "args": [],
14 | "cwd": "${workspaceFolder}",
15 | "console": "internalConsole",
16 | "stopAtEntry": false
17 | },
18 | {
19 | "name": ".NET Core Attach",
20 | "type": "coreclr",
21 | "request": "attach",
22 | "processId": "${command:pickProcess}"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "build",
8 | "command": "dotnet",
9 | "type": "shell",
10 | "args": [
11 | "build"
12 | ],
13 | "group": {
14 | "kind": "build",
15 | "isDefault": true
16 | },
17 | "problemMatcher": "$msCompile"
18 | },
19 | {
20 | "label": "test",
21 | "command": "dotnet",
22 | "type": "shell",
23 | "args": [
24 | "test"
25 | ],
26 | "group": {
27 | "kind": "test",
28 | "isDefault": true
29 | },
30 | "problemMatcher": "$msCompile"
31 | }
32 | ]
33 | }
--------------------------------------------------------------------------------
/Contracts/Contracts.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard20
5 | $(SolutionDir)\bin\$(Configuration)\$(AssemblyName)\
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Contracts/Faction.cs:
--------------------------------------------------------------------------------
1 | /*
2 | TileData.json Contract.
3 | */
4 |
5 | namespace MegaDungeon.Contracts
6 | {
7 | public enum Factions
8 | {
9 | Player,
10 | Neutral,
11 | Monster
12 | }
13 | }
--------------------------------------------------------------------------------
/Contracts/TileData.cs:
--------------------------------------------------------------------------------
1 | /*
2 | TileData.json Contract.
3 | */
4 |
5 | using System.Collections.Generic;
6 |
7 | namespace MegaDungeon.Contracts
8 | {
9 | public class TileData
10 | {
11 | public int tile_size;
12 | public Dictionary data;
13 |
14 | }
15 |
16 | public class TileDataData
17 | {
18 | public string name;
19 | public string type;
20 | }
21 |
22 | public interface ITileManager
23 | {
24 | byte[] GetTileBmpBytes(int index);
25 | int GetGlyphNumByName(string name);
26 | }
27 | }
--------------------------------------------------------------------------------
/Engine/ActorManager.cs:
--------------------------------------------------------------------------------
1 | using EntityComponentSystemCSharp;
2 | using EntityComponentSystemCSharp.Components;
3 | using static MegaDungeon.EngineConstants;
4 |
5 | namespace MegaDungeon
6 | {
7 | public class ActorManager
8 | {
9 | EntityManager _entityManager;
10 | public ActorManager(EntityManager entityManager)
11 | {
12 | _entityManager = entityManager;
13 | }
14 |
15 | public EntityManager.Entity GetPlayerActor(int playerGlyph)
16 | {
17 | var actor = CreateActor(
18 | playerGlyph,
19 | name: "Valkerie",
20 | maxHealth: 10,
21 | defense: 10,
22 | power: 10,
23 | accuracy: 75,
24 | speed: 10
25 | );
26 | actor.AddComponent(new SightStat(){Range=5});
27 | actor.AddComponent();
28 | return actor;
29 | }
30 |
31 | public EntityManager.Entity CreateActor(int glyph, string name = "actor", int maxHealth = 1,int defense = 1, int power = 1,int accuracy = 70, float speed = 8.0F)
32 | {
33 | var actor = _entityManager.CreateEntity();
34 | actor.AddComponent(new Actor(){Gold = 0, Speed = speed});
35 | actor.AddComponent(new AttackStat(){Accuracy = accuracy, Power = power});
36 | actor.AddComponent(new DefenseStat(){Chance = defense});
37 | actor.AddComponent(new Life(){Health = maxHealth, MaxHealth = maxHealth});
38 | actor.AddComponent(new Name(){NameString = name});
39 | actor.AddComponent(new Glyph{glyph = glyph});
40 | return actor;
41 | }
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Engine/CaveMapCreationStrategy.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using RogueSharp;
3 | using FeatureDetector;
4 | using RogueSharp.MapCreation;
5 | using Engine;
6 | using System;
7 | using RoyT.AStar;
8 | using System.Collections.Generic;
9 | using static FeatureDetector.MapFeatureDetector;
10 | using System.Linq;
11 |
12 | namespace MegaDungeon
13 | {
14 | public class CaveMapCreationStrategy : IMapCreationStrategy where T : IMap, new()
15 | {
16 | Random random = new Random();
17 | int _width;
18 | int _height;
19 | double _density;
20 | public CaveMapCreationStrategy(int width, int height, double density = 0.50)
21 | {
22 | _width = width;
23 | _height = height;
24 | _density = density;
25 | }
26 |
27 | public T CreateMap()
28 | {
29 | var cave = CellularAutomata.GenerateCaves(_width, _height, _density);
30 | var regionMap = MapFeatureDetector.GetRegions(cave);
31 |
32 | // Pick a random room to start and dig a tunnel to a random other room.
33 | // Go from there to another random room until all are connected.
34 | var roomCenters = GetRoomCenters(regionMap).ToList();
35 | var startPoint = roomCenters[random.Next(roomCenters.Count)];
36 | roomCenters.Remove(startPoint);
37 |
38 | while(roomCenters.Count > 0)
39 | {
40 | var nextPoint = roomCenters[random.Next(roomCenters.Count)];
41 | roomCenters.Remove(nextPoint);
42 | cave = CreatePath(cave, startPoint.X, startPoint.Y, nextPoint.X, nextPoint.Y);
43 | startPoint = nextPoint;
44 | }
45 | var map = new RogueSharp.Map(_width, _height);
46 | foreach(var cell in map.GetAllCells())
47 | {
48 | var open = cave[cell.X, cell.Y] == 0;
49 | map.SetCellProperties(cell.X, cell.Y, isTransparent: open, isWalkable: open, false);
50 | }
51 |
52 | return (T)(object)map;
53 | }
54 |
55 | private int[,] CreatePath(int[,] map, int x1, int y1, int x2, int y2)
56 | {
57 | int[,] returnMap = (int[,]) map.Clone();
58 | Grid grid = CreateGrid(map);
59 | var start = new Position(x1, y1);
60 | var end = new Position(x2, y2);
61 | var path = grid.GetPath(start, end, MovementPatterns.LateralOnly);
62 | foreach(var p in path)
63 | {
64 | returnMap[p.X, p.Y] = 0;
65 | }
66 | return returnMap;
67 | }
68 |
69 | private Grid CreateGrid(int[,] cave)
70 | {
71 | var pathfinder = new RoyT.AStar.Grid(_width, _height);
72 | for (int x = 0; x < _width; x++)
73 | {
74 | for (int y = 0; y < _height; y++)
75 | {
76 | pathfinder.SetCellCost(new RoyT.AStar.Position(x, y), (cave[x, y] + 1) * 10);
77 | }
78 | }
79 |
80 | return pathfinder;
81 | }
82 |
83 |
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Engine/CelluarAutomataTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using FeatureDetector;
3 | using MegaDungeon;
4 | using System.Diagnostics;
5 |
6 | namespace Engine
7 | {
8 | [TestFixture]
9 | public class CelluarAutomataTests
10 | {
11 |
12 |
13 | [Test]
14 | public void RandomFillTest()
15 | {
16 | var w = 10;
17 | var h = 10;
18 | var total = 0;
19 | for (int i = 0; i < 100; i++)
20 | {
21 | var result = CellularAutomata.RandomFill(h, w);
22 | total += result.Total();
23 | }
24 | var expected = w * h / 2;
25 | var avg = total / 100;
26 | var epsilon = w * h / 4;
27 | Assert.AreEqual(expected, avg, epsilon);
28 | }
29 |
30 | [Test]
31 | public void ConvoleTest()
32 | {
33 |
34 | var grid = CellularAutomata.RandomFill(10, 15);
35 | var conv = CellularAutomata.Convolve(grid, FeatureFilters.Identity);
36 | var gTotal = grid.Total();
37 | var cTotal = conv.Total();
38 | Assert.AreEqual(gTotal, cTotal);
39 | }
40 |
41 | [Test]
42 | public void TimeSteptest()
43 | {
44 | var w = 100;
45 | var h = 150;
46 | var grid = CellularAutomata.RandomFill(w, h, 0.45);
47 |
48 | // caves B678/S345678
49 | int[] born = new[] { 6,7,8 };
50 | int[] survive = new[] { 3, 4, 5, 6, 7, 8 };
51 |
52 | for (int i = 0; i < 5; i++)
53 | {
54 | grid = CellularAutomata.RunAutomataTimestep(grid, born, survive);
55 | Debug.WriteLine(grid.ToRowString(asMap: true));
56 | }
57 | }
58 |
59 | [Test]
60 | public void CaveTest()
61 | {
62 | var strat = new CaveMapCreationStrategy(100, 120, 0.65);
63 | var map = strat.CreateMap();
64 | Debug.WriteLine(map.ToString());
65 | }
66 |
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/Engine/CellularAutomata.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using FeatureDetector;
4 | using System.Diagnostics;
5 |
6 | namespace Engine
7 | {
8 | public static class CellularAutomata
9 | {
10 | static Random _rand = new Random();
11 |
12 | public static int[,] RandomFill(int width, int height, double fill = 0.5F)
13 | {
14 | var grid = new int[width, height];
15 | grid.UpDate(c => c = (_rand.NextDouble() < fill)? 1 : 0);
16 | return grid;
17 | }
18 |
19 |
20 | public static int[,] Convolve(int[,] grid, int[,] filter)
21 | {
22 | return FeatureDetector.MapFeatureDetector.ConvolveFilter(grid, filter);
23 | }
24 |
25 | public static int[,] RunAutomataTimestep(int[,] grid, int[] born, int[] survive)
26 | {
27 | var newgrid = new int[grid.GetLength(0), grid.GetLength(1)];
28 | var neighbors = CellularAutomata.Convolve(grid, FeatureFilters.NeighborCount);
29 | Debug.WriteLine(neighbors.Total());
30 | for (int x = 0; x < grid.GetLength(0); x++)
31 | {
32 | for (int y = 0; y < grid.GetLength(1); y++)
33 | {
34 | if (grid[x, y] == 1 && survive.Contains(neighbors[x, y]))
35 | {
36 | newgrid[x, y] = 1;
37 | }
38 | else if (grid[x, y] == 0 && born.Contains(neighbors[x, y]))
39 | {
40 | newgrid[x, y] = 1;
41 | }
42 | else
43 | {
44 | newgrid[x, y] = 0;
45 | }
46 | }
47 | }
48 | return newgrid;
49 | }
50 |
51 | public static int[,] GenerateCaves(int width, int height, double density = 0.45)
52 | {
53 | // caves B678/S345678
54 | var grid = CellularAutomata.RandomFill(width, height, density);
55 |
56 | int[] born = new[] { 6,7,8 };
57 | int[] survive = new[] { 3, 4, 5, 6, 7, 8 };
58 |
59 | for (int i = 0; i < 5; i++)
60 | {
61 | grid = CellularAutomata.RunAutomataTimestep(grid, born, survive);
62 | }
63 |
64 | return grid;
65 | }
66 |
67 |
68 | }
69 | }
--------------------------------------------------------------------------------
/Engine/Engine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Diagnostics;
5 | using EntityComponentSystemCSharp;
6 | using EntityComponentSystemCSharp.Components;
7 | using EntityComponentSystemCSharp.Systems;
8 | using RogueSharp;
9 | using FeatureDetector;
10 | using MegaDungeon.Contracts;
11 | using static MegaDungeon.EngineConstants;
12 | using static EntityComponentSystemCSharp.EntityManager;
13 |
14 | namespace MegaDungeon
15 | {
16 | public class Engine : IEngine
17 | {
18 | int _doorPercentChance = 50; // Percentage of possible doors that will actually spawn.
19 | int _messageLimit = 5;
20 | Random random = new Random();
21 | int _width;
22 | int _height;
23 | int[,] _floor;
24 | int[,] _floor_view; // a copy to return to make _floor effectively readonly
25 | RogueSharp.IMap _map;
26 | ITileManager _tileManager;
27 | Location _playerLocation = new Location();
28 | List _doorways = new List();
29 | EntityManager _entityManager = new EntityManager();
30 | List _spawnLocations = new List();
31 | List _turnSystems = new List();
32 | internal Queue _messages = new Queue();
33 | SightStat _playerSiteDistance;
34 | EntityManager.Entity _player;
35 | ActorManager _actorManager;
36 | HashSet _viewable;
37 | EngineLogger _logger;
38 | List _doors = new List();
39 | public ISystemLogger GetLogger() {return _logger;}
40 | public RogueSharp.IMap GetMap() {return _map;}
41 | public ITileManager GetTileManager() {return _tileManager;}
42 | public EntityManager GetEntityManager() {return _entityManager;}
43 | public HashSet GetPlayerViewable() {return _viewable;}
44 | public Point GetPlayerLocation() {return new Point(){X = _playerLocation.X, Y = _playerLocation.Y};}
45 | int DIRT, FLOOR, TILEABLEWALL, DARK, DOOR, PLAYER;
46 |
47 | public HashSet Viewable
48 | {
49 | get => _viewable;
50 | }
51 |
52 | public EntityManager.Entity PlayerEntity
53 | {
54 | get => _player;
55 | }
56 |
57 | public Point PlayerLocation
58 | {
59 | get => new Point(_playerLocation.X, _playerLocation.Y);
60 | }
61 |
62 | public string[] Messages
63 | {
64 | get => _messages.ToArray();
65 | }
66 |
67 | ///
68 | /// A grid of glyphs representing the discovered map.
69 | ///
70 | ///
71 | public int[,] Floor
72 | {
73 | get{ return _floor_view;}
74 | }
75 |
76 | public int[,] RevealedFloor
77 | {
78 | get{ return (int[,])_floor;}
79 | }
80 |
81 | ///
82 | /// Dungeon floor engine, seperate from any UI.
83 | ///
84 | ///
85 | ///
86 | ///
87 | public Engine(int width, int height, ITileManager tileManager)
88 | {
89 | _width = width;
90 | _height = height;
91 | _floor = new int[width, height];
92 | _tileManager = tileManager;
93 | SetCommonTileGlyphs();
94 |
95 | // RandomizeCave();
96 | RandomizeFloor();
97 | // BigRoom();
98 | InitCellGlyphs();
99 | _actorManager = new ActorManager(_entityManager);
100 | InitializePlayer();
101 | PlaceMonsters();
102 | UpdateViews();
103 |
104 | // Add systems that should run every turn here.
105 | _logger = new EngineLogger(this);
106 |
107 | // Setup systems to run. Order matters.
108 | _turnSystems.Add(new CombatSystem(this));
109 | _turnSystems.Add(new HealthSystem(this));
110 | _turnSystems.Add(new EnergySystem(this));
111 | _turnSystems.Add(new WanderingMonsterSystem(this));
112 | _turnSystems.Add(new MovementSystem(this));
113 | }
114 |
115 | private void SetCommonTileGlyphs()
116 | {
117 | DARK = _tileManager.GetGlyphNumByName("dark part of a room");
118 | DIRT = _tileManager.GetGlyphNumByName("sub mine walls 0");
119 | FLOOR = _tileManager.GetGlyphNumByName("floor of a room");
120 | TILEABLEWALL = _tileManager.GetGlyphNumByName("tileable wall");
121 | DARK = _tileManager.GetGlyphNumByName("dark part of a room");
122 | DOOR = _tileManager.GetGlyphNumByName("closed door 1");
123 | PLAYER = _tileManager.GetGlyphNumByName("valkyrie");
124 | }
125 |
126 | ///
127 | /// Given the player input, advance the game one turn.
128 | ///
129 | ///
130 | public void DoTurn(PlayerInput playerInput)
131 | {
132 | if(_player != null)
133 | {
134 | // Attach or modify any components needed to the player.
135 | var position = _player.GetComponent();
136 | if(INPUTMAP.ContainsKey(playerInput))
137 | {
138 | var delta = INPUTMAP[playerInput];
139 | var desired = delta + new Point(position.X, position.Y);
140 | var desiredComp = _player.GetComponent();
141 | if(desiredComp == null)
142 | {
143 | desiredComp = new Destination();
144 | _player.AddComponent(desiredComp);
145 | }
146 | desiredComp.X = desired.X;
147 | desiredComp.Y = desired.Y;
148 | }
149 | }
150 |
151 | // Cycle each entity through every system in turn.
152 | foreach(var entity in _entityManager.Entities)
153 | foreach(var system in _turnSystems)
154 | {
155 | system.Run(entity);
156 | }
157 |
158 | UpdateViews();
159 | while(_messages.Count() > _messageLimit)
160 | {
161 | _messages.Dequeue();
162 | }
163 | }
164 |
165 |
166 | void InitializePlayer()
167 | {
168 | _player = _actorManager.GetPlayerActor(PLAYER);
169 | ICell cell = GetWalkableCell();
170 | _playerSiteDistance = _player.GetComponent();
171 | _playerLocation = new Location() { X = cell.X, Y = cell.Y };
172 | _player.AddComponent(_playerLocation);
173 | }
174 |
175 | ICell GetWalkableCell()
176 | {
177 | var location = random.Next(0, _spawnLocations.Count);
178 | var cell = _spawnLocations[location];
179 | _spawnLocations.Remove(cell);
180 | return cell;
181 | }
182 |
183 | void PlaceMonsters()
184 | {
185 | var numMonsters = RogueSharp.DiceNotation.Dice.Roll("1D6+3");
186 | for(int i = 0; i < numMonsters; i++)
187 | {
188 | var location = GetWalkableCell();
189 | string name = $"Kobold";
190 | var monster = _actorManager.CreateActor(60, name);
191 | monster.AddComponent(new Location(){X = location.X, Y = location.Y});
192 | monster.AddComponent(new Faction(){Type = Factions.Monster});
193 | monster.AddComponent();
194 | Debug.WriteLine($"Spawned {name} ({location.X},{location.Y})");
195 | }
196 | }
197 |
198 | ///
199 | /// Examine each cell and pick a suitable glyph for walls.
200 | ///
201 | void InitCellGlyphs()
202 | {
203 | int[,] mapArray = new int[_width, _height];
204 | for(int x = 0; x < _width; x++)
205 | {
206 | for(int y = 0; y < _height; y++)
207 | {
208 | var cell = _map.GetCell(x,y);
209 | if(cell.IsWalkable)
210 | {
211 | _spawnLocations.Add(cell);
212 | }
213 | mapArray[x,y] = cell.IsWalkable ? 0 : 1;
214 | }
215 | }
216 |
217 | var detector = new MapFeatureDetector(mapArray);
218 | var walls = detector.FindWalls();
219 | var doorways = detector.FindDoorways();
220 |
221 | for(int x = 0; x < _width; x++)
222 | {
223 | for(int y = 0; y < _height; y++)
224 | {
225 | _floor[x,y] = DIRT;
226 | if(mapArray[x,y] == 0)
227 | {
228 | _floor[x,y] = FLOOR;
229 | if(doorways[x,y] > 0) {ConsiderAddDoor(x,y, (Orientation) doorways[x,y] -1);}
230 | }
231 | else
232 | {
233 | if(walls[x,y] == 1) {_floor[x,y] = TILEABLEWALL;}
234 | }
235 | }
236 | }
237 | }
238 |
239 | void ConsiderAddDoor(int x, int y, Orientation orientation)
240 | {
241 | var doorRoll = random.Next(100);
242 | if(doorRoll < _doorPercentChance)
243 | {
244 | var doorPoint = new Point(x, y);
245 | foreach(Point d in _doors)
246 | {
247 | // No side by side doors
248 | if(PointDistance(doorPoint, d) == 1)
249 | {
250 | return;
251 | }
252 | }
253 | var entity = _entityManager.CreateEntity();
254 | var isDoor = new IsDoor(){Orientation = orientation, IsOpen = false};
255 | entity.AddComponent(isDoor);
256 | var location = new Location(){X = x, Y = y};
257 | entity.AddComponent(location);
258 | var glyph = new Glyph(){glyph = DOOR};
259 | entity.AddComponent(glyph);
260 | _map.SetCellProperties(x, y, isTransparent: false, isWalkable: true);
261 | _doors.Add(doorPoint);
262 | var cell = _map.GetCell(x, y);
263 | _spawnLocations.Remove(cell); // Remove doors as a spawn location
264 | }
265 | }
266 |
267 | double PointDistance(Point a, Point b)
268 | {
269 | var dx = a.X - b.X;
270 | var dy = a.Y - b.Y;
271 | var dist = Math.Sqrt((dx * dx) + (dy * dy));
272 | return dist;
273 | }
274 |
275 | ///
276 | /// Copy the private _floor to the public _floor_view
277 | ///
278 | void UpdateViews()
279 | {
280 | var circleView = GetFieldOfView(_playerLocation.X, _playerLocation.Y, _playerSiteDistance.Range, _map);
281 | var viewable = new List();
282 | foreach(var cell in circleView)
283 | {
284 | viewable.Add(new Point(cell.X, cell.Y));
285 | _map.AppendFov(cell.X, cell.Y, 0, true);
286 | }
287 | _viewable = new HashSet(viewable);
288 |
289 | if(_floor_view == null)
290 | {
291 | _floor_view = new int[_floor.GetLength(0), _floor.GetLength(1)];
292 | }
293 |
294 | for(int x = 0; x < _floor.GetLength(0); x++ )
295 | {
296 | for(int y = 0; y < _floor.GetLength(1); y++)
297 | {
298 | if(!_map.IsInFov(x, y))
299 | {
300 | _floor_view[x,y] = DARK;
301 | }
302 | else
303 | {
304 | _floor_view[x,y] = _floor[x,y];
305 | }
306 | }
307 | }
308 | }
309 |
310 | private static IEnumerable GetFieldOfView( int x, int y, int selectionSize, IMap map )
311 | {
312 | List circleFov = new List();
313 | var fieldOfView = new FieldOfView( map );
314 | var cellsInFov = fieldOfView.ComputeFov( x, y, (int) ( selectionSize * 1.5 ), true );
315 | var circle = map.GetCellsInCircle( x, y, selectionSize ).ToList();
316 | foreach ( ICell cell in cellsInFov )
317 | {
318 | if ( circle.Contains( cell ) )
319 | {
320 | circleFov.Add( cell );
321 | }
322 | }
323 | return circleFov;
324 | }
325 |
326 | private void BigRoom()
327 | {
328 | var bigroom = new RogueSharp.MapCreation.BorderOnlyMapCreationStrategy(_width, _height);
329 | _map = bigroom.CreateMap();
330 | }
331 |
332 | private void RandomizeFloor()
333 | {
334 | var maxRooms = (int) Math.Sqrt(_height * _width) * 2;
335 | var randomRooms = new RogueSharp.MapCreation.RandomRoomsMapCreationStrategy(_width, _height, maxRooms, 10, 5);
336 | _map = randomRooms.CreateMap();
337 | }
338 |
339 | private void RandomizeCave()
340 | {
341 | var randomCaves = new CaveMapCreationStrategy(_width, _height);
342 | _map = randomCaves.CreateMap();
343 | }
344 | }
345 |
346 | }
347 |
--------------------------------------------------------------------------------
/Engine/Engine.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard20;net461
5 | $(SolutionDir)\bin\$(Configuration)\$(AssemblyName)\
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/Engine/EngineConstants.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using RogueSharp;
3 |
4 | namespace MegaDungeon
5 | {
6 | ///
7 | /// A collection of constants used by the Engine class.
8 | ///
9 | public class EngineConstants
10 | {
11 | public static Point UP = new Point(0,-1);
12 | public static Point UPRIGHT = new Point(1, -1);
13 | public static Point RIGHT = new Point(1, 0);
14 | public static Point DOWNRIGHT = new Point(1, 1);
15 | public static Point DOWN = new Point(0, 1);
16 | public static Point DOWNLEFT = new Point(-1, 1);
17 | public static Point LEFT = new Point(-1, 0);
18 | public static Point UPLEFT = new Point(-1, -1);
19 | public static Point CENTER = new Point(0,0);
20 |
21 | public static Point[] COMPASSPOINTS = new[] {
22 | UPLEFT, UP, UPRIGHT,
23 | LEFT, CENTER, RIGHT,
24 | DOWNLEFT, DOWN, DOWNRIGHT
25 | };
26 |
27 | public static Dictionary INPUTMAP = new Dictionary()
28 | {
29 | {PlayerInput.UP, UP},
30 | {PlayerInput.UPRIGHT, UPRIGHT},
31 | {PlayerInput.RIGHT, RIGHT},
32 | {PlayerInput.DOWNRIGHT, DOWNRIGHT},
33 | {PlayerInput.DOWN, DOWN},
34 | {PlayerInput.DOWNLEFT, DOWNLEFT},
35 | {PlayerInput.LEFT, LEFT},
36 | {PlayerInput.UPLEFT, UPLEFT},
37 | {PlayerInput.WAIT, CENTER},
38 | };
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Engine/EngineLogger.cs:
--------------------------------------------------------------------------------
1 | using EntityComponentSystemCSharp.Systems;
2 |
3 | namespace MegaDungeon
4 | {
5 | public class EngineLogger : ISystemLogger
6 | {
7 | Engine _engine;
8 | public EngineLogger(Engine engine)
9 | {
10 | _engine = engine;
11 | }
12 |
13 | public void Log(string message)
14 | {
15 | _engine._messages.Enqueue(message);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Engine/Filters.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using RogueSharp;
4 | using FeatureDetector;
5 | using static MegaDungeon.EngineConstants;
6 |
7 | namespace MegaDungeon
8 | {
9 | ///
10 | /// Filters for matching small segments of the dungeon against to detect features.
11 | /// A simplified form of convalutional filters.
12 | ///
13 | public static class Filters
14 | {
15 | // 1 == impassable
16 | public static int[] Vertical = new []{
17 | 0,1,0,
18 | 0,0,0,
19 | 0,1,0
20 | };
21 |
22 | public static int[,] IdentityFilter = new int[,]{
23 | {0,0,0},
24 | {0,1,0},
25 | {0,0,0}
26 | };
27 |
28 |
29 |
30 |
31 |
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Engine/PlayerInput.cs:
--------------------------------------------------------------------------------
1 | namespace MegaDungeon
2 | {
3 | public enum PlayerInput
4 | {
5 | NONE,
6 | UP,
7 | UPRIGHT,
8 | RIGHT,
9 | DOWNRIGHT,
10 | DOWN,
11 | DOWNLEFT,
12 | LEFT,
13 | UPLEFT,
14 | WAIT
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Components.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using RogueSharp;
4 | using static EntityComponentSystemCSharp.EntityManager;
5 |
6 |
7 | namespace EntityComponentSystemCSharp.Components
8 | {
9 | ///
10 | /// Defines allowable components. Components SHOULD only have data members.
11 | /// Components SHOULD be simple to serialize.
12 | ///
13 | ///
14 | /// An entity may one have ONE of a a give component type.
15 | /// Use collections of entities for aggregates.
16 | ///
17 | public interface IComponent
18 | {
19 |
20 | }
21 |
22 | public class WanderingMonster : IComponent
23 | {
24 | }
25 |
26 | public class Attacked : IComponent
27 | {
28 | public Entity attacker;
29 | }
30 |
31 | public class Faction : IComponent
32 | {
33 | public MegaDungeon.Contracts.Factions Type;
34 | }
35 |
36 | public class AttackStat : IComponent
37 | {
38 | public int Power;
39 | public int Accuracy;
40 | }
41 |
42 | public class DefenseStat : IComponent
43 | {
44 | public int Chance;
45 | }
46 |
47 | public class SightStat : IComponent
48 | {
49 | public int Range;
50 | }
51 |
52 | public class Dead : IComponent
53 | {
54 |
55 | }
56 |
57 | public class Life : IComponent
58 | {
59 | public int Health;
60 | public int MaxHealth;
61 | }
62 |
63 | public class IsDoor : IComponent
64 | {
65 | public Orientation Orientation;
66 | public bool IsOpen;
67 | public bool Locked = false;
68 | }
69 |
70 | public class Destination : PointWrapper, IComponent
71 | {
72 |
73 | }
74 |
75 | public class Player : IComponent
76 | {
77 |
78 | }
79 |
80 | public class Actor : IComponent
81 | {
82 | public float Speed;
83 | public int Gold;
84 | public float Energy;
85 | }
86 |
87 | public class Glyph : IComponent
88 | {
89 | public int glyph = -1;
90 | }
91 |
92 | public class Location : PointWrapper, IComponent
93 | {
94 | }
95 |
96 | public class Demand : IComponent
97 | {
98 | public Dictionary Demands = new Dictionary();
99 | }
100 | public class Item : IComponent
101 | {
102 | public string Type = "";
103 | }
104 |
105 | public class Name : IComponent
106 | {
107 | public string NameString = null;
108 | }
109 |
110 | public class Producer : IComponent
111 | {
112 | public List ProducedItems = new List();
113 |
114 | public class ProductionItem
115 | {
116 | public string product = null;
117 | public float rate = 0.0f;
118 | public float inprogress = 0;
119 | }
120 | }
121 |
122 | public class Inventory : IComponent
123 | {
124 | public List Items = new List();
125 | public int Size = int.MaxValue;
126 | }
127 |
128 | public class Stackable : IComponent
129 | {
130 | }
131 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/DuplicateComponentException.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp
2 | {
3 | [System.Serializable]
4 | public class DuplicateComponentException : System.Exception
5 | {
6 | public DuplicateComponentException() { }
7 | public DuplicateComponentException(string message) : base(message) { }
8 | public DuplicateComponentException(string message, System.Exception inner) : base(message, inner) { }
9 | protected DuplicateComponentException(
10 | System.Runtime.Serialization.SerializationInfo info,
11 | System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/EntityComponentSystemCSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard20;net461
4 | true
5 |
6 | Library
7 |
8 | $(SolutionDir)\bin\$(Configuration)\$(AssemblyName)\
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | ..\lib\Newtonsoft.Json.dll
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/EntityExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using EntityComponentSystemCSharp.Components;
3 | using static EntityComponentSystemCSharp.EntityManager;
4 |
5 | namespace EntityComponentSystemCSharp
6 | {
7 | ///
8 | /// Convienence methods for dealing with EntityManager entities.
9 | ///
10 | public static class EntityExtensions
11 | {
12 | ///
13 | ///
14 | ///
15 | ///
16 | /// List of components attached to entity
17 | public static IEnumerable GetComponents(this Entity entity)
18 | {
19 | return entity.Manager.GetAllComponentsOnEntity(entity);
20 | }
21 |
22 | ///
23 | /// Return the component of type T
24 | ///
25 | /// null if empty
26 | public static T GetComponent(this Entity entity) where T: class
27 | {
28 | return entity.Manager.GetComponent(entity);
29 | }
30 |
31 | public static void RemoveComponent(this Entity entity) where T: class
32 | {
33 | entity.Manager.RemoveComponent(entity);
34 | }
35 |
36 | public static void RemoveComponent(this Entity entity, IComponent component)
37 | {
38 | entity.Manager.RemoveComponent(entity.Id, component);
39 | }
40 |
41 | ///
42 | /// Permanently remove this enity and all it's components from the EntityManager
43 | ///
44 | ///
45 | public static void Destroy(this Entity entity)
46 | {
47 | entity.Manager.DestroyEntity(entity);
48 | }
49 |
50 | public static void AddComponent(this Entity entity, IComponent component)
51 | {
52 | entity.Manager.AddComponent(entity, component);
53 | }
54 |
55 | public static IComponent AddOrUpdateComponent(this Entity entity, IComponent component)
56 | {
57 | return entity.Manager.AddOrUpdateComponent(entity, component);
58 | }
59 |
60 | ///
61 | /// Adds and returns a new type T component to the entity.
62 | ///
63 | /// New component where T: IComponent
64 | public static T AddComponent(this Entity entity) where T: class, new()
65 | {
66 | CheckComponentAndThrow();
67 | var component = (IComponent) new T();
68 | entity.AddComponent(component);
69 | return (T) component;
70 | }
71 |
72 | public static bool HasComponent(this Entity entity) where T: class
73 | {
74 | CheckComponentAndThrow();
75 | var component = entity.GetComponent();
76 | return component != null;
77 | }
78 |
79 | ///
80 | /// Type check components to prevent random objects from being added.
81 | ///
82 | ///
83 | static void CheckComponentAndThrow()
84 | {
85 | if(!typeof(IComponent).IsAssignableFrom(typeof(T)))
86 | {
87 | throw new NotComponentException("You must specify a type that implement IComponent");
88 | }
89 | }
90 |
91 | }
92 |
93 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/EntityManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Text;
4 | using System.Collections.Generic;
5 | using EntityComponentSystemCSharp.Components;
6 | using Newtonsoft.Json;
7 |
8 | namespace EntityComponentSystemCSharp
9 | {
10 | ///
11 | /// Manages and stores entities and components.
12 | /// Based on http://entity-systems.wikidot.com/rdbms-beta
13 | ///
14 | public class EntityManager
15 | {
16 | // Entities are just and only integers. Entity class is a wrapper with a reference back to the entity
17 | // manager to allow extension methods to work more fluently.
18 | public sealed class Entity
19 | {
20 | private int _id;
21 | private EntityManager _manager;
22 |
23 | public int Id { get{ return _id; } }
24 | public EntityManager Manager { get { return _manager; } }
25 |
26 | internal Entity(int id, EntityManager manager)
27 | {
28 | _id = id;
29 | _manager = manager;
30 | }
31 |
32 | public override string ToString()
33 | {
34 | return $"Id = {_id}";
35 | }
36 | }
37 |
38 | JsonSerializerSettings _serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
39 |
40 | public IEnumerable Entities => _entities.ToArray(); // Read Only version of current entities
41 | HashSet _entities = new HashSet();
42 |
43 | // key is $"{entityInt}+{typeof(component).ToString()}"
44 | Dictionary _map = new Dictionary();
45 | bool isFrozen = false;
46 |
47 | ///
48 | /// Add an entity to the collection
49 | ///
50 | /// New entity created
51 | public Entity CreateEntity()
52 | {
53 | if(isFrozen)
54 | {
55 | return new Entity(id: -1, manager: this);
56 | }
57 |
58 | var id = 0;
59 | while(_entities.Any(e => e.Id == id))
60 | {
61 | id++;
62 | }
63 |
64 | var entity = new Entity(id, this);
65 | _entities.Add(entity);
66 | return entity;
67 | }
68 |
69 | ///
70 | /// Permanently remove an enitity and all it's components. The ID will be re-used.
71 | ///
72 | ///
73 | public void DestroyEntity(Entity entity)
74 | {
75 | if(isFrozen)
76 | {
77 | return;
78 | }
79 |
80 | _entities.Remove(entity);
81 | List removeKeys = new List();
82 | foreach (var item in _map)
83 | {
84 | var pattern = $"{entity.Id}+";
85 | if(item.Key.StartsWith(pattern))
86 | {
87 | removeKeys.Add(item.Key);
88 | }
89 | }
90 | foreach(var key in removeKeys)
91 | {
92 | _map.Remove(key);
93 | }
94 | }
95 |
96 | public IEnumerable GetAllComponentsOfType() where T : class
97 | {
98 | var returnList = new List();
99 | foreach(var entity in _entities)
100 | {
101 | var component = GetComponent(entity);
102 | if(component != null)
103 | {
104 | returnList.Add((T)component);
105 | }
106 | }
107 | return returnList;
108 | }
109 |
110 | public T GetComponent(Entity entity) where T: class
111 | {
112 | CheckComponentAndThrow();
113 | return GetComponent(entity.Id);
114 | }
115 |
116 | public T GetComponent(int id) where T: class
117 | {
118 | var componentType = typeof(T);
119 |
120 | T returnVal = null;
121 | var key = GetMapKey(id, componentType);
122 |
123 | if(_map.ContainsKey(key))
124 | {
125 | returnVal = (T)_map[key];
126 | }
127 | return returnVal;
128 | }
129 |
130 | public List GetAllComponentsOnEntity(Entity entity)
131 | {
132 | return GetAllComponentsOnEntity(entity.Id);
133 | }
134 |
135 | private List GetAllComponentsOnEntity(int id)
136 | {
137 | var returnList = new List();
138 | foreach(var entry in _map)
139 | {
140 | if(entry.Key.StartsWith($"{id}+"))
141 | {
142 | returnList.Add(entry.Value);
143 | }
144 | }
145 | return returnList;
146 | }
147 |
148 | public List GetAllEntitiesWithComponent() where T : class
149 | {
150 | Type componentType = typeof(T);
151 | var returnList = new List();
152 | foreach(var entity in _entities)
153 | {
154 | var component = GetComponent(entity);
155 | if(component != null)
156 | {
157 | returnList.Add(entity);
158 | }
159 | }
160 | return returnList;
161 | }
162 |
163 | public void RemoveComponent(Entity entity) where T: class
164 | {
165 | var component = (IComponent) GetComponent(entity);
166 | if(component != null)
167 | {
168 | RemoveComponent(entity.Id, component);
169 | }
170 | }
171 |
172 | internal void RemoveComponent(int id, IComponent component)
173 | {
174 | if(isFrozen)
175 | {
176 | return;
177 | }
178 |
179 | var key = GetMapKey(id, component.GetType());
180 | if(_map.ContainsKey(key))
181 | {
182 | _map.Remove(key);
183 | }
184 | }
185 |
186 | public void AddComponent(Entity entity, IComponent component)
187 | {
188 | AddComponent(entity.Id, component);
189 | }
190 |
191 | public IComponent AddOrUpdateComponent(Entity entity, IComponent component)
192 | {
193 | var key = GetMapKey(entity.Id, component.GetType());
194 | _map[key] = component;
195 | return component;
196 | }
197 |
198 | void AddComponent(int entityId, IComponent component)
199 | {
200 | if(isFrozen)
201 | {
202 | return;
203 | }
204 |
205 | var key = GetMapKey(entityId, component.GetType());
206 | if(!_map.ContainsKey(key))
207 | {
208 | _map.Add(key, component);
209 | }
210 | else
211 | {
212 | throw new DuplicateComponentException($"Entity already has a component of type {component.GetType()}. Modify existing or remove first.");
213 | }
214 | }
215 |
216 | internal bool HasComponent(Entity entity) where T : class
217 | {
218 | var component = GetComponent(entity);
219 | return component != null;
220 | }
221 |
222 | ///
223 | /// Prevent any changes to entities and components for debugging.
224 | ///
225 | public void Freeze()
226 | {
227 | isFrozen = true;
228 | }
229 |
230 | ///
231 | /// Allow changes to entities and components after Freeze-ing
232 | ///
233 | public void UnFreeze()
234 | {
235 | isFrozen = false;
236 | }
237 |
238 | public override string ToString()
239 | {
240 | var sb = new StringBuilder();
241 | foreach(var item in _map)
242 | {
243 | sb.AppendLine(item.Key);
244 | }
245 | return sb.ToString();
246 | }
247 |
248 | ///
249 | /// Returns a string template for creating more entities with the same parameters.
250 | ///
251 | ///
252 | ///
253 | public Dictionary GetEntityPrototype(Entity entity)
254 | {
255 | var components = entity.GetComponents();
256 | var dict = new Dictionary();
257 | foreach(var c in components)
258 | {
259 | dict.Add(c.GetType().Name, c);
260 | }
261 | return dict;
262 | }
263 |
264 | public Entity NewEntityFromPrototype(string prototype)
265 | {
266 | var components = JsonConvert.DeserializeObject>(prototype);
267 | var entity = CreateEntity();
268 | foreach(var component in components)
269 | {
270 | var compStr = JsonConvert.SerializeObject(component.Value);
271 | compStr = compStr.Replace("{","{" + " \"$type\": " + $"\"EntityComponentSystemCSharp.Components.{component.Key}, EntityComponentSystemCSharp\",\n");
272 | var actualComp = JsonConvert.DeserializeObject(compStr, _serializerSettings);
273 | entity.AddComponent(actualComp);
274 | }
275 |
276 | return entity;
277 | }
278 |
279 | string GetMapKey(int entity, Type componentType)
280 | {
281 | return $"{entity}+{componentType.ToString()}";
282 | }
283 |
284 | void CheckComponentAndThrow()
285 | {
286 | if(!typeof(IComponent).IsAssignableFrom(typeof(T)))
287 | {
288 | throw new NotComponentException("You must specify a type that implement IComponent");
289 | }
290 | }
291 | }
292 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/MissingComponentException.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp.Systems
2 | {
3 | [System.Serializable]
4 | public class MissingComponentException : System.Exception
5 | {
6 | public MissingComponentException() { }
7 | public MissingComponentException(string message) : base(message) { }
8 | public MissingComponentException(string message, System.Exception inner) : base(message, inner) { }
9 | protected MissingComponentException(
10 | System.Runtime.Serialization.SerializationInfo info,
11 | System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
12 | }
13 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/NotComponentException.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp
2 | {
3 | [System.Serializable]
4 | public class NotComponentException : System.Exception
5 | {
6 | public NotComponentException
7 | () { }
8 | public NotComponentException
9 | (string message) : base(message) { }
10 | public NotComponentException
11 | (string message, System.Exception inner) : base(message, inner) { }
12 | protected NotComponentException
13 | (
14 | System.Runtime.Serialization.SerializationInfo info,
15 | System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Orientation.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp.Components
2 | {
3 | public enum Orientation
4 | {
5 | N,
6 | E,
7 | S,
8 | W
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/PointWrapper.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp.Components
2 | {
3 | ///
4 | /// RogueSharp implements Point as a struct, which is in effect sealed.
5 | /// Wrapper allows various components to be points with different names under the hood.
6 | ///
7 | public class PointWrapper
8 | {
9 | RogueSharp.Point point = new RogueSharp.Point();
10 |
11 | public int X { get => point.X; set => point.X = value;}
12 | public int Y { get => point.Y; set => point.Y = value;}
13 |
14 | public PointWrapper()
15 | {
16 |
17 | }
18 |
19 | public PointWrapper(int value)
20 | {
21 | point = new RogueSharp.Point(value);
22 | }
23 |
24 | public PointWrapper(int x, int y)
25 | {
26 | point = new RogueSharp.Point(x,y);
27 | }
28 |
29 | PointWrapper(RogueSharp.Point point)
30 | {
31 | this.point = point;
32 | }
33 |
34 | public static PointWrapper Add(PointWrapper value1, PointWrapper value2)
35 | {
36 | var rpoint = RogueSharp.Point.Add(value1.point, value2.point);
37 | return new PointWrapper(rpoint);
38 | }
39 |
40 | public static float Distance(PointWrapper value1, PointWrapper value2)
41 | {
42 | return RogueSharp.Point.Distance(value1.point, value2.point);
43 | }
44 |
45 | public static PointWrapper Divide(PointWrapper value1, PointWrapper value2)
46 | {
47 | var rpoint = RogueSharp.Point.Divide(value1.point, value2.point);
48 | return new PointWrapper(rpoint);
49 | }
50 |
51 | public static PointWrapper Multiply(PointWrapper value1, PointWrapper value2)
52 | {
53 | var rpoint = RogueSharp.Point.Multiply(value1.point, value2.point);
54 | return new PointWrapper(rpoint);
55 | }
56 |
57 | public static PointWrapper Negate(PointWrapper value1)
58 | {
59 | var rpoint = RogueSharp.Point.Negate(value1.point);
60 | return new PointWrapper(rpoint);
61 | }
62 |
63 | public static PointWrapper Subtract(PointWrapper value1, PointWrapper value2)
64 | {
65 | var rpoint = RogueSharp.Point.Subtract(value1.point, value2.point);
66 | return new PointWrapper(rpoint);
67 | }
68 |
69 | public override bool Equals(object obj)
70 | {
71 | var wrapper = obj as PointWrapper;
72 | return wrapper != null && wrapper.point != null && point.Equals(obj);
73 | }
74 |
75 | // override object.GetHashCode
76 | public override int GetHashCode()
77 | {
78 | return point.GetHashCode();
79 | }
80 |
81 | public override string ToString()
82 | {
83 | return point.ToString();
84 | }
85 |
86 | public static PointWrapper operator +(PointWrapper value1, PointWrapper value2)
87 | {
88 | var wrapper = new PointWrapper((value1.point + value2.point));
89 | return wrapper;
90 | }
91 |
92 | public static PointWrapper operator -(PointWrapper value1, PointWrapper value2)
93 | {
94 | var wrapper = new PointWrapper((value1.point - value2.point));
95 | return wrapper;
96 | }
97 |
98 | public static PointWrapper operator *(PointWrapper value1, PointWrapper value2)
99 | {
100 | var wrapper = new PointWrapper((value1.point * value2.point));
101 | return wrapper;
102 | }
103 |
104 | public static PointWrapper operator /(PointWrapper source, PointWrapper divisor)
105 | {
106 | var wrapper = new PointWrapper((source.point / divisor.point));
107 | return wrapper;
108 | }
109 | public static bool operator ==(PointWrapper a, PointWrapper b)
110 | {
111 | return a?.point == b?.point;
112 | }
113 |
114 | public static bool operator !=(PointWrapper a, PointWrapper b)
115 | {
116 | return a?.point != b?.point;
117 | }
118 |
119 |
120 | }
121 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/CombatSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using EntityComponentSystemCSharp.Components;
3 | using RogueSharp;
4 |
5 | namespace EntityComponentSystemCSharp.Systems
6 | {
7 |
8 | public class CombatSystem : SystemBase, ISystem
9 | {
10 | Random _rand = new Random();
11 |
12 | public CombatSystem(IEngine engine) : base(engine)
13 | {
14 | }
15 |
16 | public override void Run(EntityManager.Entity entity)
17 | {
18 | if(!entity.HasComponent()) {return;}
19 |
20 | var attacked = entity.GetComponent();
21 | var alive = entity.GetComponent();
22 | var attackStat = attacked.attacker.GetComponent();
23 | var defense = entity.GetComponent();
24 | if(alive != null && attackStat != null)
25 | {
26 | string attackerName = attacked.attacker.GetComponent()?.NameString ?? entity.Id.ToString();
27 | string victimName = entity.GetComponent()?.NameString ?? entity.Id.ToString();
28 |
29 | var hit = _rand.Next(100);
30 | if(hit < attackStat.Accuracy)
31 | {
32 | var damage = _rand.Next(attackStat.Power) + 1;
33 | if(defense != null)
34 | {
35 | if (hit > defense.Chance)
36 | {
37 | _logger.Log($"{attackerName} hit {victimName} for {damage} damage.");
38 | alive.Health -= damage;
39 | }
40 | }
41 | }
42 | else
43 | {
44 | _logger.Log($"{attackerName} missed {victimName}.");
45 | }
46 | }
47 | entity.RemoveComponent();
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/DemandSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using EntityComponentSystemCSharp;
4 | using EntityComponentSystemCSharp.Components;
5 | using static EntityComponentSystemCSharp.EntityManager;
6 |
7 | namespace EntityComponentSystemCSharp.Systems
8 | {
9 |
10 | public class DemandSystem : SystemBase, ISystem
11 | {
12 | public DemandSystem(IEngine engine) : base(engine)
13 | {
14 | }
15 |
16 | public override void Run(Entity entity)
17 | {
18 | if(!entity.HasComponent()){return;}
19 |
20 | var demand = entity.GetComponent();
21 | var inventory = entity.GetComponent();
22 | if(demand != null)
23 | {
24 | foreach(var d in demand.Demands)
25 | {
26 | var items = GetItemsFromInventory(entity, d.Key);
27 | var numToRemove = Math.Min(items.Length, d.Value);
28 | for(int i = 0; i < numToRemove; i++)
29 | {
30 | inventory.Items.Remove(items[i]);
31 | }
32 | }
33 | }
34 | }
35 |
36 | Entity[] GetItemsFromInventory(Entity entity, string type)
37 | {
38 | var inventory = entity.GetComponent();
39 | if(inventory == null)
40 | {
41 | throw new MissingComponentException("Production requires an inventory for storage.");
42 | }
43 | var returnList = new List();
44 | foreach(var item in inventory.Items)
45 | {
46 | var itemComponent = item.GetComponent- ();
47 | if(itemComponent != null && itemComponent.Type == type)
48 | {
49 | returnList.Add(item);
50 | }
51 | }
52 | return returnList.ToArray();
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/EnergySystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using RogueSharp;
5 | using EntityComponentSystemCSharp.Components;
6 |
7 | namespace EntityComponentSystemCSharp.Systems
8 | {
9 | public class EnergySystem : SystemBase, ISystem
10 | {
11 | public EnergySystem(IEngine engine) : base(engine)
12 | {
13 | }
14 |
15 | public override void Run(EntityManager.Entity entity)
16 | {
17 | if(!entity.HasComponent()){return;}
18 |
19 | var actor = entity.GetComponent();
20 | actor.Energy += actor.Speed;
21 |
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/HealthSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using EntityComponentSystemCSharp.Components;
3 | using RogueSharp;
4 |
5 | namespace EntityComponentSystemCSharp.Systems
6 | {
7 | public class HealthSystem : SystemBase, ISystem
8 | {
9 | int CORPSE = 636;
10 | Random rand = new Random();
11 | public HealthSystem(IEngine engine) : base(engine)
12 | {
13 | }
14 |
15 | public override void Run(EntityManager.Entity entity)
16 | {
17 | var life = entity.GetComponent();
18 | if(life == null) {return;}
19 |
20 | if(life.Health < life.MaxHealth)
21 | {
22 | var regenRole = rand.Next(1000);
23 | if (regenRole < life.MaxHealth)
24 | {
25 | life.Health++;
26 | }
27 | }
28 |
29 | if(life.Health <= 0)
30 | {
31 | var nameComponent = entity.GetComponent();
32 | string name = "";
33 | if(nameComponent != null)
34 | {
35 | name = nameComponent.NameString;
36 | }
37 |
38 | _logger.Log($"{name}({entity.Id.ToString()}) has run out of hitpoints and died.");
39 |
40 | entity.RemoveComponent();
41 | entity.RemoveComponent();
42 | entity.AddComponent();
43 |
44 | var glyph = entity.GetComponent();
45 | glyph.glyph = CORPSE;
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/IEngine.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using EntityComponentSystemCSharp.Systems;
3 | using MegaDungeon.Contracts;
4 | using RogueSharp;
5 |
6 | namespace EntityComponentSystemCSharp
7 | {
8 | public interface IEngine
9 | {
10 | EntityManager GetEntityManager();
11 | RogueSharp.IMap GetMap();
12 | ISystemLogger GetLogger();
13 | HashSet GetPlayerViewable();
14 | Point GetPlayerLocation();
15 | ITileManager GetTileManager();
16 | }
17 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/ISystem.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp.Systems
2 | {
3 | public interface ISystem
4 | {
5 | void Run(EntityManager.Entity entity);
6 | }
7 |
8 | public interface ISystemLogger
9 | {
10 | void Log(string message);
11 | }
12 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/MovementSystem.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using EntityComponentSystemCSharp.Components;
4 | using static EntityComponentSystemCSharp.EntityManager;
5 | using RogueSharp;
6 |
7 | namespace EntityComponentSystemCSharp.Systems
8 | {
9 | public class MovementSystem : SystemBase, ISystem
10 | {
11 | bool _isClear = true;
12 | RogueSharp.PathFinder _pathfinder;
13 | int _nsOpenDoorGlyph, _ewOpenDoorGlyph;
14 | public MovementSystem(IEngine engine) : base(engine)
15 | {
16 | _pathfinder = new RogueSharp.PathFinder(_map, 1);
17 | var tm = _engine.GetTileManager();
18 | _nsOpenDoorGlyph = tm.GetGlyphNumByName("open door NS");
19 | _ewOpenDoorGlyph = tm.GetGlyphNumByName("open door EW");
20 | }
21 |
22 | public override void Run(Entity entity)
23 | {
24 | if(!(entity.HasComponent() &&
25 | entity.HasComponent() &&
26 | entity.GetComponent().Energy >= 10))
27 | {return;}
28 |
29 | var locationEntities = _em.GetAllEntitiesWithComponent()
30 | .Where(e => e.HasComponent() || e.HasComponent());
31 |
32 | entity.GetComponent().Energy -= 10;
33 | var allComponents = entity.GetComponents();
34 | var current = entity.GetComponent();
35 | var desired = entity.GetComponent();
36 | if(_map != null && desired != null && desired.X >= 0 && desired.X < _map.Width && desired.Y >= 0 && desired.Y < _map.Height)
37 | {
38 | var start = _map.GetCell(current.X, current.Y);
39 | var dest = _map.GetCell(desired.X, desired.Y);
40 | var path = _pathfinder.TryFindShortestPath(start, dest);
41 | _isClear = true;
42 | if(path != null && path.Length > 1)
43 | {
44 | var next = path.StepForward();
45 | ResolveCollisions(entity, locationEntities, current, next);
46 | if (_isClear)
47 | {
48 | current.X = next.X;
49 | current.Y = next.Y;
50 | }
51 | }
52 | }
53 | }
54 |
55 |
56 | void ResolveCollisions(Entity entity, IEnumerable locationEntities, Location current, ICell next)
57 | {
58 | _isClear = true;
59 | foreach(var other in locationEntities)
60 | {
61 | var othersLocation = other.GetComponent();
62 | if (othersLocation.X == next.X && othersLocation.Y == next.Y)
63 | {
64 | var handled = DoorCheck(other, othersLocation);
65 | if(!handled){ResolveAttack(entity, current, other, othersLocation);}
66 | }
67 | }
68 | }
69 |
70 | bool DoorCheck(Entity other, Location othersLocation)
71 | {
72 | var handled = false;
73 | if(other.HasComponent())
74 | {
75 | var door = other.GetComponent();
76 | var glyph = other.GetComponent();
77 |
78 | // TODO: Check for locked doors.
79 |
80 | door.IsOpen = true;
81 | if(door.Orientation == Orientation.N || door.Orientation == Orientation.S)
82 | {
83 | glyph.glyph = _nsOpenDoorGlyph;
84 | }
85 | else
86 | {
87 | glyph.glyph = _ewOpenDoorGlyph;
88 | }
89 | _map.SetCellProperties(othersLocation.X, othersLocation.Y, isTransparent: true, isWalkable: true);
90 | handled = true;
91 | }
92 | return handled;
93 | }
94 |
95 | bool ResolveAttack(Entity entity, Location current, Entity other, Location othersLocation)
96 | {
97 | var handled = false;
98 | var myFaction = entity.GetComponent();
99 | var theirFaction = other.GetComponent();
100 | var theirAttacked = other.GetComponent();
101 |
102 | // Check to see if the two are eligible to swap.
103 | // Must be same faction and target not under (unresolved) attack.
104 | if (myFaction != null &&
105 | theirFaction != null &&
106 | theirAttacked == null &&
107 | myFaction.Type == theirFaction.Type)
108 | {
109 | othersLocation.X = current.X;
110 | othersLocation.Y = current.Y;
111 | handled = true;
112 | }
113 | else
114 | {
115 | other.AddOrUpdateComponent(new Attacked() { attacker = entity });
116 | _isClear = false; //Attacking cancels move
117 | handled = true;
118 | }
119 | return handled;
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/ProductionSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using EntityComponentSystemCSharp.Components;
3 | using RogueSharp;
4 |
5 | namespace EntityComponentSystemCSharp.Systems
6 | {
7 | public class ProductionSystem : SystemBase, ISystem
8 | {
9 | public ProductionSystem(IEngine engine) : base(engine)
10 | {
11 | }
12 |
13 | public override void Run(EntityManager.Entity entity)
14 | {
15 | if(!entity.HasComponent()){return;}
16 |
17 | var production = entity.GetComponent();
18 |
19 | foreach(var product in production.ProducedItems)
20 | {
21 | product.inprogress += product.rate;
22 | var wholeItems = (int)(product.inprogress);
23 | product.inprogress =- wholeItems;
24 | var inventory = entity.GetComponent();
25 | var numToAdd = Math.Min(inventory.Size, wholeItems);
26 | for(int i = 0; i < numToAdd; i++)
27 | {
28 | var item = _em.CreateEntity();
29 | item.AddComponent(new Item(){Type = product.product});
30 | inventory.Items.Add(item);
31 | }
32 | }
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/StackSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using EntityComponentSystemCSharp;
4 | using EntityComponentSystemCSharp.Components;
5 | using RogueSharp;
6 | using static EntityComponentSystemCSharp.EntityManager;
7 |
8 | namespace EntityComponentSystemCSharp.Systems
9 | {
10 | public class StackSystem : SystemBase, ISystem
11 | {
12 | public StackSystem(IEngine engine) : base(engine)
13 | {
14 | }
15 |
16 | public override void Run(Entity entity)
17 | {
18 | throw new NotImplementedException();
19 | }
20 |
21 | public Dictionary GetStacks(Entity entity)
22 | {
23 | var results = new Dictionary();
24 | var inventory = entity.GetComponent();
25 | if(inventory != null)
26 | {
27 | foreach(var item in inventory.Items)
28 | {
29 | var itemComponent = item.GetComponent
- ();
30 |
31 | if(itemComponent != null && item.HasComponent())
32 | {
33 | if(!results.ContainsKey(itemComponent.Type))
34 | {
35 | results.Add(itemComponent.Type, 0);
36 | }
37 | results[itemComponent.Type] += 1;
38 | }
39 | }
40 | }
41 | return results;
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/SystemBase.cs:
--------------------------------------------------------------------------------
1 | using EntityComponentSystemCSharp;
2 | using static EntityComponentSystemCSharp.EntityManager;
3 | using RogueSharp;
4 |
5 |
6 | namespace EntityComponentSystemCSharp.Systems
7 | {
8 | public abstract class SystemBase: ISystem
9 | {
10 | protected readonly EntityManager _em;
11 | protected readonly ISystemLogger _logger;
12 | protected readonly IMap _map;
13 | protected IEngine _engine;
14 | public SystemBase(IEngine engine)
15 | {
16 | _em = engine.GetEntityManager();
17 | _logger = engine.GetLogger();
18 | _map = engine.GetMap();
19 | _engine = engine;
20 | }
21 | public abstract void Run(Entity entity);
22 | }
23 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Systems/WanderingMonsterSystem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using EntityComponentSystemCSharp.Components;
4 | using RogueSharp;
5 |
6 | namespace EntityComponentSystemCSharp.Systems
7 | {
8 | ///
9 | /// Entities with the wandering monster component will wander around at random
10 | /// and attack the player if they see them.
11 | ///
12 | public class WanderingMonsterSystem : SystemBase
13 | {
14 | Random rand = new Random();
15 | List walkable = new List();
16 | public WanderingMonsterSystem(IEngine engine): base(engine)
17 | {
18 | foreach(var cell in _map.GetAllCells())
19 | {
20 | if(cell.IsWalkable)
21 | {
22 | walkable.Add(cell);
23 | }
24 | }
25 | }
26 |
27 | public override void Run(EntityManager.Entity entity)
28 | {
29 | if(!entity.HasComponent()){return;}
30 | if(!entity.HasComponent()){return;}
31 |
32 | var actual = entity.GetComponent();
33 | var desired = entity.GetComponent();
34 |
35 | var point = new Point(actual.X, actual.Y);
36 | if (_engine.GetPlayerViewable().Contains(point))
37 | {
38 | desired = new Destination() {X =_engine.GetPlayerLocation().X, Y = _engine.GetPlayerLocation().Y};
39 | entity.AddOrUpdateComponent((IComponent)desired);
40 | }
41 | else if(desired == null || desired == actual)
42 | {
43 | entity.RemoveComponent();
44 | var randCell = walkable[rand.Next(0, walkable.Count)];
45 | desired = entity.AddComponent();
46 | desired.X = randCell.X;
47 | desired.Y = randCell.Y;
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Test/EntityManagerTests.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using NUnit.Framework;
3 | using EntityComponentSystemCSharp.Components;
4 |
5 | namespace EntityComponentSystemCSharp
6 | {
7 | [TestFixture]
8 | public class EntityManagerTests
9 | {
10 |
11 | [Test]
12 | public void CreateEntityTest()
13 | {
14 | var _em = new EntityManager();
15 | var entity = _em.CreateEntity();
16 | Assert.IsNotNull(entity);
17 | }
18 |
19 | [Test]
20 | public void KillEntityTest()
21 | {
22 | var _em = new EntityManager();
23 | var entity = _em.CreateEntity();
24 | var tag = new Name();
25 | entity.AddComponent(tag);
26 | entity.Destroy();
27 | var entities = _em.GetAllEntitiesWithComponent();
28 | Assert.AreEqual(0, entities.Count);
29 | }
30 |
31 | [Test]
32 | public void AddAndGetComponentTest()
33 | {
34 | var _em = new EntityManager();
35 | var entity = _em.CreateEntity();
36 | var tag = new Name(){NameString = "test"};
37 | entity.AddComponent(tag);
38 | var actaul = entity.GetComponent();
39 | Assert.AreEqual(tag, actaul);
40 | }
41 |
42 | [Test]
43 | public void RemoveComponentTest()
44 | {
45 | var _em = new EntityManager();
46 | var entity = _em.CreateEntity();
47 | var tag = new Name(){NameString = "test"};
48 | entity.AddComponent(tag);
49 | entity.RemoveComponent(tag);
50 | var actual = entity.GetComponent();
51 | Assert.Null(actual);
52 |
53 | entity.AddComponent(tag);
54 | entity.RemoveComponent();
55 | actual = entity.GetComponent();
56 | Assert.Null(actual);
57 | }
58 |
59 | [Test]
60 | public void RemoveComponentGenericTest()
61 | {
62 | var _em = new EntityManager();
63 | var entity = _em.CreateEntity();
64 | var tag = new Name(){NameString = "test"};
65 | entity.AddComponent(tag);
66 | entity.RemoveComponent();
67 | var actual = entity.GetComponent();
68 | Assert.Null(actual);
69 | }
70 |
71 | [Test]
72 | public void NotComponentException()
73 | {
74 | var _em = new EntityManager();
75 | var entity = _em.CreateEntity();
76 | Assert.That(( ) => entity.GetComponent(), Throws.TypeOf());
77 | }
78 |
79 | [Test]
80 | public void GetAllComponentsOnEntityTest()
81 | {
82 | var _em = new EntityManager();
83 | var entity = _em.CreateEntity();
84 | var tag = new Name(){NameString = "test"};
85 | var producer = new Producer();
86 | entity.AddComponent(tag);
87 | entity.AddComponent(producer);
88 | var allComponents = entity.GetComponents();
89 | Assert.AreEqual(2, allComponents.Count());
90 | }
91 |
92 | [Test]
93 | public void GetComponentOfTypeTest()
94 | {
95 | var _em = new EntityManager();
96 | var entity = _em.CreateEntity();
97 | var tag = new Name(){NameString = "test"};
98 | var producer = new Producer();
99 | entity.AddComponent(tag);
100 | entity.AddComponent(producer);
101 | var actual = entity.GetComponent();
102 | Assert.AreEqual(tag, actual);
103 | }
104 |
105 | [Test]
106 | public void GetAllComponentsOfTypeTest()
107 | {
108 | var _em = new EntityManager();
109 | var entity = _em.CreateEntity();
110 | var tag = new Name(){NameString = "test"};
111 | var producer = new Producer();
112 | entity.AddComponent(tag);
113 | entity.AddComponent(producer);
114 |
115 | var entity2 = _em.CreateEntity();
116 | var tag2 = new Name(){NameString = "test2"};
117 | var producer2 = new Producer();
118 | entity2.AddComponent(tag2);
119 | entity2.AddComponent(producer2);
120 |
121 | var tagComponents = _em.GetAllComponentsOfType();
122 | Assert.AreEqual(2, tagComponents.Count());
123 | Assert.AreEqual(tagComponents.First().GetType(), typeof(Name));
124 | }
125 |
126 | [Test]
127 | public void GetAllEntitiesWithComponentTest()
128 | {
129 | var _em = new EntityManager();
130 | _em.CreateEntity();
131 | var entity = _em.CreateEntity();
132 | var tag = new Name(){NameString = "test"};
133 | var producer = new Producer();
134 | entity.AddComponent(tag);
135 | entity.AddComponent(producer);
136 |
137 | var entity2 = _em.CreateEntity();
138 | var producer2 = new Producer();
139 | entity2.AddComponent(producer2);
140 |
141 | var entities = _em.GetAllEntitiesWithComponent();
142 | Assert.AreEqual(2, entities.Count);
143 | Assert.IsTrue(entities.Contains(entity));
144 | Assert.IsTrue(entities.Contains(entity2));
145 | }
146 |
147 | [Test]
148 | public void HasComponentTest()
149 | {
150 | var _em = new EntityManager();
151 | var entity = _em.CreateEntity();
152 | var tag = new Name(){NameString = "test"};
153 | entity.AddComponent(tag);
154 | var hasTag = _em.HasComponent(entity);
155 | Assert.IsTrue(hasTag);
156 |
157 | var hasProducer = _em.HasComponent(entity);
158 | Assert.IsFalse(hasProducer);
159 | }
160 |
161 | [Test]
162 | public void FreezeTest()
163 | {
164 | var _em = new EntityManager();
165 | _em.Freeze();
166 | var negaEntity = _em.CreateEntity();
167 | var count = _em.Entities.Count();
168 | Assert.AreEqual(0, count);
169 | _em.UnFreeze();
170 |
171 | var entity = _em.CreateEntity();
172 | _em.Freeze();
173 | var tag = new Name();
174 | entity.AddComponent(tag);
175 | var entities = _em.GetAllEntitiesWithComponent();
176 | Assert.AreEqual(0, entities.Count);
177 | }
178 |
179 | [Test]
180 | public void UnfreezeTest()
181 | {
182 | var _em = new EntityManager();
183 | var entity = _em.CreateEntity();
184 | _em.Freeze();
185 | _em.UnFreeze();
186 | var tag = new Name();
187 | entity.AddComponent(tag);
188 | var entities = _em.GetAllEntitiesWithComponent();
189 | Assert.AreEqual(1, entities.Count);
190 | }
191 |
192 | [Test]
193 | public void DuplicateComponentsTest()
194 | {
195 | var _em = new EntityManager();
196 | var entity = _em.CreateEntity();
197 | var tag1 = new Name();
198 | var tag2 = new Name();
199 | entity.AddComponent(tag1);
200 | Assert.That(( ) => entity.AddComponent(tag2), Throws.TypeOf());
201 | }
202 | }
203 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Test/EntityPrototypeTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Reflection;
4 | using System.Diagnostics;
5 | using NUnit.Framework;
6 | using EntityComponentSystemCSharp;
7 | using EntityComponentSystemCSharp.Components;
8 | using System.Collections.Generic;
9 | using Newtonsoft.Json;
10 | using static EntityComponentSystemCSharp.EntityManager;
11 | using MegaDungeon.Contracts;
12 |
13 | namespace EntityComponentSystemCSharp.Test
14 | {
15 | [TestFixture]
16 | public class EntityPrototypeTests
17 | {
18 | [Test]
19 | public void GetEntityDetailsTest()
20 | {
21 | var em = new EntityManager();
22 | var entity = em.CreateEntity();
23 | entity.AddComponent(new Location(){X = 1, Y = 2});
24 | entity.AddComponent();
25 | var prototype = em.GetEntityPrototype(entity);
26 | Assert.NotNull(prototype["Actor"]);
27 | }
28 |
29 | [Test]
30 | public void RoundTripTest()
31 | {
32 | var em = new EntityManager();
33 | var entity = em.CreateEntity();
34 | entity.AddComponent(new Location(){X = 1, Y = 2});
35 | entity.AddComponent();
36 | var prototype = em.GetEntityPrototype(entity);
37 | var protoString = JsonConvert.SerializeObject(prototype);
38 | var newEntity = em.NewEntityFromPrototype(protoString);
39 | var location = newEntity.GetComponent();
40 | Assert.AreEqual(1, location.X);
41 | Assert.AreEqual(2, location.Y);
42 | Assert.AreNotEqual(entity.Id, newEntity.Id);
43 | }
44 |
45 | [Test]
46 | public void CreateRealEntityPrototype()
47 | {
48 | var em = new EntityManager();
49 | var actor1 = CreateActor(em, 0, "Giant Ant", 10, 5, 2, 50, 9.5F);
50 | var actor2 = CreateActor(em, 71, "Goblin", 5, 1, 2, 50);
51 | var actor3 = CreateActor(em, 60, "Kobold");
52 | var serial1 = em.GetEntityPrototype(actor1);
53 | var serial2 = em.GetEntityPrototype(actor2);
54 | var serial3 = em.GetEntityPrototype(actor3);
55 | var dict = new Dictionary>(){
56 | {"Giant Ant", serial1},
57 | {"Goblin", serial2},
58 | {"Kobold", serial3}};
59 | var json = JsonConvert.SerializeObject(dict, Formatting.Indented);
60 | var codebase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
61 | var testPath = (new Uri(Assembly.GetExecutingAssembly().CodeBase)).LocalPath;
62 | var protoTypePath = Path.Combine(Path.GetDirectoryName(testPath), "EntityPrototypes.json");
63 | System.IO.File.WriteAllText(protoTypePath, json);
64 | }
65 |
66 | EntityManager.Entity CreateActor(EntityManager em, int glyph, string name = "actor", int maxHealth = 1,int defense = 1, int power = 1,int accuracy = 70, float speed = 8.0F)
67 | {
68 | var actor = em.CreateEntity();
69 | actor.AddComponent(new Actor(){Gold = 0, Speed = speed});
70 | actor.AddComponent(new AttackStat(){Accuracy = accuracy, Power = power});
71 | actor.AddComponent(new DefenseStat(){Chance = defense});
72 | actor.AddComponent(new Life(){Health = maxHealth, MaxHealth = maxHealth});
73 | actor.AddComponent(new Name(){NameString = name});
74 | actor.AddComponent(new Glyph{glyph = glyph});
75 |
76 | actor.AddComponent(new Faction(){Type = Factions.Monster});
77 | actor.AddComponent();
78 | return actor;
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Test/MockEngine.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using EntityComponentSystemCSharp.Systems;
3 | using MegaDungeon.Contracts;
4 | using RogueSharp;
5 |
6 | namespace EntityComponentSystemCSharp
7 | {
8 | public class MockEngine : IEngine
9 | {
10 | EntityManager _em;
11 | ISystemLogger _logger;
12 | IMap _map;
13 | public MockEngine(EntityManager entityManager, ISystemLogger systemLogger, IMap map)
14 | {
15 | _em = entityManager;
16 | _logger = systemLogger;
17 | _map = map;
18 | }
19 | public EntityManager GetEntityManager()
20 | {
21 | return _em;
22 | }
23 |
24 | public ISystemLogger GetLogger()
25 | {
26 | return _logger;
27 | }
28 |
29 | public IMap GetMap()
30 | {
31 | return _map;
32 | }
33 |
34 | public Point GetPlayerLocation()
35 | {
36 | throw new System.NotImplementedException();
37 | }
38 |
39 | public HashSet GetPlayerViewable()
40 | {
41 | throw new System.NotImplementedException();
42 | }
43 |
44 | public ITileManager GetTileManager()
45 | {
46 | throw new System.NotImplementedException();
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Test/MockLogger.cs:
--------------------------------------------------------------------------------
1 | namespace EntityComponentSystemCSharp
2 | {
3 | public class MockLogger : EntityComponentSystemCSharp.Systems.ISystemLogger
4 | {
5 | public void Log(string message)
6 | {
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Test/ProductionTests.MockMap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RogueSharp;
3 | using System.Collections.Generic;
4 | using System.Collections.ObjectModel;
5 |
6 | namespace EntityComponentSystemCSharp
7 | {
8 |
9 | public class MockMap : RogueSharp.IMap
10 | {
11 | public int Width => 0;
12 |
13 | public int Height => 0;
14 |
15 | public ReadOnlyCollection AppendFov(int xOrigin, int yOrigin, int radius, bool lightWalls)
16 | {
17 | throw new NotImplementedException();
18 | }
19 |
20 | public ICell CellFor(int index)
21 | {
22 | throw new NotImplementedException();
23 | }
24 |
25 | public void Clear()
26 | {
27 | throw new NotImplementedException();
28 | }
29 |
30 | public void Clear(bool isTransparent, bool isWalkable)
31 | {
32 | throw new NotImplementedException();
33 | }
34 |
35 | public IMap Clone()
36 | {
37 | throw new NotImplementedException();
38 | }
39 |
40 | public ReadOnlyCollection ComputeFov(int xOrigin, int yOrigin, int radius, bool lightWalls)
41 | {
42 | throw new NotImplementedException();
43 | }
44 |
45 | public void Copy(IMap sourceMap)
46 | {
47 | throw new NotImplementedException();
48 | }
49 |
50 | public void Copy(IMap sourceMap, int left, int top)
51 | {
52 | throw new NotImplementedException();
53 | }
54 |
55 | public IEnumerable GetAllCells()
56 | {
57 | throw new NotImplementedException();
58 | }
59 |
60 | public IEnumerable GetBorderCellsInCircle(int xCenter, int yCenter, int radius)
61 | {
62 | throw new NotImplementedException();
63 | }
64 |
65 | public IEnumerable GetBorderCellsInDiamond(int xCenter, int yCenter, int distance)
66 | {
67 | throw new NotImplementedException();
68 | }
69 |
70 | public IEnumerable GetBorderCellsInSquare(int xCenter, int yCenter, int distance)
71 | {
72 | throw new NotImplementedException();
73 | }
74 |
75 | public ICell GetCell(int x, int y)
76 | {
77 | throw new NotImplementedException();
78 | }
79 |
80 | public IEnumerable GetCellsAlongLine(int xOrigin, int yOrigin, int xDestination, int yDestination)
81 | {
82 | throw new NotImplementedException();
83 | }
84 |
85 | public IEnumerable GetCellsInCircle(int xCenter, int yCenter, int radius)
86 | {
87 | throw new NotImplementedException();
88 | }
89 |
90 | public IEnumerable GetCellsInColumns(params int[] columnNumbers)
91 | {
92 | throw new NotImplementedException();
93 | }
94 |
95 | public IEnumerable GetCellsInDiamond(int xCenter, int yCenter, int distance)
96 | {
97 | throw new NotImplementedException();
98 | }
99 |
100 | public IEnumerable GetCellsInRows(params int[] rowNumbers)
101 | {
102 | throw new NotImplementedException();
103 | }
104 |
105 | public IEnumerable GetCellsInSquare(int xCenter, int yCenter, int distance)
106 | {
107 | throw new NotImplementedException();
108 | }
109 |
110 | public int IndexFor(int x, int y)
111 | {
112 | throw new NotImplementedException();
113 | }
114 |
115 | public int IndexFor(ICell cell)
116 | {
117 | throw new NotImplementedException();
118 | }
119 |
120 | public void Initialize(int width, int height)
121 | {
122 | throw new NotImplementedException();
123 | }
124 |
125 | public bool IsExplored(int x, int y)
126 | {
127 | throw new NotImplementedException();
128 | }
129 |
130 | public bool IsInFov(int x, int y)
131 | {
132 | throw new NotImplementedException();
133 | }
134 |
135 | public bool IsTransparent(int x, int y)
136 | {
137 | throw new NotImplementedException();
138 | }
139 |
140 | public bool IsWalkable(int x, int y)
141 | {
142 | throw new NotImplementedException();
143 | }
144 |
145 | public void Restore(MapState state)
146 | {
147 | throw new NotImplementedException();
148 | }
149 |
150 | public MapState Save()
151 | {
152 | throw new NotImplementedException();
153 | }
154 |
155 | public void SetCellProperties(int x, int y, bool isTransparent, bool isWalkable, bool isExplored)
156 | {
157 | throw new NotImplementedException();
158 | }
159 |
160 | public void SetCellProperties(int x, int y, bool isTransparent, bool isWalkable)
161 | {
162 | throw new NotImplementedException();
163 | }
164 |
165 | public string ToString(bool useFov)
166 | {
167 | throw new NotImplementedException();
168 | }
169 | }
170 |
171 | }
172 |
173 |
--------------------------------------------------------------------------------
/EntityComponentSystemCSharp/Test/ProductionTests.cs:
--------------------------------------------------------------------------------
1 | using NUnit.Framework;
2 | using EntityComponentSystemCSharp.Components;
3 | using EntityComponentSystemCSharp.Systems;
4 | using System.Linq;
5 |
6 | namespace EntityComponentSystemCSharp
7 | {
8 |
9 | public partial class ProductionSystemTests
10 | {
11 | MockEngine _mockEngine;
12 | [OneTimeSetUp]
13 | public void OneTimeSetUp()
14 | {
15 | _mockEngine = new MockEngine(new EntityManager(), new MockLogger(), new MockMap());
16 | }
17 |
18 | [Test]
19 | public void ConstructorTest()
20 | {
21 | var mockEngine = new MockEngine(new EntityManager(), new MockLogger(), new MockMap());
22 | var productionSystem = new ProductionSystem(mockEngine);
23 | }
24 |
25 | [Test]
26 | public void ProductionTest()
27 | {
28 | var em = new EntityManager();
29 | var entity = em.CreateEntity();
30 | var producer = CreateWidgetFactory();
31 | entity.AddComponent( producer);
32 |
33 | var inventory = new Inventory();
34 | entity.AddComponent( inventory);
35 |
36 | var productionSystem = new ProductionSystem(_mockEngine);
37 | productionSystem.Run(entity);
38 |
39 | Assert.AreEqual(11, inventory.Items.Count);
40 | }
41 |
42 |
43 | [Test]
44 | public void InventoryLimitTest()
45 | {
46 | var em = new EntityManager();
47 | var entity = em.CreateEntity();
48 | var producer = CreateWidgetFactory();
49 | entity.AddComponent(producer);
50 |
51 | var inventory = new Inventory();
52 | inventory.Size = 10;
53 | entity.AddComponent( inventory);
54 |
55 | var productionSystem = new ProductionSystem(_mockEngine);
56 | productionSystem.Run(entity);
57 | Assert.AreEqual(10, inventory.Items.Count);
58 | }
59 |
60 | [Test]
61 | public void ProducedItemNameTest()
62 | {
63 | var em = new EntityManager();
64 | var entity = em.CreateEntity();
65 | var producer = CreateWidgetFactory();
66 | entity.AddComponent( producer);
67 | var inventory = new Inventory();
68 | inventory.Size = 10;
69 | entity.AddComponent( inventory);
70 | var productionSystem = new ProductionSystem(_mockEngine);
71 | productionSystem.Run(entity);
72 |
73 | var item = inventory.Items[0];
74 | var name = item.GetComponent
- ().Type;
75 | Assert.AreEqual(name, producer.ProducedItems[0].product);
76 | }
77 |
78 | [Test]
79 | public void DemandTest()
80 | {
81 | var em = new EntityManager();
82 | var entity = em.CreateEntity();
83 | var producer = CreateWidgetFactory();
84 | entity.AddComponent(producer);
85 | var inventory = new Inventory();
86 | inventory.Size = 10;
87 | entity.AddComponent( inventory);
88 | var productionSystem = new ProductionSystem(_mockEngine);
89 | productionSystem.Run(entity);
90 |
91 | var demand = new Demand();
92 | demand.Demands.Add("widget", 1);
93 | entity.AddComponent( demand);
94 | var demandSystem = new DemandSystem(_mockEngine);
95 | demandSystem.Run(entity);
96 |
97 | Assert.Less(inventory.Items.Count, 10);
98 | }
99 |
100 | [Test]
101 | public void StackSystemTest()
102 | {
103 | var em = new EntityManager();
104 | var entity = em.CreateEntity();
105 | var inventory = new Inventory();
106 | entity.AddComponent(inventory);
107 | var itemEntity = em.CreateEntity();
108 | var itemComponent = new Item(){Type = "widget"};
109 | itemEntity.AddComponent();
110 | itemEntity.AddComponent(itemComponent);
111 | inventory.Items.Add(itemEntity);
112 |
113 | itemEntity = em.CreateEntity();
114 | itemEntity.AddComponent(itemComponent);
115 | itemEntity.AddComponent();
116 | inventory.Items.Add(itemEntity);
117 |
118 | var stackSystem = new StackSystem(_mockEngine);
119 | var stacks = stackSystem.GetStacks(entity);
120 |
121 | Assert.AreEqual(2, stacks["widget"]);
122 | }
123 |
124 | // * //////////////// Helpers /////////////////
125 | Producer CreateWidgetFactory()
126 | {
127 | var producer = new Producer();
128 | var item = new Producer.ProductionItem(){product = "widget", rate = 11};
129 | producer.ProducedItems.Add(item);
130 | return producer;
131 | }
132 |
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/EntityPrototypes.json:
--------------------------------------------------------------------------------
1 | {
2 | "Giant Ant": {
3 | "Actor": {
4 | "Speed": 9.5,
5 | "Gold": 0,
6 | "Energy": 0.0
7 | },
8 | "AttackStat": {
9 | "Power": 2,
10 | "Accuracy": 50
11 | },
12 | "DefenseStat": {
13 | "Chance": 5
14 | },
15 | "Life": {
16 | "Health": 10,
17 | "MaxHealth": 10
18 | },
19 | "Name": {
20 | "NameString": "Giant Ant"
21 | },
22 | "Glyph": {
23 | "glyph": 0
24 | },
25 | "Faction": {
26 | "Type": 2
27 | },
28 | "WanderingMonster": {}
29 | },
30 | "Goblin": {
31 | "Actor": {
32 | "Speed": 8.0,
33 | "Gold": 0,
34 | "Energy": 0.0
35 | },
36 | "AttackStat": {
37 | "Power": 2,
38 | "Accuracy": 50
39 | },
40 | "DefenseStat": {
41 | "Chance": 1
42 | },
43 | "Life": {
44 | "Health": 5,
45 | "MaxHealth": 5
46 | },
47 | "Name": {
48 | "NameString": "Goblin"
49 | },
50 | "Glyph": {
51 | "glyph": 71
52 | },
53 | "Faction": {
54 | "Type": 2
55 | },
56 | "WanderingMonster": {}
57 | },
58 | "Kobold": {
59 | "Actor": {
60 | "Speed": 8.0,
61 | "Gold": 0,
62 | "Energy": 0.0
63 | },
64 | "AttackStat": {
65 | "Power": 1,
66 | "Accuracy": 70
67 | },
68 | "DefenseStat": {
69 | "Chance": 1
70 | },
71 | "Life": {
72 | "Health": 1,
73 | "MaxHealth": 1
74 | },
75 | "Name": {
76 | "NameString": "Kobold"
77 | },
78 | "Glyph": {
79 | "glyph": 60
80 | },
81 | "Faction": {
82 | "Type": 2
83 | },
84 | "WanderingMonster": {}
85 | }
86 | }
--------------------------------------------------------------------------------
/FeatureDetector/DetectorTests.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using NUnit.Framework;
3 |
4 | namespace FeatureDetector
5 | {
6 | [TestFixture]
7 | public class DetectorTests
8 | {
9 | [Test]
10 | public void ConstructorTest()
11 | {
12 | var detector = new MapFeatureDetector(mapIntArray);
13 | }
14 |
15 | [Test]
16 | public void FindWallsTest()
17 | {
18 | var detector = new MapFeatureDetector(mapIntArray);
19 | var walls = detector.FindWalls();
20 | Debug.WriteLine(detector.ToMapString(walls));
21 | Assert.AreEqual(1, walls[12,45]);
22 | Assert.AreEqual(1, walls[12,27]);
23 | Assert.AreEqual(1, walls[13,27]);
24 | Assert.AreEqual(1, walls[14,27]);
25 | Assert.AreEqual(1, walls[20,34]);
26 | Assert.AreEqual(1, walls[8,30]);
27 | Assert.AreEqual(1, walls[8,31]);
28 | Assert.AreEqual(1, walls[8,32]);
29 | Assert.AreEqual(1, walls[8,33]);
30 | Assert.AreEqual(1, walls[8,34]);
31 | Assert.AreEqual(1, walls[8,35]);
32 | }
33 |
34 |
35 | [Test]
36 | public void FindDoorwaysTest()
37 | {
38 | var detector = new MapFeatureDetector(mapIntArray);
39 | var doorways = detector.FindDoorways();
40 | Debug.WriteLine(detector.ToMapString(doorways));
41 |
42 | Assert.AreEqual(2, doorways[19, 21]);
43 | Assert.AreEqual(3, doorways[29, 28]);
44 | Assert.AreEqual(4, doorways[34, 24]);
45 | Assert.AreEqual(0, doorways[23, 43]);
46 | }
47 |
48 | [Test]
49 | public void Temp()
50 | {
51 | var detector = new MapFeatureDetector(mapIntArray);
52 | var conv = MapFeatureDetector.ConvolveFilter(mapIntArray, FeatureFilters.NeighborCount);
53 | IterateMaps(detector, conv);
54 | }
55 |
56 | [Test]
57 | public void GetApproximateRoomCenter()
58 | {
59 | var regions = MapFeatureDetector.GetRegions(mapIntArray);
60 | var approxCenter = MapFeatureDetector.GetApproximateRoomCenter(regions, 2);
61 | }
62 |
63 | private static void IterateMaps(MapFeatureDetector detector, int[,] conv)
64 | {
65 | var min = conv.Min();
66 | var max = conv.Max();
67 | for (int i = min; i <= max; i++)
68 | {
69 | var splats = detector.FilterArray(conv, i);
70 | if(splats.Total() > 0)
71 | {
72 | Debug.WriteLine(i);
73 | Debug.WriteLine(detector.ToMapString(splats));
74 | }
75 | }
76 | }
77 |
78 |
79 | [Test]
80 | public void FloodFillTest()
81 | {
82 | var testArray = (int[,]) mapIntArray.Clone();
83 | MapFeatureDetector.AdamMilFill(testArray, 10, 9);
84 | Assert.AreEqual(1, testArray[10, 9]);
85 | }
86 |
87 | [Test]
88 | public void RegionTest()
89 | {
90 | var regionArray = MapFeatureDetector.GetRegions(mapIntArray);
91 | Debug.WriteLine(regionArray.ToRowString(asMap: true));
92 | Assert.AreEqual(3, regionArray[12,9]);
93 | Assert.AreEqual(4, regionArray[27,14]);
94 | Assert.AreEqual(2, regionArray[23,56]);
95 | }
96 |
97 |
98 | int[,] mapIntArray = new int[,]{
99 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
100 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
101 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
102 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
103 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
104 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
105 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
106 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
107 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
108 | {1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
109 | {1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
110 | {1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
111 | {1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
112 | {1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
113 | {1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
114 | {1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
115 | {1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
116 | {1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
117 | {1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
118 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
119 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1},
120 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1},
121 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
122 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
123 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1},
124 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1},
125 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1},
126 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1},
127 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1},
128 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1},
129 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1},
130 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1},
131 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1},
132 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1},
133 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1},
134 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1},
135 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
136 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
137 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
138 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}};
139 |
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/FeatureDetector/FeatureDetector.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard20;net461
5 | $(SolutionDir)\bin\$(Configuration)\$(AssemblyName)\
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/FeatureDetector/FeatureFilters.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace FeatureDetector
7 | {
8 | public static class FeatureFilters
9 | {
10 | // 1 == impassable/wall
11 | public static int[,] Vertical = new int[,]{
12 | {-1, 4,-1},
13 | {-1, 4,-1},
14 | {-1, 4,-1}
15 | };
16 |
17 | public static int[,] Doorway = new int[,]{
18 | { -2,-16,-2},
19 | { 2,-16, 2},
20 | { 2,-16, 2},
21 | };
22 |
23 | public static int[,] OuterCorner = new int[,]{
24 | { 0,-32,-32},
25 | { 8, 8,-32},
26 | { 8, 8, 0},
27 | };
28 |
29 | public static int[,] InnerCorner = new int[,]{
30 | { 4, 4,-8},
31 | { 4, 4, 4},
32 | { 4, 4, 4},
33 | };
34 |
35 | public static int[,] NeighborCount = new int[,]{
36 | { 1, 1, 1},
37 | { 1, 0, 1},
38 | { 1, 1, 1},
39 | };
40 |
41 | public static int[,] Identity = new int[,]{
42 | {0,0,0},
43 | {0,1,0},
44 | {0,0,0}
45 | };
46 |
47 | public static int[,] Rotate180Degrees(int[,] oldMatrix)
48 | {
49 | int[,] newMatrix = Rotate90CCW(oldMatrix);
50 | newMatrix = Rotate90CCW(newMatrix);
51 | return newMatrix;
52 | }
53 |
54 | public static int[,] Rotate90CCW(int[,] oldMatrix)
55 | {
56 | int[,] newMatrix = new int[oldMatrix.GetLength(1), oldMatrix.GetLength(0)];
57 | int newColumn, newRow = 0;
58 | for (int oldColumn = oldMatrix.GetLength(1) - 1; oldColumn >= 0; oldColumn--)
59 | {
60 | newColumn = 0;
61 | for (int oldRow = 0; oldRow < oldMatrix.GetLength(0); oldRow++)
62 | {
63 | newMatrix[newRow, newColumn] = oldMatrix[oldRow, oldColumn];
64 | newColumn++;
65 | }
66 | newRow++;
67 | }
68 | return newMatrix;
69 | }
70 |
71 | ///
72 | /// Matrix multiply two int[]
73 | ///
74 | ///
75 | ///
76 | /// Matrix of multiplied values
77 | public static int[] MultiplyFilter(int[] sample, int[] filter)
78 | {
79 | if (sample.Length != filter.Length)
80 | {
81 | throw new ArgumentException("sample and filter must be the same size.");
82 | }
83 | var outArray = new int[filter.Length];
84 | for (int i = 0; i < filter.Length; i++)
85 | {
86 | outArray[i] = sample[i] * filter[i];
87 | }
88 | return outArray;
89 | }
90 |
91 | public static string ToFilterString(int[,] filter)
92 | {
93 | var sb = new StringBuilder();
94 | for (int i = 0; i < filter.GetLength(0); i++)
95 | {
96 | for (int j = 0; j < filter.GetLength(1); j++)
97 | {
98 | sb.Append($"{filter[i, j]:##}");
99 | }
100 | sb.AppendLine();
101 | }
102 | return sb.ToString();
103 | }
104 | }
105 |
106 | public static class GridExtentsions
107 | {
108 | public static void UpDate(this int[,] grid, Func action)
109 | {
110 | if (grid.Rank != 2)
111 | {
112 | throw new NotImplementedException("Only valid on 2D arrays.");
113 | }
114 |
115 | for (int i = 0; i < grid.GetLength(0); i++)
116 | {
117 | for (int j = 0; j < grid.GetLength(1); j++)
118 | {
119 | grid[i, j] = action(grid[i, j]);
120 | }
121 | }
122 | }
123 |
124 |
125 | ///
126 | /// Total the array elements
127 | ///
128 | ///
129 | ///
130 | public static int Total(this int[] array)
131 | {
132 | var total = 0;
133 | for (int i = 0; i < array.Length; i++)
134 | {
135 | total += array[i];
136 | }
137 | return total;
138 | }
139 |
140 | ///
141 | /// Total the array elements
142 | ///
143 | ///
144 | ///
145 | public static int Total(this int[,] array)
146 | {
147 | var total = 0;
148 | for (int i = 0; i < array.GetLength(0); i++)
149 | {
150 | for (int j = 0; j < array.GetLength(1); j++)
151 | {
152 | total += array[i, j];
153 | }
154 | }
155 | return total;
156 | }
157 |
158 | public static int Min(this int[,] array)
159 | {
160 | var min = int.MaxValue;
161 | for (int i = 0; i < array.GetLength(0); i++)
162 | {
163 | for (int j = 0; j < array.GetLength(1); j++)
164 | {
165 | min = Math.Min(array[i, j], min);
166 | }
167 | }
168 | return min;
169 | }
170 |
171 | public static int Max(this int[,] array)
172 | {
173 | var max = int.MinValue;
174 | for (int i = 0; i < array.GetLength(0); i++)
175 | {
176 | for (int j = 0; j < array.GetLength(1); j++)
177 | {
178 | max = Math.Max(array[i, j], max);
179 | }
180 | }
181 | return max;
182 | }
183 |
184 | public static int[] UniqueValues (this int[,] array)
185 | {
186 | var flat = array.Flatten();
187 | var hashSet = new HashSet();
188 | foreach(var v in flat)
189 | {
190 | hashSet.Add(v);
191 | }
192 | return hashSet.ToArray();
193 | }
194 |
195 | ///
196 | /// Pointwise multiply two int[,] arrays
197 | ///
198 | ///
199 | ///
200 | ///
201 | public static int[,] Multiply(this int[,] a, int[,] b)
202 | {
203 | // TODO: Check arrays are same shape.
204 | var outArr = (int[,]) a.Clone();
205 | for (int x = 0; x < a.GetLength(0); x++)
206 | {
207 | for (int y = 0; y < a.GetLength(1); y++)
208 | {
209 | outArr[x,y] = a[x,y] * b[x,y];
210 | }
211 |
212 | }
213 | return outArr;
214 | }
215 |
216 | public static byte[] FlattenToByteArray(this int[,] sample)
217 | {
218 | var width = sample.GetLength(0);
219 | var height = sample.GetLength(1);
220 | byte[] flat = new byte[width * height];
221 | for (int i = 0; i < width; i++)
222 | {
223 | for (int j = 0; j < height; j++)
224 | {
225 | if(sample[i,j] > byte.MaxValue || sample[i,j] < byte.MinValue)
226 | {
227 | throw new IndexOutOfRangeException($"[{i},{j}] == '{sample[i,j]}' out of range for byte conversion");
228 | }
229 | flat[i + (j * width)] = (byte)sample[i, j];
230 | }
231 | }
232 | return flat;
233 | }
234 | public static int[] Flatten(this int[,] sample)
235 | {
236 | var width = sample.GetLength(0);
237 | var height = sample.GetLength(1);
238 | int[] flat = new int[width * height];
239 | for (int i = 0; i < width; i++)
240 | {
241 | for (int j = 0; j < height; j++)
242 | {
243 | flat[i + (j * width)] = sample[i, j];
244 | }
245 | }
246 | return flat;
247 | }
248 |
249 | public static string ToRowString(this int[,] sample, bool asMap = false)
250 | {
251 | var rows = sample.GetLength(1);
252 | var flat = sample.Flatten();
253 | return flat.ToRowString(rows, asMap);
254 | }
255 |
256 | ///
257 | /// Returns an array as a grid of numRows
258 | ///
259 | ///
260 | ///
261 | /// String representation
262 | public static string ToRowString(this int[] sample, int numRows, bool asMap = false)
263 | {
264 | var sb = new StringBuilder();
265 | var perRow = sample.Length / numRows;
266 | for (int i = 0; i < sample.Length; i++)
267 | {
268 | var output = sample[i].ToString();
269 | if (asMap)
270 | {
271 | output = sample[i] == 0 ? "." : "#";
272 | if (sample[i] > 1)
273 | {
274 | output = sample[i].ToString();
275 | }
276 | }
277 |
278 | sb.Append(output);
279 | if (i < sample.Length - 1 && !asMap)
280 | {
281 | sb.Append(", ");
282 | }
283 | if ((i + 1) % perRow == 0)
284 | {
285 | sb.AppendLine();
286 | }
287 | }
288 | sb.AppendLine();
289 | return sb.ToString();
290 | }
291 | }
292 | }
--------------------------------------------------------------------------------
/InventionHackGameplay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionHackGameplay.gif
--------------------------------------------------------------------------------
/InventionUiAndroid/InventionUiAndroid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {7FA2F095-811B-4018-8C3A-8A0E8E1453D5}
9 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
10 | {122416d6-6b49-4ee2-a1e8-b825f31c79fe}
11 | Library
12 | Properties
13 | InventionUiAndroid
14 | InventionUiAndroid
15 | 512
16 | True
17 | Resources\Resource.designer.cs
18 | Resource
19 | Off
20 | false
21 | v9.0
22 | Properties\AndroidManifest.xml
23 | Resources
24 | Assets
25 | true
26 | true
27 | Xamarin.Android.Net.AndroidClientHandler
28 |
29 |
30 | True
31 | portable
32 | False
33 | bin\Debug\
34 | DEBUG;TRACE
35 | prompt
36 | 4
37 | True
38 | None
39 | False
40 |
41 |
42 | True
43 | portable
44 | True
45 | bin\Release\
46 | TRACE
47 | prompt
48 | 4
49 | true
50 | False
51 | SdkOnly
52 | True
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | Assets\tiledata.json
70 |
71 |
72 |
73 |
74 |
75 | Designer
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | 1.0.50
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | {5c3415f8-c59a-4c93-85fb-c373cbff34fe}
114 | Portable
115 |
116 |
117 |
118 |
119 | Assets\absurd64.bmp
120 |
121 |
122 |
123 |
130 |
--------------------------------------------------------------------------------
/InventionUiAndroid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | namespace InventionUiAndroid
2 | {
3 | [Android.App.Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true, ConfigurationChanges = Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
4 | public class MainActivity : Inv.AndroidActivity
5 | {
6 | protected override void Install(Inv.Application Application)
7 | {
8 | Portable.Shell.Install(Application);
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/InventionUiAndroid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using Android.App;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("InventionUiAndroid")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("InventionUiAndroid")]
14 | [assembly: AssemblyCopyright("Copyright © 2018")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: ComVisible(false)]
18 |
19 | // Version information for an assembly consists of the following four values:
20 | //
21 | // Major Version
22 | // Minor Version
23 | // Build Number
24 | // Revision
25 | //
26 | // You can specify all the values or you can default the Build and Revision Numbers
27 | // by using the '*' as shown below:
28 | // [assembly: AssemblyVersion("1.0.*")]
29 | [assembly: AssemblyVersion("1.0.0.0")]
30 | [assembly: AssemblyFileVersion("1.0.0.0")]
31 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiAndroid/Resources/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2c3e50
4 | #1B3147
5 | #3498db
6 |
7 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2C3E50
4 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | InventionUiAndroid
3 | Settings
4 |
5 |
--------------------------------------------------------------------------------
/InventionUiAndroid/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/InventionUiUwp/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InventionUiUwp/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Controls.Primitives;
13 | using Windows.UI.Xaml.Data;
14 | using Windows.UI.Xaml.Input;
15 | using Windows.UI.Xaml.Media;
16 | using Windows.UI.Xaml.Navigation;
17 |
18 | namespace InventionUiUwp
19 | {
20 | ///
21 | /// Provides application-specific behavior to supplement the default Application class.
22 | ///
23 | sealed partial class App : Application
24 | {
25 | ///
26 | /// Initializes the singleton application object. This is the first line of authored code
27 | /// executed, and as such is the logical equivalent of main() or WinMain().
28 | ///
29 | public App()
30 | {
31 | this.InitializeComponent();
32 | this.Suspending += OnSuspending;
33 | }
34 |
35 | ///
36 | /// Invoked when the application is launched normally by the end user. Other entry points
37 | /// will be used such as when the application is launched to open a specific file.
38 | ///
39 | /// Details about the launch request and process.
40 | protected override void OnLaunched(LaunchActivatedEventArgs e)
41 | {
42 | Frame rootFrame = Window.Current.Content as Frame;
43 |
44 | // Do not repeat app initialization when the Window already has content,
45 | // just ensure that the window is active
46 | if (rootFrame == null)
47 | {
48 | // Create a Frame to act as the navigation context and navigate to the first page
49 | rootFrame = new Frame();
50 |
51 | rootFrame.NavigationFailed += OnNavigationFailed;
52 |
53 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
54 | {
55 | //TODO: Load state from previously suspended application
56 | }
57 |
58 | // Place the frame in the current Window
59 | Window.Current.Content = rootFrame;
60 | }
61 |
62 | if (e.PrelaunchActivated == false)
63 | {
64 | if (rootFrame.Content == null)
65 | {
66 | // When the navigation stack isn't restored navigate to the first page,
67 | // configuring the new page by passing required information as a navigation
68 | // parameter
69 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
70 | }
71 | // Ensure the current window is active
72 | Window.Current.Activate();
73 | }
74 | }
75 |
76 | ///
77 | /// Invoked when Navigation to a certain page fails
78 | ///
79 | /// The Frame which failed navigation
80 | /// Details about the navigation failure
81 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
82 | {
83 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
84 | }
85 |
86 | ///
87 | /// Invoked when application execution is being suspended. Application state is saved
88 | /// without knowing whether the application will be terminated or resumed with the contents
89 | /// of memory still intact.
90 | ///
91 | /// The source of the suspend request.
92 | /// Details about the suspend request.
93 | private void OnSuspending(object sender, SuspendingEventArgs e)
94 | {
95 | var deferral = e.SuspendingOperation.GetDeferral();
96 | //TODO: Save application state and stop any background activity
97 | deferral.Complete();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/InventionUiUwp/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiUwp/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/InventionUiUwp/InventionUiUwp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {268B3734-8A91-42E7-B475-F429B924EE94}
8 | AppContainerExe
9 | Properties
10 | InventionUiUwp
11 | InventionUiUwp
12 | en-US
13 | UAP
14 | 10.0.18362.0
15 | 10.0.16299.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | true
20 | false
21 |
22 |
23 | true
24 | bin\x86\Debug\
25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
26 | ;2008
27 | full
28 | x86
29 | false
30 | prompt
31 | true
32 |
33 |
34 | bin\x86\Release\
35 | TRACE;NETFX_CORE;WINDOWS_UWP
36 | true
37 | ;2008
38 | pdbonly
39 | x86
40 | false
41 | prompt
42 | true
43 | true
44 |
45 |
46 | true
47 | bin\ARM\Debug\
48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
49 | ;2008
50 | full
51 | ARM
52 | false
53 | prompt
54 | true
55 |
56 |
57 | bin\ARM\Release\
58 | TRACE;NETFX_CORE;WINDOWS_UWP
59 | true
60 | ;2008
61 | pdbonly
62 | ARM
63 | false
64 | prompt
65 | true
66 | true
67 |
68 |
69 | true
70 | bin\ARM64\Debug\
71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
72 | ;2008
73 | full
74 | ARM64
75 | false
76 | prompt
77 | true
78 | true
79 |
80 |
81 | bin\ARM64\Release\
82 | TRACE;NETFX_CORE;WINDOWS_UWP
83 | true
84 | ;2008
85 | pdbonly
86 | ARM64
87 | false
88 | prompt
89 | true
90 | true
91 |
92 |
93 | true
94 | bin\x64\Debug\
95 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
96 | ;2008
97 | full
98 | x64
99 | false
100 | prompt
101 | true
102 |
103 |
104 | bin\x64\Release\
105 | TRACE;NETFX_CORE;WINDOWS_UWP
106 | true
107 | ;2008
108 | pdbonly
109 | x64
110 | false
111 | prompt
112 | true
113 | true
114 |
115 |
116 | PackageReference
117 |
118 |
119 |
120 | App.xaml
121 |
122 |
123 | MainPage.xaml
124 |
125 |
126 |
127 |
128 |
129 | Designer
130 |
131 |
132 |
133 |
134 | Assets\absurd64.bmp
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 | MSBuild:Compile
148 | Designer
149 |
150 |
151 | MSBuild:Compile
152 | Designer
153 |
154 |
155 |
156 |
157 | 1.0.50
158 |
159 |
160 | 6.2.9
161 |
162 |
163 |
164 |
165 | {5c3415f8-c59a-4c93-85fb-c373cbff34fe}
166 | Portable
167 |
168 |
169 |
170 |
171 | Assets\tiledata.json
172 |
173 |
174 |
175 | 14.0
176 |
177 |
178 |
185 |
--------------------------------------------------------------------------------
/InventionUiUwp/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/InventionUiUwp/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
2 |
3 | namespace InventionUiUwp
4 | {
5 | ///
6 | /// An empty page that can be used on its own or navigated to within a Frame.
7 | ///
8 | public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page
9 | {
10 | public MainPage()
11 | {
12 | this.InitializeComponent();
13 |
14 | Inv.UwaShell.Attach(this, Portable.Shell.Install);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/InventionUiUwp/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | InventionUiUwp
18 | callanh
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/InventionUiUwp/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("InventionUiUwp")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("InventionUiUwp")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/InventionUiUwp/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/InventionUiWpf/InventionUiWpf.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net461
6 | true
7 | $(SolutionDir)\bin\$(Configuration)\$(AssemblyName)\
8 | x64
9 | portable
10 |
11 |
12 |
13 |
14 | PreserveNewest
15 |
16 |
17 | PreserveNewest
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/InventionUiWpf/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace InventionUiWpf
4 | {
5 | public class Program
6 | {
7 | [STAThread]
8 | static void Main(string[] args)
9 | {
10 | Inv.WpfShell.CheckRequirements(
11 | () =>
12 | {
13 | // #if DEBUG
14 | // Inv.WpfShell.Options.PreventDeviceEmulation = false;
15 | // Inv.WpfShell.Options.DeviceEmulation = Inv.WpfDeviceEmulation.iPad_Mini;
16 | // #endif
17 | Inv.WpfShell.Options.FullScreenMode = false;
18 | Inv.WpfShell.Options.DefaultWindowWidth = 800;
19 | Inv.WpfShell.Options.DefaultWindowHeight = 600;
20 | Inv.WpfShell.Run(Portable.Shell.Install);
21 | });
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/InventionUiWpf/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/InventionUiiOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 |
4 | namespace InventionUiiOS
5 | {
6 | // The UIApplicationDelegate for the application. This class is responsible for launching the
7 | // User Interface of the application, as well as listening (and optionally responding) to application events from iOS.
8 | [Register("AppDelegate")]
9 | public class AppDelegate : UIApplicationDelegate
10 | {
11 | // class-level declarations
12 |
13 | public override UIWindow Window
14 | {
15 | get;
16 | set;
17 | }
18 |
19 | public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
20 | {
21 | // create a new window instance based on the screen size
22 | Window = new UIWindow(UIScreen.MainScreen.Bounds);
23 | Window.RootViewController = new UIViewController();
24 |
25 | // make the window visible
26 | Window.MakeKeyAndVisible();
27 |
28 | return true;
29 | }
30 |
31 | public override void OnResignActivation(UIApplication application)
32 | {
33 | // Invoked when the application is about to move from active to inactive state.
34 | // This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
35 | // or when the user quits the application and it begins the transition to the background state.
36 | // Games should use this method to pause the game.
37 | }
38 |
39 | public override void DidEnterBackground(UIApplication application)
40 | {
41 | // Use this method to release shared resources, save user data, invalidate timers and store the application state.
42 | // If your application supports background execution this method is called instead of WillTerminate when the user quits.
43 | }
44 |
45 | public override void WillEnterForeground(UIApplication application)
46 | {
47 | // Called as part of the transition from background to active state.
48 | // Here you can undo many of the changes made on entering the background.
49 | }
50 |
51 | public override void OnActivated(UIApplication application)
52 | {
53 | // Restart any tasks that were paused (or not yet started) while the application was inactive.
54 | // If the application was previously in the background, optionally refresh the user interface.
55 | }
56 |
57 | public override void WillTerminate(UIApplication application)
58 | {
59 | // Called when the application is about to terminate. Save data, if needed. See also DidEnterBackground.
60 | }
61 | }
62 | }
63 |
64 |
65 |
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "scale": "2x",
5 | "size": "20x20",
6 | "idiom": "iphone",
7 | "filename": "Icon40.png"
8 | },
9 | {
10 | "scale": "3x",
11 | "size": "20x20",
12 | "idiom": "iphone",
13 | "filename": "Icon60.png"
14 | },
15 | {
16 | "scale": "2x",
17 | "size": "29x29",
18 | "idiom": "iphone",
19 | "filename": "Icon58.png"
20 | },
21 | {
22 | "scale": "3x",
23 | "size": "29x29",
24 | "idiom": "iphone",
25 | "filename": "Icon87.png"
26 | },
27 | {
28 | "scale": "2x",
29 | "size": "40x40",
30 | "idiom": "iphone",
31 | "filename": "Icon80.png"
32 | },
33 | {
34 | "scale": "3x",
35 | "size": "40x40",
36 | "idiom": "iphone",
37 | "filename": "Icon120.png"
38 | },
39 | {
40 | "scale": "2x",
41 | "size": "60x60",
42 | "idiom": "iphone",
43 | "filename": "Icon120.png"
44 | },
45 | {
46 | "scale": "3x",
47 | "size": "60x60",
48 | "idiom": "iphone",
49 | "filename": "Icon180.png"
50 | },
51 | {
52 | "scale": "1x",
53 | "size": "20x20",
54 | "idiom": "ipad",
55 | "filename": "Icon20.png"
56 | },
57 | {
58 | "scale": "2x",
59 | "size": "20x20",
60 | "idiom": "ipad",
61 | "filename": "Icon40.png"
62 | },
63 | {
64 | "scale": "1x",
65 | "size": "29x29",
66 | "idiom": "ipad",
67 | "filename": "Icon29.png"
68 | },
69 | {
70 | "scale": "2x",
71 | "size": "29x29",
72 | "idiom": "ipad",
73 | "filename": "Icon58.png"
74 | },
75 | {
76 | "scale": "1x",
77 | "size": "40x40",
78 | "idiom": "ipad",
79 | "filename": "Icon40.png"
80 | },
81 | {
82 | "scale": "2x",
83 | "size": "40x40",
84 | "idiom": "ipad",
85 | "filename": "Icon80.png"
86 | },
87 | {
88 | "scale": "1x",
89 | "size": "76x76",
90 | "idiom": "ipad",
91 | "filename": "Icon76.png"
92 | },
93 | {
94 | "scale": "2x",
95 | "size": "76x76",
96 | "idiom": "ipad",
97 | "filename": "Icon152.png"
98 | },
99 | {
100 | "scale": "2x",
101 | "size": "83.5x83.5",
102 | "idiom": "ipad",
103 | "filename": "Icon167.png"
104 | },
105 | {
106 | "scale": "1x",
107 | "size": "1024x1024",
108 | "idiom": "ios-marketing",
109 | "filename": "Icon1024.png"
110 | }
111 | ],
112 | "properties": {},
113 | "info": {
114 | "version": 1,
115 | "author": "xcode"
116 | }
117 | }
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon120.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon152.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon167.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon180.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon20.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon29.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon40.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon58.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon58.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon60.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon76.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon80.png
--------------------------------------------------------------------------------
/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon87.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/InventionUiiOS/Assets.xcassets/AppIcon.appiconset/Icon87.png
--------------------------------------------------------------------------------
/InventionUiiOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/InventionUiiOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | InventionUiiOS
7 | CFBundleIdentifier
8 | com.companyname.InventionUiiOS
9 | CFBundleShortVersionString
10 | 1.0
11 | CFBundleVersion
12 | 1.0
13 | LSRequiresIPhoneOS
14 |
15 | MinimumOSVersion
16 | 8.0
17 | UIDeviceFamily
18 |
19 | 1
20 | 2
21 |
22 | UILaunchStoryboardName
23 | LaunchScreen
24 | UIRequiredDeviceCapabilities
25 |
26 | armv7
27 |
28 | UISupportedInterfaceOrientations
29 |
30 | UIInterfaceOrientationPortrait
31 | UIInterfaceOrientationLandscapeLeft
32 | UIInterfaceOrientationLandscapeRight
33 |
34 | UISupportedInterfaceOrientations~ipad
35 |
36 | UIInterfaceOrientationPortrait
37 | UIInterfaceOrientationPortraitUpsideDown
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | XSAppIconAssets
42 | Assets.xcassets/AppIcon.appiconset
43 |
44 |
--------------------------------------------------------------------------------
/InventionUiiOS/InventionUiiOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | {F162B517-8CA6-43CA-A86C-611E6027AAE8}
7 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
8 | {440aa056-593a-4519-8708-27081dee632f}
9 | Exe
10 | InventionUiiOS
11 | Resources
12 | InventionUiiOS
13 | true
14 | NSUrlSessionHandler
15 | PackageReference
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\iPhoneSimulator\Debug
22 | DEBUG
23 | prompt
24 | 4
25 | x86_64
26 | None
27 | true
28 | true
29 |
30 |
31 | none
32 | true
33 | bin\iPhoneSimulator\Release
34 | prompt
35 | 4
36 | None
37 | x86_64
38 |
39 |
40 | true
41 | full
42 | false
43 | bin\iPhone\Debug
44 | DEBUG
45 | prompt
46 | 4
47 | ARM64
48 | Entitlements.plist
49 | iPhone Developer
50 | true
51 |
52 |
53 | none
54 | true
55 | bin\iPhone\Release
56 | prompt
57 | 4
58 | Entitlements.plist
59 | ARM64
60 | iPhone Developer
61 |
62 |
63 |
64 |
65 |
66 | Resources\tiledata.json
67 |
68 |
69 |
70 |
71 | Resources\absurd64.bmp
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | 1.0.50
87 |
88 |
89 |
90 |
91 |
92 | false
93 |
94 |
95 | false
96 |
97 |
98 | false
99 |
100 |
101 | false
102 |
103 |
104 | false
105 |
106 |
107 | false
108 |
109 |
110 | false
111 |
112 |
113 | false
114 |
115 |
116 | false
117 |
118 |
119 | false
120 |
121 |
122 | false
123 |
124 |
125 | false
126 |
127 |
128 | false
129 |
130 |
131 | false
132 |
133 |
134 |
135 |
136 |
137 | {5c3415f8-c59a-4c93-85fb-c373cbff34fe}
138 | Portable
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/InventionUiiOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/InventionUiiOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace InventionUiiOS
4 | {
5 | public class Application
6 | {
7 | // This is the main entry point of the application.
8 | static void Main(string[] args)
9 | {
10 | Inv.iOSShell.Run(Portable.Shell.Install);
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/InventionUiiOS/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("InventionUiiOS")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("InventionUiiOS")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("50c7b8c9-e664-45af-b88e-0c9b8b9c1be1")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/InventionUiiOS/Resources/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/InventionUiiOS/SceneDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Foundation;
3 | using UIKit;
4 |
5 | namespace NewSingleViewTemplate {
6 | [Register ("SceneDelegate")]
7 | public class SceneDelegate : UIResponder, IUIWindowSceneDelegate {
8 |
9 | [Export ("window")]
10 | public UIWindow Window { get; set; }
11 |
12 | [Export ("scene:willConnectToSession:options:")]
13 | public void WillConnect (UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
14 | {
15 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
16 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
17 | // This delegate does not imply the connecting scene or session are new (see UIApplicationDelegate `GetConfiguration` instead).
18 | }
19 |
20 | [Export ("sceneDidDisconnect:")]
21 | public void DidDisconnect (UIScene scene)
22 | {
23 | // Called as the scene is being released by the system.
24 | // This occurs shortly after the scene enters the background, or when its session is discarded.
25 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
26 | // The scene may re-connect later, as its session was not neccessarily discarded (see UIApplicationDelegate `DidDiscardSceneSessions` instead).
27 | }
28 |
29 | [Export ("sceneDidBecomeActive:")]
30 | public void DidBecomeActive (UIScene scene)
31 | {
32 | // Called when the scene has moved from an inactive state to an active state.
33 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
34 | }
35 |
36 | [Export ("sceneWillResignActive:")]
37 | public void WillResignActive (UIScene scene)
38 | {
39 | // Called when the scene will move from an active state to an inactive state.
40 | // This may occur due to temporary interruptions (ex. an incoming phone call).
41 | }
42 |
43 | [Export ("sceneWillEnterForeground:")]
44 | public void WillEnterForeground (UIScene scene)
45 | {
46 | // Called as the scene transitions from the background to the foreground.
47 | // Use this method to undo the changes made on entering the background.
48 | }
49 |
50 | [Export ("sceneDidEnterBackground:")]
51 | public void DidEnterBackground (UIScene scene)
52 | {
53 | // Called as the scene transitions from the foreground to the background.
54 | // Use this method to save data, release shared resources, and store enough scene-specific state information
55 | // to restore the scene back to its current state.
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Dustin Andrews
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 |
--------------------------------------------------------------------------------
/Portable/Cloth.cs:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Cloth class by Callan Hodgskin 2019, Modified by Dustin Andrews 2019
4 | Original code https://gitlab.com/snippets/1905512
5 |
6 | Example:
7 | var Cloth = new Cloth();
8 | Cloth.Dimension = new Inv.Dimension(20, 20);
9 | Cloth.DrawEvent += (DC, Patch) =>
10 | {
11 | if ((Patch.X % 2) == (Patch.Y % 2))
12 | DC.DrawRectangle(Inv.Colour.DarkGray, null, 0, Patch.Rect);
13 | else
14 | DC.DrawRectangle(Inv.Colour.LightGray, null, 0, Patch.Rect);
15 | };
16 | Cloth.Draw();
17 |
18 | */
19 |
20 | using System;
21 |
22 | namespace Inv
23 | {
24 |
25 | public class Patch
26 | {
27 | public int X;
28 | public int Y;
29 | public int CellX;
30 | public int CellY;
31 | public Rect Rect;
32 |
33 | }
34 |
35 | internal sealed class Cloth : Inv.Panel
36 | {
37 | public Cloth()
38 | {
39 | this.CellSizeProperty = 32;
40 | this.Patch = new Patch();
41 |
42 | Base = Inv.Canvas.New();
43 | Base.PressEvent += (Point) =>
44 | {
45 | this.PanningPoint = Point;
46 |
47 | Base.Draw();
48 | };
49 |
50 | Base.AdjustEvent += () =>
51 | {
52 | Base.Draw();
53 | };
54 |
55 | Base.MoveEvent += (Point) =>
56 | {
57 | if (PanningPoint != null)
58 | {
59 | var DeltaPoint = PanningPoint.Value - Point;
60 |
61 | PanningX += DeltaPoint.X;
62 | PanningY += DeltaPoint.Y;
63 |
64 | this.PanningPoint = Point;
65 |
66 | Base.Draw();
67 | }
68 | };
69 |
70 | Base.ReleaseEvent += (Point) =>
71 | {
72 | PanningPoint = null;
73 |
74 | Base.Draw();
75 | };
76 |
77 | Base.ZoomEvent += (Z) =>
78 | {
79 | Zoom(Z.Point.X, Z.Point.Y, Z.Delta );
80 | };
81 |
82 | Base.DrawEvent += (DC) =>
83 | {
84 | var CanvasDimension = Base.GetDimension();
85 | var CanvasWidth = CanvasDimension.Width;
86 | var CanvasHeight = CanvasDimension.Height;
87 | var MapWidth = Dimension.Width * CellSizeProperty;
88 | var MapHeight = Dimension.Height * CellSizeProperty;
89 | var BufferX = Math.Max(300, CanvasWidth - MapWidth);
90 | var BufferY = Math.Max(300, CanvasHeight - MapHeight);
91 |
92 | if (InitialDraw)
93 | {
94 | this.InitialDraw = false;
95 |
96 | if (PanningX == 0 && PanningY == 0)
97 | {
98 | if (MapWidth < CanvasWidth)
99 | PanningX = (MapWidth - CanvasWidth) / 2;
100 |
101 | if (MapHeight < CanvasHeight)
102 | PanningY = (MapHeight - CanvasHeight) / 2;
103 | }
104 | }
105 |
106 | if (PanningX + CanvasWidth > MapWidth + BufferX)
107 | PanningX = MapWidth - CanvasWidth + BufferX;
108 |
109 | if (PanningX < -BufferX)
110 | PanningX = -BufferX;
111 |
112 | if (PanningY + CanvasHeight > MapHeight + BufferY)
113 | PanningY = MapHeight - CanvasHeight + BufferY;
114 |
115 | if (PanningY < -BufferY)
116 | PanningY = -BufferY;
117 |
118 | SetPanningParameters();
119 |
120 | var CellY = -(PanningY % CellSizeProperty);
121 |
122 | for (var Y = PanningTop; Y <= PanningBottom; Y++)
123 | {
124 | var CellX = -(PanningX % CellSizeProperty);
125 |
126 | for (var X = PanningLeft; X <= PanningRight; X++)
127 | {
128 | if (X >= 0 && X < Dimension.Width && Y >= 0 && Y < Dimension.Height)
129 | {
130 | Patch.X = X;
131 | Patch.Y = Y;
132 | Patch.Rect = new Inv.Rect(CellX, CellY, CellSizeProperty, CellSizeProperty);
133 |
134 | DrawEvent?.Invoke(DC, Patch);
135 | }
136 |
137 | CellX += CellSizeProperty;
138 | }
139 |
140 | CellY += CellSizeProperty;
141 | }
142 | };
143 | }
144 |
145 | public void Zoom(int X, int Y, int Delta)
146 | {
147 | var GlobalX = PanningX + X;
148 | var GlobalY = PanningY + Y;
149 | var OldX = GlobalX / CellSizeProperty;
150 | var OldY = GlobalY / CellSizeProperty;
151 | var ModX = GlobalX % CellSizeProperty;
152 | var ModY = GlobalY % CellSizeProperty;
153 | var smoothing = Math.Max(1, CellSize / 8);
154 | CellSizeProperty += Delta * smoothing;
155 | if (CellSizeProperty > 256)
156 | CellSizeProperty = 256;
157 | else if (CellSizeProperty < 4)
158 | CellSizeProperty = 4;
159 | PanningX = (OldX * CellSizeProperty) - X + ModX;
160 | PanningY = (OldY * CellSizeProperty) - Y + ModY;
161 | Base.Draw();
162 | }
163 |
164 | void SetPanningParameters()
165 | {
166 | var CanvasDimensions = Base.GetDimension();
167 | var CanvasWidth = CanvasDimensions.Width;
168 | var CanvasHeight = CanvasDimensions.Height;
169 | this.PanningWidth = CanvasWidth / CellSizeProperty;
170 | this.PanningHeight = CanvasHeight / CellSizeProperty;
171 | this.PanningLeft = PanningX / CellSizeProperty;
172 | this.PanningTop = PanningY / CellSizeProperty;
173 | this.PanningRight = PanningLeft + PanningWidth + 1;
174 | this.PanningBottom = PanningTop + PanningHeight + 1;
175 | }
176 |
177 | public void SetPanningXY(int X, int Y)
178 | {
179 | PanningX = (int) ((X - (PanningWidth / 2.0)) * CellSize);
180 | PanningY = (int) ((Y - (PanningHeight / 2.0)) * CellSize);
181 | }
182 |
183 | public void KeepXYOnScreen(int X, int Y)
184 | {
185 |
186 | int buffer = 5;
187 | if (X < PanningLeft || X > PanningRight || Y < PanningTop || Y > PanningBottom ||
188 | buffer > PanningWidth || buffer > PanningHeight)
189 | {
190 | PanningX = (int) ((X - (PanningWidth / 2.0)) * CellSize);
191 | PanningY = (int) ((Y - (PanningHeight / 2.0)) * CellSize);
192 | }
193 | else
194 | {
195 | if (X < PanningLeft + buffer)
196 | {
197 | PanningX = (PanningLeft - 1) * CellSize;
198 | }
199 | else if (X + 1 > PanningRight - buffer)
200 | {
201 | PanningX = (PanningLeft + 1) * CellSize;
202 | }
203 |
204 | if(Y < PanningTop + buffer)
205 | {
206 | PanningY = (PanningTop - 1) * CellSize;
207 | }
208 | else if (Y + 1 > PanningBottom - buffer)
209 | {
210 | PanningY = (PanningTop + 1) * CellSize;
211 | }
212 | }
213 | }
214 |
215 | public Inv.Dimension Dimension { get; set; }
216 | public int CellSize { get => CellSizeProperty; set => CellSizeProperty = value; }
217 | public Inv.Dimension BaseDimension => Base.GetDimension();
218 | public event Action DrawEvent;
219 | public void Draw() => Base.Draw();
220 | private bool InitialDraw;
221 | private int CellSizeProperty;
222 | private int PanningX;
223 | private int PanningY;
224 | private Inv.Point? PanningPoint;
225 | private int PanningWidth;
226 | private int PanningHeight;
227 | private int PanningLeft;
228 | private int PanningTop;
229 | private int PanningRight;
230 | private int PanningBottom;
231 | private Patch Patch;
232 | }
233 | }
--------------------------------------------------------------------------------
/Portable/ColorPallete.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text.RegularExpressions;
4 | using Inv;
5 |
6 | namespace Portable
7 | {
8 | // See http://paletton.com
9 | public static class ColorPallette
10 | {
11 |
12 | public static Colour PrimaryColor;
13 | public static Colour PrimaryColorLightest;
14 | public static Colour PrimaryColorLighter;
15 | public static Colour PrimaryColorDarker;
16 | public static Colour PrimaryColorDarkest;
17 |
18 | public static Colour Secondary1Color;
19 | public static Colour Secondary1ColorLightest;
20 | public static Colour Secondary1ColorLighter;
21 | public static Colour Secondary1ColorDarker;
22 | public static Colour Secondary1ColorDarkest;
23 |
24 | public static Colour Secondary2Color;
25 | public static Colour Secondary2ColorLightest;
26 | public static Colour Secondary2ColorLighter;
27 | public static Colour Secondary2ColorDarker;
28 | public static Colour Secondary2ColorDarkest;
29 |
30 | public static Colour ComplementColor;
31 | public static Colour ComplementColorLightest;
32 | public static Colour ComplementColorLighter;
33 | public static Colour ComplementColorDarker;
34 | public static Colour ComplementColorDarkest;
35 |
36 |
37 | static ColorPallette()
38 | {
39 | var lines = colorMapString.Split('\n');
40 | List colors = new List();
41 | foreach(var line in lines)
42 | {
43 | Match colorMatch = rgbRe.Match(line);
44 | if(colorMatch.Success)
45 | {
46 | var r = byte.Parse(colorMatch.Groups["r"].Value);
47 | var g = byte.Parse(colorMatch.Groups["g"].Value);
48 | var b = byte.Parse(colorMatch.Groups["b"].Value);
49 | var color = Colour.FromArgb(byte.MaxValue, r, g, b);
50 | colors.Add(color);
51 | }
52 | }
53 | PrimaryColor = colors[0];
54 | PrimaryColorLightest = colors[1];
55 | PrimaryColorLighter = colors[2];
56 | PrimaryColorDarker = colors[3];
57 | PrimaryColorDarkest = colors[4];
58 |
59 | Secondary1Color = colors[5];
60 | Secondary1ColorLightest = colors[6];
61 | Secondary1ColorLighter = colors[7];
62 | Secondary1ColorDarker = colors[8];
63 | Secondary1ColorDarkest = colors[9];
64 |
65 | Secondary2Color = colors[10];
66 | Secondary2ColorLightest = colors[11];
67 | Secondary2ColorLighter = colors[12];
68 | Secondary2ColorDarker = colors[13];
69 | Secondary2ColorDarkest = colors[14];
70 |
71 | ComplementColor = colors[15];
72 | ComplementColorLightest = colors[16];
73 | ComplementColorLighter = colors[17];
74 | ComplementColorDarker = colors[18];
75 | ComplementColorDarkest = colors[19];
76 | }
77 |
78 | static Regex rgbRe = new Regex(@" rgb\((?[ \d]+),(?[ \d]+),(?[ \d]+)\)");
79 |
80 |
81 |
82 |
83 |
84 | // I'm too lazy to keep copy-pasting colors. Just read in the whole text map from paletton.
85 | static string colorMapString = @"
86 | ##### Color Palette by Paletton.com
87 | ##### Palette URL: http://paletton.com/#uid=72O0u0klVl63+Jtc+t1uFdmQU5s
88 |
89 |
90 | *** Primary color:
91 |
92 | shade 0 = #30882B = rgb( 48,136, 43) = rgba( 48,136, 43,1) = rgb0(0.188,0.533,0.169)
93 | shade 1 = #C9E4C8 = rgb(201,228,200) = rgba(201,228,200,1) = rgb0(0.788,0.894,0.784)
94 | shade 2 = #73BB6F = rgb(115,187,111) = rgba(115,187,111,1) = rgb0(0.451,0.733,0.435)
95 | shade 3 = #085604 = rgb( 8, 86, 4) = rgba( 8, 86, 4,1) = rgb0(0.031,0.337,0.016)
96 | shade 4 = #022300 = rgb( 2, 35, 0) = rgba( 2, 35, 0,1) = rgb0(0.008,0.137,0)
97 |
98 | *** Secondary color (1):
99 |
100 | shade 0 = #206664 = rgb( 32,102,100) = rgba( 32,102,100,1) = rgb0(0.125,0.4,0.392)
101 | shade 1 = #AFC8C7 = rgb(175,200,199) = rgba(175,200,199,1) = rgb0(0.686,0.784,0.78)
102 | shade 2 = #538D8A = rgb( 83,141,138) = rgba( 83,141,138,1) = rgb0(0.325,0.553,0.541)
103 | shade 3 = #03413E = rgb( 3, 65, 62) = rgba( 3, 65, 62,1) = rgb0(0.012,0.255,0.243)
104 | shade 4 = #001A19 = rgb( 0, 26, 25) = rgba( 0, 26, 25,1) = rgb0(0,0.102,0.098)
105 |
106 | *** Secondary color (2):
107 |
108 | shade 0 = #A86835 = rgb(168,104, 53) = rgba(168,104, 53,1) = rgb0(0.659,0.408,0.208)
109 | shade 1 = #FFEDDF = rgb(255,237,223) = rgba(255,237,223,1) = rgb0(1,0.929,0.875)
110 | shade 2 = #E7B389 = rgb(231,179,137) = rgba(231,179,137,1) = rgb0(0.906,0.702,0.537)
111 | shade 3 = #6A3204 = rgb(106, 50, 4) = rgba(106, 50, 4,1) = rgb0(0.416,0.196,0.016)
112 | shade 4 = #2B1300 = rgb( 43, 19, 0) = rgba( 43, 19, 0,1) = rgb0(0.169,0.075,0)
113 |
114 | *** Complement color:
115 |
116 | shade 0 = #A73537 = rgb(167, 53, 55) = rgba(167, 53, 55,1) = rgb0(0.655,0.208,0.216)
117 | shade 1 = #FEDEDF = rgb(254,222,223) = rgba(254,222,223,1) = rgb0(0.996,0.871,0.875)
118 | shade 2 = #E5888B = rgb(229,136,139) = rgba(229,136,139,1) = rgb0(0.898,0.533,0.545)
119 | shade 3 = #690407 = rgb(105, 4, 7) = rgba(105, 4, 7,1) = rgb0(0.412,0.016,0.027)
120 | shade 4 = #2B0001 = rgb( 43, 0, 1) = rgba( 43, 0, 1,1) = rgb0(0.169,0,0.004)
121 |
122 |
123 | ##### Generated by Paletton.com (c) 2002-2014
124 | ";
125 | }
126 | }
--------------------------------------------------------------------------------
/Portable/EntityData.cs:
--------------------------------------------------------------------------------
1 | using EntityComponentSystemCSharp.Components;
2 | using EntityComponentSystemCSharp;
3 | using static EntityComponentSystemCSharp.EntityManager;
4 | using Inv;
5 |
6 | namespace Portable
7 | {
8 | ///
9 | /// Provides a table of standard display data for entities.
10 | ///
11 | internal class EntityData
12 | {
13 | Label _name;
14 | Label _health;
15 | Label _maxHealth;
16 | Label _attack;
17 | Label _accuracy;
18 | Label _defense;
19 | Label _gold;
20 | Label _speed;
21 | Table _table;
22 |
23 |
24 | public Table Table => _table;
25 |
26 | public EntityData(Surface surface, Colour fontColor, Colour backgroundColor)
27 | {
28 | _table = surface.NewTable();
29 | _table.Background.Colour = backgroundColor;
30 | _name = surface.NewLabel();
31 | var n = surface.NewLabel();
32 | n.Text = "Name: ";
33 |
34 | _health = surface.NewLabel();
35 | _maxHealth = surface.NewLabel();
36 | var h = surface.NewLabel();
37 | h.Text = "Health: ";
38 | var divider = surface.NewLabel();
39 | divider.Text = " / ";
40 | var healthPanel = surface.NewHorizontalStack();
41 | healthPanel.AddPanel(h);
42 | healthPanel.AddPanel(_health);
43 | var maxHealthPanel = surface.NewHorizontalStack();
44 | maxHealthPanel.AddPanel(divider);
45 | maxHealthPanel.AddPanel(_maxHealth);
46 |
47 | _attack = surface.NewLabel();
48 | var at = surface.NewLabel();
49 | at.Text = "Attack: ";
50 |
51 | _accuracy = surface.NewLabel();
52 | var ac = surface.NewLabel();
53 | ac.Text = "Accuracy: ";
54 |
55 | _defense = surface.NewLabel();
56 | var def = surface.NewLabel();
57 | def.Text = "Defense: ";
58 |
59 | _speed = surface.NewLabel();
60 | var s = surface.NewLabel();
61 | s.Text = "Speed: ";
62 |
63 | _gold = surface.NewLabel();
64 | var gl = surface.NewLabel();
65 | gl.Text = "Gold: ";
66 |
67 | _table = surface.NewTable();
68 | _table.Compose(
69 | new Panel[,]
70 | {
71 | {n, _name},
72 | {healthPanel, maxHealthPanel},
73 | {at, _attack},
74 | {ac, _accuracy},
75 | {def, _defense},
76 | {s, _speed},
77 | {gl, _gold}
78 | });
79 |
80 | SetFontInfo(fontColor, backgroundColor);
81 | _gold.Font.Colour = Colour.Gold;
82 | var padding = _table.AddAutoRow();
83 | padding.Star();
84 | }
85 |
86 | private void SetFontInfo(Colour fontColor, Colour backgroundColor)
87 | {
88 | foreach(var row in _table.GetRows())
89 | {
90 | row.Auto();
91 | }
92 |
93 | foreach(var col in _table.GetColumns())
94 | {
95 | col.Star();
96 | }
97 | var index = 0;
98 | foreach (var cell in _table.GetCells())
99 | {
100 | var label = cell.Content.Control as Label;
101 | if (label != null)
102 | {
103 | label.Font.Colour = fontColor;
104 | label.Font.Large();
105 | label.Font.Bold();
106 | if(index % 2 == 1)
107 | {
108 | label.Alignment.CenterRight();
109 | }
110 | label.Background.Colour = backgroundColor;
111 | }
112 | var stack = cell.Content.Control as Stack;
113 | if (stack != null)
114 | {
115 | foreach (var panel in stack.GetPanels())
116 | {
117 | label = panel.Control as Label;
118 | if (label != null)
119 | {
120 | label.Font.Colour = fontColor;
121 | label.Font.Large();
122 | label.Font.Bold();
123 | if(index % 2 == 1)
124 | {
125 | label.Alignment.CenterRight();
126 | }
127 | label.Background.Colour = backgroundColor;
128 | }
129 | }
130 | }
131 | index++;
132 | }
133 | }
134 |
135 | public void SetData(Entity entity)
136 | {
137 | var alive = entity.GetComponent();
138 | var name = entity.GetComponent();
139 | var attack = entity.GetComponent();
140 | var defense = entity.GetComponent();
141 | var actor = entity.GetComponent();
142 |
143 | if (alive != null)
144 | {
145 | _health.Text = alive.Health.ToString();
146 | _maxHealth.Text = alive.MaxHealth.ToString();
147 | }
148 |
149 | if(name != null)
150 | {
151 | _name.Text = name.NameString;
152 | }
153 |
154 | if(attack != null)
155 | {
156 | _attack.Text = attack.Power.ToString();
157 | _accuracy.Text = attack.Accuracy.ToString();
158 | }
159 |
160 | if(defense != null)
161 | {
162 | _defense.Text = defense.Chance.ToString();
163 | }
164 |
165 | if(actor != null)
166 | {
167 | _gold.Text = actor.Gold.ToString();
168 | _speed.Text = actor.Speed.ToString();
169 | }
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/Portable/MegaDungeonUI.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Collections.Generic;
4 | using EntityComponentSystemCSharp.Components;
5 | using EntityComponentSystemCSharp;
6 | using static EntityComponentSystemCSharp.EntityManager;
7 | using static Portable.MegaDungeonUIConstants;
8 | using Inv;
9 |
10 | namespace Portable
11 | {
12 |
13 | public class MegaDungeonUI
14 | {
15 | int _horizontalCellCount;
16 | int _verticalCellCount;
17 | Surface _surface;
18 | MegaDungeon.Engine _engine;
19 | MegaDungeon.PlayerInput _lastInput = MegaDungeon.PlayerInput.NONE;
20 | TileManager _tileManager;
21 | Dictionary _lastLocation = new Dictionary();
22 | Dictionary _actorLocationMap = new Dictionary();
23 | Cloth _cloth;
24 | Dock _outerDock;
25 | Dock _innerDock;
26 | Label _topLabel;
27 | Label _bottomLabel;
28 | Label _rightLabel;
29 | Label _gameOver;
30 | EntityData _leftPanel;
31 | bool _showDebugInfo = false;
32 |
33 | static Dictionary UICommands = new Dictionary();
34 | public MegaDungeon.PlayerInput LastInput { get => _lastInput; set => _lastInput = value; }
35 |
36 | ///
37 | /// Constructor for Main UI logic class. Sets up all UI windows.
38 | ///
39 | ///
40 | ///
41 | ///
42 | public MegaDungeonUI(Surface surface, int horizontalCellCount, int verticalCellCount)
43 | {
44 | _horizontalCellCount = horizontalCellCount;
45 | _verticalCellCount = verticalCellCount;
46 |
47 | var directory = surface.Window.Application.Directory;
48 | _tileManager = new TileManager(directory.NewAsset("absurd64.bmp"), directory.NewAsset("tiledata.json"));
49 | _engine = new MegaDungeon.Engine(horizontalCellCount, verticalCellCount, _tileManager);
50 |
51 | _tileManager = new TileManager(directory.NewAsset("absurd64.bmp"), directory.NewAsset("tiledata.json"));
52 | _engine = new MegaDungeon.Engine(horizontalCellCount, verticalCellCount, _tileManager);
53 | _surface = surface;
54 | _cloth = CreateCloth();
55 | _outerDock = _surface.NewDock(Inv.Orientation.Vertical);
56 | _innerDock = _surface.NewDock(Inv.Orientation.Horizontal);
57 |
58 | _topLabel = InitLabel("Top", ColorPallette.PrimaryColorLightest, ColorPallette.PrimaryColorDarkest, ColorPallette.PrimaryColorDarker);
59 | _bottomLabel = InitLabel("Bottom", ColorPallette.Secondary1ColorLightest, ColorPallette.Secondary1ColorDarkest, ColorPallette.Secondary1ColorDarker);
60 | _outerDock.AddHeader(_topLabel);
61 | _outerDock.AddClient(_innerDock);
62 | _outerDock.AddFooter(_bottomLabel);
63 |
64 | var vstack = _surface.NewVerticalStack();
65 | vstack.Background.Colour = ColorPallette.Secondary1ColorDarkest;
66 | vstack.Border.Set(5);
67 | vstack.Border.Colour = ColorPallette.Secondary1ColorDarkest;
68 |
69 | _leftPanel = new EntityData(_surface, ColorPallette.Secondary1ColorLightest, ColorPallette.Secondary1ColorDarkest);
70 | vstack.AddPanel(_leftPanel.Table);
71 | _rightLabel = InitLabel("Right", ColorPallette.ComplementColorLightest, ColorPallette.ComplementColorDarkest, ColorPallette.ComplementColorDarker);
72 | _innerDock.AddHeader(vstack);
73 | _innerDock.AddClient(_cloth);
74 | _innerDock.AddFooter(_rightLabel);
75 | _surface.Content = _outerDock;
76 | _surface.ComposeEvent += Warmup();
77 |
78 | _gameOver = _surface.NewLabel();
79 | _gameOver.Text = "YOU HAVE DIED.";
80 | _gameOver.Font.ExtraMassive();
81 | _gameOver.Font.Colour = Colour.Red;
82 | _gameOver.Background.Colour = Colour.DarkBlue;
83 | _gameOver.Justify.Center();
84 |
85 | InitUiCommands();
86 |
87 | _engine = new MegaDungeon.Engine(horizontalCellCount, verticalCellCount, _tileManager);
88 | }
89 |
90 | ///
91 | /// Commands the only do something in the UI layer and are not passed into the game engine.
92 | ///
93 | void InitUiCommands()
94 | {
95 | UICommands[Inv.Key.Plus] = () => {_cloth.Zoom(0,0,1);};
96 | UICommands[Inv.Key.Minus] = () => {_cloth.Zoom(0,0,-1);};
97 | UICommands[Inv.Key.F2] = () => {_showDebugInfo = !_showDebugInfo;_cloth.Draw();};
98 | }
99 | ///
100 | /// Check for full _cloth init before going to usual update
101 | ///
102 | /// null
103 | ///
104 | /// Update gets called a few times before the window is fully laid out.
105 | /// When base dimensions are available center the player and connect main Update();
106 | /// (Cannot use a lambda because -= won't be able to unregister without a method handle.)
107 | ///
108 | System.Action Warmup()
109 | {
110 | return new Action( () =>
111 | {
112 | if(_cloth.BaseDimension.Height == 0)
113 | {
114 | return;
115 | }
116 | _surface.ComposeEvent -= Warmup();
117 | _cloth.SetPanningXY(_engine.PlayerLocation.X, _engine.PlayerLocation.Y);
118 | GetActorsFromEngine();
119 | _leftPanel.SetData(_engine.PlayerEntity);
120 | _surface.ComposeEvent += () => Update();
121 | _cloth.Draw();
122 | });
123 | }
124 |
125 | ///
126 | /// Update one atomic unit of the UI.
127 | ///
128 | ///
129 | /// This method is the pump for the game. It should be fast enough to always return in less than
130 | /// one frame (1/60th sec.)
131 | ///
132 | void Update()
133 | {
134 | if (_lastInput != MegaDungeon.PlayerInput.NONE)
135 | {
136 | if(!_engine.PlayerEntity.HasComponent())
137 | {
138 | _surface.Content = _gameOver;
139 | return;
140 | }
141 | _engine.DoTurn(_lastInput);
142 | GetActorsFromEngine();
143 | _cloth.KeepXYOnScreen(_engine.PlayerLocation.X, _engine.PlayerLocation.Y);
144 | _bottomLabel.Text = string.Join("\n", _engine.Messages);
145 | _leftPanel.SetData(_engine.PlayerEntity);
146 | _cloth.Draw();
147 | _lastInput = MegaDungeon.PlayerInput.NONE;
148 | }
149 | }
150 |
151 | public void AcceptInput(Inv.Keystroke keystroke)
152 | {
153 | if (KeyMap.ContainsKey(keystroke.Key))
154 | {
155 | _lastInput = KeyMap[keystroke.Key];
156 | }
157 | else if (UICommands.ContainsKey(keystroke.Key))
158 | {
159 | UICommands[keystroke.Key]();
160 | }
161 | }
162 |
163 | Label InitLabel(string text, Colour fontColor, Colour border, Colour background)
164 | {
165 | var newLabel = _surface.NewLabel();
166 | newLabel.Text = text;
167 | newLabel.Background.Colour = background;
168 | newLabel.Font.Colour = fontColor;
169 | newLabel.Border.Colour = border;
170 | newLabel.Border.Set(1);
171 | return newLabel;
172 | }
173 |
174 | internal Cloth CreateCloth()
175 | {
176 | var cloth = new Cloth();
177 | cloth.Dimension = new Inv.Dimension(_horizontalCellCount, _verticalCellCount);
178 | cloth.CellSize = (_surface.Window.Width / _horizontalCellCount) * 2; //How much of initial map to show.
179 | cloth.Draw();
180 | cloth.DrawEvent += (DC, patch) => Cloth_DrawEvent(DC, patch);
181 | return cloth;
182 | }
183 |
184 | void Cloth_DrawEvent(DrawContract dc, Patch patch)
185 | {
186 | var point = new RogueSharp.Point(patch.X, patch.Y);
187 | int glyph;
188 | if(_showDebugInfo)
189 | {
190 | glyph = _engine.RevealedFloor[patch.X, patch.Y];
191 | }
192 | else
193 | {
194 | glyph = _engine.Floor[patch.X, patch.Y];
195 | }
196 |
197 | Inv.Image image;
198 | if(_engine.Viewable.Contains(point) || _showDebugInfo)
199 | {
200 | if(_actorLocationMap.ContainsKey(patch.X + (patch.Y * _horizontalCellCount)))
201 | {
202 | glyph = _actorLocationMap[patch.X + (patch.Y * _horizontalCellCount)];
203 | image = _tileManager.GetInvImage(glyph);
204 | dc.DrawImage(image, patch.Rect);
205 | if(_showDebugInfo)
206 | {
207 | foreach(var loc in _lastLocation)
208 | {
209 | if(loc.Value.X == patch.X && loc.Value.Y == patch.Y)
210 | {
211 | DrawText(loc.Key.Id.ToString(), dc, patch);
212 | }
213 | }
214 | }
215 | }
216 | else
217 | {
218 | image = _tileManager.GetInvImage(glyph);
219 | dc.DrawImage(image, patch.Rect);
220 | }
221 | }
222 | else
223 | {
224 | image = _tileManager.GetInvImageDark(glyph);
225 | dc.DrawImage(image, patch.Rect);
226 | }
227 | }
228 |
229 | void DrawText(string text, DrawContract dc, Patch patch)
230 | {
231 | dc.DrawText(text, "Courier", 11,FontWeight.Regular, Colour.YellowGreen, new Point(patch.Rect.Left, patch.Rect.Top), HorizontalPosition.Left, VerticalPosition.Top);
232 | }
233 | void GetActorsFromEngine()
234 | {
235 | // Remove old location from the map.
236 | foreach (var actor in _engine.GetEntityManager().GetAllEntitiesWithComponent())
237 | {
238 | var location = actor.GetComponent();
239 | var glyph = actor.GetComponent();
240 | if (_lastLocation.ContainsKey(actor))
241 | {
242 | var last = _lastLocation[actor];
243 | _actorLocationMap.Remove(last.X + (last.Y * _horizontalCellCount));
244 | }
245 | }
246 |
247 | // Add new locations
248 | foreach(var actor in _engine.GetEntityManager().GetAllEntitiesWithComponent())
249 | {
250 | var location = actor.GetComponent();
251 | var glyph = actor.GetComponent();
252 | _actorLocationMap[location.X + (location.Y * _horizontalCellCount)] = glyph.glyph;
253 | _lastLocation[actor] = new EntityComponentSystemCSharp.Components.Location() {X = location.X, Y = location.Y};
254 | }
255 | }
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/Portable/MegaDungeonUIConstants.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Inv;
3 |
4 | namespace Portable
5 | {
6 | public static class MegaDungeonUIConstants
7 | {
8 | ///
9 | /// Mapping from UI implementation to game.
10 | ///
11 | ///
12 | /// Enforce a strong firewall between the game the UI implmentation.
13 | ///
14 | ///
15 | ///
16 | ///
17 | public static Dictionary KeyMap = new Dictionary()
18 | {
19 | {Inv.Key.n1,MegaDungeon.PlayerInput.DOWNLEFT},
20 | {Inv.Key.n2,MegaDungeon.PlayerInput.DOWN},
21 | {Inv.Key.n3,MegaDungeon.PlayerInput.DOWNRIGHT},
22 | {Inv.Key.n4,MegaDungeon.PlayerInput.LEFT},
23 | {Inv.Key.n5,MegaDungeon.PlayerInput.WAIT},
24 | {Inv.Key.n6,MegaDungeon.PlayerInput.RIGHT},
25 | {Inv.Key.n7,MegaDungeon.PlayerInput.UPLEFT},
26 | {Inv.Key.n8,MegaDungeon.PlayerInput.UP},
27 | {Inv.Key.n9,MegaDungeon.PlayerInput.UPRIGHT},
28 | {Inv.Key.Up,MegaDungeon.PlayerInput.UP},
29 | {Inv.Key.Down,MegaDungeon.PlayerInput.DOWN},
30 | {Inv.Key.Left,MegaDungeon.PlayerInput.LEFT},
31 | {Inv.Key.Right,MegaDungeon.PlayerInput.RIGHT},
32 | {Inv.Key.Space,MegaDungeon.PlayerInput.WAIT},
33 |
34 | // vi keys
35 | {Inv.Key.B,MegaDungeon.PlayerInput.DOWNLEFT},
36 | {Inv.Key.J,MegaDungeon.PlayerInput.DOWN},
37 | {Inv.Key.N,MegaDungeon.PlayerInput.DOWNRIGHT},
38 | {Inv.Key.H,MegaDungeon.PlayerInput.LEFT},
39 | {Inv.Key.L,MegaDungeon.PlayerInput.RIGHT},
40 | {Inv.Key.Y,MegaDungeon.PlayerInput.UPLEFT},
41 | {Inv.Key.K,MegaDungeon.PlayerInput.UP},
42 | {Inv.Key.U,MegaDungeon.PlayerInput.UPRIGHT},
43 |
44 | // qWeASDzc
45 | {Inv.Key.Z,MegaDungeon.PlayerInput.DOWNLEFT},
46 | {Inv.Key.S,MegaDungeon.PlayerInput.DOWN},
47 | {Inv.Key.C,MegaDungeon.PlayerInput.DOWNRIGHT},
48 | {Inv.Key.A,MegaDungeon.PlayerInput.LEFT},
49 | {Inv.Key.D,MegaDungeon.PlayerInput.RIGHT},
50 | {Inv.Key.Q,MegaDungeon.PlayerInput.UPLEFT},
51 | {Inv.Key.W,MegaDungeon.PlayerInput.UP},
52 | {Inv.Key.E,MegaDungeon.PlayerInput.UPRIGHT},
53 | };
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Portable/Portable.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard20
4 | $(SolutionDir)\bin\$(Configuration)\$(AssemblyName)\
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Portable/Shell.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using Inv;
6 |
7 | namespace Portable
8 | {
9 | public static class Shell
10 | {
11 | static TimeSpan frameTime = TimeSpan.FromMilliseconds(8);
12 | public static void Install(Inv.Application application)
13 | {
14 | application.Title = "MegaDungeon";
15 | var surface = application.Window.NewSurface();
16 | var h = application.Window.Height;
17 | var w = application.Window.Width;
18 | var start = DateTime.UtcNow;
19 | var ui = new MegaDungeonUI(surface, 60, 40);
20 | var end = DateTime.UtcNow;
21 | var ms = (end - start).TotalMilliseconds;
22 | Console.WriteLine($"Initialized in {ms} milliseconds");
23 |
24 | surface.ArrangeEvent += () =>
25 | {
26 | Surface_ArrangeEvent(surface);
27 | };
28 |
29 | application.Window.Transition(surface);
30 |
31 | surface.ComposeEvent += () =>
32 | {
33 | Surface_ComposeEvent(ui);
34 | };
35 |
36 | surface.KeystrokeEvent += (keyStroke) =>
37 | {
38 | Surface_KeystrokeEvent(keyStroke, ui);
39 | };
40 | Console.WriteLine("Boot completed.");
41 | }
42 |
43 | static void Surface_KeystrokeEvent(Keystroke keystroke, MegaDungeonUI ui)
44 | {
45 | // Console.WriteLine($"{keystroke.Modifier}{keystroke.Key}");
46 | ui.AcceptInput(keystroke);
47 | }
48 | static void Surface_ArrangeEvent(Surface surface)
49 | {
50 |
51 | }
52 |
53 | // Fires up to 60 times a second.
54 | static void Surface_ComposeEvent(MegaDungeonUI ui)
55 | {
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Portable/TileManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using SixLabors.ImageSharp;
4 | using SixLabors.ImageSharp.Processing;
5 | using SixLabors.Primitives;
6 | using Newtonsoft.Json;
7 | using System.Collections.Generic;
8 | using MegaDungeon.Contracts;
9 | using SixLabors.ImageSharp.PixelFormats;
10 |
11 | namespace Portable
12 | {
13 | public class TileManager : ITileManager
14 | {
15 | Image _tileset;
16 | int _tileSize;
17 | TileData _tileData;
18 |
19 | public Inv.Image TransparentDarken;
20 |
21 | Dictionary _tileCache = new Dictionary();
22 | Dictionary _darkTileCache = new Dictionary();
23 | Dictionary _glyphsByName = new Dictionary();
24 |
25 | public TileManager(Inv.Asset tileImageFile, Inv.Asset tileDataJson)
26 | {
27 | using (var tileStream = tileImageFile.Open())
28 | {
29 | _tileset = Image.Load(tileStream);
30 | }
31 |
32 | _tileData = JsonConvert.DeserializeObject(tileDataJson.AsText().ReadAll());
33 | _tileSize = _tileData.tile_size;
34 |
35 | foreach(var tile in _tileData.data)
36 | {
37 | _glyphsByName.Add(tile.Value.name, int.Parse(tile.Key));
38 | }
39 |
40 | }
41 |
42 | public int GetGlyphNumByName(string name)
43 | {
44 | return _glyphsByName[name];
45 | }
46 |
47 | public Inv.Image GetInvImage(int index)
48 | {
49 | if(!_tileCache.ContainsKey(index))
50 | {
51 | var invImage = new Inv.Image(GetTileBmpBytes(index), "bmp");
52 | _tileCache.Add(index, invImage);
53 | }
54 | return _tileCache[index];
55 | }
56 |
57 | public Inv.Image GetInvImageDark(int index)
58 | {
59 | Inv.Image invImage;
60 | if(_darkTileCache.ContainsKey(index))
61 | {
62 | invImage = _darkTileCache[index];
63 | }
64 | else
65 | {
66 | var tile = GetTileAsSLImage(index);
67 | tile.Mutate(m => m.Brightness(0.5F));
68 | invImage = new Inv.Image(GetBytesFromImage(tile), "bmp");
69 | _darkTileCache[index] = invImage;
70 | }
71 | return invImage;
72 | }
73 |
74 | public byte[] GetTileBmpBytes(int index)
75 | {
76 | Image tile = GetTileAsSLImage(index);
77 | return GetBytesFromImage(tile);
78 | }
79 |
80 | public Image GetTileAsSLImage(int index)
81 | {
82 | var x = (index * _tileSize) % _tileset.Width;
83 | var y = _tileSize * (int)((index * _tileSize) / _tileset.Width);
84 | var tile = _tileset.Clone(m => m.Crop(new Rectangle(x, y, _tileSize, _tileSize)));
85 | return tile;
86 | }
87 |
88 | private static byte[] GetBytesFromImage(Image tile)
89 | {
90 | byte[] imgBytes;
91 | using (var memstream = new MemoryStream())
92 | {
93 | var enc = new SixLabors.ImageSharp.Formats.Bmp.BmpEncoder();
94 | enc.BitsPerPixel = SixLabors.ImageSharp.Formats.Bmp.BmpBitsPerPixel.Pixel32;
95 | tile.Save(memstream, enc);
96 | imgBytes = new Byte[memstream.Length];
97 | memstream.Seek(0, SeekOrigin.Begin);
98 | memstream.Read(imgBytes, 0, imgBytes.Length);
99 | }
100 | return imgBytes;
101 | }
102 |
103 | Image DrawImageOnImageExample(Image tile)
104 | {
105 | var borderSize = 8;
106 | var borderRect = new Rectangle(borderSize, 0, tile.Width - (borderSize * 2), borderSize);
107 | var borderImage = tile.Clone(c => c.Crop(borderRect));
108 | var point = new Point(borderSize, 0);
109 | var newTile = new Image(tile.Width, tile.Height);
110 | newTile.Mutate( i => i.DrawImage(borderImage,point, 1.0F));
111 |
112 | return newTile;
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # InventionHack
2 | The C# Roguelike built on top of the [Invention API](https://gitlab.com/hodgskin-callan/Invention) by Callan Hodgskin and [RogueSharp](https://github.com/FaronBracy/RogueSharp) by FaronBracy.
3 | ## The Mission
4 | Use the Invention API to create a basic roguelike with all the features of the [Roguesharp C# tutorial](https://roguesharp.wordpress.com/) and put it on github with an MIT license as a jumping off point for aspiring roguelike creators. Primarily those on [r/roguelikedev](https://www.reddit.com/r/roguelikedev/).
5 |
6 | 
7 |
8 | ## Features
9 |
10 | - Basic roguelike gameplay
11 | - Line of site
12 | - Random floor creation
13 | - Basic combat
14 | - Speed system
15 | - RDBMS style ECS system
16 | - UI is loosely coupled to the underlying game engine
17 | - Builds with the dotnet.exe command
18 | - Not too buggy!
19 | - Invention is a very good UI engine and the starter game only scratches the surface of whats possible with it.
20 |
21 | ## Cloning, Building and running in Windows 10
22 | There may be other valid ways to build this.
23 | #### Pre-Reqs
24 |
25 | - Visual Studio 2017/2019 community edition
26 | - Git
27 | - [Dotnet 4.6 developer pack](https://www.microsoft.com/en-us/download/details.aspx?id=53321)
28 | - Optional: [Visual Studio Code](https://code.visualstudio.com/)
29 |
30 | #### Clone
31 |
32 | Change to a directory where you like to clone stuff.
33 |
34 | C:\local> git clone https://github.com/dustinandrews/InventionHackSharp.git
35 | C:\local> cd InventionHackSharp
36 |
37 |
38 | #### Build and test
39 | If you are building from the command line in Windows these commands should work. If you wish to build for Android, swap in the MegaDungeon.sln.Android file for the MegaDungeon.sln and build from Visual Studio. You will need Xamarin correctly installed. You can also build for iOS.
40 |
41 | C:\local\InventionHackSharp>dotnet build
42 | ...
43 | C:\local\InventionHackSharp\bin\Debug\EntityComponentSystemCSharp\net4.6.1\EntityComponentSystemCSharp.dll
44 | Engine -> C:\local\InventionHackSharp\bin\Debug\Engine\net461\Engine.dll
45 | Portable -> C:\local\InventionHackSharp\bin\Debug\Portable\net461\Portable.dll
46 | InventionUiWpf -> C:\local\InventionHackSharp\bin\Debug\InventionUiWpf\net461\InventionUiWpf.exe
47 |
48 | Build succeeded.
49 | 0 Warning(s)
50 | 0 Error(s)
51 |
52 | PS C:\local\InventionHackSharp> .\runtests.ps1
53 | NUnit Console Runner 3.10.0 (.NET 2.0)
54 | Copyright (c) 2019 Charlie Poole, Rob Prouse
55 | Sunday, November 17, 2019 6:47:32 PM
56 |
57 | Runtime Environment
58 | OS Version: Microsoft Windows NT 10.0.17763.0
59 | CLR Version: 4.0.30319.42000
60 |
61 | Test Files
62 | bin\Debug\Engine\net461\Engine.dll
63 | bin\Debug\EntityComponentSystemCSharp\net461\EntityComponentSystemCSharp.dll
64 | bin\Debug\FeatureDetector\net461\FeatureDetector.dll
65 |
66 |
67 |
68 | Test Run Summary
69 | Overall result: Passed
70 | Test Count: 34, Passed: 34, Failed: 0, Warnings: 0, Inconclusive: 0, Skipped: 0
71 | Start time: 2019-11-18 02:47:32Z
72 | End time: 2019-11-18 02:47:35Z
73 | Duration: 2.463 seconds
74 |
75 |
76 | #### Run the game
77 | C:\local\InventionHackSharp\bin\Debug\InventionUiWpf\net461\InventionUiWpf.exe
78 |
79 | ## Tour
80 | If you think this is cool and want to fork the repo to create your own roguelike please help yourself! Here is a brief description of the projects inside.
81 | #### Engine
82 | This is the game logic. It manages the game turns, maps and sits on top of the ECS. It also manages player specific stuff.
83 | #### EntityComponentSystemCSharp
84 | This is the Entity Component System that drives the game. Components are bare-bones C# classes with zero or more data members. The game engine calls every system for every entity each turn and gives it an opportunity to act. Systems filter for appropriate entities and change the data as appropriate.
85 |
86 | ### FeatureDetector
87 | Reads dungeon maps and flags walls and candidate locations for doors. It relies on [NumSharp](https://github.com/SciSharp/NumSharp) and uses a convolution filter. NumSharp is the C# port of numpy from Python. Things that are a breeze and super fast with numpy can be a downright chore in C#. NumSharp is still in beta and it shows. I plan to extend the convolution filter for use in cellular automata level generation at some point.
88 |
89 | ### InventionUiWpf
90 | This is the Windows WPF project that makes the UI work on that platform. Right now it's the only supported platform, but the other ones shouldn't be too hard to get working. I want to keep compatibility with dotnet.exe and vscode, so I haven't tried to integrate them.
91 |
92 | ### lib
93 | This is a custom build of the Invention API for x64 since the current nuget packages were x86 and vscode can only debug x64 binaries.
94 | ### Portable (AKA the Portable UI)
95 | This is the platform agnostic UI code that displays the game and ties the user to the engine.
96 |
97 | ## Pull requests
98 | I am happy to receive any pull requests and consider them. As the point of this repository is to be a clean starting point, new features are (probably) not going to be added. Any pull requests should:
99 |
100 | - Fix a bug
101 | - Make the code cleaner and easier to understand
102 | - Add unit tests that will either help downstream authors, be explanatory code, or both
103 | - Anything else that makes this a better starting point without making it too complex.
104 |
105 | ## Various Provisos, Quid pro quo and Caveats
106 | - Projects build .net 4.6.1 binaries.
107 | - There is no sound support in the custom Invention binaries as they require a third party library that requires licensing.
108 | - "dotnet.exe build" and "dotnet.exe test" must continue to work for pull requests to be accepted.
109 |
110 | ## Getting Help
111 | The primary help channel is [r/roguelikedev](https://www.reddit.com/r/roguelikedev/). Use the [announcement thread](https://www.reddit.com/r/roguelikedev/comments/ds3n8y/inventionhacksharp_the_basic_windows_c_roguelike/) or tag u/madsciencestache. For Invention help the Invention channel on the [Pathos](https://pathos.azurewebsites.net/) Lounge discord is a good place or tag u/callanh on Reddit.
112 |
113 | ## TODO:
114 |
115 | - Consider changing the MegaDungeon namespaces. (MegaDungeon is my own fork where I will develop my unique game.)
116 | - ~~Remove NumSharp since it's incomplete and much slower for this use than plain C#.~~ Done!
117 |
118 | ## Change-log:
119 | 11/17/2019 - Callanh has upgraded the Invention nuget to support this project! Accepted pull request and added some multi-targeting to keep Nunit tests working since it doesn't support netstandard yet.
120 |
121 | ## Backstory
122 | After stumbling on [Pathos](https://pathos.azurewebsites.net/) the Nethack Reboot I learned that the author, Callan Hodgskin, built it on top of a code-first API capable of building for Windows, iOS, Android and Linux. I checked out the API and found it to be excellent. It re-ignited my desire to create a roguelike. I also want to promote Invention as a platform, so I created this repository as a basic starting point for roguelike developers who want to program in C#.
123 |
--------------------------------------------------------------------------------
/absurd64.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/absurd64.bmp
--------------------------------------------------------------------------------
/nuget.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dustinandrews/InventionHackSharp/2ebde7af75e82eabc18ca31d6214e54933651161/nuget.exe
--------------------------------------------------------------------------------
/runtests.ps1:
--------------------------------------------------------------------------------
1 | # dotnet.exe test has problems with these multi-target dlls.
2 | # Enumerate test dlls here and run tests with this script
3 |
4 | $testFixtures = @('bin\Debug\Engine\net461\Engine.dll',
5 | 'bin\Debug\EntityComponentSystemCSharp\net461\EntityComponentSystemCSharp.dll',
6 | 'bin\Debug\FeatureDetector\net461\FeatureDetector.dll'
7 | )
8 |
9 | $nunit = 'nunit.consolerunner\3.10.0\tools\nunit3-console.exe'
10 | $config = Invoke-Expression ".\nuget.exe locals all -list"
11 | foreach($line in $config)
12 | {
13 | if ($line -match 'global-packages: (?.*)')
14 | {
15 | $packagePath = $Matches.path
16 | $nunitPath = [System.IO.Path]::Combine($packagePath,$nunit)
17 | if(Test-Path $nunitPath -PathType Leaf)
18 | {
19 | $fixtures = [String]::Join(" ", $testFixtures)
20 | Invoke-Expression "$nunitPath $fixtures"
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------