This commit is contained in:
pan.codes 2023-05-21 19:04:10 +02:00
parent 18dce569c0
commit e98762df73
16 changed files with 333 additions and 93 deletions

View file

@ -13,6 +13,18 @@
<None Remove="Assemblies\**" />
<None Remove="Classes\Rendering\Particles\explosion.cfx" />
<EmbeddedResource Include="Classes\Rendering\Particles\explosion.cfx" />
<None Update="Resources\Audio\in_custody0.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\Audio\missing0.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\Audio\missing1.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\ExplosionHole.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\NoiseTexture.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
@ -110,7 +122,7 @@
<None Update="Resources\Garage.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\Audio\helicopter.mp3">
<None Update="Resources\Audio\helicopter0.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\Helicopter.png">

View file

@ -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<Car> Cars = new List<Car>();
@ -41,10 +43,10 @@ namespace CityGame.Classes.Entities
}
public float Speed { get; set; } = 128;
float currentSpeed = 0;
public static ConcurrentDictionary<Tile, Car> OccupiedTilesFill = new ConcurrentDictionary<Tile, Car>();
public static ConcurrentDictionary<Tile, Car> OccupiedTiles = new ConcurrentDictionary<Tile, Car>();
public static ConcurrentDictionary<Tile, Car> OccupiedTilesFill2 = new ConcurrentDictionary<Tile, Car>();
public static ConcurrentDictionary<Tile, Car> OccupiedTiles2 = new ConcurrentDictionary<Tile, Car>();
public static ConcurrentDictionary<Tile, ConcurrentBag<Car>> OccupiedTilesFill = new ConcurrentDictionary<Tile, ConcurrentBag<Car>>();
public static ConcurrentDictionary<Tile, ConcurrentBag<Car>> OccupiedTiles = new ConcurrentDictionary<Tile, ConcurrentBag<Car>>();
public static ConcurrentDictionary<Tile, ConcurrentBag<Car>> OccupiedTilesFill2 = new ConcurrentDictionary<Tile, ConcurrentBag<Car>>();
public static ConcurrentDictionary<Tile, ConcurrentBag<Car>> OccupiedTiles2 = new ConcurrentDictionary<Tile, ConcurrentBag<Car>>();
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<Point[]> 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<TileType, string>[] fullBlockTiles = new Tuple<TileType, string>[]
visualX = X;
visualY = Y;
visualRotation = Rotation;
UseVisualPosition = true;
float r = Rotation;
if (laneMode == LaneMode.WrongLane)
{
new Tuple<TileType, string>(TileType.Road, "4c"),
new Tuple<TileType, string>(TileType.Road, "3c"),
new Tuple<TileType, string>(TileType.Road, "1"),
new Tuple<TileType, string>(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<TileType, string>[] fullBlockTiles = new Tuple<TileType, string>[]
{
new Tuple<TileType, string>(TileType.Road, "4c"),
new Tuple<TileType, string>(TileType.Road, "3c"),
new Tuple<TileType, string>(TileType.Road, "1"),
new Tuple<TileType, string>(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);
}
}
}

View file

@ -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<Tile> targetTiles = new List<Tile>();
public static List<CriminalCar> CCars = new List<CriminalCar>();
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();
}
}
}
}

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -12,6 +12,7 @@ namespace CityGame.Classes.Entities
public PoliceCar() : base()
{
grid = 2;
mightSwitchLane = true;
PCars.Add(this);
Speed = 192;
PNGFile = "PoliceCar.png";

View file

@ -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<T1, T2>(this ConcurrentDictionary<T1, ConcurrentBag<T2>> list, T1 myTile, T2 car)
{
if(!list.ContainsKey(myTile)) list.TryAdd(myTile, new ConcurrentBag<T2>());
list[myTile].Add(car);
}
}
}

View file

@ -69,5 +69,11 @@ namespace CityGame.Classes.Rendering
{ "#fc4141", "#4141fc" },
{ "#b80000", "#0000b8" }
};
public static Dictionary<string, string> CarToCaughtCar = new Dictionary<string, string>()
{
{ "#ff0000", "#00ff00" },
{ "#fc4141", "#41fc41" },
{ "#b80000", "#00b800" }
};
}
}

View file

@ -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);

View file

@ -2,6 +2,8 @@
{
public enum TileType
{
Invalid = -100,
Skyscraper = 100,
House = 101,
Helipad = 102,

View file

@ -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<Tile>();
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<IntPoint>();
var processed = new List<IntPoint>();
searchers.Add(startPoint);
while (!resultFound)
{
if (searchers.Count == 0) return new IntPoint(-1, -1);
var s = searchers.ToList();
searchers = new List<IntPoint>();
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;
}
/// <summary>
/// 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
/// </summary>
/// <param name="tile">The tile to update</param>
/// <param name="value">The value to update the tile to</param>
@ -163,16 +215,18 @@ namespace CityGame
ImageConverter.ChangeColor("Error", "ErrorRed", new Dictionary<string, string> { { "#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<string, string>());
#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<Tile, Car>();
Car.OccupiedTilesFill = new System.Collections.Concurrent.ConcurrentDictionary<Tile, System.Collections.Concurrent.ConcurrentBag<Car>>();
Car.OccupiedTiles2 = Car.OccupiedTilesFill2;
Car.OccupiedTilesFill2 = new System.Collections.Concurrent.ConcurrentDictionary<Tile, Car>();
Car.OccupiedTilesFill2 = new System.Collections.Concurrent.ConcurrentDictionary<Tile, System.Collections.Concurrent.ConcurrentBag<Car>>();
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 B