diff --git a/CityGame/CityGame.csproj b/CityGame/CityGame.csproj
index a921639..6212e42 100644
--- a/CityGame/CityGame.csproj
+++ b/CityGame/CityGame.csproj
@@ -13,6 +13,18 @@
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
@@ -110,7 +122,7 @@
PreserveNewest
-
+
Always
diff --git a/CityGame/Classes/Entities/Car.cs b/CityGame/Classes/Entities/Car.cs
index 22769c3..1b18165 100644
--- a/CityGame/Classes/Entities/Car.cs
+++ b/CityGame/Classes/Entities/Car.cs
@@ -11,12 +11,14 @@ using System.Threading;
using AStar;
using System.Threading.Tasks;
using System.Collections.Concurrent;
+using NAudio.Wave;
namespace CityGame.Classes.Entities
{
public class Car : Entity
{
public int grid = 1;
+ public bool mightSwitchLane = false;
public long TimeUntilReroute = 5000;
protected long RerouteTimePassed = 0;
public static List Cars = new List();
@@ -41,10 +43,10 @@ namespace CityGame.Classes.Entities
}
public float Speed { get; set; } = 128;
float currentSpeed = 0;
- public static ConcurrentDictionary OccupiedTilesFill = new ConcurrentDictionary();
- public static ConcurrentDictionary OccupiedTiles = new ConcurrentDictionary();
- public static ConcurrentDictionary OccupiedTilesFill2 = new ConcurrentDictionary();
- public static ConcurrentDictionary OccupiedTiles2 = new ConcurrentDictionary();
+ public static ConcurrentDictionary> OccupiedTilesFill = new ConcurrentDictionary>();
+ public static ConcurrentDictionary> OccupiedTiles = new ConcurrentDictionary>();
+ public static ConcurrentDictionary> OccupiedTilesFill2 = new ConcurrentDictionary>();
+ public static ConcurrentDictionary> OccupiedTiles2 = new ConcurrentDictionary>();
protected string PNGFile = "NPCCar.png";
protected ColoredRectangle debugRect;
protected Tile lastTile;
@@ -101,6 +103,12 @@ namespace CityGame.Classes.Entities
private float curveModePixelDuration;
private int curveModeStartedAt;
private bool pathfindingInProgress;
+ LaneMode laneMode = LaneMode.Default;
+ private long laneSwitchCooldown = 0;
+ enum LaneMode
+ {
+ WrongLane = -1, Parked = 0, Default = 1
+ }
private async Task CalculatePathAsync(Point start, Point target, PathFinder pathfinder)
{
return await Task.Run(() =>
@@ -110,18 +118,19 @@ namespace CityGame.Classes.Entities
}
public override async void Tick(long deltaTime)
{
- //deltaTime /= 10;
- //deltaTime *= 500;
- Tuple[] fullBlockTiles = new Tuple[]
+ visualX = X;
+ visualY = Y;
+ visualRotation = Rotation;
+ UseVisualPosition = true;
+ float r = Rotation;
+ if (laneMode == LaneMode.WrongLane)
{
- new Tuple(TileType.Road, "4c"),
- new Tuple(TileType.Road, "3c"),
- new Tuple(TileType.Road, "1"),
- new Tuple(TileType.Garage, null)
- };
- //if (this == MainWindow.Selected) Debug.WriteLine("Selected.");
+ r = (r + 180) % 360;
+ Vector2 offsetVector = new Vector2(0,-1).RotateBy(Rotation - 90) * MainWindow.TileSize / 3;
+ visualX += offsetVector.X;
+ visualY += offsetVector.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));
if (myTile.Type == TileType.Garage)
{
Rotation = ((Canvas)myTile.Element).Children[1].Rotation - 90;
@@ -163,16 +172,7 @@ namespace CityGame.Classes.Entities
Path = null;
NextTarget = 0;
JourneyFinished(this);
- if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
- {
- if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.TryAdd(myTile, this);
- if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.TryAdd(myTile, this);
- }
- if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
- {
- if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.TryAdd(myTile, this);
- if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.TryAdd(myTile, this);
- }
+ DoLaneBlockades();
return;
}
if (X.CloselyEquals(nextTarget.X * MainWindow.TileSize) && Y.CloselyEquals(nextTarget.Y * MainWindow.TileSize))
@@ -189,30 +189,35 @@ namespace CityGame.Classes.Entities
Tile targetTile = MainWindow.Grid[nextTarget.X, nextTarget.Y];
Car blockingCar = null;
- if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
+ DoLaneBlockades();
+ if (Math.Round(r) == 0 || Math.Round(r) == 90)
{
- if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.TryAdd(myTile, this);
- if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.TryAdd(myTile, this);
- if (OccupiedTiles.ContainsKey(targetTile) && OccupiedTiles[targetTile] != this)
+ if (OccupiedTiles.ContainsKey(targetTile) && OccupiedTiles[targetTile].Any(x => x != this))
{
SpeedMulti = 0;
- blockingCar = OccupiedTiles[targetTile];
+ blockingCar = OccupiedTiles[targetTile].First(x => x != this);
+ if (blockingCar is null) blockingCar = this;
}
}
- if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
+ if (Math.Round(r) == 180 || Math.Round(r) == 270)
{
- if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.TryAdd(myTile, this);
- if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.TryAdd(myTile, this);
- if (OccupiedTiles2.ContainsKey(targetTile) && OccupiedTiles2[targetTile] != this)
+ if (OccupiedTiles2.ContainsKey(targetTile) && OccupiedTiles2[targetTile].Any(x => x != this))
{
SpeedMulti = 0;
- blockingCar = OccupiedTiles2[targetTile];
+ blockingCar = OccupiedTiles2[targetTile].First(x => x != this);
+ if (blockingCar is null) blockingCar = this;
}
}
+ laneSwitchCooldown -= (long)Speed * deltaTime;
if (SpeedMulti == 0 && blockingCar is not null)
{
RerouteTimePassed += deltaTime;
+ if (mightSwitchLane && laneSwitchCooldown <= 0)
+ {
+ laneMode = (LaneMode)((int)laneMode * -1);
+ laneSwitchCooldown = MainWindow.TileSize * 3 * 1000;
+ }
if (RerouteTimePassed > TimeUntilReroute)
{
var resetFunc = MainWindow.UpdatePathfinding(targetTile, 0, 3);
@@ -221,6 +226,7 @@ namespace CityGame.Classes.Entities
}
else
{
+ if (laneSwitchCooldown <= 0) laneMode = LaneMode.Default;
RerouteTimePassed = 0;
}
@@ -251,11 +257,11 @@ namespace CityGame.Classes.Entities
}
}
+ if (this is CriminalCar && SpeedMulti > 0 && deltaTime > 0) Debug.WriteLine("running");
var possibleDistance = Speed * deltaTime / 1000 * SpeedMulti;
var finalDistance = Math.Min(possibleDistance, travel.Length());
Vector2 travelFinal = direction * finalDistance;
- UseVisualPosition = false;
if (curveMode != 0)
{
float rotationStart = MainWindow.TileSize * 1.25f;
@@ -265,8 +271,6 @@ namespace CityGame.Classes.Entities
if (curveModePixelDuration <= rotationEnd) curveMode = 0;
else
{
- UseVisualPosition = true;
-
if (curveModePixelDuration < rotationStart && curveModePixelDuration > rotationEnd)
{
float percentage = (curveModePixelDuration - rotationEnd) / (rotationStart - rotationEnd);
@@ -284,15 +288,10 @@ namespace CityGame.Classes.Entities
vRotDeg = (-45 * percentage2) * curveMode;
}
if (this == MainWindow.Selected) Debug.WriteLine(vRotDeg);
- visualX = X;
- visualY = Y;
- visualRotation = Rotation + vRotDeg;
+ visualRotation += vRotDeg;
}
else
{
- visualX = X;
- visualY = Y;
- visualRotation = Rotation;
}
}
}
@@ -302,16 +301,33 @@ namespace CityGame.Classes.Entities
}
else
{
- if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
- {
- if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.TryAdd(myTile, this);
- if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.TryAdd(myTile, this);
- }
- if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
- {
- if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.TryAdd(myTile, this);
- if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.TryAdd(myTile, this);
- }
+ DoLaneBlockades();
+ }
+ }
+ public void DoLaneBlockades()
+ {
+ Tuple[] fullBlockTiles = new Tuple[]
+ {
+ new Tuple(TileType.Road, "4c"),
+ new Tuple(TileType.Road, "3c"),
+ new Tuple(TileType.Road, "1"),
+ new Tuple(TileType.Garage, null)
+ };
+ //if (this == MainWindow.Selected) Debug.WriteLine("Selected.");
+ 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));
+ if (laneMode == LaneMode.Parked) return;
+ float r = Rotation;
+ if (laneMode == LaneMode.WrongLane) r = (r + 180) % 360;
+ if (Math.Round(r) == 0 || Math.Round(r) == 90)
+ {
+ if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.WeirdAddToList(myTile, this);
+ if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.WeirdAddToList(myTile, this);
+ }
+ if (Math.Round(r) == 180 || Math.Round(r) == 270)
+ {
+ if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.WeirdAddToList(myTile, this);
+ if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.WeirdAddToList(myTile, this);
}
}
}
diff --git a/CityGame/Classes/Entities/CriminalCar.cs b/CityGame/Classes/Entities/CriminalCar.cs
new file mode 100644
index 0000000..3e25b04
--- /dev/null
+++ b/CityGame/Classes/Entities/CriminalCar.cs
@@ -0,0 +1,89 @@
+using CityGame.Classes.Rendering;
+using CityGame.Classes.World;
+using Microsoft.Xna.Framework;
+using OrpticonGameHelper;
+using OrpticonGameHelper.Classes.Elements;
+using SixLabors.ImageSharp.Processing;
+using System;
+using System.Collections.Generic;
+
+namespace CityGame.Classes.Entities
+{
+ public class CriminalCar : Car
+ {
+ public long CaughtTimer { get; set; }
+ public bool GotAway { get; set; } = false;
+ public bool Caught { get; set; } = false;
+ public static List targetTiles = new List();
+ public static List CCars = new List();
+ public CriminalCar() : base()
+ {
+ CCars.Add(this);
+ if (targetTiles.Count == 0)
+ {
+ for (int x = 0; x < MainWindow.Grid.GetLength(0); x++)
+ {
+ targetTiles.Add(MainWindow.Grid[x, 0]);
+ targetTiles.Add(MainWindow.Grid[x, MainWindow.Grid.GetLength(1) - 1]);
+ }
+ for (int y = 0; y < MainWindow.Grid.GetLength(1); y++)
+ {
+ targetTiles.Add(MainWindow.Grid[0, y]);
+ targetTiles.Add(MainWindow.Grid[MainWindow.Grid.GetLength(0) - 1, y]);
+ }
+ }
+ grid = 2;
+ //mightSwitchLane = true;
+ Speed = 160;
+ PNGFile = "CriminalCar.png";
+ TimeUntilReroute = 1000;
+ }
+ public override OCanvas Render()
+ {
+ OCanvas canvas = base.Render();
+
+ return canvas;
+ }
+ public override void Tick(long deltaTime)
+ {
+ if (!Caught && !GotAway)
+ {
+ if (CaughtTimer >= 0)
+ {
+ if (Path is null || Path.Length == 0)
+ {
+ var myTile = MainWindow.Grid[(int)X / MainWindow.TileSize, (int)Y / MainWindow.TileSize];
+ Target = MainWindow.FindNearestTile(myTile, MainWindow.Grids[grid], targetTiles.ToArray());
+ if (Target is Tile tile && tile.X == myTile.X && tile.Y == myTile.Y)
+ {
+ GotAway = true;
+ Window.FireSound("missing");
+ Object.Visible = false;
+ }
+ }
+
+ base.Tick(deltaTime);
+
+ if (Path is null || Path.Length == 0)
+ {
+ CaughtTimer -= deltaTime;
+ }
+ else
+ {
+ CaughtTimer = 10000;
+ }
+ }
+ else
+ {
+ ((SourcedImage)Object.Children[0]).Source = Environment.CurrentDirectory + "\\Resources\\CaughtCar.png";
+ Caught = true;
+ Window.FireSound("in_custody");
+ }
+ }
+ if(Caught)
+ {
+ DoLaneBlockades();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/CityGame/Classes/Entities/Entity.cs b/CityGame/Classes/Entities/Entity.cs
index a9154e4..4d8a5ec 100644
--- a/CityGame/Classes/Entities/Entity.cs
+++ b/CityGame/Classes/Entities/Entity.cs
@@ -48,13 +48,14 @@ namespace CityGame.Classes.Entities
if (pipe.Exploded > 0) return false;
Explosion x = new Explosion();
pipe.canvas.Children.Add(x);
- Canvas.SetLeft(x, pipe.GetParticleOrigin().X);
- Canvas.SetTop(x, pipe.GetParticleOrigin().Y);
+ Canvas.SetLeft(x, pipe.GetParticleOrigin().X - 8);
+ Canvas.SetTop(x, pipe.GetParticleOrigin().Y - 8);
x.RotationOrigin = new Microsoft.Xna.Framework.Point(MainWindow.TileSize / 2);
x.Size = 16;
x.MaxParticleDistance = 32;
x.Emit();
pipe.Exploded = 1;
+ pipe.image.Source = pipe.image.Source.Replace("ManholeCover", "ExplosionHole");
return true;
}
return false;
diff --git a/CityGame/Classes/Entities/GasPipe.cs b/CityGame/Classes/Entities/GasPipe.cs
index 4b97e8f..98d9cd5 100644
--- a/CityGame/Classes/Entities/GasPipe.cs
+++ b/CityGame/Classes/Entities/GasPipe.cs
@@ -1,5 +1,7 @@
-using CityGame.Classes.Rendering;
+using AStar.Collections.MultiDimensional;
+using CityGame.Classes.Rendering;
using CityGame.Classes.Rendering.Particles;
+using CityGame.Classes.World;
using Microsoft.Xna.Framework;
using OrpticonGameHelper.Classes.Elements;
@@ -8,9 +10,9 @@ namespace CityGame.Classes.Entities
public class GasPipe : Entity
{
public long Exploded { get; set; }
+ public long LastSmoke { get; set; }
public Image image { get; set; }
public OCanvas canvas { get; set; }
- public Explosion Smoke { get; set; }
public GasPipe()
{
if (MainWindow.random.Next(0, 2) == 0) Rotation += 180;
@@ -32,31 +34,36 @@ namespace CityGame.Classes.Entities
if (Exploded > 0)
{
Exploded += deltaTime;
- if(Smoke is null)
+ LastSmoke += deltaTime;
+ if (LastSmoke > 0 && Exploded < 6500)
{
+ LastSmoke -= 500;
CreateSmoke();
}
+ Tile tile = MainWindow.Grid[(int)(X / MainWindow.TileSize), (int)(Y / MainWindow.TileSize)];
+ Car.OccupiedTilesFill.WeirdAddToList(tile, null);
+ Car.OccupiedTilesFill2.WeirdAddToList(tile, null);
}
}
- void CreateSmoke()
+ Explosion CreateSmoke()
{
Explosion smoke = new Explosion();
smoke.DirectionTendency = MainWindow.Wind;
smoke.DirectionVariance = 22.5f;
- smoke.MinColor = Color.LightGray;
- smoke.MaxColor = Color.DarkGray;
+ smoke.MinColor = new Color(225, 225, 225);
+ smoke.MaxColor = new Color(30, 30, 30);
smoke.MaxParticleDistance = MainWindow.TileSize * 3;
- smoke.EmissionTime = 3;
+ smoke.EmissionTime = 6;
smoke.ParticleCountMin = 1;
smoke.ParticleCountMax = 2;
smoke.Size = 16;
smoke.RotationOrigin = new Microsoft.Xna.Framework.Point(MainWindow.TileSize / 2);
smoke.EaseMovement = false;
- Smoke = smoke;
- Object.Children.Add(Smoke);
- Canvas.SetLeft(Smoke, GetParticleOrigin().X);
- Canvas.SetTop(Smoke, GetParticleOrigin().Y);
+ Object.Children.Add(smoke);
+ Canvas.SetLeft(smoke, GetParticleOrigin().X - 8);
+ Canvas.SetTop(smoke, GetParticleOrigin().Y - 8);
smoke.Emit().ContinueWith(t => CreateSmoke());
+ return smoke;
}
}
}
diff --git a/CityGame/Classes/Entities/PoliceCar.cs b/CityGame/Classes/Entities/PoliceCar.cs
index bebc257..8fbbc72 100644
--- a/CityGame/Classes/Entities/PoliceCar.cs
+++ b/CityGame/Classes/Entities/PoliceCar.cs
@@ -12,6 +12,7 @@ namespace CityGame.Classes.Entities
public PoliceCar() : base()
{
grid = 2;
+ mightSwitchLane = true;
PCars.Add(this);
Speed = 192;
PNGFile = "PoliceCar.png";
diff --git a/CityGame/Classes/Misc/Extensions.cs b/CityGame/Classes/Misc/Extensions.cs
index 6fc534c..15b958d 100644
--- a/CityGame/Classes/Misc/Extensions.cs
+++ b/CityGame/Classes/Misc/Extensions.cs
@@ -1,5 +1,8 @@
-using Microsoft.Xna.Framework;
+using CityGame.Classes.Entities;
+using CityGame.Classes.World;
+using Microsoft.Xna.Framework;
using System;
+using System.Collections.Concurrent;
using System.Numerics;
using System.Reflection.Metadata;
@@ -45,5 +48,10 @@ namespace CityGame
float rotatedY = v.X * sin + v.Y * cos;
return new System.Numerics.Vector2(rotatedX, rotatedY);
}
+ public static void WeirdAddToList(this ConcurrentDictionary> list, T1 myTile, T2 car)
+ {
+ if(!list.ContainsKey(myTile)) list.TryAdd(myTile, new ConcurrentBag());
+ list[myTile].Add(car);
+ }
}
}
\ No newline at end of file
diff --git a/CityGame/Classes/Rendering/ColorConversionMaps.cs b/CityGame/Classes/Rendering/ColorConversionMaps.cs
index 4e90312..ff37bc6 100644
--- a/CityGame/Classes/Rendering/ColorConversionMaps.cs
+++ b/CityGame/Classes/Rendering/ColorConversionMaps.cs
@@ -69,5 +69,11 @@ namespace CityGame.Classes.Rendering
{ "#fc4141", "#4141fc" },
{ "#b80000", "#0000b8" }
};
+ public static Dictionary CarToCaughtCar = new Dictionary()
+ {
+ { "#ff0000", "#00ff00" },
+ { "#fc4141", "#41fc41" },
+ { "#b80000", "#00b800" }
+ };
}
}
diff --git a/CityGame/Classes/Rendering/IntPoint.cs b/CityGame/Classes/Rendering/IntPoint.cs
index ff3a1af..7afe630 100644
--- a/CityGame/Classes/Rendering/IntPoint.cs
+++ b/CityGame/Classes/Rendering/IntPoint.cs
@@ -1,4 +1,6 @@
-namespace CityGame.Classes.Rendering
+using Microsoft.Xna.Framework;
+
+namespace CityGame.Classes.Rendering
{
public struct IntPoint
{
@@ -13,6 +15,14 @@
{
return new IntPoint(a.X + b.X, a.Y + b.Y);
}
+ public static IntPoint operator -(IntPoint a, Vector2 b)
+ {
+ return new IntPoint(a.X - (int)b.X, a.Y - (int)b.Y);
+ }
+ public static IntPoint operator +(IntPoint a, Vector2 b)
+ {
+ return new IntPoint(a.X + (int)b.X, a.Y + (int)b.Y);
+ }
public static IntPoint operator *(IntPoint a, int b)
{
return new IntPoint(a.X * b, a.Y * b);
diff --git a/CityGame/Classes/World/TileType.cs b/CityGame/Classes/World/TileType.cs
index f140721..0189c2d 100644
--- a/CityGame/Classes/World/TileType.cs
+++ b/CityGame/Classes/World/TileType.cs
@@ -2,6 +2,8 @@
{
public enum TileType
{
+ Invalid = -100,
+
Skyscraper = 100,
House = 101,
Helipad = 102,
diff --git a/CityGame/MainWindow.cs b/CityGame/MainWindow.cs
index 4d71a1d..0f8f7d6 100644
--- a/CityGame/MainWindow.cs
+++ b/CityGame/MainWindow.cs
@@ -16,6 +16,7 @@ using OrpticonGameHelper;
using OrpticonGameHelper.Classes.Elements;
using static CityGame.Classes.Entities.Car;
using OrpticonGameHelper.Classes.Misc;
+using System.Diagnostics;
namespace CityGame
{
@@ -78,9 +79,60 @@ namespace CityGame
internal static Canvas GameCanvas = new OCanvas();
Canvas CameraCanvas = new OCanvas();
Canvas UICanvas = new OCanvas();
+ public static Tile FindNearestTile(Tile startPoint, short[,] pfGrid, params Tile[] targets)
+ {
+ var t = FindNearestTarget(new IntPoint(startPoint.X, startPoint.Y), pfGrid, targets.Select(x => new IntPoint(x.X, x.Y)).ToArray());
+ if (t.X == -1 && t.Y == -1) return new Tile { Type = TileType.Invalid };
+ return Grid[t.X, t.Y];
+ }
+ public static Tile FindNearestTile(Tile startPoint, short[,] pfGrid, TileType targetTile)
+ {
+ var targets = new List();
+ for (int i = 0; i < Grid.Length; i++)
+ {
+ if (Grid[i % Grid.GetLength(0), i / Grid.GetLength(0)].Type == targetTile) targets.Add(Grid[i % Grid.GetLength(0), i / Grid.GetLength(0)]);
+ }
+ return FindNearestTile(startPoint, pfGrid, targets.ToArray());
+ }
+ public static IntPoint FindNearestTarget(IntPoint startPoint, short[,] pfGrid, params IntPoint[] targets)
+ {
+ var directions = new Vector2[] { new Vector2(0, 1), new Vector2(1, 0), new Vector2(0, -1), new Vector2(-1, 0) };
+ IntPoint result = new IntPoint(0, 0);
+ bool resultFound = false;
+ var searchers = new List();
+ var processed = new List();
+ searchers.Add(startPoint);
+ while (!resultFound)
+ {
+ if (searchers.Count == 0) return new IntPoint(-1, -1);
+ var s = searchers.ToList();
+ searchers = new List();
+ foreach (var searcher in s)
+ {
+ if (targets.Contains(searcher))
+ {
+ result = searcher;
+ resultFound = true;
+ break;
+ }
+ foreach (var direction in directions)
+ {
+ var p = searcher + direction;
+ if (p.X < 0 || p.Y < 0) continue;
+ if (p.X >= pfGrid.GetLength(1)) continue;
+ if (p.Y >= pfGrid.GetLength(0)) continue;
+ if (processed.Contains(p)) continue;
+ if (pfGrid[p.Y, p.X] == 0) continue;
+ processed.Add(p);
+ searchers.Add(p);
+ }
+ }
+ }
+ return result;
+ }
///
- /// Updates the pathfinding grids of all grid numbers includes in the "grids" parameter
+ /// Updates the pathfinding grids of all grid numbers included in the "grids" parameter
///
/// The tile to update
/// The value to update the tile to
@@ -163,16 +215,18 @@ namespace CityGame
ImageConverter.ChangeColor("Error", "ErrorRed", new Dictionary { { "#000000", "#ff0000" } });
ImageConverter.ChangeColor("Car", "NPCCar", ColorConversionMaps.CarToNPCCar);
ImageConverter.ChangeColor("Car", "PoliceCar", ColorConversionMaps.CarToPoliceCar);
+ ImageConverter.ChangeColor("Car", "CaughtCar", ColorConversionMaps.CarToCaughtCar);
+ ImageConverter.ChangeColor("Car", "CriminalCar", new Dictionary());
#endregion
-
+
LoadableContent.Add(ShaderLoader.Create());
- int seed = 8;
+ int seed = (int)(DateTime.Now.Ticks % int.MaxValue);
Noise.Seed = seed;
- int mapHeight = 100;
- int mapWidth = 200;
+ int mapHeight = 50;
+ int mapWidth = 50;
float[,] lakeMap = Noise.Calc2D(mapWidth, mapHeight, 0.05f);
@@ -194,6 +248,7 @@ namespace CityGame
int minBlockWidth = 3;
int NPCCount = (int)Math.Ceiling(mapHeight * mapWidth / 100f);
+ int CriminalCount = 1;
//NPCCount = 1;
//NPCCount = 0;
//NPCCount /= 2;
@@ -310,6 +365,22 @@ namespace CityGame
if (IntermediateGrid[x, y].Type == TileType.Park) changeTo = TileType.Path;
if (x < doubleWidth - 1 && IntermediateGrid[x + 1, y].BlockID != myID) IntermediateGrid[x, y].Type = changeTo;
if (y < doubleHeight - 1 && IntermediateGrid[x, y + 1].BlockID != myID) IntermediateGrid[x, y].Type = changeTo;
+ var type = IntermediateGrid[x, y].Type;
+ if (type == TileType.Bridge) bridgeTiles.Add(IntermediateGrid[x, y]);
+ if (type == TileType.Road) roadTiles.Add(IntermediateGrid[x, y]);
+ bool walkable = ((int)type) / 100 == 4;
+ Grids[2][y, x] = (short)(walkable ? 1 : 0);
+ if (type == TileType.Path) walkable = false;
+ Grids[1][y, x] = (short)(walkable ? 1 : 0);
+ }
+ }
+ bool checkBridges = true;
+ if (checkBridges)
+ {
+ foreach (var tile in bridgeTiles)
+ {
+ IntPoint road = FindNearestTarget(new IntPoint(tile.X, tile.Y), Grids[1], roadTiles.Select(x => new IntPoint(x.X, x.Y)).ToArray());
+ if (road.X == -1 && road.Y == -1) IntermediateGrid[tile.X, tile.Y].Type = TileType.Lake;
}
}
@@ -355,9 +426,21 @@ namespace CityGame
startPoint += step;
}
}
- #endregion
+ for (int y = 0; y < doubleHeight; y++)
+ {
+ for (int x = 0; x < doubleWidth; x++)
+ {
+ var type = IntermediateGrid[x, y].Type;
+ bool walkable = ((int)type) / 100 == 4;
+ Grids[2][y, x] = (short)(walkable ? 1 : 0);
+ if (type == TileType.Path) walkable = false;
+ Grids[1][y, x] = (short)(walkable ? 1 : 0);
+ if (type == TileType.Road || type == TileType.Bridge) npcWalkable.Add(IntermediateGrid[x, y]);
+ }
+ }
Grid = IntermediateGrid;
+ #endregion
//for(int y = 0; y < mapHeight; y++)
//{
// for(int x = 0; x < mapWidth; x++)
@@ -400,20 +483,6 @@ namespace CityGame
GameCanvas.Children.Add(image);
}
}
- for (int y = 0; y < doubleHeight; y++)
- {
- for (int x = 0; x < doubleWidth; x++)
- {
- var type = IntermediateGrid[x, y].Type;
- bool walkable = ((int)type) / 100 == 4;
- Grids[2][y, x] = (short)(walkable ? 1 : 0);
- if (type == TileType.Path) walkable = false;
- Grids[1][y, x] = (short)(walkable ? 1 : 0);
- if (type == TileType.Bridge) bridgeTiles.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]);
- }
- }
foreach (var kvp in Grids) WorldGrids.Add(kvp.Key, new WorldGrid(kvp.Value));
InstantiatePathfinders();
@@ -436,7 +505,7 @@ namespace CityGame
Entities.Add(new PoliceCar { X = x, Y = y });
}
var roads = SourcedImage.GetObjectsBySourceFile("Road1.png", "Road2.png", "Road2c.png", "Road3c.png", "Road4c.png");
- var pipeCount = NPCCount;
+ var pipeCount = NPCCount * 2;
var pipeRoads = roads.OrderBy(x => random.Next(0, roads.Count)).Take(pipeCount).ToArray();
foreach (Image image in pipeRoads)
{
@@ -464,19 +533,35 @@ namespace CityGame
Entities.Add(car);
}
+ for (int n = 0; n < CriminalCount; n++)
+ {
+ CriminalCar car = new CriminalCar();
+ bool foundStartPoint = false;
+ Tile startTile = Grid[0, 0];
+ while(!foundStartPoint)
+ {
+ startTile = npcWalkable[random.Next(0, npcWalkable.Count)];
+ if (startTile.X > doubleWidth / 3 && startTile.Y > doubleHeight / 3 && startTile.X < doubleWidth / 3 * 2 && startTile.Y < doubleHeight / 3 * 2) foundStartPoint = true;
+ }
+
+ car.Point = new Point(startTile.X, startTile.Y);
+ Entities.Add(car);
+ }
SoundEffectListener = new AudioListener { Position = new Vector3(0, 0, 100) };
Show();
}
int swv;
+ public bool PauseEntities = true;
protected override Color SkyColor(long SpeedFactor)
{
- return base.SkyColor(180);
+ return Color.Gray;
}
protected override void Update(GameTime time)
{
MouseState state = Mouse.GetState();
+ KeyboardState kstate = Keyboard.GetState();
if (state.MiddleButton == ButtonState.Pressed)
{
@@ -522,12 +607,15 @@ namespace CityGame
Selected.RunAction(select);
}
}
+ if (kstate.IsKeyDown(Keys.Space)) PauseEntities = !PauseEntities;
+ PauseParticles = PauseEntities;
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
foreach (Entity entity in Entities)
{
long deltaTime = milliseconds - entity.Time;
deltaTime = (long)time.ElapsedGameTime.TotalMilliseconds;
+ if (PauseEntities) deltaTime = 0;
entity.Time = milliseconds;
entity.Tick(deltaTime);
entity.BaseTick(deltaTime);
@@ -542,9 +630,9 @@ namespace CityGame
Canvas.SetTop(entity.Object, entity.VisualY);
}
Car.OccupiedTiles = Car.OccupiedTilesFill;
- Car.OccupiedTilesFill = new System.Collections.Concurrent.ConcurrentDictionary();
+ Car.OccupiedTilesFill = new System.Collections.Concurrent.ConcurrentDictionary>();
Car.OccupiedTiles2 = Car.OccupiedTilesFill2;
- Car.OccupiedTilesFill2 = new System.Collections.Concurrent.ConcurrentDictionary();
+ Car.OccupiedTilesFill2 = new System.Collections.Concurrent.ConcurrentDictionary>();
}
}
}
\ No newline at end of file
diff --git a/CityGame/Resources/Audio/helicopter.mp3 b/CityGame/Resources/Audio/helicopter0.mp3
similarity index 100%
rename from CityGame/Resources/Audio/helicopter.mp3
rename to CityGame/Resources/Audio/helicopter0.mp3
diff --git a/CityGame/Resources/Audio/in_custody0.mp3 b/CityGame/Resources/Audio/in_custody0.mp3
new file mode 100644
index 0000000..8434868
Binary files /dev/null and b/CityGame/Resources/Audio/in_custody0.mp3 differ
diff --git a/CityGame/Resources/Audio/missing0.mp3 b/CityGame/Resources/Audio/missing0.mp3
new file mode 100644
index 0000000..b9b7e4e
Binary files /dev/null and b/CityGame/Resources/Audio/missing0.mp3 differ
diff --git a/CityGame/Resources/Audio/missing1.mp3 b/CityGame/Resources/Audio/missing1.mp3
new file mode 100644
index 0000000..de2d743
Binary files /dev/null and b/CityGame/Resources/Audio/missing1.mp3 differ
diff --git a/CityGame/Resources/ExplosionHole.png b/CityGame/Resources/ExplosionHole.png
new file mode 100644
index 0000000..2707a31
Binary files /dev/null and b/CityGame/Resources/ExplosionHole.png differ