This commit is contained in:
pan.codes 2023-05-08 23:00:31 +02:00
parent bd93ae2f5f
commit e1f4d4ec11
9 changed files with 132 additions and 22 deletions

View file

@ -10,6 +10,8 @@
<ItemGroup>
<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.Lame" Version="2.0.1" />
<PackageReference Include="SimplexNoise" Version="2.0.0" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
<PackageReference Include="System.Speech" Version="7.0.0" />
@ -86,6 +88,9 @@
<None Update="Resources\Garage.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\helicopter.mp3">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Resources\Helicopter.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

View file

@ -3,6 +3,7 @@ using CityGame.Classes.World;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Windows;
@ -10,27 +11,15 @@ using WPFGame;
namespace CityGame.Classes.Entities
{
public class PoliceCar : Car
{
public static List<PoliceCar> Cars = new List<PoliceCar>();
public PoliceCar() : base()
{
Cars.Add(this);
Speed = 192;
PNGFile = "PoliceCar.png";
}
public override void Tick(long deltaTime)
{
base.Tick(deltaTime);
}
}
public class Car : Entity
{
public bool desperate = false;
public static List<Car> Cars = new List<Car>();
public delegate void CarEvent(Car car);
public event CarEvent JourneyFinished;
public event CarEvent JourneyImpossible;
public ISelectable Target { get; set; } = null;
ISelectable target = null;
public ISelectable Target { get { return target; } set { target = value; Path = null; } }
public int NextTarget { get; set; } = 0;
public Point[]? Path { get; set; } = null;
public Point Point
@ -84,20 +73,27 @@ namespace CityGame.Classes.Entities
lights.Add(blight);
lights.Add(blight2);
debugRect = new ColoredRectangle();
MainWindow.GameCanvas.Children.Add(debugRect);
return canvas;
}
public Car()
{
Cars.Add(this);
JourneyFinished += c => { };
JourneyImpossible += c => { };
}
public override void Tick(long deltaTime)
{
//deltaTime *= 500;
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)
};
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;
@ -109,7 +105,9 @@ namespace CityGame.Classes.Entities
//if(Object is not null) Object.ToolTip = Target.ToString();
if (Path is null)
{
Path = MainWindow.pathfinder.FindPath(Point.Convert(), new Point((int)(Target.X() / MainWindow.TileSize), (int)(Target.Y() / MainWindow.TileSize)).Convert()).Select(x => x.Convert()).ToArray();
var pf = MainWindow.pathfinder;
if (desperate) 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();
NextTarget = 0;
}
if (Path.Length == 0)
@ -128,6 +126,16 @@ namespace CityGame.Classes.Entities
Path = null;
NextTarget = 0;
JourneyFinished(this);
if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
{
if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.Add(myTile, this);
if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.Add(myTile, this);
}
if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
{
if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.Add(myTile, this);
if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.Add(myTile, this);
}
return;
}
if (X.CloselyEquals(nextTarget.X * MainWindow.TileSize) && Y.CloselyEquals(nextTarget.Y * MainWindow.TileSize))
@ -146,12 +154,14 @@ namespace CityGame.Classes.Entities
if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
{
if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.Add(myTile, this);
if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.Add(myTile, this);
if (OccupiedTiles.ContainsKey(targetTile) && OccupiedTiles[targetTile] != this) SpeedMulti = 0;
}
if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
{
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);
}
var possibleDistance = Speed * deltaTime / 1000 * SpeedMulti;
@ -159,6 +169,18 @@ namespace CityGame.Classes.Entities
Vector2 travelFinal = direction * finalDistance;
X += travelFinal.X;
Y += travelFinal.Y;
} else
{
if (Math.Round(Rotation) == 0 || Math.Round(Rotation) == 90)
{
if (!OccupiedTilesFill.ContainsKey(myTile)) OccupiedTilesFill.Add(myTile, this);
if (!OccupiedTilesFill2.ContainsKey(myTile) && fullBlock) OccupiedTilesFill2.Add(myTile, this);
}
if (Math.Round(Rotation) == 180 || Math.Round(Rotation) == 270)
{
if (!OccupiedTilesFill2.ContainsKey(myTile)) OccupiedTilesFill2.Add(myTile, this);
if (!OccupiedTilesFill.ContainsKey(myTile) && fullBlock) OccupiedTilesFill.Add(myTile, this);
}
}
}
}

View file

@ -1,6 +1,7 @@
using CityGame.Classes.Rendering;
using CityGame.Classes.World;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using System;
using WPFGame;
@ -19,8 +20,17 @@ namespace CityGame.Classes.Entities
public ISelectable Target;
bool Move;
public LightSource Spotlight;
SoundEffectInstance Sound;
AudioEmitter emitter;
public override OCanvas Render()
{
Sound = Window.GetSound("helicopter").CreateInstance();
Sound.IsLooped = true;
emitter = new AudioEmitter { Position = new Vector3(X, Y, 25) };
Sound.Apply3D(MainWindow.SoundEffectListener, emitter);
OCanvas canvas = new OCanvas();
Heli1 = new SourcedImage("Helicopter.png");
Heli2 = new SourcedImage("HelicopterFlight.png");
@ -52,9 +62,11 @@ namespace CityGame.Classes.Entities
public override void Tick(long deltaTime)
{
if (Heli1 is null) return;
emitter.Position = new Vector3(X, Y, 25);
Tile myTile = MainWindow.Grid[(int)(X / MainWindow.TileSize), (int)(Y / MainWindow.TileSize)];
if (myTile.Type != TileType.Helipad)
{
//if (Sound.State == SoundState.Paused || Sound.State == SoundState.Stopped) Sound.Play();
Spotlight.Visible = true;
Heli2.Visible = true;
Heli1.Visible = false;
@ -71,6 +83,7 @@ namespace CityGame.Classes.Entities
}
} else
{
if (Sound.State == SoundState.Playing) Sound.Pause();
Spotlight.Visible = false;
Blades1.Visible = true;
Blades2.Visible = false;

View file

@ -0,0 +1,48 @@
using CityGame.Classes.Rendering;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using WPFGame;
namespace CityGame.Classes.Entities
{
public class PoliceCar : Car
{
public static List<PoliceCar> PCars = new List<PoliceCar>();
protected LightSource sirenLight;
public PoliceCar() : base()
{
desperate = true;
PCars.Add(this);
Speed = 192;
PNGFile = "PoliceCar.png";
}
public override OCanvas 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;
}
public override void Tick(long deltaTime)
{
if (sirenLight is null) return;
long ms = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
if (ms / 250 % 2 == 0)
{
sirenLight.Color = Color.Red;
}
else
{
sirenLight.Color = Color.Blue;
}
base.Tick(deltaTime);
}
}
}

View file

@ -4,7 +4,7 @@ using CityGame.Classes.World;
namespace CityGame.Classes.Rendering
{
public class Pattern
public struct Pattern
{
public string PatternCode { get; set; }
public int Rotation { get; set; }

View file

@ -42,16 +42,20 @@ namespace CityGame.Classes.Rendering
if (pattern.PatternCode == "0" && Grid[x, y].Type == TileType.Garage) canvas.Children.Add(new SourcedImage("Garage.png:270"));
if (Grid[x,y].Type == TileType.Helipad) canvas.Children.Add(new SourcedImage("Helipad.png"));
Grid[x, y].Pattern = pattern;
return canvas;
}
if (type == TileType.Lake || type == TileType.River)
{
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Lake, TileType.Bridge, TileType.River, TileType.HighwayBridge);
Grid[x, y].Pattern = pattern;
return new SourcedImage("Lake" + pattern.PatternCode + ".png:" + pattern.Rotation, tooltip);
}
if (type == TileType.Park)
{
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Park, TileType.Path);
Grid[x, y].Pattern = pattern;
OCanvas canvas = new SourcedImage("Park" + pattern.PatternCode + ".png:" + pattern.Rotation);
if (MainWindow.random.Next(0, 4) == 0) canvas.Children.Add(new SourcedImage("Tree.png:" + MainWindow.random.Next(0, 4) * 90, tooltip));
return canvas;
@ -59,6 +63,7 @@ namespace CityGame.Classes.Rendering
if (type == TileType.Road)
{
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Path, TileType.Bridge, TileType.Highway, TileType.HighwayBridge);
Grid[x, y].Pattern = pattern;
if (pattern.PatternCode == "2c") pattern.Rotation += 270;
if (pattern.PatternCode == "1") pattern.Rotation += 180;
return new SourcedImage("Road" + pattern.PatternCode + ".png:" + pattern.Rotation, tooltip);
@ -66,6 +71,7 @@ namespace CityGame.Classes.Rendering
if (type == TileType.Highway)
{
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Path, TileType.Bridge, TileType.Highway, TileType.HighwayBridge);
Grid[x, y].Pattern = pattern;
if (pattern.PatternCode == "2c") pattern.Rotation += 270;
if (pattern.PatternCode == "1") pattern.Rotation += 180;
return new SourcedImage("Highway" + pattern.PatternCode + ".png:" + pattern.Rotation, tooltip);
@ -74,6 +80,7 @@ namespace CityGame.Classes.Rendering
{
Pattern roadpattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Path, TileType.Bridge, TileType.Highway, TileType.HighwayBridge);
Pattern parkpattern = Pattern.Calculate(Grid, x, y, TileType.Path, TileType.Park);
Grid[x, y].Pattern = roadpattern;
if (roadpattern.PatternCode == "2c") roadpattern.Rotation += 270;
if (roadpattern.PatternCode == "1") roadpattern.Rotation += 180;
Image path = new SourcedImage("Path" + roadpattern.PatternCode + ".png:" + roadpattern.Rotation, tooltip);
@ -88,6 +95,7 @@ namespace CityGame.Classes.Rendering
{
Pattern roadpattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Bridge, TileType.Path, TileType.Highway, TileType.HighwayBridge);
Pattern parkpattern = Pattern.Calculate(Grid, x, y, TileType.Bridge, TileType.Lake, TileType.River, TileType.HighwayBridge);
Grid[x, y].Pattern = roadpattern;
if (roadpattern.PatternCode == "2c") roadpattern.Rotation += 270;
if (roadpattern.PatternCode == "1") roadpattern.Rotation += 180;
Image path = new SourcedImage("Bridge" + roadpattern.PatternCode + ".png:" + roadpattern.Rotation, tooltip);
@ -102,6 +110,7 @@ namespace CityGame.Classes.Rendering
{
Pattern roadpattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Bridge, TileType.Path, TileType.Highway, TileType.HighwayBridge);
Pattern parkpattern = Pattern.Calculate(Grid, x, y, TileType.Bridge, TileType.Lake, TileType.River, TileType.HighwayBridge);
Grid[x, y].Pattern = roadpattern;
if (roadpattern.PatternCode == "2c") roadpattern.Rotation += 270;
if (roadpattern.PatternCode == "1") roadpattern.Rotation += 180;
Image path = new SourcedImage("HighwayBridge" + roadpattern.PatternCode + ".png:" + roadpattern.Rotation, tooltip);

View file

@ -7,6 +7,7 @@ namespace CityGame.Classes.World
{
public int BlockID;
public TileType Type;
public Pattern Pattern;
public int X;
public int Y;
public UIElement Element;

View file

@ -4,6 +4,7 @@ using CityGame.Classes.Entities;
using CityGame.Classes.Rendering;
using CityGame.Classes.World;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Input;
using SimplexNoise;
using System;
@ -12,6 +13,7 @@ using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Speech.Synthesis;
using System.Speech.Synthesis.TtsEngine;
using WPFGame;
namespace CityGame
@ -61,6 +63,7 @@ namespace CityGame
public static bool MouseIsDown = false;
public static Vector2 MousePos = new Vector2(0, 0);
public static PathFinder pathfinder;
public static PathFinder pathfinderDesperate;
public static short[,] pathfindingGrid;
public static short[,] pathfindingGridDesperate;
public static List<Tile> npcWalkable = new List<Tile>();
@ -75,6 +78,8 @@ namespace CityGame
internal static Canvas GameCanvas = new OCanvas();
Canvas CameraCanvas = new OCanvas();
Canvas UICanvas = new OCanvas();
public static AudioListener SoundEffectListener;
public MainWindow()
{
AddPenumbra();
@ -353,7 +358,8 @@ namespace CityGame
var worldGrid = new WorldGrid(pathfindingGrid);
pathfinder = new PathFinder(worldGrid, new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean });
var worldGridDesperate = new WorldGrid(pathfindingGridDesperate);
pathfinderDesperate = new PathFinder(worldGridDesperate, new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean });
foreach (Image image in SourcedImage.GetObjectsBySourceFile("Helipad.png"))
{
@ -393,11 +399,14 @@ namespace CityGame
Entities.Add(car);
}
SoundEffectListener = new AudioListener { Position = new Vector3(0, 0, 100) };
Show();
}
int swv;
protected override Color SkyColor(long SpeedFactor)
{
return Color.Black;
return base.SkyColor(180);
}
protected override void Update(GameTime time)
@ -410,6 +419,7 @@ namespace CityGame
var diff = newpos - MousePos;
diff /= CameraZoom;
CameraPosition += diff;
SoundEffectListener.Position = new Vector3(CameraPosition, SoundEffectListener.Position.Z);
}
MousePos = new Vector2(state.X, state.Y);
@ -425,6 +435,8 @@ namespace CityGame
if (delta != 0)
{
if (multi > 1) SoundEffectListener.Position = new Vector3(SoundEffectListener.Position.X, SoundEffectListener.Position.Y, SoundEffectListener.Position.Z - 10);
else SoundEffectListener.Position = new Vector3(SoundEffectListener.Position.X, SoundEffectListener.Position.Y, SoundEffectListener.Position.Z + 10);
CameraZoom *= multi;
}

Binary file not shown.