Projektdateien hinzufügen.
25
CityGame.sln
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.3.32929.385
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CityGame", "CityGame\CityGame.csproj", "{5D76B596-FC17-4F47-B5C6-D811DE04F806}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{5D76B596-FC17-4F47-B5C6-D811DE04F806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5D76B596-FC17-4F47-B5C6-D811DE04F806}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5D76B596-FC17-4F47-B5C6-D811DE04F806}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5D76B596-FC17-4F47-B5C6-D811DE04F806}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {B17891C9-0FBF-46C7-8697-0CD3D795A9FD}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
9
CityGame/App.xaml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<Application x:Class="CityGame.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:CityGame"
|
||||||
|
StartupUri="MainWindow.xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
17
CityGame/App.xaml.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
10
CityGame/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
121
CityGame/CityGame.csproj
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net6.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Resources\BlueTint.hlsl" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AStarLite" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Microsoft.HLSL.CSharpVB" Version="1.0.2" />
|
||||||
|
<PackageReference Include="SimplexNoise" Version="2.0.0" />
|
||||||
|
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PixelShader Include="Resources\BlueTint.hlsl" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="Resources\Building0.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building1.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building2.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building2c.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building3.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building3a.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building3ab.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building3c.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building4.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building4c.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building4m.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building5.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building7.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Building8.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Car.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Error.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\ParkingLot.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Road2.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Road4c.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Road2c.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Road1.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Road3c.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Tree.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Vent1.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Vent2.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="Resources\Vent3.png">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
60
CityGame/ColorConversionMaps.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class ColorConversionMaps
|
||||||
|
{
|
||||||
|
|
||||||
|
public static Dictionary<string, string> HouseToLakeMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#616161", "#006bb3" },
|
||||||
|
{ "#3b3b3b", "#005485" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> LakeToRiver = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#006bb3", "#005ba3" },
|
||||||
|
{ "#005485", "#004475" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> HouseToBuildingDarkMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#616161", "#3b3b3b" },
|
||||||
|
{ "#3b3b3b", "#1b1b1b" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> HouseToBuildingBlueMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#616161", "#616181" },
|
||||||
|
{ "#3b3b3b", "#3b3b5b" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> HouseToBuildingRedMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#616161", "#816161" },
|
||||||
|
{ "#3b3b3b", "#5b3b3b" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> HouseToBuildingGreenMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#616161", "#618161" },
|
||||||
|
{ "#3b3b3b", "#3b5b3b" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> HouseToParkMap = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "#616161", "#00a34b" },
|
||||||
|
{ "#3b3b3b", "#007534" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> RoadToPathMap = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "#00000000", "#00b36b00" },
|
||||||
|
{ "#616161", "#00b36b00" },
|
||||||
|
{ "#303030", "#8a5e00" },
|
||||||
|
{ "#ffffff", "#8a5e00" }
|
||||||
|
};
|
||||||
|
public static Dictionary<string, string> RoadToBridgeMap = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "#00000000", "#00b36b00" },
|
||||||
|
{ "#616161", "#00b36b00" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
35
CityGame/CustomShader.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Effects;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class CustomShader : ShaderEffect
|
||||||
|
{
|
||||||
|
private const string _kshaderAsBase64 = @"AAP///7/HwBDVEFCHAAAAE8AAAAAA///AQAAABwAAAAAAQAASAAAADAAAAADAAAAAQACADgAAAAAAAAAaW5wdXQAq6sEAAwAAQABAAEAAAAAAAAAcHNfM18wAE1pY3Jvc29mdCAoUikgSExTTCBTaGFkZXIgQ29tcGlsZXIgMTAuMQCrUQAABQAAD6AAAIA/AAAAAAAAAAAAAAAAHwAAAgUAAIAAAAOQHwAAAgAAAJAACA+gQgAAAwAAD4AAAOSQAAjkoAEAAAIACAuAAADkgAEAAAIACASAAAAAoP//AAA=";
|
||||||
|
private readonly PixelShader _shader;
|
||||||
|
|
||||||
|
public CustomShader(string shaderName)
|
||||||
|
{
|
||||||
|
_shader = new PixelShader();
|
||||||
|
using (var stream = new MemoryStream(Convert.FromBase64String(_kshaderAsBase64)))
|
||||||
|
{
|
||||||
|
_shader.SetStreamSource(stream);
|
||||||
|
}
|
||||||
|
PixelShader = _shader;
|
||||||
|
UpdateShaderValue(InputProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Brush Input
|
||||||
|
{
|
||||||
|
get { return (Brush)GetValue(InputProperty); }
|
||||||
|
set { SetValue(InputProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty InputProperty =
|
||||||
|
ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(CustomShader), 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
33
CityGame/ImageConverter.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class ImageConverter
|
||||||
|
{
|
||||||
|
public static void ChangeColor(string srcFile, string destFile, Dictionary<string, string> conversions)
|
||||||
|
{
|
||||||
|
destFile = Environment.CurrentDirectory + "\\Resources\\" + destFile + ".png";
|
||||||
|
//if (File.Exists(destFile)) return;
|
||||||
|
srcFile = Environment.CurrentDirectory + "\\Resources\\" + srcFile + ".png";
|
||||||
|
if (!File.Exists(srcFile)) return;
|
||||||
|
|
||||||
|
Dictionary<System.Drawing.Color, System.Drawing.Color> Conversions = conversions.Select(x => new KeyValuePair<System.Drawing.Color, System.Drawing.Color>(System.Drawing.ColorTranslator.FromHtml(x.Key), System.Drawing.ColorTranslator.FromHtml(x.Value))).ToDictionary(x => x.Key, x => x.Value);
|
||||||
|
System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Bitmap.FromFile(srcFile);
|
||||||
|
for (int x = 0; x < bmp.Width; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < bmp.Height; y++)
|
||||||
|
{
|
||||||
|
var color = bmp.GetPixel(x, y);
|
||||||
|
if (Conversions.ContainsKey(color))
|
||||||
|
{
|
||||||
|
bmp.SetPixel(x, y, Conversions[color]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bmp.Save(destFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
CityGame/MainWindow.xaml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<Window x:Class="CityGame.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:CityGame"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="MainWindow" Height="450" Width="800">
|
||||||
|
</Window>
|
||||||
507
CityGame/MainWindow.xaml.cs
Normal file
|
|
@ -0,0 +1,507 @@
|
||||||
|
using AStar;
|
||||||
|
using AStar.Options;
|
||||||
|
using SimplexNoise;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public abstract class Entity
|
||||||
|
{
|
||||||
|
public float X { get; set; }
|
||||||
|
public float Y { get; set; }
|
||||||
|
public float Rotation { get; set; }
|
||||||
|
public long Time { get; set; }
|
||||||
|
public OCanvas Object { get; set; }
|
||||||
|
public abstract OCanvas Render();
|
||||||
|
public abstract void Tick(long deltaTime);
|
||||||
|
}
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static System.Drawing.Point Convert(this Point point)
|
||||||
|
{
|
||||||
|
return new System.Drawing.Point((int)point.X, (int)point.Y);
|
||||||
|
}
|
||||||
|
public static Point Convert(this System.Drawing.Point point)
|
||||||
|
{
|
||||||
|
return new Point(point.X, point.Y);
|
||||||
|
}
|
||||||
|
public static bool CloselyEquals(this double A, double B)
|
||||||
|
{
|
||||||
|
return Math.Round(A) == Math.Round(B);
|
||||||
|
}
|
||||||
|
public static bool CloselyEquals(this float A, double B)
|
||||||
|
{
|
||||||
|
return Math.Round(A) == Math.Round(B);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class Car : Entity
|
||||||
|
{
|
||||||
|
public delegate void CarEvent(Car car);
|
||||||
|
public event CarEvent JourneyFinished;
|
||||||
|
public event CarEvent JourneyImpossible;
|
||||||
|
public Point? Target { get; set; } = null;
|
||||||
|
public int NextTarget { get; set; } = 0;
|
||||||
|
public Point[]? Path { get; set; } = null;
|
||||||
|
public Point Point {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Point((int)X / MainWindow.TileSize, (int)Y / MainWindow.TileSize);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
X = (float)value.X * MainWindow.TileSize;
|
||||||
|
Y = (float)value.Y * MainWindow.TileSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public float Speed { get; set; } = 256;
|
||||||
|
public override OCanvas Render()
|
||||||
|
{
|
||||||
|
return new SourcedImage("Car.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Tick(long deltaTime)
|
||||||
|
{
|
||||||
|
if(Target is not null)
|
||||||
|
{
|
||||||
|
if (Path is null)
|
||||||
|
{
|
||||||
|
Path = MainWindow.pathfinder.FindPath(Point.Convert(), ((Point)Target).Convert()).Select(x => x.Convert()).ToArray();
|
||||||
|
NextTarget = 0;
|
||||||
|
}
|
||||||
|
if (Path.Length == 0)
|
||||||
|
{
|
||||||
|
JourneyImpossible(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Point nextTarget = Path[NextTarget];
|
||||||
|
if (X.CloselyEquals(nextTarget.X * MainWindow.TileSize) && Y.CloselyEquals(nextTarget.Y * MainWindow.TileSize))
|
||||||
|
{
|
||||||
|
NextTarget++;
|
||||||
|
}
|
||||||
|
if(NextTarget == Path.Length)
|
||||||
|
{
|
||||||
|
Path = null;
|
||||||
|
Target = null;
|
||||||
|
NextTarget = 0;
|
||||||
|
JourneyFinished(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (X.CloselyEquals(nextTarget.X * MainWindow.TileSize) && Y.CloselyEquals(nextTarget.Y * MainWindow.TileSize))
|
||||||
|
return;
|
||||||
|
Vector2 travel = new Vector2((float)nextTarget.X * 64 - X, (float)nextTarget.Y * 64 - Y);
|
||||||
|
Vector2 direction = Vector2.Normalize(travel);
|
||||||
|
float degrees = (float)(Math.Atan2(direction.Y, direction.X) * (180 / Math.PI)) + 90;
|
||||||
|
Rotation = degrees;
|
||||||
|
var possibleDistance = Speed * deltaTime / 1000;
|
||||||
|
var finalDistance = Math.Min(possibleDistance, travel.Length());
|
||||||
|
Vector2 travelFinal = direction * finalDistance;
|
||||||
|
X += travelFinal.X;
|
||||||
|
Y += travelFinal.Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
public static Random random;
|
||||||
|
public static bool MouseIsDown = false;
|
||||||
|
public static Point MousePos = new Point(0, 0);
|
||||||
|
public static PathFinder pathfinder;
|
||||||
|
public static short[,] pathfindingGrid;
|
||||||
|
public static List<Tile> npcWalkable = new List<Tile>();
|
||||||
|
public static List<Entity> Entities { get; set; } = new List<Entity>();
|
||||||
|
public const int TileSize = 64;
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
#region | Texture Conversions |
|
||||||
|
string[] patternCodes = new[] { "0", "1", "2", "2c", "3", "3a", "3ab", "3c", "4", "4m", "4c", "5", "7", "8" };
|
||||||
|
|
||||||
|
foreach (var code in patternCodes)
|
||||||
|
{
|
||||||
|
ImageConverter.ChangeColor("Building" + code, "Lake" + code, ColorConversionMaps.HouseToLakeMap);
|
||||||
|
ImageConverter.ChangeColor("Lake" + code, "River" + code, ColorConversionMaps.LakeToRiver);
|
||||||
|
ImageConverter.ChangeColor("Building" + code, "BuildingDark" + code, ColorConversionMaps.HouseToBuildingDarkMap);
|
||||||
|
ImageConverter.ChangeColor("Building" + code, "BuildingBlue" + code, ColorConversionMaps.HouseToBuildingBlueMap);
|
||||||
|
ImageConverter.ChangeColor("Building" + code, "BuildingRed" + code, ColorConversionMaps.HouseToBuildingRedMap);
|
||||||
|
ImageConverter.ChangeColor("Building" + code, "BuildingGreen" + code, ColorConversionMaps.HouseToBuildingGreenMap);
|
||||||
|
ImageConverter.ChangeColor("Building" + code, "Park" + code, ColorConversionMaps.HouseToParkMap);
|
||||||
|
ImageConverter.ChangeColor("Road" + code, "Path" + code, ColorConversionMaps.RoadToPathMap);
|
||||||
|
ImageConverter.ChangeColor("Road" + code, "Bridge" + code, ColorConversionMaps.RoadToBridgeMap);
|
||||||
|
}
|
||||||
|
ImageConverter.ChangeColor("ParkingLot", "ParkingLotDark", ColorConversionMaps.HouseToBuildingDarkMap);
|
||||||
|
ImageConverter.ChangeColor("ParkingLot", "ParkingLotBlue", ColorConversionMaps.HouseToBuildingBlueMap);
|
||||||
|
ImageConverter.ChangeColor("ParkingLot", "ParkingLotRed", ColorConversionMaps.HouseToBuildingRedMap);
|
||||||
|
ImageConverter.ChangeColor("ParkingLot", "ParkingLotGreen", ColorConversionMaps.HouseToBuildingGreenMap);
|
||||||
|
|
||||||
|
ImageConverter.ChangeColor("Error", "ErrorRed", new Dictionary<string, string> { { "#000000", "#ff0000" } });
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
#region | Map Generation |
|
||||||
|
#region | Map Generation Constants |
|
||||||
|
int seed = 1;
|
||||||
|
|
||||||
|
Noise.Seed = seed;
|
||||||
|
|
||||||
|
int mapHeight = 100;
|
||||||
|
int mapWidth = 100;
|
||||||
|
|
||||||
|
float[,] lakeMap = Noise.Calc2D(mapWidth, mapHeight, 0.05f);
|
||||||
|
|
||||||
|
Noise.Seed = seed * 24 + 1;
|
||||||
|
float[,] parkMap = Noise.Calc2D(mapWidth, mapHeight, 0.05f);
|
||||||
|
|
||||||
|
Noise.Seed = Noise.Seed * 24 + 1;
|
||||||
|
float[,] riverMap = Noise.Calc2D(mapWidth, mapHeight, 0.01f);
|
||||||
|
|
||||||
|
mapHeight /= 2;
|
||||||
|
mapWidth /= 2;
|
||||||
|
|
||||||
|
int doubleHeight = mapHeight * 2;
|
||||||
|
int doubleWidth = mapWidth * 2;
|
||||||
|
|
||||||
|
int maxBlockHeight = 5;
|
||||||
|
int maxBlockWidth = 5;
|
||||||
|
int minBlockHeight = 3;
|
||||||
|
int minBlockWidth = 3;
|
||||||
|
|
||||||
|
int NPCCount = 100;
|
||||||
|
|
||||||
|
random = new Random(seed);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Map Initialization |
|
||||||
|
Tile[,] InitialGrid = new Tile[mapWidth, mapHeight];
|
||||||
|
|
||||||
|
List<Tuple<int, int>> coords = new List<Tuple<int, int>>();
|
||||||
|
for (int y = 0; y < mapHeight; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < mapWidth; x++)
|
||||||
|
{
|
||||||
|
coords.Add(new Tuple<int, int>(x, y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coords = coords.OrderBy(x => random.Next(0, coords.Count)).ToList();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Main Algorithm |
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
foreach (var coord in coords)
|
||||||
|
{
|
||||||
|
int x = coord.Item1;
|
||||||
|
int y = coord.Item2;
|
||||||
|
|
||||||
|
int height = random.Next(minBlockHeight, maxBlockHeight + 1);
|
||||||
|
int width = random.Next(minBlockWidth, maxBlockWidth + 1);
|
||||||
|
int yOffset = random.Next(0, height);
|
||||||
|
int xOffset = random.Next(0, width);
|
||||||
|
|
||||||
|
TileType BlockType = TileType.Skyscraper;
|
||||||
|
|
||||||
|
for (int y2 = y - yOffset; y2 < y - yOffset + height; y2++)
|
||||||
|
{
|
||||||
|
for (int x2 = x - xOffset; x2 < x - xOffset + width; x2++)
|
||||||
|
{
|
||||||
|
if (x2 < 0) continue;
|
||||||
|
if (y2 < 0) continue;
|
||||||
|
if (x2 >= mapWidth) continue;
|
||||||
|
if (y2 >= mapHeight) continue;
|
||||||
|
InitialGrid[x2, y2].BlockID = i;
|
||||||
|
InitialGrid[x2, y2].Type = BlockType;
|
||||||
|
if (lakeMap[x2, y2] > 214) InitialGrid[x2, y2].Type = TileType.Park;
|
||||||
|
if (lakeMap[x2, y2] > 219) InitialGrid[x2, y2].Type = TileType.Lake;
|
||||||
|
if (parkMap[x2, y2] > 214 && parkMap[x2, y2] > lakeMap[x2, y2]) InitialGrid[x2, y2].Type = TileType.Park;
|
||||||
|
if (riverMap[x2, y2] > 128 && riverMap[x2,y2] < 148) InitialGrid[x2, y2].Type = TileType.River;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Doubling |
|
||||||
|
|
||||||
|
Tile[,] IntermediateGrid = new Tile[doubleWidth, doubleHeight];
|
||||||
|
for (int y = 0; y < mapHeight; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < mapWidth; x++)
|
||||||
|
{
|
||||||
|
IntermediateGrid[x * 2, y * 2] = InitialGrid[x, y];
|
||||||
|
IntermediateGrid[x * 2, y * 2 + 1] = InitialGrid[x, y];
|
||||||
|
IntermediateGrid[x * 2 + 1, y * 2 + 1] = InitialGrid[x, y];
|
||||||
|
IntermediateGrid[x * 2 + 1, y * 2] = InitialGrid[x, y];
|
||||||
|
|
||||||
|
IntermediateGrid[x * 2, y * 2].X = x * 2;
|
||||||
|
IntermediateGrid[x * 2, y * 2].Y = y * 2;
|
||||||
|
|
||||||
|
IntermediateGrid[x * 2, y * 2 + 1].X = x * 2;
|
||||||
|
IntermediateGrid[x * 2, y * 2 + 1].Y = y * 2 + 1;
|
||||||
|
|
||||||
|
IntermediateGrid[x * 2 + 1, y * 2 + 1].X = x * 2 + 1;
|
||||||
|
IntermediateGrid[x * 2 + 1, y * 2 + 1].Y = y * 2 + 1;
|
||||||
|
|
||||||
|
IntermediateGrid[x * 2 + 1, y * 2].X = x * 2 + 1;
|
||||||
|
IntermediateGrid[x * 2 + 1, y * 2].Y = y * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Roads and Bridges |
|
||||||
|
Dictionary<int, bool> decidedBridges = new Dictionary<int, bool>();
|
||||||
|
pathfindingGrid = new short[doubleWidth, doubleHeight];
|
||||||
|
List<Tile> bridgeTiles = new List<Tile>();
|
||||||
|
List<Tile> roadTiles = new List<Tile>();
|
||||||
|
for (int y = 0; y < doubleHeight; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < doubleWidth; x++)
|
||||||
|
{
|
||||||
|
TileType changeTo = TileType.Road;
|
||||||
|
int myID = IntermediateGrid[x, y].BlockID;
|
||||||
|
if (IntermediateGrid[x, y].Type == TileType.Lake || IntermediateGrid[x, y].Type == TileType.River)
|
||||||
|
{
|
||||||
|
if (!decidedBridges.ContainsKey(myID))
|
||||||
|
{
|
||||||
|
decidedBridges[myID] = random.Next(0, 2) == 0;
|
||||||
|
}
|
||||||
|
if (decidedBridges[myID])
|
||||||
|
{
|
||||||
|
changeTo = TileType.Bridge;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
bool walkable = ((int)IntermediateGrid[x, y].Type) / 100 == 4;
|
||||||
|
pathfindingGrid[y, x] = (short)(walkable ? 1 : 0);
|
||||||
|
if (IntermediateGrid[x, y].Type == TileType.Bridge) bridgeTiles.Add(IntermediateGrid[x, y]);
|
||||||
|
if (IntermediateGrid[x, y].Type == TileType.Road) roadTiles.Add(IntermediateGrid[x, y]);
|
||||||
|
if (IntermediateGrid[x, y].Type == TileType.Road || IntermediateGrid[x, y].Type == TileType.Bridge) npcWalkable.Add(IntermediateGrid[x, y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Pathfinding |
|
||||||
|
|
||||||
|
var worldGrid = new WorldGrid(pathfindingGrid);
|
||||||
|
pathfinder = new PathFinder(worldGrid, new PathFinderOptions { PunishChangeDirection = true, UseDiagonals = false, SearchLimit = int.MaxValue, HeuristicFormula = AStar.Heuristics.HeuristicFormula.Euclidean });
|
||||||
|
|
||||||
|
//foreach(var tile in bridgeTiles)
|
||||||
|
//{
|
||||||
|
// List<Tile> sortedRoads = roadTiles.OrderBy(x => Math.Abs(x.X - tile.X) + Math.Abs(x.Y - tile.Y)).ToList();
|
||||||
|
// if(!sortedRoads.Any(x => pathfinder.FindPath(new System.Drawing.Point(x.X, x.Y), new System.Drawing.Point(tile.X, tile.Y)).Length > 0))
|
||||||
|
// {
|
||||||
|
// IntermediateGrid[tile.X, tile.Y].Type = TileType.House;
|
||||||
|
// }
|
||||||
|
// i++;
|
||||||
|
//}
|
||||||
|
|
||||||
|
int mainRoadCount = random.Next(1, 2);
|
||||||
|
for(int m = 0; m < mainRoadCount; m++)
|
||||||
|
{
|
||||||
|
int variant = random.Next(0, 2);
|
||||||
|
Point startPoint = new Point(0, 0);
|
||||||
|
Point endPoint = new Point(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
Tile[,] Grid = IntermediateGrid;
|
||||||
|
//for(int y = 0; y < mapHeight; y++)
|
||||||
|
//{
|
||||||
|
// for(int x = 0; x < mapWidth; x++)
|
||||||
|
// {
|
||||||
|
// Grid[x, y] = IntermediateGrid[x * 2 + 1, y * 2 + 1];
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
mapHeight *= 2;
|
||||||
|
mapWidth *= 2;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
Show();
|
||||||
|
|
||||||
|
#region | Rendering |
|
||||||
|
|
||||||
|
Canvas MainCanvas = new OCanvas();
|
||||||
|
Canvas BGCanvas = new OCanvas();
|
||||||
|
Canvas GameCanvas = new OCanvas();
|
||||||
|
Canvas CameraCanvas = new OCanvas();
|
||||||
|
Canvas UICanvas = new OCanvas();
|
||||||
|
|
||||||
|
Canvas.SetLeft(CameraCanvas, 0);
|
||||||
|
Canvas.SetTop(CameraCanvas, 0);
|
||||||
|
|
||||||
|
RenderOptions.SetEdgeMode(GameCanvas, EdgeMode.Aliased);
|
||||||
|
|
||||||
|
MainCanvas.Children.Add(CameraCanvas);
|
||||||
|
MainCanvas.Children.Add(UICanvas);
|
||||||
|
|
||||||
|
CameraCanvas.Children.Add(BGCanvas);
|
||||||
|
CameraCanvas.Children.Add(GameCanvas);
|
||||||
|
|
||||||
|
MainCanvas.HorizontalAlignment = HorizontalAlignment.Left;
|
||||||
|
MainCanvas.VerticalAlignment = VerticalAlignment.Top;
|
||||||
|
|
||||||
|
Content = MainCanvas;
|
||||||
|
|
||||||
|
int tileSize = TileSize;
|
||||||
|
for (int x = 0; x < mapWidth; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < mapHeight; y++)
|
||||||
|
{
|
||||||
|
Canvas image = Renderer.Render(Grid[x, y].Type, x, y, Grid);
|
||||||
|
|
||||||
|
image.Height = tileSize;
|
||||||
|
image.Width = tileSize;
|
||||||
|
|
||||||
|
RenderOptions.SetBitmapScalingMode(image, BitmapScalingMode.NearestNeighbor);
|
||||||
|
|
||||||
|
Canvas.SetLeft(image, x * tileSize);
|
||||||
|
Canvas.SetTop(image, y * tileSize);
|
||||||
|
|
||||||
|
//image.Opacity = pathfindingGrid[y, x];
|
||||||
|
|
||||||
|
GameCanvas.Children.Add(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Controls |
|
||||||
|
|
||||||
|
MainCanvas.MouseDown += (a, b) => MouseIsDown = true;
|
||||||
|
MainCanvas.MouseUp += (a, b) => MouseIsDown = false;
|
||||||
|
MainCanvas.MouseMove += (a, b) =>
|
||||||
|
{
|
||||||
|
if (MouseIsDown)
|
||||||
|
{
|
||||||
|
var newpos = PointToScreen(Mouse.GetPosition(this));
|
||||||
|
var diff = newpos - MousePos;
|
||||||
|
Canvas.SetLeft(CameraCanvas, Canvas.GetLeft(CameraCanvas) + diff.X);
|
||||||
|
Canvas.SetTop(CameraCanvas, Canvas.GetTop(CameraCanvas) + diff.Y);
|
||||||
|
}
|
||||||
|
MousePos = PointToScreen(Mouse.GetPosition(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
ScaleTransform scale = new ScaleTransform(1, 1);
|
||||||
|
CameraCanvas.RenderTransform = scale;
|
||||||
|
|
||||||
|
MainCanvas.MouseWheel += (a, b) =>
|
||||||
|
{
|
||||||
|
float multi = 0.952f;
|
||||||
|
if (b.Delta > 0) multi = 1.05f;
|
||||||
|
|
||||||
|
scale.ScaleX *= multi;
|
||||||
|
scale.ScaleY *= multi;
|
||||||
|
|
||||||
|
if (b.Delta < 0)
|
||||||
|
{
|
||||||
|
scale.ScaleX = Math.Floor(scale.ScaleX * 100) / 100f;
|
||||||
|
scale.ScaleY = Math.Floor(scale.ScaleY * 100) / 100f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scale.ScaleX = Math.Ceiling(scale.ScaleX * 100) / 100f;
|
||||||
|
scale.ScaleY = Math.Ceiling(scale.ScaleY * 100) / 100f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine(scale.ScaleX);
|
||||||
|
};
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region | Entities |
|
||||||
|
|
||||||
|
DispatcherTimer EntityLoop = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1 / 20) };
|
||||||
|
EntityLoop.Tick += (a, b) =>
|
||||||
|
{
|
||||||
|
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
|
||||||
|
foreach(Entity entity in Entities)
|
||||||
|
{
|
||||||
|
long delta = milliseconds - entity.Time;
|
||||||
|
entity.Time = milliseconds;
|
||||||
|
entity.Tick(delta);
|
||||||
|
|
||||||
|
if(entity.Object is null)
|
||||||
|
{
|
||||||
|
entity.Object = entity.Render();
|
||||||
|
RenderOptions.SetBitmapScalingMode(entity.Object, BitmapScalingMode.NearestNeighbor);
|
||||||
|
var rt = new RotateTransform(entity.Rotation);
|
||||||
|
rt.CenterX = MainWindow.TileSize / 2;
|
||||||
|
rt.CenterY = MainWindow.TileSize / 2;
|
||||||
|
entity.Object.RenderTransform = rt;
|
||||||
|
GameCanvas.Children.Add(entity.Object);
|
||||||
|
}
|
||||||
|
((RotateTransform)entity.Object.RenderTransform).Angle = entity.Rotation;
|
||||||
|
Canvas.SetLeft(entity.Object, entity.X);
|
||||||
|
Canvas.SetTop(entity.Object, entity.Y);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EntityLoop.Start();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
for(int n = 0; n < NPCCount; n++)
|
||||||
|
{
|
||||||
|
Car car = new Car();
|
||||||
|
Tile startTile = npcWalkable[random.Next(0, npcWalkable.Count)];
|
||||||
|
Tile targetTile = npcWalkable[random.Next(0, npcWalkable.Count)];
|
||||||
|
|
||||||
|
car.Point = new Point(startTile.X, startTile.Y);
|
||||||
|
|
||||||
|
car.Target = new Point(targetTile.X, targetTile.Y);
|
||||||
|
|
||||||
|
Car.CarEvent reset = car =>
|
||||||
|
{
|
||||||
|
Tile targetTile = npcWalkable[random.Next(0, npcWalkable.Count)];
|
||||||
|
DispatcherTimer delay = new DispatcherTimer { Interval = TimeSpan.FromSeconds(random.Next(1, 5)) };
|
||||||
|
delay.Tick += (a, b) =>
|
||||||
|
{
|
||||||
|
car.Target = new Point(targetTile.X, targetTile.Y);
|
||||||
|
delay.Stop();
|
||||||
|
};
|
||||||
|
delay.Start();
|
||||||
|
};
|
||||||
|
|
||||||
|
car.JourneyFinished += reset;
|
||||||
|
car.JourneyImpossible += reset;
|
||||||
|
|
||||||
|
Entities.Add(car);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
CityGame/OCanvas.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class OCanvas : Canvas
|
||||||
|
{
|
||||||
|
public static implicit operator OCanvas(Image image)
|
||||||
|
{
|
||||||
|
OCanvas canvas = new OCanvas();
|
||||||
|
canvas.Children.Add(image);
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
public OCanvas() : base()
|
||||||
|
{
|
||||||
|
this.Height = 100;
|
||||||
|
this.Width = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
85
CityGame/Pattern.cs
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class Pattern
|
||||||
|
{
|
||||||
|
public string PatternCode { get; set; }
|
||||||
|
public int Rotation { get; set; }
|
||||||
|
public Pattern(string pattern)
|
||||||
|
{
|
||||||
|
PatternCode = pattern;
|
||||||
|
Rotation = 0;
|
||||||
|
}
|
||||||
|
public Pattern(string pattern, int rotation)
|
||||||
|
{
|
||||||
|
PatternCode = pattern;
|
||||||
|
Rotation = rotation;
|
||||||
|
}
|
||||||
|
public Pattern(string pattern, string rotation)
|
||||||
|
{
|
||||||
|
PatternCode = pattern;
|
||||||
|
int.TryParse(rotation, out int rot);
|
||||||
|
Rotation = rot;
|
||||||
|
}
|
||||||
|
public static Pattern Calculate(Tile[,] Grid, int x, int y, params TileType[] allowed)
|
||||||
|
{
|
||||||
|
Func<int, int, bool> IsAdjacent = (X, Y) =>
|
||||||
|
{
|
||||||
|
if (!Renderer.IsInGrid(Grid, X, Y)) return false;
|
||||||
|
if (Grid[x, y].BlockID != Grid[X, Y].BlockID && Grid[x, y].Type == TileType.Skyscraper) return false;
|
||||||
|
return allowed.Contains(Grid[X, Y].Type);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y) && IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y + 1)) return new Pattern("8");
|
||||||
|
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y) && IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y + 1)) return new Pattern("7");
|
||||||
|
if (IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y) && IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y + 1)) return new Pattern("7", "90");
|
||||||
|
if (IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y) && IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1)) return new Pattern("7", "180");
|
||||||
|
if (IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y + 1)) return new Pattern("7", "270");
|
||||||
|
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x + 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y + 1)) return new Pattern("5");
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x - 1, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x - 1, y + 1)) return new Pattern("5", "180");
|
||||||
|
if (IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y)) return new Pattern("5", "270");
|
||||||
|
if (IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y + 1) && IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y)) return new Pattern("5", "90");
|
||||||
|
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x + 1, y)) return new Pattern("4");
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y) && IsAdjacent(x + 1, y + 1) && IsAdjacent(x, y + 1)) return new Pattern("4", "90");
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x - 1, y) && IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1)) return new Pattern("4", "180");
|
||||||
|
if (IsAdjacent(x, y + 1) && IsAdjacent(x - 1, y) && IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1)) return new Pattern("4", "270");
|
||||||
|
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x - 1, y - 1)) return new Pattern("4m");
|
||||||
|
if (IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y) && IsAdjacent(x, y - 1) && IsAdjacent(x + 1, y - 1)) return new Pattern("4m", "90");
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x + 1, y) && IsAdjacent(x + 1, y + 1)) return new Pattern("4m", "180");
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x - 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x - 1, y + 1)) return new Pattern("4m", "270");
|
||||||
|
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x - 1, y) && IsAdjacent(x, y - 1)) return new Pattern("4c");
|
||||||
|
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x + 1, y + 1) && IsAdjacent(x, y + 1)) return new Pattern("3");
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x - 1, y + 1) && IsAdjacent(x, y + 1)) return new Pattern("3", "90");
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x - 1, y - 1) && IsAdjacent(x, y - 1)) return new Pattern("3", "180");
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x + 1, y - 1) && IsAdjacent(x, y - 1)) return new Pattern("3", "270");
|
||||||
|
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x, y + 1) && IsAdjacent(x - 1, y)) return new Pattern("3c");
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y - 1) && IsAdjacent(x - 1, y)) return new Pattern("3c", "90");
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y - 1) && IsAdjacent(x, y + 1)) return new Pattern("3c", "180");
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y + 1) && IsAdjacent(x - 1, y)) return new Pattern("3c", "270");
|
||||||
|
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x + 1, y)) return new Pattern("2", "90");
|
||||||
|
if (IsAdjacent(x, y - 1) && IsAdjacent(x, y + 1)) return new Pattern("2");
|
||||||
|
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y + 1)) return new Pattern("2c");
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x, y + 1)) return new Pattern("2c", "90");
|
||||||
|
if (IsAdjacent(x - 1, y) && IsAdjacent(x, y - 1)) return new Pattern("2c", "180");
|
||||||
|
if (IsAdjacent(x + 1, y) && IsAdjacent(x, y - 1)) return new Pattern("2c", "270");
|
||||||
|
|
||||||
|
if (IsAdjacent(x + 1, y)) return new Pattern("1");
|
||||||
|
if (IsAdjacent(x - 1, y)) return new Pattern("1", "180");
|
||||||
|
if (IsAdjacent(x, y + 1)) return new Pattern("1", "90");
|
||||||
|
if (IsAdjacent(x, y - 1)) return new Pattern("1", "270");
|
||||||
|
|
||||||
|
return new Pattern("0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
CityGame/Properties/Resources.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// Dieser Code wurde von einem Tool generiert.
|
||||||
|
// Laufzeitversion:4.0.30319.42000
|
||||||
|
//
|
||||||
|
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
|
||||||
|
// der Code erneut generiert wird.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace CityGame.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
|
||||||
|
/// </summary>
|
||||||
|
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
|
||||||
|
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
|
||||||
|
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
|
||||||
|
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CityGame.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
|
||||||
|
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
CityGame/Properties/Resources.resx
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
88
CityGame/Renderer.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class Renderer
|
||||||
|
{
|
||||||
|
public static bool IsRoad(Tile[,] Grid, int x, int y)
|
||||||
|
{
|
||||||
|
return IsInGrid(Grid, x, y) && (Grid[x, y].Type == TileType.Road || Grid[x, y].Type == TileType.Bridge);
|
||||||
|
}
|
||||||
|
public static bool IsInGrid(Tile[,] Grid, int x, int y)
|
||||||
|
{
|
||||||
|
return !(x < 0 || y < 0 || x >= Grid.GetLength(0) || y >= Grid.GetLength(1));
|
||||||
|
}
|
||||||
|
public static bool IsBuilding(Tile[,] Grid, int x, int y)
|
||||||
|
{
|
||||||
|
return IsInGrid(Grid, x, y) && (Grid[x, y].Type == TileType.Skyscraper || Grid[x, y].Type == TileType.House);
|
||||||
|
}
|
||||||
|
public static OCanvas Render(TileType type, int x, int y, Tile[,] Grid)
|
||||||
|
{
|
||||||
|
if (type == TileType.Skyscraper)
|
||||||
|
{
|
||||||
|
string theme = "";
|
||||||
|
if (Grid[x, y].BlockID % 2 == 1) theme = "Dark";
|
||||||
|
if (Grid[x, y].BlockID % 30 == 1) theme = "Blue";
|
||||||
|
if (Grid[x, y].BlockID % 30 == 2) theme = "Red";
|
||||||
|
if (Grid[x, y].BlockID % 30 == 3) theme = "Green";
|
||||||
|
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Skyscraper);
|
||||||
|
if (pattern.PatternCode == "1" && MainWindow.random.Next(0, 3) == 0) return new SourcedImage("ParkingLot"+theme+".png:" + pattern.Rotation);
|
||||||
|
if (pattern.PatternCode == "3" && MainWindow.random.Next(0, 12) == 0) pattern.PatternCode = "3a";
|
||||||
|
if (pattern.PatternCode == "3" && MainWindow.random.Next(0, 12) == 1) pattern.PatternCode = "3ab";
|
||||||
|
OCanvas canvas = new SourcedImage("Building"+ theme + pattern.PatternCode + ".png:" + pattern.Rotation);
|
||||||
|
|
||||||
|
if (MainWindow.random.Next(0, 10) == 0 && pattern.PatternCode != "3a") canvas.Children.Add(new SourcedImage("Vent" + (MainWindow.random.Next(0, 3) + 1) + ".png:" + (MainWindow.random.Next(0, 4) * 90)));
|
||||||
|
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
if (type == TileType.Lake || type == TileType.River)
|
||||||
|
{
|
||||||
|
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Lake, TileType.Bridge, TileType.River);
|
||||||
|
return new SourcedImage("Lake" + pattern.PatternCode + ".png:" + pattern.Rotation);
|
||||||
|
}
|
||||||
|
if (type == TileType.Park)
|
||||||
|
{
|
||||||
|
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Park, TileType.Path);
|
||||||
|
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));
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
if (type == TileType.Road)
|
||||||
|
{
|
||||||
|
Pattern pattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Path, TileType.Bridge);
|
||||||
|
if (pattern.PatternCode == "2c") pattern.Rotation += 270;
|
||||||
|
if (pattern.PatternCode == "1") pattern.Rotation += 180;
|
||||||
|
return new SourcedImage("Road" + pattern.PatternCode + ".png:" + pattern.Rotation);
|
||||||
|
}
|
||||||
|
if (type == TileType.Path)
|
||||||
|
{
|
||||||
|
Pattern roadpattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Path, TileType.Bridge);
|
||||||
|
Pattern parkpattern = Pattern.Calculate(Grid, x, y, TileType.Path, TileType.Park);
|
||||||
|
if (roadpattern.PatternCode == "2c") roadpattern.Rotation += 270;
|
||||||
|
if (roadpattern.PatternCode == "1") roadpattern.Rotation += 180;
|
||||||
|
Image path = new SourcedImage("Path" + roadpattern.PatternCode + ".png:" + roadpattern.Rotation);
|
||||||
|
Image park = new SourcedImage("Park" + parkpattern.PatternCode + ".png:" + parkpattern.Rotation);
|
||||||
|
|
||||||
|
OCanvas result = new OCanvas();
|
||||||
|
result.Children.Add(park);
|
||||||
|
result.Children.Add(path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (type == TileType.Bridge)
|
||||||
|
{
|
||||||
|
Pattern roadpattern = Pattern.Calculate(Grid, x, y, TileType.Road, TileType.Bridge, TileType.Path);
|
||||||
|
Pattern parkpattern = Pattern.Calculate(Grid, x, y, TileType.Bridge, TileType.Lake, TileType.River);
|
||||||
|
if (roadpattern.PatternCode == "2c") roadpattern.Rotation += 270;
|
||||||
|
if (roadpattern.PatternCode == "1") roadpattern.Rotation += 180;
|
||||||
|
Image path = new SourcedImage("Bridge" + roadpattern.PatternCode + ".png:" + roadpattern.Rotation);
|
||||||
|
Image park = new SourcedImage("Lake" + parkpattern.PatternCode + ".png:" + parkpattern.Rotation);
|
||||||
|
|
||||||
|
OCanvas result = new OCanvas();
|
||||||
|
result.Children.Add(park);
|
||||||
|
result.Children.Add(path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return new SourcedImage("Error.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
CityGame/Resources/BlueTint.hlsl
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
Texture2D inputTexture : register(t0);
|
||||||
|
SamplerState inputSampler : register(s0);
|
||||||
|
|
||||||
|
float4 main(float2 uv : TEXCOORD) : SV_Target
|
||||||
|
{
|
||||||
|
float4 color = inputTexture.Sample(inputSampler, uv);
|
||||||
|
float4 grayscaleColor = float4(dot(color.rgb, float3(0.299, 0.587, 0.114)), dot(color.rgb, float3(0.299, 0.587, 0.114)), dot(color.rgb, float3(0.299, 0.587, 0.114)), color.a);
|
||||||
|
return grayscaleColor;
|
||||||
|
}
|
||||||
BIN
CityGame/Resources/Building0.png
Normal file
|
After Width: | Height: | Size: 348 B |
BIN
CityGame/Resources/Building1.png
Normal file
|
After Width: | Height: | Size: 285 B |
BIN
CityGame/Resources/Building2.png
Normal file
|
After Width: | Height: | Size: 254 B |
BIN
CityGame/Resources/Building2c.png
Normal file
|
After Width: | Height: | Size: 295 B |
BIN
CityGame/Resources/Building3.png
Normal file
|
After Width: | Height: | Size: 274 B |
BIN
CityGame/Resources/Building3a.png
Normal file
|
After Width: | Height: | Size: 381 B |
BIN
CityGame/Resources/Building3ab.png
Normal file
|
After Width: | Height: | Size: 433 B |
BIN
CityGame/Resources/Building3c.png
Normal file
|
After Width: | Height: | Size: 298 B |
BIN
CityGame/Resources/Building4.png
Normal file
|
After Width: | Height: | Size: 266 B |
BIN
CityGame/Resources/Building4c.png
Normal file
|
After Width: | Height: | Size: 308 B |
BIN
CityGame/Resources/Building4m.png
Normal file
|
After Width: | Height: | Size: 280 B |
BIN
CityGame/Resources/Building5.png
Normal file
|
After Width: | Height: | Size: 237 B |
BIN
CityGame/Resources/Building7.png
Normal file
|
After Width: | Height: | Size: 247 B |
BIN
CityGame/Resources/Building8.png
Normal file
|
After Width: | Height: | Size: 200 B |
BIN
CityGame/Resources/Car.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
CityGame/Resources/Error.png
Normal file
|
After Width: | Height: | Size: 544 B |
BIN
CityGame/Resources/ParkingLot.png
Normal file
|
After Width: | Height: | Size: 478 B |
BIN
CityGame/Resources/Road1.png
Normal file
|
After Width: | Height: | Size: 410 B |
BIN
CityGame/Resources/Road2.png
Normal file
|
After Width: | Height: | Size: 324 B |
BIN
CityGame/Resources/Road2c.png
Normal file
|
After Width: | Height: | Size: 402 B |
BIN
CityGame/Resources/Road3c.png
Normal file
|
After Width: | Height: | Size: 369 B |
BIN
CityGame/Resources/Road4c.png
Normal file
|
After Width: | Height: | Size: 362 B |
BIN
CityGame/Resources/Tree.png
Normal file
|
After Width: | Height: | Size: 736 B |
BIN
CityGame/Resources/Vent1.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
CityGame/Resources/Vent2.png
Normal file
|
After Width: | Height: | Size: 514 B |
BIN
CityGame/Resources/Vent3.png
Normal file
|
After Width: | Height: | Size: 655 B |
69
CityGame/SourcedImage.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public class SourcedImage : Image
|
||||||
|
{
|
||||||
|
public Dictionary<string, List<string>> Alternatives = new Dictionary<string, List<string>>()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Dictionary<string, BitmapSource> loadedSources = new Dictionary<string, BitmapSource>();
|
||||||
|
|
||||||
|
public SourcedImage(string source)
|
||||||
|
{
|
||||||
|
Source = SourceToImage(source);
|
||||||
|
Height = 64;
|
||||||
|
Width = 64;
|
||||||
|
|
||||||
|
ImageFailed += SourcedImage_ImageFailed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SourcedImage_ImageFailed(object? sender, ExceptionRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitmapSource SourceToImage(string src, UriKind kind = UriKind.Absolute)
|
||||||
|
{
|
||||||
|
string degs = src.Split(':').Last();
|
||||||
|
string uri = src;
|
||||||
|
int deg = 0;
|
||||||
|
if (degs == "0" || degs == "90" || degs == "180" || degs == "270" || degs == "360" || degs == "450" || degs == "540" || degs == "630" || degs == "720")
|
||||||
|
{
|
||||||
|
deg = Convert.ToInt32(degs);
|
||||||
|
uri = string.Join(":", src.Split(':').Take(src.Split(':').Count() - 1).ToArray());
|
||||||
|
}
|
||||||
|
string last = "";
|
||||||
|
while (Alternatives.ContainsKey(uri) && uri != last)
|
||||||
|
{
|
||||||
|
last = uri;
|
||||||
|
List<string> alts = Alternatives[uri];
|
||||||
|
alts.Add(uri);
|
||||||
|
uri = alts[MainWindow.random.Next(0, alts.Count)];
|
||||||
|
}
|
||||||
|
uri = Environment.CurrentDirectory + "\\Resources\\" + uri;
|
||||||
|
if (loadedSources.ContainsKey(src))
|
||||||
|
{
|
||||||
|
return loadedSources[src];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!File.Exists(uri))
|
||||||
|
{
|
||||||
|
uri = Environment.CurrentDirectory + "\\Resources\\ErrorRed.png";
|
||||||
|
}
|
||||||
|
loadedSources.Add(src, new TransformedBitmap(new BitmapImage(new Uri(uri, kind)), new RotateTransform(deg)));
|
||||||
|
return loadedSources[src];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
CityGame/Tile.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public struct Tile
|
||||||
|
{
|
||||||
|
public int BlockID;
|
||||||
|
public TileType Type;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
CityGame/TileType.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace CityGame
|
||||||
|
{
|
||||||
|
public enum TileType
|
||||||
|
{
|
||||||
|
Skyscraper = 100,
|
||||||
|
House = 101,
|
||||||
|
|
||||||
|
Park = 200,
|
||||||
|
|
||||||
|
Lake = 300,
|
||||||
|
River = 301,
|
||||||
|
|
||||||
|
Road = 400,
|
||||||
|
Path = 401,
|
||||||
|
Bridge = 410
|
||||||
|
}
|
||||||
|
}
|
||||||