This commit is contained in:
riedel 2023-05-09 14:54:36 +02:00
parent 1784f417f1
commit 3c1c7f6898
16 changed files with 328 additions and 59 deletions

View file

@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CityGame", "CityGame\CityGa
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPFGame", "..\WPFGame\WPFGame\WPFGame.csproj", "{4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPFGame", "..\WPFGame\WPFGame\WPFGame.csproj", "{4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MGUI", "..\..\RE-UI-a-Monogame-GUI\MGUI\MGUI.csproj", "{BEEAE3E9-28E8-4052-90FC-1A84E40526F6}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -21,6 +23,10 @@ Global
{4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}.Debug|Any CPU.Build.0 = Debug|Any CPU {4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}.Release|Any CPU.Build.0 = Release|Any CPU {4F2DC7EE-24BA-4383-9AB6-EBA46EB191DF}.Release|Any CPU.Build.0 = Release|Any CPU
{BEEAE3E9-28E8-4052-90FC-1A84E40526F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEEAE3E9-28E8-4052-90FC-1A84E40526F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEEAE3E9-28E8-4052-90FC-1A84E40526F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEEAE3E9-28E8-4052-90FC-1A84E40526F6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -9,15 +9,13 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AStarLite" Version="1.1.0" /> <PackageReference Include="AStarLite" Version="1.1.0" />
<PackageReference Include="Microsoft.HLSL.CSharpVB" Version="1.0.2" />
<PackageReference Include="NAudio" Version="2.1.0" /> <PackageReference Include="NAudio" Version="2.1.0" />
<PackageReference Include="NAudio.Lame" Version="2.0.1" /> <PackageReference Include="NAudio.Lame" Version="2.0.1" />
<PackageReference Include="SimplexNoise" Version="2.0.0" /> <PackageReference Include="SimplexNoise" Version="2.0.0" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
<PackageReference Include="System.Speech" Version="7.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\RE-UI-a-Monogame-GUI\MGUI\MGUI.csproj" />
<ProjectReference Include="..\..\WPFGame\WPFGame\WPFGame.csproj" /> <ProjectReference Include="..\..\WPFGame\WPFGame\WPFGame.csproj" />
</ItemGroup> </ItemGroup>
@ -37,6 +35,21 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="Licenses\ASTARLITE-LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Licenses\LAME-LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Licenses\NAUDIO-LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Licenses\RE-UI-LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Licenses\SIMPLEXNOISE-LICENSE.htm">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\Building0.png"> <None Update="Resources\Building0.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>

View file

@ -3,17 +3,17 @@ using CityGame.Classes.World;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Windows;
using WPFGame; using WPFGame;
namespace CityGame.Classes.Entities namespace CityGame.Classes.Entities
{ {
public class Car : Entity public class Car : Entity
{ {
public bool desperate = false; public int grid = 1;
public long TimeUntilReroute = 5000;
protected long RerouteTimePassed = 0;
public static List<Car> Cars = new List<Car>(); public static List<Car> Cars = new List<Car>();
public delegate void CarEvent(Car car); public delegate void CarEvent(Car car);
public event CarEvent JourneyFinished; public event CarEvent JourneyFinished;
@ -44,6 +44,7 @@ namespace CityGame.Classes.Entities
protected ColoredRectangle debugRect; protected ColoredRectangle debugRect;
protected Tile lastTile; protected Tile lastTile;
protected List<LightSource> lights = new List<LightSource>(); protected List<LightSource> lights = new List<LightSource>();
protected LightSource PointLight;
public override OCanvas Render() public override OCanvas Render()
{ {
OCanvas canvas = new OCanvas(); OCanvas canvas = new OCanvas();
@ -73,6 +74,12 @@ namespace CityGame.Classes.Entities
lights.Add(blight); lights.Add(blight);
lights.Add(blight2); lights.Add(blight2);
PointLight = new LightSource { Type = LightSourceType.PointLight, Color = Color.White, Radius = 24, Angle = 24, RotationOrigin = new Point(MainWindow.TileSize / 2, MainWindow.TileSize / 2) };
Canvas.SetLeft(PointLight, 43);
Canvas.SetTop(PointLight, 32);
canvas.Children.Add(PointLight);
return canvas; return canvas;
} }
public Car() public Car()
@ -80,7 +87,9 @@ namespace CityGame.Classes.Entities
Cars.Add(this); Cars.Add(this);
JourneyFinished += c => { }; JourneyFinished += c => { };
JourneyImpossible += c => { }; JourneyImpossible += c => { };
Move += c => { };
} }
public event CarEvent Move;
public override void Tick(long deltaTime) public override void Tick(long deltaTime)
{ {
@ -92,11 +101,12 @@ namespace CityGame.Classes.Entities
new Tuple<TileType, string>(TileType.Road, "1"), new Tuple<TileType, string>(TileType.Road, "1"),
new Tuple<TileType, string>(TileType.Garage, null) new Tuple<TileType, string>(TileType.Garage, null)
}; };
if (this == MainWindow.Selected) Debug.WriteLine("Selected.");
Tile myTile = MainWindow.Grid[Point.X, Point.Y]; Tile myTile = MainWindow.Grid[Point.X, Point.Y];
bool fullBlock = fullBlockTiles.Any(x => (x.Item1 == myTile.Type || (x.Item1 == TileType.Road && (myTile.Type == TileType.Path || myTile.Type == TileType.Highway || myTile.Type == TileType.Bridge || myTile.Type == TileType.HighwayBridge))) && (x.Item2 == myTile.Pattern.PatternCode || x.Item2 is null)); bool fullBlock = fullBlockTiles.Any(x => (x.Item1 == myTile.Type || (x.Item1 == TileType.Road && (myTile.Type == TileType.Path || myTile.Type == TileType.Highway || myTile.Type == TileType.Bridge || myTile.Type == TileType.HighwayBridge))) && (x.Item2 == myTile.Pattern.PatternCode || x.Item2 is null));
if (myTile.Type == TileType.Garage) if (myTile.Type == TileType.Garage)
{ {
Rotation = ((Canvas)myTile.Element).Children[1].Rotation-90; Rotation = ((Canvas)myTile.Element).Children[1].Rotation - 90;
lights.ForEach(x => x.Visible = false); lights.ForEach(x => x.Visible = false);
} }
else lights.ForEach(x => x.Visible = true); else lights.ForEach(x => x.Visible = true);
@ -106,10 +116,11 @@ namespace CityGame.Classes.Entities
if (Path is null) if (Path is null)
{ {
var pf = MainWindow.pathfinder; var pf = MainWindow.pathfinder;
if (desperate) pf = MainWindow.pathfinderDesperate; if (grid == 2) pf = MainWindow.pathfinderDesperate;
Path = pf.FindPath(Point.Convert(), new Point((int)(Target.X() / MainWindow.TileSize), (int)(Target.Y() / MainWindow.TileSize)).Convert()).Select(x => x.Convert()).ToArray(); Path = pf.FindPath(Point.Convert(), new Point((int)(Target.X() / MainWindow.TileSize), (int)(Target.Y() / MainWindow.TileSize)).Convert()).Select(x => x.Convert()).ToArray();
NextTarget = 0; NextTarget = 0;
} }
if(new Point(Target.X() / 64, Target.Y() / 64) != Point) Move(this);
if (Path.Length == 0) if (Path.Length == 0)
{ {
JourneyImpossible(this); JourneyImpossible(this);
@ -150,18 +161,40 @@ namespace CityGame.Classes.Entities
float degrees = (float)(Math.Atan2(direction.Y, direction.X) * (180 / Math.PI)) + 90; float degrees = (float)(Math.Atan2(direction.Y, direction.X) * (180 / Math.PI)) + 90;
Rotation = degrees; Rotation = degrees;
Tile targetTile = MainWindow.Grid[nextTarget.X, nextTarget.Y]; Tile targetTile = MainWindow.Grid[nextTarget.X, nextTarget.Y];
Car blockingCar = null;
if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90) if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
{ {
if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.Add(myTile, this); if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.Add(myTile, this);
if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.Add(myTile, this); if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.Add(myTile, this);
if (OccupiedTiles.ContainsKey(targetTile) && OccupiedTiles[targetTile] != this) SpeedMulti = 0; if (OccupiedTiles.ContainsKey(targetTile) && OccupiedTiles[targetTile] != this)
{
SpeedMulti = 0;
blockingCar = OccupiedTiles[targetTile];
}
} }
if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270) if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
{ {
if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.Add(myTile, this); if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.Add(myTile, this);
if (OccupiedTiles2.ContainsKey(targetTile) && OccupiedTiles2[targetTile] != this) SpeedMulti = 0;
if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.Add(myTile, this); if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.Add(myTile, this);
if (OccupiedTiles2.ContainsKey(targetTile) && OccupiedTiles2[targetTile] != this)
{
SpeedMulti = 0;
blockingCar = OccupiedTiles2[targetTile];
}
}
if (SpeedMulti == 0 && blockingCar is not null)
{
RerouteTimePassed += deltaTime;
if (RerouteTimePassed > TimeUntilReroute)
{
var resetFunc = MainWindow.UpdatePathfinding(targetTile, 0, 3);
blockingCar.Move += resetFunc;
}
} else
{
RerouteTimePassed = 0;
} }
var possibleDistance = Speed * deltaTime / 1000 * SpeedMulti; var possibleDistance = Speed * deltaTime / 1000 * SpeedMulti;
@ -169,7 +202,8 @@ namespace CityGame.Classes.Entities
Vector2 travelFinal = direction * finalDistance; Vector2 travelFinal = direction * finalDistance;
X += travelFinal.X; X += travelFinal.X;
Y += travelFinal.Y; Y += travelFinal.Y;
} else }
else
{ {
if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90) if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
{ {

View file

@ -9,7 +9,7 @@ namespace CityGame.Classes.Entities
{ {
public class Helicopter : Entity public class Helicopter : Entity
{ {
public float Speed { get; set; } = 256; public float Speed { get; set; } = 512;
public float RotSpeed { get; set; } = 1; public float RotSpeed { get; set; } = 1;
public bool Landed = false; public bool Landed = false;
Image Heli1; Image Heli1;
@ -93,6 +93,7 @@ namespace CityGame.Classes.Entities
if (Target is not null) if (Target is not null)
{ {
Vector2 nextTarget = new Vector2(Target.X(), Target.Y()); Vector2 nextTarget = new Vector2(Target.X(), Target.Y());
if (Target is Tile) nextTarget += new Vector2(1, 1);
if (Target is Car car) if (Target is Car car)
{ {
var correctionvector = new Vector2((float)Math.Cos(MathHelper.ToRadians(car.Rotation)), (float)Math.Sin(MathHelper.ToRadians(car.Rotation))); var correctionvector = new Vector2((float)Math.Cos(MathHelper.ToRadians(car.Rotation)), (float)Math.Sin(MathHelper.ToRadians(car.Rotation)));

View file

@ -1,18 +1,17 @@
using CityGame.Classes.Rendering; using CityGame.Classes.Rendering;
using CityGame.Classes.World;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using WPFGame;
namespace CityGame.Classes.Entities namespace CityGame.Classes.Entities
{ {
public class PoliceCar : Car public class PoliceCar : Car
{ {
public static List<PoliceCar> PCars = new List<PoliceCar>(); public static List<PoliceCar> PCars = new List<PoliceCar>();
protected LightSource sirenLight;
public PoliceCar() : base() public PoliceCar() : base()
{ {
desperate = true; grid = 2;
PCars.Add(this); PCars.Add(this);
Speed = 192; Speed = 192;
PNGFile = "PoliceCar.png"; PNGFile = "PoliceCar.png";
@ -21,25 +20,26 @@ namespace CityGame.Classes.Entities
{ {
OCanvas canvas = base.Render(); OCanvas canvas = base.Render();
sirenLight = new LightSource { Radius = 24, Angle = 24, Intensity = 4f, Color = Color.Red, Type = LightSourceType.PointLight, RotationOrigin = new Point(MainWindow.TileSize / 2) };
canvas.Children.Add(sirenLight);
lights.Add(sirenLight);
Canvas.SetLeft(sirenLight, 43);
Canvas.SetTop(sirenLight, 32);
return canvas; return canvas;
} }
public override void Tick(long deltaTime) public override void Tick(long deltaTime)
{ {
if (sirenLight is null) return; if (PointLight is null) return;
long ms = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; long ms = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
if (ms / 250 % 2 == 0) Tile myTile = MainWindow.Grid[Point.X, Point.Y]; if (myTile.Type == TileType.Garage)
{ {
sirenLight.Color = Color.Red; PointLight.Color = Color.White;
} }
else else
{ {
sirenLight.Color = Color.Blue; if (ms / 250 % 2 == 0)
{
PointLight.Color = Color.Red;
}
else
{
PointLight.Color = Color.Blue;
}
} }
base.Tick(deltaTime); base.Tick(deltaTime);

View file

@ -1,6 +1,5 @@
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using System; using System;
using System.Windows;
namespace CityGame namespace CityGame
{ {

View file

@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CityGame.Classes.Rendering namespace CityGame.Classes.Rendering
{ {

View file

@ -1,6 +1,4 @@
using System; /*
using System.IO;
/*
namespace CityGame namespace CityGame
{ {
public class CustomShader : ShaderEffect public class CustomShader : ShaderEffect

View file

@ -1,10 +1,4 @@
using System; /*
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using WPFGame;
/*
namespace CityGame.OldSourcedImage namespace CityGame.OldSourcedImage
{ {

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Val Antonini
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013-2019 Corey Murtagh
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,7 @@
Copyright 2020 Mark Heath
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Evan Reeves
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,80 @@
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="SIMPLEXNOISE-LICENSE_files/Site.css">
<title>'BSD-3-Clause' reference</title>
</head>
<body>
<div id="main-content">
<h1>BSD 3-Clause "New" or "Revised" License</h1>
<h2>SPDX identifier</h2>
<div id="license-expression">BSD-3-Clause</div>
<h2>License text</h2>
<div class="replaceable-license-text">
<p>Copyright (c) &lt;year&gt; &lt;owner&gt;. </p>
</div>
<p>Redistribution and use in source and binary forms, with or without modification, <var class="replaceable-license-text"> are</var> permitted provided
that the following conditions are met:</p>
<ul style="list-style:none">
<li>
<var class="replaceable-license-text"> 1.</var>
Redistributions of source code must retain the above copyright notice, this list of conditions
and the following disclaimer.
</li>
<li>
<var class="replaceable-license-text"> 2.</var>
Redistributions in binary form must reproduce the above copyright notice, this list of conditions
and the following disclaimer in the documentation and/or other materials provided with the
distribution.
</li>
<li>
<var class="replaceable-license-text"> 3.</var>
<var class="replaceable-license-text">
Neither the name of the copyright holder nor the names of its contributors may</var>
be used to endorse or promote products derived from this
software without specific prior written permission.
</li>
</ul>
<p>THIS SOFTWARE IS PROVIDED <var class="replaceable-license-text"> BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS</var> "AS IS" AND ANY <var class="replaceable-license-text"> EXPRESS</var> OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <var class="replaceable-license-text"> THE
COPYRIGHT HOLDER OR CONTRIBUTORS</var> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</p>
<h2>Notes</h2>
<p>Note that the Eclipse Distribution License - v 1.0 (EDL 1.0) is a match to BSD-3-Clause, even though it uses a different name.</p>
<h2>SPDX web page</h2>
<ul>
<li><a href="https://spdx.org/licenses/BSD-3-Clause.html">https://spdx.org/licenses/BSD-3-Clause.html</a></li>
</ul>
<h2>Notice</h2>
<p>This license content is provided by the <a href="https://spdx.dev/">SPDX project</a>. For more information about <b>licenses.nuget.org</b>, see <a href="https://aka.ms/licenses.nuget.org">our documentation</a>.
</p><p><i>Data pulled from <a href="https://github.com/spdx/license-list-data">spdx/license-list-data</a> on February 9, 2023.</i></p>
</div>
</body></html>

View file

@ -10,16 +10,12 @@ using SimplexNoise;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Speech.Synthesis;
using System.Speech.Synthesis.TtsEngine;
using WPFGame; using WPFGame;
using static CityGame.Classes.Entities.Car;
namespace CityGame namespace CityGame
{ {
public class Program { public static void Main() { new MainWindow(); } }
/// <summary> /// <summary>
/// Interaction logic for MainWindow.xaml /// Interaction logic for MainWindow.xaml
/// </summary> /// </summary>
@ -64,10 +60,10 @@ namespace CityGame
public static Vector2 MousePos = new Vector2(0, 0); public static Vector2 MousePos = new Vector2(0, 0);
public static PathFinder pathfinder; public static PathFinder pathfinder;
public static PathFinder pathfinderDesperate; public static PathFinder pathfinderDesperate;
public static short[,] pathfindingGrid; public static Dictionary<int, short[,]> Grids = new Dictionary<int, short[,]>();
public static short[,] pathfindingGridDesperate; public static Dictionary<int, WorldGrid> WorldGrids = new Dictionary<int, WorldGrid>();
public static List<Tile> npcWalkable = new List<Tile>(); public static List<Tile> npcWalkable = new List<Tile>();
public static List<Entity> Entities { get; set; } = new List<Entity>(); public static List<Entity> Entities { get; set; }
public const int TileSize = 64; public const int TileSize = 64;
public static Tile[,] Grid; public static Tile[,] Grid;
public static ISelectable Selected; public static ISelectable Selected;
@ -79,9 +75,63 @@ namespace CityGame
Canvas CameraCanvas = new OCanvas(); Canvas CameraCanvas = new OCanvas();
Canvas UICanvas = new OCanvas(); Canvas UICanvas = new OCanvas();
/// <summary>
/// Updates the pathfinding grids of all grid numbers includes in the "grids" parameter
/// </summary>
/// <param name="tile">The tile to update</param>
/// <param name="value">The value to update the tile to</param>
/// <param name="grids">The grids to perform the update for</param>
/// <returns>A function that should be called once the reason for the update has resolved</returns>
public static CarEvent UpdatePathfinding(Tile tile, short value, int grids = 3, params Car[] exclude)
{
Dictionary<int, short> resetValues = new Dictionary<int, short>();
foreach (var kvp in Grids)
{
if ((grids & kvp.Key) == kvp.Key)
{
resetValues[kvp.Key] = kvp.Value[tile.Y, tile.X];
kvp.Value[tile.Y, tile.X] = value;
WorldGrids[kvp.Key][tile.Y, tile.X] = value;
}
}
bool hasExecuted = false;
object lockObject = new object();
CarEvent resetFunc = (Car exclude) =>
{
lock (lockObject)
{
if (!hasExecuted)
{
hasExecuted = true;
foreach (var kvp in Grids)
{
if ((grids & kvp.Key) == kvp.Key)
{
UpdatePathfinding(tile, resetValues[kvp.Key], kvp.Key, exclude);
}
}
}
}
};
InstantiatePathfinders();
Car.Cars.ForEach(car => car.Path = !exclude.Contains(car) && (grids & car.grid) == car.grid ? null : car.Path);
return resetFunc;
}
public static void InstantiatePathfinders()
{
pathfinder = new PathFinder(WorldGrids[1], new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean });
pathfinderDesperate = new PathFinder(WorldGrids[2], new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean });
}
public static AudioListener SoundEffectListener; public static AudioListener SoundEffectListener;
public MainWindow() public MainWindow()
{ {
_graphics.PreferredBackBufferWidth = 1920;
_graphics.PreferredBackBufferHeight = 1080;
AddPenumbra(); AddPenumbra();
#region | Texture Conversions | #region | Texture Conversions |
@ -116,7 +166,7 @@ namespace CityGame
Noise.Seed = seed; Noise.Seed = seed;
int mapHeight = 100; int mapHeight = 100;
int mapWidth = 100; int mapWidth = 200;
float[,] lakeMap = Noise.Calc2D(mapWidth, mapHeight, 0.05f); float[,] lakeMap = Noise.Calc2D(mapWidth, mapHeight, 0.05f);
@ -139,6 +189,7 @@ namespace CityGame
int NPCCount = (int)Math.Ceiling(mapHeight * mapWidth / 100f); int NPCCount = (int)Math.Ceiling(mapHeight * mapWidth / 100f);
//NPCCount = 1; //NPCCount = 1;
//NPCCount = 0;
random = new Random(seed); random = new Random(seed);
@ -223,8 +274,8 @@ namespace CityGame
} }
} }
Dictionary<int, bool> decidedBridges = new Dictionary<int, bool>(); Dictionary<int, bool> decidedBridges = new Dictionary<int, bool>();
pathfindingGrid = new short[doubleWidth, doubleHeight]; Grids.Add(1, new short[doubleHeight, doubleWidth]);
pathfindingGridDesperate = new short[doubleWidth, doubleHeight]; Grids.Add(2, new short[doubleHeight, doubleWidth]);
List<Tile> bridgeTiles = new List<Tile>(); List<Tile> bridgeTiles = new List<Tile>();
List<Tile> roadTiles = new List<Tile>(); List<Tile> roadTiles = new List<Tile>();
for (int y = 0; y < doubleHeight; y++) for (int y = 0; y < doubleHeight; y++)
@ -347,19 +398,19 @@ namespace CityGame
{ {
var type = IntermediateGrid[x, y].Type; var type = IntermediateGrid[x, y].Type;
bool walkable = ((int)type) / 100 == 4; bool walkable = ((int)type) / 100 == 4;
pathfindingGridDesperate[y, x] = (short)(walkable ? 1 : 0); Grids[2][y, x] = (short)(walkable ? 1 : 0);
if (type == TileType.Path) walkable = false; if (type == TileType.Path) walkable = false;
pathfindingGrid[y, x] = (short)(walkable ? 1 : 0); Grids[1][y, x] = (short)(walkable ? 1 : 0);
if (type == TileType.Bridge) bridgeTiles.Add(IntermediateGrid[x, y]); if (type == TileType.Bridge) bridgeTiles.Add(IntermediateGrid[x, y]);
if (type == TileType.Road) roadTiles.Add(IntermediateGrid[x, y]); if (type == TileType.Road) roadTiles.Add(IntermediateGrid[x, y]);
if (type == TileType.Road || type == TileType.Bridge) npcWalkable.Add(IntermediateGrid[x, y]); if (type == TileType.Road || type == TileType.Bridge) npcWalkable.Add(IntermediateGrid[x, y]);
} }
} }
var worldGrid = new WorldGrid(pathfindingGrid); foreach (var kvp in Grids) WorldGrids.Add(kvp.Key, new WorldGrid(kvp.Value));
pathfinder = new PathFinder(worldGrid, new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean }); InstantiatePathfinders();
var worldGridDesperate = new WorldGrid(pathfindingGridDesperate);
pathfinderDesperate = new PathFinder(worldGridDesperate, new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean }); Entities = new List<Entity>();
foreach (Image image in SourcedImage.GetObjectsBySourceFile("Helipad.png")) foreach (Image image in SourcedImage.GetObjectsBySourceFile("Helipad.png"))
{ {

28
CityGame/Program.cs Normal file
View file

@ -0,0 +1,28 @@
using Microsoft.Xna.Framework.Graphics;
using WPFGame;
namespace CityGame
{
public class Program {
public static void Main() {
var menu = new MenuWindow();
}
}
public class MenuWindow : Window
{
private GraphicsDevice graphics;
public MenuWindow()
{
Show();
}
}
public class GenerationSettings
{
public GenerationSettings()
{
}
}
}