old experiments in writing C# games
5
Dakota/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
3
Dakota/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "Nez"]
|
||||||
|
path = Nez
|
||||||
|
url = git@github.com:prime31/Nez.git
|
11
Dakota/.idea/.idea.Dakota/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/.idea.Dakota.iml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/modules.xml
|
||||||
|
/contentModel.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
4
Dakota/.idea/.idea.Dakota/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
8
Dakota/.idea/.idea.Dakota/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
7
Dakota/.idea/.idea.Dakota/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/Nez" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
28
Dakota/Dakota.sln
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dakota", "Dakota\Dakota.csproj", "{2FF89EAA-6572-40AB-8A4D-BCE3275F113F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.MG38", "Nez\Nez.Portable\Nez.MG38.csproj", "{0A2DAF9B-E04C-4624-BA85-82CEA0F7D1F6}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DakotaTests", "DakotaTests\DakotaTests.csproj", "{24B9130D-9930-43D2-A3EA-8D3055355502}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{2FF89EAA-6572-40AB-8A4D-BCE3275F113F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2FF89EAA-6572-40AB-8A4D-BCE3275F113F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2FF89EAA-6572-40AB-8A4D-BCE3275F113F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2FF89EAA-6572-40AB-8A4D-BCE3275F113F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0A2DAF9B-E04C-4624-BA85-82CEA0F7D1F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0A2DAF9B-E04C-4624-BA85-82CEA0F7D1F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0A2DAF9B-E04C-4624-BA85-82CEA0F7D1F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0A2DAF9B-E04C-4624-BA85-82CEA0F7D1F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{24B9130D-9930-43D2-A3EA-8D3055355502}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{24B9130D-9930-43D2-A3EA-8D3055355502}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{24B9130D-9930-43D2-A3EA-8D3055355502}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{24B9130D-9930-43D2-A3EA-8D3055355502}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
2
Dakota/Dakota.sln.DotSettings
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=batcher/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
12
Dakota/Dakota.sln.DotSettings.user
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=04195ef0_002Db45a_002D4c34_002D9acc_002D490c75ed258a/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" Name="All tests from &lt;DakotaTests&gt; #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||||
|
<Project Location="/Users/james/Desktop/Dakota/DakotaTests" Presentation="&lt;DakotaTests&gt;" />
|
||||||
|
</SessionState></s:String>
|
||||||
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=3c8f59d4_002Debac_002D44f8_002Dbbfc_002D599bf5002101/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;DakotaTests&gt; #3" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||||
|
<Project Location="/Users/james/Desktop/Dakota/DakotaTests" Presentation="&lt;DakotaTests&gt;" />
|
||||||
|
</SessionState></s:String>
|
||||||
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=b58decbb_002Df9a2_002D4b45_002Db0f2_002D95bdb60e00b7/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" Name="All tests from &lt;DakotaTests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||||
|
<Project Location="/Users/james/Desktop/Dakota/DakotaTests" Presentation="&lt;DakotaTests&gt;" />
|
||||||
|
</SessionState></s:String>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Renderable/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Renderables/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
27
Dakota/Dakota/Content/Content.mgcb
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#----------------------------- Global Properties ----------------------------#
|
||||||
|
|
||||||
|
/outputDir:bin/$(Platform)
|
||||||
|
/intermediateDir:obj/$(Platform)
|
||||||
|
/platform:DesktopGL
|
||||||
|
/config:
|
||||||
|
/profile:Reach
|
||||||
|
/compress:False
|
||||||
|
|
||||||
|
#-------------------------------- References --------------------------------#
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------- Content ---------------------------------#
|
||||||
|
|
||||||
|
#begin Sprites/Ship00.png
|
||||||
|
/importer:TextureImporter
|
||||||
|
/processor:TextureProcessor
|
||||||
|
/processorParam:ColorKeyColor=255,0,255,255
|
||||||
|
/processorParam:ColorKeyEnabled=True
|
||||||
|
/processorParam:GenerateMipmaps=False
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:ResizeToPowerOfTwo=False
|
||||||
|
/processorParam:MakeSquare=False
|
||||||
|
/processorParam:TextureFormat=Color
|
||||||
|
/build:Sprites/Ship00.png
|
||||||
|
|
BIN
Dakota/Dakota/Content/Sprites/Ship00.png
Normal file
After Width: | Height: | Size: 233 B |
33
Dakota/Dakota/Dakota.csproj
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
<TieredCompilation>false</TieredCompilation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Icon.ico" />
|
||||||
|
<None Remove="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<MonoGameContentReference Include="Content\Content.mgcb" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<TrimmerRootAssembly Include="Microsoft.Xna.Framework.Content.ContentTypeReader" Visible="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nez\Nez.Portable\Nez.MG38.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
31
Dakota/Dakota/Data/GameConstants.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Dakota.Data
|
||||||
|
{
|
||||||
|
public static class GameConstants
|
||||||
|
{
|
||||||
|
public const int UiRenderLayerBg = 910;
|
||||||
|
public const int UiRenderLayerFg = 900;
|
||||||
|
public const int BackgroundRenderLayer = 50;
|
||||||
|
|
||||||
|
public static Color ColorBlack = Color.Black;
|
||||||
|
|
||||||
|
// Space UI
|
||||||
|
public static Color SpaceUiColor = Color.White;
|
||||||
|
public static Color SpaceHudFontColor = new Color(0, 255, 0);
|
||||||
|
|
||||||
|
// Space Gameplay
|
||||||
|
public const float ShipAcceleration = 100;
|
||||||
|
public const float ShipTurnSpeed = 10;
|
||||||
|
|
||||||
|
// Space Colors
|
||||||
|
public static Color ShipColor = Color.White;
|
||||||
|
|
||||||
|
public static Color BoostColor = new Color(255, 128, 0);
|
||||||
|
public static Color AsteroidColor = new Color(128, 128, 128);
|
||||||
|
public static Color FriendlyWeaponColor = new Color(0, 255, 0);
|
||||||
|
public static Color HostileWeaponColor = new Color(255, 0, 255);
|
||||||
|
public static Color SpaceCommandColor = new Color(128, 128, 255);
|
||||||
|
public static Color NoFlyZoneColor = new Color(200, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
24
Dakota/Dakota/Data/PrimaryWeapon.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Dakota.Space;
|
||||||
|
|
||||||
|
namespace Dakota.Data
|
||||||
|
{
|
||||||
|
public enum ProjectileType
|
||||||
|
{
|
||||||
|
Bullet,
|
||||||
|
Beam
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrimaryWeapon
|
||||||
|
{
|
||||||
|
public static PrimaryWeapon Gun = new PrimaryWeapon
|
||||||
|
{Name = "MASS DRIVER", Projectile = ProjectileType.Bullet, Speed = 200f, Duration = 2};
|
||||||
|
|
||||||
|
public static PrimaryWeapon Beam = new PrimaryWeapon
|
||||||
|
{Name = "PHASE BEAM", Projectile = ProjectileType.Beam, Speed = 100f, Duration = 0.2f};
|
||||||
|
|
||||||
|
public float Duration;
|
||||||
|
public string Name;
|
||||||
|
public ProjectileType Projectile;
|
||||||
|
public float Speed;
|
||||||
|
}
|
||||||
|
}
|
58
Dakota/Dakota/Data/ZoneData.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
namespace Dakota.Data
|
||||||
|
{
|
||||||
|
public class Zone
|
||||||
|
{
|
||||||
|
public int Height;
|
||||||
|
public bool IsCurvedX;
|
||||||
|
|
||||||
|
public bool IsCurvedY;
|
||||||
|
// a rectangular region in space
|
||||||
|
|
||||||
|
public int UniversalX;
|
||||||
|
public int UniversalY;
|
||||||
|
public int Width;
|
||||||
|
|
||||||
|
public Zone()
|
||||||
|
{
|
||||||
|
UniversalX = 0;
|
||||||
|
UniversalY = 0;
|
||||||
|
Width = 3000;
|
||||||
|
Height = 3000;
|
||||||
|
IsCurvedX = false;
|
||||||
|
IsCurvedY = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ZoneData
|
||||||
|
{
|
||||||
|
private static Zone[,] _zones = new Zone[26, 26];
|
||||||
|
|
||||||
|
public static Zone GetZone(int x, int y)
|
||||||
|
{
|
||||||
|
if (_zones[x, y] is null)
|
||||||
|
{
|
||||||
|
var zone = new Zone
|
||||||
|
{
|
||||||
|
UniversalX = x,
|
||||||
|
UniversalY = y,
|
||||||
|
Width = 3000,
|
||||||
|
Height = 3000
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act 1, Scene 1
|
||||||
|
if (x == 16 && y == 13)
|
||||||
|
{
|
||||||
|
zone.Width = 1000;
|
||||||
|
zone.Height = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x == 3 && y == 3) zone.IsCurvedX = true;
|
||||||
|
|
||||||
|
if (x == 3 && y > 8 && y < 16) zone.IsCurvedY = true;
|
||||||
|
_zones[x, y] = zone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _zones[x, y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
Dakota/Dakota/Game1.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using Dakota.Space;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota
|
||||||
|
{
|
||||||
|
public class Game1 : Core
|
||||||
|
{
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
Scene = new SpaceScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
Dakota/Dakota/Icon.bmp
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
Dakota/Dakota/Icon.ico
Normal file
After Width: | Height: | Size: 144 KiB |
118
Dakota/Dakota/Missions/Mission1.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Dakota.Space;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Missions
|
||||||
|
{
|
||||||
|
public class Mission1 : SpaceMission
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 1) fly into boundary: add asteroids & boundary
|
||||||
|
* 2) destroy one asteroid: OK 3 more
|
||||||
|
* 3) three more: zone map
|
||||||
|
* 4) fly to highlighted zone
|
||||||
|
* this is a metroidvania shooter?
|
||||||
|
*/
|
||||||
|
|
||||||
|
private NoFlyZone _noFlyZone;
|
||||||
|
private string _status;
|
||||||
|
private const int SmallAsteroidGoal = 16;
|
||||||
|
|
||||||
|
public override string GetMissionStatus()
|
||||||
|
{
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnStart()
|
||||||
|
{
|
||||||
|
ZoneShiftDisabled = true;
|
||||||
|
SpaceScene.CurrentZone = ZoneData.GetZone(16, 13);
|
||||||
|
SpaceScene.PlayerWarpTo(new Vector2(500, 500));
|
||||||
|
SpaceScene.Primary = PrimaryWeapon.Gun;
|
||||||
|
|
||||||
|
_status = "EXPLORE AREA";
|
||||||
|
|
||||||
|
AddBoundary("inner",
|
||||||
|
new Rectangle(100, 100, SpaceScene.CurrentZone.Width - 100, SpaceScene.CurrentZone.Height - 100));
|
||||||
|
_noFlyZone = SpaceScene.CreateEntity("no fly zone").AddComponent(new NoFlyZone(100));
|
||||||
|
_noFlyZone.Enabled = false;
|
||||||
|
|
||||||
|
Core.Schedule(0.1f,
|
||||||
|
timer => SpaceScene.DialogBox.ShowDialog(
|
||||||
|
"THIS IS YOUR FIRST TIME FLYING \nOUTSIDE SIMULATION.\nTRY AND FLY AROUND A BIT.", 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddEmitters()
|
||||||
|
{
|
||||||
|
SpaceScene.AsteroidEmitter.EmitSpeed = 5;
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(0, 0));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(1000, 1000));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(0, 1000));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(1000, 0));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(500, 0));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(0, 500));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(1000, 500));
|
||||||
|
SpaceScene.AsteroidEmitter.AddEmitter(new Vector2(500, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnExitRegion(string name)
|
||||||
|
{
|
||||||
|
if (!_noFlyZone.Enabled)
|
||||||
|
{
|
||||||
|
SpaceScene.DialogBox.ShowDialog("IT IS EASY TO GET LOST IN SPACE\nLET'S STAY CLOSE FOR NOW", 3);
|
||||||
|
_noFlyZone.Enabled = true;
|
||||||
|
_status = "DESTROY ASTEROIDS";
|
||||||
|
AddEmitters();
|
||||||
|
}
|
||||||
|
|
||||||
|
AutopilotReverse(150);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAsteroidDestroyed(AsteroidSize size)
|
||||||
|
{
|
||||||
|
base.OnAsteroidDestroyed(size);
|
||||||
|
|
||||||
|
if (size == AsteroidSize.LARGE && AsteroidsDestroyed[AsteroidSize.LARGE] == 1)
|
||||||
|
{
|
||||||
|
SpaceScene.DialogBox.ShowDialog("GREAT JOB! BE SURE TO BREAK UP THE REST OF IT", 3);
|
||||||
|
}
|
||||||
|
else if (size == AsteroidSize.MEDIUM && AsteroidsDestroyed[AsteroidSize.MEDIUM] % 3 == 0)
|
||||||
|
{
|
||||||
|
SpaceScene.DialogBox.ShowDialog("KEEP IT UP!", 3);
|
||||||
|
}
|
||||||
|
else if (size == AsteroidSize.SMALL)
|
||||||
|
{
|
||||||
|
if (AsteroidsDestroyed[AsteroidSize.SMALL] >= 4 &&
|
||||||
|
AsteroidsDestroyed[AsteroidSize.SMALL] < SmallAsteroidGoal)
|
||||||
|
{
|
||||||
|
var percent = (int) ((float) AsteroidsDestroyed[AsteroidSize.SMALL] / SmallAsteroidGoal * 100);
|
||||||
|
_status = $"DESTROY ASTEROIDS\n{percent}";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (AsteroidsDestroyed[AsteroidSize.SMALL])
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
SpaceScene.DialogBox.ShowDialog("OK ONE DOWN, PHEW!\nTAKE OUT 3 MORE", 3);
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
SpaceScene.DialogBox.ShowDialog("JUST A FEW MORE!", 3);
|
||||||
|
break;
|
||||||
|
case SmallAsteroidGoal:
|
||||||
|
SpaceScene.DialogBox.ShowDialog("ALL DONE! LET'S LOOK AT YOUR MAP.", 3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnPlayerHit()
|
||||||
|
{
|
||||||
|
base.OnPlayerHit();
|
||||||
|
|
||||||
|
if (PlayerHitCount == 1)
|
||||||
|
SpaceScene.DialogBox.ShowDialog("WATCH OUT, THESE SHIPS ARE EXPENSIVE", 3);
|
||||||
|
else if (PlayerHitCount == 10)
|
||||||
|
SpaceScene.DialogBox.ShowDialog("YOU ARE TERRIBLE AT THIS", 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
Dakota/Dakota/Missions/SpaceMission.cs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dakota.Data;
|
||||||
|
using Dakota.Space;
|
||||||
|
using Dakota.Utils;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
|
||||||
|
namespace Dakota.Missions
|
||||||
|
{
|
||||||
|
public class SpaceMission : SceneComponent
|
||||||
|
{
|
||||||
|
protected SpaceScene SpaceScene => (SpaceScene) Scene;
|
||||||
|
protected int PlayerHitCount;
|
||||||
|
protected Dictionary<AsteroidSize, int> AsteroidsDestroyed;
|
||||||
|
public bool ZoneShiftDisabled;
|
||||||
|
private readonly Dictionary<string, Rectangle> _boundaries;
|
||||||
|
private readonly Dictionary<string, bool> _lastFrame;
|
||||||
|
private Vector2? _autopilotDestination;
|
||||||
|
|
||||||
|
protected SpaceMission()
|
||||||
|
{
|
||||||
|
ZoneShiftDisabled = false;
|
||||||
|
AsteroidsDestroyed = new Dictionary<AsteroidSize, int>();
|
||||||
|
foreach (AsteroidSize size in Enum.GetValues(typeof(AsteroidSize))) AsteroidsDestroyed[size] = 0;
|
||||||
|
_boundaries = new Dictionary<string, Rectangle>();
|
||||||
|
_lastFrame = new Dictionary<string, bool>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AddBoundary(string name, Rectangle rect)
|
||||||
|
{
|
||||||
|
_boundaries[name] = rect;
|
||||||
|
_lastFrame[name] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AutopilotTo(Vector2 to)
|
||||||
|
{
|
||||||
|
_autopilotDestination = to;
|
||||||
|
SpaceScene.CenterText.SetText("AUTOPILOT ENGAGED", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void AutopilotReverse(int magnitude)
|
||||||
|
{
|
||||||
|
var backwards = -Vector2.Normalize(SpaceScene.Player.GetComponent<SpaceObject>().Velocity);
|
||||||
|
AutopilotTo(SpaceScene.Player.Position + backwards * magnitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Hooks
|
||||||
|
|
||||||
|
// these methods can be overriden on missions to control behavior
|
||||||
|
|
||||||
|
public virtual string GetMissionStatus()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnStart()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnAsteroidDestroyed(AsteroidSize size)
|
||||||
|
{
|
||||||
|
AsteroidsDestroyed[size] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnPlayerHit()
|
||||||
|
{
|
||||||
|
PlayerHitCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnEnterRegion(string name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnExitRegion(string name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
// check boundaries
|
||||||
|
foreach (var (name, rect) in _boundaries)
|
||||||
|
{
|
||||||
|
var thisFrame = rect.Contains(SpaceScene.Player.Position);
|
||||||
|
if (thisFrame && !_lastFrame[name])
|
||||||
|
OnEnterRegion(name);
|
||||||
|
if (!thisFrame && _lastFrame[name])
|
||||||
|
OnExitRegion(name);
|
||||||
|
_lastFrame[name] = thisFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
// autopilot adjustments
|
||||||
|
if (_autopilotDestination != null)
|
||||||
|
{
|
||||||
|
var dist = SpaceScene.Player.Position - (Vector2) _autopilotDestination;
|
||||||
|
|
||||||
|
if (dist.Length() < 35)
|
||||||
|
{
|
||||||
|
_autopilotDestination = null;
|
||||||
|
SpaceScene.CenterText.SetText("AUTOPILOT DISENGAGED", 3);
|
||||||
|
SpaceScene.Player.GetComponent<SpaceObject>().Velocity = Vector2.Zero;
|
||||||
|
SpaceScene.Player.GetComponent<PlayerShip>().Thrust(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var targetAngle = DakotaUtils.ToAngle(dist);
|
||||||
|
if (dist.Length() > 100)
|
||||||
|
targetAngle += (float) Math.PI;
|
||||||
|
|
||||||
|
if (SpaceScene.Player.Rotation - targetAngle > 0.1f)
|
||||||
|
SpaceScene.Player.Rotation -= GameConstants.ShipTurnSpeed * Time.DeltaTime;
|
||||||
|
else if (targetAngle - SpaceScene.Player.Rotation > 0.1f)
|
||||||
|
SpaceScene.Player.Rotation += GameConstants.ShipTurnSpeed * Time.DeltaTime;
|
||||||
|
else
|
||||||
|
SpaceScene.Player.GetComponent<PlayerShip>().Thrust(.01f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
Dakota/Dakota/Program.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Dakota
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
private static void Main()
|
||||||
|
{
|
||||||
|
using (var game = new Game1())
|
||||||
|
{
|
||||||
|
game.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
Dakota/Dakota/Renderables/DialogBox.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Renderables
|
||||||
|
{
|
||||||
|
public class DialogBox : RenderableComponent, IUpdatable
|
||||||
|
{
|
||||||
|
public override float Width => 1000;
|
||||||
|
public override float Height => 100;
|
||||||
|
|
||||||
|
private const int Padding = 10;
|
||||||
|
private const int PhotoBoxSize = 72;
|
||||||
|
|
||||||
|
private float _durationRemaining;
|
||||||
|
private VectorText _vt;
|
||||||
|
private StaticBox _sb;
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
RenderLayer = GameConstants.UiRenderLayerBg;
|
||||||
|
_vt = Entity.AddComponent(new VectorText("", 20, GameConstants.SpaceUiColor));
|
||||||
|
_vt.LocalOffset = new Vector2(Padding * 2 + PhotoBoxSize, Padding);
|
||||||
|
|
||||||
|
_sb = Entity.AddComponent(new StaticBox(72, 72, GameConstants.SpaceCommandColor));
|
||||||
|
_sb.LocalOffset = new Vector2(Padding, Padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
batcher.DrawRect(Entity.Position, Width, Height, GameConstants.ColorBlack);
|
||||||
|
batcher.DrawHollowRect(Entity.Position, Width - 5, Height, GameConstants.SpaceUiColor);
|
||||||
|
batcher.DrawHollowRect(Entity.Position.X + Padding, Entity.Position.Y + Padding,
|
||||||
|
PhotoBoxSize, PhotoBoxSize, GameConstants.SpaceUiColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
_durationRemaining -= Time.DeltaTime;
|
||||||
|
if (_durationRemaining < 0)
|
||||||
|
{
|
||||||
|
Enabled = false;
|
||||||
|
_vt.Enabled = false;
|
||||||
|
_sb.Enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowDialog(string text, float duration)
|
||||||
|
{
|
||||||
|
_durationRemaining = duration;
|
||||||
|
_vt.Text = text;
|
||||||
|
_vt.Color = GameConstants.SpaceCommandColor;
|
||||||
|
Enabled = true;
|
||||||
|
_vt.Enabled = true;
|
||||||
|
_sb.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
Dakota/Dakota/Renderables/StaticBox.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Renderables
|
||||||
|
{
|
||||||
|
public class StaticBox : RenderableComponent
|
||||||
|
{
|
||||||
|
public override float Width => _width;
|
||||||
|
public override float Height => _height;
|
||||||
|
|
||||||
|
private int _width;
|
||||||
|
private int _height;
|
||||||
|
|
||||||
|
public StaticBox(int width, int height, Color color)
|
||||||
|
{
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
Color = color;
|
||||||
|
|
||||||
|
RenderLayer = GameConstants.UiRenderLayerBg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < Width; ++x)
|
||||||
|
for (var y = 0; y < Height; ++y)
|
||||||
|
if (Random.Chance(0.2f))
|
||||||
|
batcher.DrawPixel(
|
||||||
|
Entity.Position.X + LocalOffset.X + x,
|
||||||
|
Entity.Position.Y + LocalOffset.Y + y,
|
||||||
|
Color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
Dakota/Dakota/Renderables/TimedVectorText.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Renderables
|
||||||
|
{
|
||||||
|
public class TimedVectorText : VectorText, IUpdatable
|
||||||
|
{
|
||||||
|
private float _durationRemaining;
|
||||||
|
|
||||||
|
public TimedVectorText(int size, Color color) : base("", size, color)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (Text.Length > 0)
|
||||||
|
{
|
||||||
|
_durationRemaining -= Time.DeltaTime;
|
||||||
|
if (_durationRemaining < 0) Text = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetText(string text, float duration)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
_durationRemaining = duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
Dakota/Dakota/Renderables/VectorSprite.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
using Nez.PhysicsShapes;
|
||||||
|
|
||||||
|
namespace Dakota.Renderables
|
||||||
|
{
|
||||||
|
public class VectorSprite : RenderableComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private Vector2[] _polygon;
|
||||||
|
private Vector2[] _rotatedPolygon;
|
||||||
|
|
||||||
|
public override float Width => 100;
|
||||||
|
public override float Height => 100;
|
||||||
|
|
||||||
|
public VectorSprite(Vector2[] polygon, Color color)
|
||||||
|
{
|
||||||
|
_polygon = polygon;
|
||||||
|
_rotatedPolygon = new Vector2[polygon.Length];
|
||||||
|
Color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
Polygon.RotatePolygonVerts(Entity.Rotation, _polygon, _rotatedPolygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
Polygon.RotatePolygonVerts(Entity.Rotation, _polygon, _rotatedPolygon);
|
||||||
|
batcher.DrawPolygon(Entity.Position, _rotatedPolygon, Color, true, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
458
Dakota/Dakota/Renderables/VectorText.cs
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dakota.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Renderables
|
||||||
|
{
|
||||||
|
public class VectorText : RenderableComponent
|
||||||
|
{
|
||||||
|
private const char Unprintable = '~';
|
||||||
|
|
||||||
|
private static Dictionary<char, Vector2?[]> _font = new Dictionary<char, Vector2?[]>();
|
||||||
|
public int Size;
|
||||||
|
public string Text;
|
||||||
|
public float Thickness = 1.0f;
|
||||||
|
|
||||||
|
static VectorText()
|
||||||
|
{
|
||||||
|
// each entry corresponds to the vectors for a given glyph
|
||||||
|
// lines are drawn from point to point the way one would if writing
|
||||||
|
// a null will "lift the pen" so to speak, starting a new set of
|
||||||
|
// lines not connected to the prior set
|
||||||
|
_font[Unprintable] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 0)
|
||||||
|
};
|
||||||
|
_font['A'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0.5f, 0),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0.2f, 0.5f),
|
||||||
|
new Vector2(0.7f, 0.5f)
|
||||||
|
};
|
||||||
|
_font['B'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 0.8f),
|
||||||
|
new Vector2(1, 0.6f),
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.4f),
|
||||||
|
new Vector2(1, 0.2f),
|
||||||
|
new Vector2(0, 0)
|
||||||
|
};
|
||||||
|
_font['C'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1)
|
||||||
|
};
|
||||||
|
_font['D'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(1, 0.6f),
|
||||||
|
new Vector2(1, 0.4f),
|
||||||
|
new Vector2(0.5f, 0),
|
||||||
|
new Vector2(0, 0)
|
||||||
|
};
|
||||||
|
_font['E'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f)
|
||||||
|
};
|
||||||
|
_font['F'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f)
|
||||||
|
};
|
||||||
|
_font['G'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0.2f),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0.7f),
|
||||||
|
new Vector2(0.5f, 0.7f)
|
||||||
|
};
|
||||||
|
_font['H'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f)
|
||||||
|
};
|
||||||
|
_font['I'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
null,
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0),
|
||||||
|
new Vector2(0.5f, 1)
|
||||||
|
};
|
||||||
|
_font['J'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(0, 0.7f)
|
||||||
|
};
|
||||||
|
_font['K'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['L'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1)
|
||||||
|
};
|
||||||
|
_font['M'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0.5f, 0.2f),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(1, 1)
|
||||||
|
};
|
||||||
|
_font['N'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0)
|
||||||
|
};
|
||||||
|
_font['O'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0)
|
||||||
|
};
|
||||||
|
_font['P'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(1, 0.4f),
|
||||||
|
new Vector2(0, 0.4f)
|
||||||
|
};
|
||||||
|
_font['Q'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
null,
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(0.5f, 0.6f)
|
||||||
|
};
|
||||||
|
_font['R'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(1, 0.4f),
|
||||||
|
new Vector2(0, 0.4f),
|
||||||
|
new Vector2(1, 1)
|
||||||
|
};
|
||||||
|
_font['S'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['T'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0),
|
||||||
|
new Vector2(0.5f, 1)
|
||||||
|
};
|
||||||
|
_font['U'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0)
|
||||||
|
};
|
||||||
|
_font['V'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(1, 0)
|
||||||
|
};
|
||||||
|
_font['W'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(0.5f, 0.7f),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0)
|
||||||
|
};
|
||||||
|
_font['X'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
null,
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['Y'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0.5f, 0.4f),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0.4f),
|
||||||
|
new Vector2(0.5f, 1)
|
||||||
|
};
|
||||||
|
_font['Z'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1)
|
||||||
|
};
|
||||||
|
_font['0'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['1'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(0.5f, 0),
|
||||||
|
new Vector2(0.3f, 0.2f)
|
||||||
|
};
|
||||||
|
_font['2'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0.2f),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1)
|
||||||
|
};
|
||||||
|
_font['3'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['4'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.8f, 1),
|
||||||
|
new Vector2(0.8f, 0),
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f)
|
||||||
|
};
|
||||||
|
_font['5'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 0.5f),
|
||||||
|
new Vector2(1, 0.5f),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['6'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0.6f),
|
||||||
|
new Vector2(0, 0.6f)
|
||||||
|
};
|
||||||
|
_font['7'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 1)
|
||||||
|
};
|
||||||
|
_font['8'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 1),
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(0, 0)
|
||||||
|
};
|
||||||
|
_font['9'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(1, 1),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(0, 0.4f),
|
||||||
|
new Vector2(1, 0.4f)
|
||||||
|
};
|
||||||
|
_font[' '] = new Vector2?[] { };
|
||||||
|
_font['.'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.5f, 0.9f),
|
||||||
|
new Vector2(0.6f, 0.9f),
|
||||||
|
new Vector2(0.6f, 1),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(0.5f, 0.9f)
|
||||||
|
};
|
||||||
|
_font['!'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.55f, 0),
|
||||||
|
new Vector2(0.55f, 0.8f),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0.9f),
|
||||||
|
new Vector2(0.6f, 0.9f),
|
||||||
|
new Vector2(0.6f, 1),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(0.5f, 0.9f)
|
||||||
|
};
|
||||||
|
_font['?'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
new Vector2(1, 0),
|
||||||
|
new Vector2(1, 0.4f),
|
||||||
|
new Vector2(0.55f, 0.4f),
|
||||||
|
new Vector2(0.55f, 0.8f),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0.9f),
|
||||||
|
new Vector2(0.6f, 0.9f),
|
||||||
|
new Vector2(0.6f, 1),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(0.5f, 0.9f)
|
||||||
|
};
|
||||||
|
_font[','] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.7f, 0.6f),
|
||||||
|
new Vector2(0.6f, 1)
|
||||||
|
};
|
||||||
|
_font['\''] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.7f, 0),
|
||||||
|
new Vector2(0.6f, 0.3f)
|
||||||
|
};
|
||||||
|
_font[':'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.5f, 0.9f),
|
||||||
|
new Vector2(0.6f, 0.9f),
|
||||||
|
new Vector2(0.6f, 1),
|
||||||
|
new Vector2(0.5f, 1),
|
||||||
|
new Vector2(0.5f, 0.9f),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0),
|
||||||
|
new Vector2(0.6f, 0),
|
||||||
|
new Vector2(0.6f, 0.1f),
|
||||||
|
new Vector2(0.5f, 0.1f),
|
||||||
|
new Vector2(0.5f, 0)
|
||||||
|
};
|
||||||
|
_font['-'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.2f, 0.5f),
|
||||||
|
new Vector2(0.8f, 0.5f)
|
||||||
|
};
|
||||||
|
_font['+'] = new Vector2?[]
|
||||||
|
{
|
||||||
|
new Vector2(0.2f, 0.5f),
|
||||||
|
new Vector2(0.8f, 0.5f),
|
||||||
|
null,
|
||||||
|
new Vector2(0.5f, 0.2f),
|
||||||
|
new Vector2(0.5f, 0.8f)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public VectorText(string text, int size, Color color)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
Size = size;
|
||||||
|
Color = color;
|
||||||
|
RenderLayer = GameConstants.UiRenderLayerFg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// approximate
|
||||||
|
public override float Width => Size * Text.Length;
|
||||||
|
public override float Height => Size;
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
var spacing = 5;
|
||||||
|
var curOffset = new Vector2(-Size, 0);
|
||||||
|
|
||||||
|
foreach (var ch in Text)
|
||||||
|
{
|
||||||
|
Vector2?[] letter;
|
||||||
|
if (ch == '\n')
|
||||||
|
{
|
||||||
|
curOffset.X = -Size;
|
||||||
|
curOffset.Y += Size + spacing;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (_font.ContainsKey(ch))
|
||||||
|
{
|
||||||
|
letter = _font[ch];
|
||||||
|
curOffset.X += Size + spacing;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
letter = _font[Unprintable];
|
||||||
|
curOffset.X += Size + spacing;
|
||||||
|
Console.WriteLine($"UNPRINTABLE: {ch}");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < letter.Length - 1; i++)
|
||||||
|
if (letter[i] != null && letter[i + 1] != null)
|
||||||
|
batcher.DrawLine(
|
||||||
|
(Vector2) letter[i] * Size + curOffset + Entity.Position + LocalOffset,
|
||||||
|
(Vector2) letter[i + 1] * Size + curOffset + Entity.Position + LocalOffset,
|
||||||
|
Color,
|
||||||
|
Thickness
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Dakota/Dakota/ScreenSpin.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota
|
||||||
|
{
|
||||||
|
public class ScreenSpin : Component, IUpdatable
|
||||||
|
{
|
||||||
|
private readonly Vector2 _around;
|
||||||
|
private float _speed;
|
||||||
|
|
||||||
|
public ScreenSpin(Vector2 around, float speed)
|
||||||
|
{
|
||||||
|
_speed = speed;
|
||||||
|
_around = around;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
Entity.Scene.Camera.Rotation += _speed * Time.DeltaTime;
|
||||||
|
if (Entity.Scene.Camera.Rotation > 5) Entity.RemoveComponent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
Entity.Scene.Camera.Position = _around;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
87
Dakota/Dakota/Space/Asteroid.cs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using Dakota.Data;
|
||||||
|
using Dakota.Renderables;
|
||||||
|
using Dakota.Utils;
|
||||||
|
using Nez;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
using Vector2 = Microsoft.Xna.Framework.Vector2;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public enum AsteroidSize
|
||||||
|
{
|
||||||
|
SMALL,
|
||||||
|
MEDIUM,
|
||||||
|
LARGE,
|
||||||
|
HUGE
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Asteroid : Component, ITriggerListener
|
||||||
|
{
|
||||||
|
public AsteroidSize Size;
|
||||||
|
|
||||||
|
public Asteroid(AsteroidSize size = AsteroidSize.LARGE)
|
||||||
|
{
|
||||||
|
Size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITriggerListener.OnTriggerEnter(Collider other, Collider self)
|
||||||
|
{
|
||||||
|
if (other.Entity.Name == "bullet" && !other.Entity.IsDestroyed)
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
scene.HitAsteroid(self.Entity, other.Entity.Position);
|
||||||
|
other.Entity.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to only process A-A collisions once, so use ID comparison
|
||||||
|
if (other.Entity.Name == "asteroid" && other.Entity.Id > self.Entity.Id)
|
||||||
|
{
|
||||||
|
other.CollidesWith(self, out var collisionResult);
|
||||||
|
self.Entity.Position += collisionResult.MinimumTranslationVector;
|
||||||
|
var p1 = self.Entity.Position;
|
||||||
|
var v1 = self.Entity.GetComponent<SpaceObject>().Velocity;
|
||||||
|
var p2 = other.Entity.Position;
|
||||||
|
var v2 = other.Entity.GetComponent<SpaceObject>().Velocity;
|
||||||
|
var diff1 = p1 - p2;
|
||||||
|
var diff2 = p2 - p1;
|
||||||
|
var newV1 = v1 - Vector2.Dot(v1 - v2, diff1) / diff1.LengthSquared() * diff1;
|
||||||
|
var newV2 = v2 - Vector2.Dot(v2 - v1, diff2) / diff2.LengthSquared() * diff2;
|
||||||
|
self.Entity.GetComponent<SpaceObject>().Velocity = newV1;
|
||||||
|
other.Entity.GetComponent<SpaceObject>().Velocity = newV2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITriggerListener.OnTriggerExit(Collider other, Collider self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
var numPoints = Random.NextInt(3) + 7;
|
||||||
|
var polygon = new Vector2[numPoints];
|
||||||
|
for (var i = 0; i < numPoints; i++)
|
||||||
|
{
|
||||||
|
var angle = (float) ((float) i / numPoints * 2 * Math.PI);
|
||||||
|
var radius = Radius() + Random.MinusOneToOne() * Radius() * 0.2f;
|
||||||
|
polygon[i] = radius * DakotaUtils.VecFromAngle(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to clone polygon here so original is intact for drawing rotations
|
||||||
|
Entity.AddComponent(new PolygonCollider((Vector2[]) polygon.Clone())).IsTrigger = true;
|
||||||
|
Entity.AddComponent(new VectorSprite(polygon, GameConstants.AsteroidColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Radius()
|
||||||
|
{
|
||||||
|
return Size switch
|
||||||
|
{
|
||||||
|
AsteroidSize.HUGE => 128,
|
||||||
|
AsteroidSize.LARGE => 72,
|
||||||
|
AsteroidSize.MEDIUM => 48,
|
||||||
|
AsteroidSize.SMALL => 24,
|
||||||
|
_ => 256
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
Dakota/Dakota/Space/BaddieEmitter.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Dakota.Utils;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class BaddieEmitter : SceneComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private List<Vector2> _emitterPoints;
|
||||||
|
private float _nextEmission;
|
||||||
|
public float EmitSpeed;
|
||||||
|
|
||||||
|
public BaddieEmitter()
|
||||||
|
{
|
||||||
|
_emitterPoints = new List<Vector2>();
|
||||||
|
EmitSpeed = 0;
|
||||||
|
_nextEmission = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddEmitter(Vector2 pos)
|
||||||
|
{
|
||||||
|
_emitterPoints.Add(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Emit()
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Scene;
|
||||||
|
var posIndex = Random.NextInt(_emitterPoints.Count);
|
||||||
|
var pos = _emitterPoints[posIndex];
|
||||||
|
var angle = DakotaUtils.ToAngle(new Vector2(scene.CurrentZone.Width / 2 - pos.X,
|
||||||
|
scene.CurrentZone.Height / 2 - pos.Y));
|
||||||
|
var vel = DakotaUtils.VecFromAngle(angle) * (Random.NextFloat(30) + 30);
|
||||||
|
scene.AddAsteroid(pos, AsteroidSize.LARGE, vel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if (EmitSpeed > 0)
|
||||||
|
{
|
||||||
|
if (_nextEmission == 0)
|
||||||
|
_nextEmission = EmitSpeed;
|
||||||
|
_nextEmission -= Time.DeltaTime;
|
||||||
|
if (_nextEmission < 0)
|
||||||
|
{
|
||||||
|
_nextEmission += EmitSpeed;
|
||||||
|
Emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
Dakota/Dakota/Space/GalacticMap.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class GalacticMap : RenderableComponent
|
||||||
|
{
|
||||||
|
private const float GridSize = 25f;
|
||||||
|
public override float Width => 500;
|
||||||
|
public override float Height => 520;
|
||||||
|
|
||||||
|
public GalacticMap()
|
||||||
|
{
|
||||||
|
RenderLayer = GameConstants.UiRenderLayerBg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FillBox(Batcher batcher, int x, int y, Color color)
|
||||||
|
{
|
||||||
|
batcher.DrawRect(
|
||||||
|
GridSize * x + 1 + Entity.Position.X,
|
||||||
|
GridSize * y + 2 + Entity.Position.Y,
|
||||||
|
GridSize - 3,
|
||||||
|
GridSize - 3,
|
||||||
|
color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
var xSectors = 26;
|
||||||
|
var ySectors = 26;
|
||||||
|
|
||||||
|
// draw horizontal lines
|
||||||
|
for (var i = 0; i <= ySectors; i++)
|
||||||
|
{
|
||||||
|
batcher.DrawLine(
|
||||||
|
0 + Entity.Position.X,
|
||||||
|
i * GridSize + Entity.Position.Y,
|
||||||
|
xSectors * GridSize + Entity.Position.X,
|
||||||
|
i * GridSize + Entity.Position.Y,
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
|
||||||
|
// draw vertical lines
|
||||||
|
for (var j = 0; j <= xSectors; j++)
|
||||||
|
{
|
||||||
|
batcher.DrawLine(
|
||||||
|
j * GridSize + Entity.Position.X,
|
||||||
|
0 + Entity.Position.Y,
|
||||||
|
j * GridSize + Entity.Position.X,
|
||||||
|
ySectors * GridSize + Entity.Position.Y,
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
|
||||||
|
if (i < ySectors && j < xSectors)
|
||||||
|
{
|
||||||
|
if (ZoneData.GetZone(j, i).IsCurvedX)
|
||||||
|
FillBox(batcher, j, i, Color.Purple);
|
||||||
|
if (ZoneData.GetZone(j, i).IsCurvedY)
|
||||||
|
FillBox(batcher, j, i, Color.Brown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// color current zone
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
FillBox(batcher, scene.CurrentZone.UniversalX, scene.CurrentZone.UniversalY, Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
Dakota/Dakota/Space/NoFlyZone.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class NoFlyZone : RenderableComponent
|
||||||
|
{
|
||||||
|
public override float Width => 800;
|
||||||
|
public override float Height => 800;
|
||||||
|
|
||||||
|
private int _padding;
|
||||||
|
private RectangleF _innerRect;
|
||||||
|
private RectangleF _outerRect;
|
||||||
|
|
||||||
|
public NoFlyZone(int padding)
|
||||||
|
{
|
||||||
|
_padding = padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
_innerRect = new RectangleF(_padding, _padding, scene.CurrentZone.Width - _padding,
|
||||||
|
scene.CurrentZone.Height - _padding);
|
||||||
|
_outerRect = new RectangleF(_padding - 10, _padding - 10, scene.CurrentZone.Width - _padding + 20,
|
||||||
|
scene.CurrentZone.Height - _padding + 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
// terrible looking, what should this look like?
|
||||||
|
batcher.DrawHollowRect(_innerRect, GameConstants.NoFlyZoneColor);
|
||||||
|
batcher.DrawHollowRect(_outerRect, GameConstants.NoFlyZoneColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
159
Dakota/Dakota/Space/PlayerShip.cs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
using System;
|
||||||
|
using Dakota.Data;
|
||||||
|
using Dakota.Renderables;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using Nez;
|
||||||
|
using Nez.Particles;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public enum ShipUpgrades
|
||||||
|
{
|
||||||
|
InertialThrusters, // reverse-thrust to create false feeling of inertia
|
||||||
|
HyperspaceStabilizer // reduce likelihood of hyperspace malfunction
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ShipWeapons
|
||||||
|
{
|
||||||
|
PhaseBlaster, // simple blaster
|
||||||
|
LaserBeam, // steady pulsed beam
|
||||||
|
RailGun // unstable spray
|
||||||
|
}
|
||||||
|
|
||||||
|
// one idea is to have these enter R&D and you can get an imperfect version that gets better as you use it
|
||||||
|
// if you're gonna have all these sweet upgrades, better have fun shit to fly near
|
||||||
|
|
||||||
|
public class PlayerShip : Component, IUpdatable, ITriggerListener
|
||||||
|
{
|
||||||
|
private VirtualButton _fireInput;
|
||||||
|
private VirtualButton _secondaryFireInput;
|
||||||
|
private VirtualIntegerAxis _rotateInput;
|
||||||
|
private VirtualButton _thrustInput;
|
||||||
|
private VirtualButton _warpInput;
|
||||||
|
private float _emitCounter;
|
||||||
|
private ParticleEmitter _emitter;
|
||||||
|
private ParticleEmitterConfig _emitterConfig;
|
||||||
|
private VectorSprite _booster;
|
||||||
|
private float _autothrustTime;
|
||||||
|
|
||||||
|
void ITriggerListener.OnTriggerEnter(Collider other, Collider self)
|
||||||
|
{
|
||||||
|
if (other.Entity.Name == "asteroid")
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
scene.PlayerHit();
|
||||||
|
scene.HitAsteroid(other.Entity, self.Entity.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ITriggerListener.OnTriggerExit(Collider other, Collider self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ThrustOn => _thrustInput.IsDown || _autothrustTime > 0;
|
||||||
|
|
||||||
|
public void Thrust(float time)
|
||||||
|
{
|
||||||
|
_autothrustTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
var obj = Entity.GetComponent<SpaceObject>();
|
||||||
|
if (_fireInput.IsPressed) ((SpaceScene) Entity.Scene).FirePrimary();
|
||||||
|
if (_warpInput.IsPressed) ((SpaceScene) Entity.Scene).Warp();
|
||||||
|
|
||||||
|
obj.SetAcceleration(ThrustOn ? GameConstants.ShipAcceleration : 0);
|
||||||
|
_booster.Enabled = ThrustOn;
|
||||||
|
|
||||||
|
if (ThrustOn)
|
||||||
|
_emitCounter += Time.DeltaTime;
|
||||||
|
while (_emitCounter > 0.01f)
|
||||||
|
{
|
||||||
|
_emitter.Emit(1);
|
||||||
|
_emitCounter -= 0.01f;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.TurnVelocity = _rotateInput.Value * GameConstants.ShipTurnSpeed;
|
||||||
|
|
||||||
|
_emitterConfig.Angle = MathHelper.ToDegrees(Entity.Rotation) + 90;
|
||||||
|
_emitter.LocalOffset = new Vector2(-16 * (float) Math.Sin(Entity.Rotation),
|
||||||
|
16 * (float) Math.Cos(Entity.Rotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
Entity.AddComponent(new SpaceObject());
|
||||||
|
|
||||||
|
var shipPolygon = new[]
|
||||||
|
{
|
||||||
|
new Vector2(0, -16),
|
||||||
|
new Vector2(-16, 16),
|
||||||
|
new Vector2(0, 10),
|
||||||
|
new Vector2(16, 16)
|
||||||
|
};
|
||||||
|
Entity.AddComponent(new VectorSprite(shipPolygon, GameConstants.ShipColor));
|
||||||
|
|
||||||
|
var boostPoly = new[]
|
||||||
|
{
|
||||||
|
new Vector2(-16, 16),
|
||||||
|
new Vector2(-8, 24),
|
||||||
|
new Vector2(0, 12),
|
||||||
|
new Vector2(8, 24),
|
||||||
|
new Vector2(16, 16)
|
||||||
|
};
|
||||||
|
_booster = Entity.AddComponent(new VectorSprite(boostPoly, GameConstants.BoostColor));
|
||||||
|
|
||||||
|
SetupInput();
|
||||||
|
|
||||||
|
// don't need indent for collider, also need own copy
|
||||||
|
// since PolygonCollider modifies the array for rotations
|
||||||
|
var colliderPolygon = new[]
|
||||||
|
{
|
||||||
|
new Vector2(0, -16),
|
||||||
|
new Vector2(-16, 16),
|
||||||
|
new Vector2(16, 16)
|
||||||
|
};
|
||||||
|
Entity.AddComponent(new PolygonCollider(colliderPolygon)).IsTrigger = true;
|
||||||
|
|
||||||
|
var ec = new ParticleEmitterConfig();
|
||||||
|
ec.SourcePositionVariance = new Vector2(2, 2);
|
||||||
|
ec.Speed = 30;
|
||||||
|
ec.SpeedVariance = 1;
|
||||||
|
ec.ParticleLifespan = 3;
|
||||||
|
ec.ParticleLifespanVariance = 1;
|
||||||
|
ec.Angle = 180;
|
||||||
|
ec.AngleVariance = 0;
|
||||||
|
ec.StartColor = Color.Orange;
|
||||||
|
ec.FinishColor = Color.Transparent;
|
||||||
|
ec.StartParticleSize = 4;
|
||||||
|
ec.FinishParticleSize = 0;
|
||||||
|
ec.MaxParticles = 200;
|
||||||
|
ec.EmitterType = ParticleEmitterType.Gravity;
|
||||||
|
_emitterConfig = ec;
|
||||||
|
_emitter = Entity.AddComponent(new ParticleEmitter(ec));
|
||||||
|
_emitter.LocalOffset = new Vector2(0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupInput()
|
||||||
|
{
|
||||||
|
_fireInput = new VirtualButton();
|
||||||
|
_fireInput.Nodes.Add(new VirtualButton.KeyboardKey(Keys.Space));
|
||||||
|
_fireInput.SetRepeat(0.5f, 0.5f);
|
||||||
|
|
||||||
|
_secondaryFireInput = new VirtualButton();
|
||||||
|
_secondaryFireInput.Nodes.Add(new VirtualButton.KeyboardKey(Keys.LeftShift));
|
||||||
|
|
||||||
|
_thrustInput = new VirtualButton();
|
||||||
|
_thrustInput.Nodes.Add(new VirtualButton.KeyboardKey(Keys.Up));
|
||||||
|
|
||||||
|
_warpInput = new VirtualButton();
|
||||||
|
_warpInput.Nodes.Add(new VirtualButton.KeyboardKey(Keys.X));
|
||||||
|
|
||||||
|
_rotateInput = new VirtualIntegerAxis();
|
||||||
|
_rotateInput.Nodes.Add(new VirtualAxis.KeyboardKeys(VirtualInput.OverlapBehavior.TakeNewer, Keys.Left,
|
||||||
|
Keys.Right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
Dakota/Dakota/Space/Projectile.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class Projectile : RenderableComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private float _duration;
|
||||||
|
|
||||||
|
private bool _playerFired;
|
||||||
|
private ProjectileType _type;
|
||||||
|
private Vector2 _velocity;
|
||||||
|
|
||||||
|
public Projectile(ProjectileType type, bool playerFired, float duration)
|
||||||
|
{
|
||||||
|
_type = type;
|
||||||
|
_playerFired = playerFired;
|
||||||
|
_duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float Width => 2;
|
||||||
|
public override float Height => 2;
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
_duration -= Time.DeltaTime;
|
||||||
|
if (_duration <= 0)
|
||||||
|
Entity.Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
_velocity = Entity.GetComponent<SpaceObject>().Velocity;
|
||||||
|
|
||||||
|
Collider collider;
|
||||||
|
switch (_type)
|
||||||
|
{
|
||||||
|
case ProjectileType.Bullet:
|
||||||
|
collider = Entity.AddComponent(new CircleCollider(1));
|
||||||
|
break;
|
||||||
|
case ProjectileType.Beam:
|
||||||
|
collider = Entity.AddComponent(new PolygonCollider(new[]
|
||||||
|
{
|
||||||
|
new Vector2(0, 0),
|
||||||
|
_velocity * 2
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
collider = Entity.AddComponent(new CircleCollider(1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
collider.IsTrigger = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
var color = _playerFired ? GameConstants.FriendlyWeaponColor : GameConstants.HostileWeaponColor;
|
||||||
|
switch (_type)
|
||||||
|
{
|
||||||
|
case ProjectileType.Bullet:
|
||||||
|
batcher.DrawCircle(Entity.Position, 1, color);
|
||||||
|
break;
|
||||||
|
case ProjectileType.Beam:
|
||||||
|
batcher.DrawLine(Entity.Position, Entity.Position + _velocity * 2, color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
47
Dakota/Dakota/Space/SpaceControls.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class SpaceControls : SceneComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private VirtualButton _pauseInput;
|
||||||
|
|
||||||
|
private VirtualButton _debugInput;
|
||||||
|
|
||||||
|
public SpaceControls()
|
||||||
|
{
|
||||||
|
_pauseInput = new VirtualButton();
|
||||||
|
_pauseInput.Nodes.Add(new VirtualButton.KeyboardKey(Keys.P));
|
||||||
|
|
||||||
|
_debugInput = new VirtualButton();
|
||||||
|
_debugInput.Nodes.Add(new VirtualButton.KeyboardKey(Keys.A));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
if (Scene is SpaceScene ss)
|
||||||
|
{
|
||||||
|
if (_pauseInput.IsPressed) ss.TogglePause();
|
||||||
|
|
||||||
|
if (_debugInput.IsPressed)
|
||||||
|
{
|
||||||
|
// horizontal
|
||||||
|
//ss.AddAsteroid(new Vector2(400, 400), AsteroidSize.LARGE, new Vector2(100, 0));
|
||||||
|
//ss.AddAsteroid(new Vector2(900, 400), AsteroidSize.LARGE, new Vector2(-100, 0));
|
||||||
|
|
||||||
|
// vertical
|
||||||
|
//ss.AddAsteroid(new Vector2(400, 0), AsteroidSize.LARGE, new Vector2(0, 100));
|
||||||
|
//ss.AddAsteroid(new Vector2(400, 900), AsteroidSize.LARGE, new Vector2(0, -100));
|
||||||
|
|
||||||
|
ss.AddAsteroid(new Vector2(0, 0), AsteroidSize.LARGE, new Vector2(100, 100));
|
||||||
|
//ss.AddAsteroid(new Vector2(300, 300), AsteroidSize.LARGE, new Vector2(100, 100));
|
||||||
|
ss.AddAsteroid(new Vector2(300, 0), AsteroidSize.LARGE, new Vector2(-100, 100));
|
||||||
|
|
||||||
|
//ss.AsteroidEmitter.Emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
96
Dakota/Dakota/Space/SpaceHud.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using Dakota.Data;
|
||||||
|
using Dakota.Renderables;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class SpaceHud : RenderableComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private const int FrameSize = 30;
|
||||||
|
private VectorText _acceleration;
|
||||||
|
private VectorText _primary;
|
||||||
|
private VectorText _spaceCoords;
|
||||||
|
private VectorText _velocity;
|
||||||
|
private VectorText _objective;
|
||||||
|
|
||||||
|
private VectorText _zoneCoords;
|
||||||
|
public override float Width => 280;
|
||||||
|
public override float Height => 720;
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
var obj = scene.Player.GetComponent<SpaceObject>();
|
||||||
|
_primary.Text = scene.Primary.Name;
|
||||||
|
_objective.Text = scene.CurrentMission.GetMissionStatus();
|
||||||
|
_zoneCoords.Text = $"Z: {scene.CurrentZone.UniversalX} {scene.CurrentZone.UniversalY}";
|
||||||
|
_spaceCoords.Text = $"P: {scene.Player.Position.X:0} {scene.Player.Position.Y:0}";
|
||||||
|
_velocity.Text = $"V: {obj.Velocity.X:0} {obj.Velocity.Y:0}";
|
||||||
|
_acceleration.Text = $"A: {obj.Acceleration.X:0} {obj.Acceleration.Y:0}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
RenderLayer = GameConstants.UiRenderLayerBg;
|
||||||
|
|
||||||
|
var map = Entity.AddComponent(new SpaceHudMap());
|
||||||
|
map.LocalOffset = new Vector2(40, 500);
|
||||||
|
map.RenderLayer = GameConstants.UiRenderLayerBg;
|
||||||
|
|
||||||
|
var line = Entity.AddComponent(new VectorText("PRIMARY", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 40);
|
||||||
|
_primary = line = Entity.AddComponent(new VectorText("", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 60);
|
||||||
|
line = Entity.AddComponent(new VectorText("SECONDARY", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 100);
|
||||||
|
line = Entity.AddComponent(new VectorText("SMART BOMB", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 120);
|
||||||
|
line = Entity.AddComponent(new VectorText("WARP CORE", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 200);
|
||||||
|
line = Entity.AddComponent(new VectorText("DISABLED", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 220);
|
||||||
|
line = Entity.AddComponent(new VectorText("OBJECTIVE", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 250);
|
||||||
|
_objective = line = Entity.AddComponent(new VectorText("", 6, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 270);
|
||||||
|
|
||||||
|
line = Entity.AddComponent(new VectorText("COORDINATES", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 350);
|
||||||
|
_zoneCoords = line = Entity.AddComponent(new VectorText("", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 370);
|
||||||
|
_spaceCoords = line = Entity.AddComponent(new VectorText("", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 390);
|
||||||
|
_velocity = line = Entity.AddComponent(new VectorText("", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 410);
|
||||||
|
_acceleration = line = Entity.AddComponent(new VectorText("", 12, GameConstants.SpaceHudFontColor));
|
||||||
|
line.LocalOffset = new Vector2(40, 430);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
batcher.DrawRect(Entity.Position, Width, Height, GameConstants.ColorBlack);
|
||||||
|
batcher.DrawHollowRect(Entity.Position, Width, Height, GameConstants.SpaceUiColor);
|
||||||
|
batcher.DrawHollowRect(
|
||||||
|
Entity.Position + new Vector2(FrameSize, FrameSize),
|
||||||
|
Width - FrameSize * 2, Height - FrameSize * 2,
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
batcher.DrawLine(
|
||||||
|
Entity.Position,
|
||||||
|
Entity.Position + new Vector2(FrameSize, FrameSize),
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
batcher.DrawLine(
|
||||||
|
Entity.Position + new Vector2(0, Height),
|
||||||
|
Entity.Position + new Vector2(FrameSize, Height - FrameSize),
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
batcher.DrawLine(
|
||||||
|
Entity.Position + new Vector2(Width, Height),
|
||||||
|
Entity.Position + new Vector2(Width - FrameSize, Height - FrameSize),
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
batcher.DrawLine(
|
||||||
|
Entity.Position + new Vector2(Width, 0),
|
||||||
|
Entity.Position + new Vector2(Width - FrameSize, FrameSize),
|
||||||
|
GameConstants.SpaceUiColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
79
Dakota/Dakota/Space/SpaceHudMap.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using Dakota.Data;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class SpaceHudMap : RenderableComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private const int Regions = 5;
|
||||||
|
private int[,] _regionCount;
|
||||||
|
private int _playerRegionX;
|
||||||
|
private int _playerRegionY;
|
||||||
|
public override float Width => 100;
|
||||||
|
public override float Height => 100;
|
||||||
|
|
||||||
|
// Rudimentary
|
||||||
|
// System Scanner
|
||||||
|
// System Scanner+
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
_regionCount = new int[Regions, Regions];
|
||||||
|
|
||||||
|
var xDiv = scene.CurrentZone.Width / Regions;
|
||||||
|
var yDiv = scene.CurrentZone.Height / Regions;
|
||||||
|
|
||||||
|
_playerRegionX = (int) (scene.Player.Position.X / xDiv);
|
||||||
|
_playerRegionY = (int) (scene.Player.Position.Y / yDiv);
|
||||||
|
|
||||||
|
// reset asteroid counts
|
||||||
|
for (var i = 0; i < Regions; i++)
|
||||||
|
for (var j = 0; j < Regions; j++)
|
||||||
|
_regionCount[i, j] = 0;
|
||||||
|
// count asteroids
|
||||||
|
foreach (var asteroid in scene.FindComponentsOfType<Asteroid>())
|
||||||
|
{
|
||||||
|
var x = (int) (asteroid.Entity.Position.X / xDiv);
|
||||||
|
var y = (int) (asteroid.Entity.Position.Y / yDiv);
|
||||||
|
if (x < 0 || x >= Regions || y < 0 || y >= Regions)
|
||||||
|
continue;
|
||||||
|
_regionCount[x, y] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
var unitSize = (Height - 1) / Regions;
|
||||||
|
|
||||||
|
batcher.DrawHollowRect(Entity.Position.X + LocalOffset.X,
|
||||||
|
Entity.Position.Y + LocalOffset.Y,
|
||||||
|
Width,
|
||||||
|
Height,
|
||||||
|
GameConstants.SpaceHudFontColor);
|
||||||
|
|
||||||
|
|
||||||
|
for (var i = 0; i < Regions; i++)
|
||||||
|
for (var j = 0; j < Regions; j++)
|
||||||
|
{
|
||||||
|
var color = GameConstants.ColorBlack;
|
||||||
|
if (_regionCount[i, j] >= 1)
|
||||||
|
color = GameConstants.AsteroidColor;
|
||||||
|
batcher.DrawRect(
|
||||||
|
Entity.Position.X + LocalOffset.X + unitSize * i,
|
||||||
|
Entity.Position.Y + LocalOffset.Y + unitSize * j,
|
||||||
|
unitSize,
|
||||||
|
unitSize,
|
||||||
|
color);
|
||||||
|
}
|
||||||
|
|
||||||
|
batcher.DrawRect(
|
||||||
|
Entity.Position.X + LocalOffset.X + unitSize * _playerRegionX + 5,
|
||||||
|
Entity.Position.Y + LocalOffset.Y + unitSize * _playerRegionY + 5,
|
||||||
|
unitSize - 10,
|
||||||
|
unitSize - 10,
|
||||||
|
GameConstants.ShipColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
Dakota/Dakota/Space/SpaceObject.cs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
using System;
|
||||||
|
using Dakota.Utils;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class SpaceObject : Component, IUpdatable
|
||||||
|
{
|
||||||
|
private Mover _mover;
|
||||||
|
public float TurnVelocity;
|
||||||
|
public Vector2 Velocity;
|
||||||
|
public Vector2 Acceleration;
|
||||||
|
|
||||||
|
public SpaceObject()
|
||||||
|
{
|
||||||
|
Velocity = new Vector2(0, 0);
|
||||||
|
Acceleration = new Vector2(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
var scene = (SpaceScene) Entity.Scene;
|
||||||
|
|
||||||
|
Entity.Rotation += Time.DeltaTime * TurnVelocity;
|
||||||
|
Velocity += Time.DeltaTime * Acceleration;
|
||||||
|
_mover.Move(
|
||||||
|
Time.DeltaTime * Velocity + 0.5f * Time.DeltaTime * Time.DeltaTime * Acceleration,
|
||||||
|
out _
|
||||||
|
);
|
||||||
|
|
||||||
|
// enforce zone boundaries
|
||||||
|
var newPos = Entity.Position;
|
||||||
|
if (Entity.Position.X < 0)
|
||||||
|
{
|
||||||
|
if (scene.CurrentZone.IsCurvedX)
|
||||||
|
newPos.X += scene.CurrentZone.Width;
|
||||||
|
else if (Entity.Name == "player")
|
||||||
|
newPos = scene.ZoneShift(-1, 0);
|
||||||
|
}
|
||||||
|
else if (Entity.Position.X > scene.CurrentZone.Width)
|
||||||
|
{
|
||||||
|
if (scene.CurrentZone.IsCurvedX)
|
||||||
|
newPos.X -= scene.CurrentZone.Width;
|
||||||
|
else if (Entity.Name == "player")
|
||||||
|
newPos = scene.ZoneShift(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Entity.Position.Y < 0)
|
||||||
|
{
|
||||||
|
if (scene.CurrentZone.IsCurvedY)
|
||||||
|
newPos.Y += scene.CurrentZone.Height;
|
||||||
|
else if (Entity.Name == "player")
|
||||||
|
newPos = scene.ZoneShift(0, -1);
|
||||||
|
}
|
||||||
|
else if (Entity.Position.Y > scene.CurrentZone.Height)
|
||||||
|
{
|
||||||
|
if (scene.CurrentZone.IsCurvedY)
|
||||||
|
newPos.Y -= scene.CurrentZone.Height;
|
||||||
|
else if (Entity.Name == "player")
|
||||||
|
newPos = scene.ZoneShift(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity.Position = newPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnAddedToEntity()
|
||||||
|
{
|
||||||
|
_mover = Entity.AddComponent(new Mover());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetAcceleration(float accel)
|
||||||
|
{
|
||||||
|
Acceleration = accel * DakotaUtils.VecFromAngle(Entity.Rotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
226
Dakota/Dakota/Space/SpaceScene.cs
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
using System;
|
||||||
|
using Dakota.Data;
|
||||||
|
using Dakota.Missions;
|
||||||
|
using Dakota.Renderables;
|
||||||
|
using Dakota.Utils;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
using Nez.Particles;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
internal enum GameMode
|
||||||
|
{
|
||||||
|
Active,
|
||||||
|
Paused
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SpaceScene : Scene
|
||||||
|
{
|
||||||
|
private const int HudWidth = 280;
|
||||||
|
|
||||||
|
private const int PauseFreezeTag = 100;
|
||||||
|
|
||||||
|
// entities
|
||||||
|
private Entity _galacticMap;
|
||||||
|
public Entity Player;
|
||||||
|
public DialogBox DialogBox;
|
||||||
|
public TimedVectorText CenterText { get; }
|
||||||
|
public BaddieEmitter AsteroidEmitter;
|
||||||
|
|
||||||
|
// game data
|
||||||
|
private GameMode _mode;
|
||||||
|
public SpaceMission CurrentMission;
|
||||||
|
public Zone CurrentZone;
|
||||||
|
public PrimaryWeapon Primary;
|
||||||
|
|
||||||
|
public SpaceScene()
|
||||||
|
{
|
||||||
|
// set up screen & camera
|
||||||
|
SetDesignResolution(1280, 720, SceneResolutionPolicy.ShowAllPixelPerfect);
|
||||||
|
Screen.SetSize(1280, 720);
|
||||||
|
ClearColor = GameConstants.ColorBlack;
|
||||||
|
// render background, then everything else, then UI layers
|
||||||
|
AddRenderer(new ScreenSpaceRenderer(0, GameConstants.BackgroundRenderLayer));
|
||||||
|
AddRenderer(new RenderLayerExcludeRenderer(10, GameConstants.UiRenderLayerBg,
|
||||||
|
GameConstants.BackgroundRenderLayer, GameConstants.UiRenderLayerFg));
|
||||||
|
AddRenderer(new ScreenSpaceRenderer(100, GameConstants.UiRenderLayerBg, GameConstants.UiRenderLayerFg));
|
||||||
|
Core.ExitOnEscapeKeypress = false;
|
||||||
|
if (Environment.GetEnvironmentVariable("DEBUG_RENDERING") != null)
|
||||||
|
Core.DebugRenderEnabled = true;
|
||||||
|
|
||||||
|
// create player and focus camera
|
||||||
|
Player = CreateEntity("player");
|
||||||
|
Player.SetTag(PauseFreezeTag);
|
||||||
|
Player.AddComponent(new PlayerShip());
|
||||||
|
var follow = Camera.Entity.AddComponent(new FollowCamera(Player));
|
||||||
|
follow.FocusOffset = new Vector2(-100, 0);
|
||||||
|
|
||||||
|
AddSceneComponent(new SpaceControls());
|
||||||
|
AsteroidEmitter = AddSceneComponent(new BaddieEmitter());
|
||||||
|
|
||||||
|
var starField = CreateEntity("StarField").AddComponent(new StarField());
|
||||||
|
starField.RenderLayer = GameConstants.BackgroundRenderLayer;
|
||||||
|
|
||||||
|
_galacticMap = CreateEntity("GalacticMap", new Vector2(10, 10));
|
||||||
|
_galacticMap.AddComponent<GalacticMap>();
|
||||||
|
|
||||||
|
// create UI
|
||||||
|
var hud = CreateEntity("HUD");
|
||||||
|
hud.Position = new Vector2(Screen.Width - HudWidth, 0);
|
||||||
|
hud.AddComponent(new SpaceHud());
|
||||||
|
DialogBox = CreateEntity("dialog box", new Vector2(1, Screen.Height - 100))
|
||||||
|
.AddComponent(new DialogBox());
|
||||||
|
CenterText = CreateEntity("center text", new Vector2(300, 300))
|
||||||
|
.AddComponent(new TimedVectorText(20, GameConstants.SpaceHudFontColor));
|
||||||
|
|
||||||
|
CurrentMission = new Mission1();
|
||||||
|
AddSceneComponent(CurrentMission);
|
||||||
|
CurrentMission.OnStart();
|
||||||
|
|
||||||
|
_mode = GameMode.Paused;
|
||||||
|
TogglePause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TogglePause()
|
||||||
|
{
|
||||||
|
if (_mode == GameMode.Active)
|
||||||
|
{
|
||||||
|
_mode = GameMode.Paused;
|
||||||
|
_galacticMap.Enabled = true;
|
||||||
|
|
||||||
|
foreach (var e in FindEntitiesWithTag(PauseFreezeTag))
|
||||||
|
e.Enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_mode = GameMode.Active;
|
||||||
|
_galacticMap.Enabled = false;
|
||||||
|
|
||||||
|
foreach (var e in FindEntitiesWithTag(PauseFreezeTag))
|
||||||
|
e.Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayerHit()
|
||||||
|
{
|
||||||
|
CurrentMission.OnPlayerHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PlayerWarpTo(Vector2 pos)
|
||||||
|
{
|
||||||
|
Player.Position = pos;
|
||||||
|
Camera.Position = Player.Position - Camera.Entity.GetComponent<FollowCamera>().FocusOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector2 ZoneShift(int xShift, int yShift)
|
||||||
|
{
|
||||||
|
if (CurrentMission.ZoneShiftDisabled)
|
||||||
|
return Player.Position;
|
||||||
|
|
||||||
|
var newZone = ZoneData.GetZone(
|
||||||
|
CurrentZone.UniversalX + xShift,
|
||||||
|
CurrentZone.UniversalY + yShift
|
||||||
|
);
|
||||||
|
|
||||||
|
var newPos = Player.Position;
|
||||||
|
|
||||||
|
// wrap around or scale to new area (so middle = middle)
|
||||||
|
newPos.X = xShift switch
|
||||||
|
{
|
||||||
|
-1 => newZone.Width,
|
||||||
|
1 => 0,
|
||||||
|
_ => newPos.X / CurrentZone.Width * newZone.Width
|
||||||
|
};
|
||||||
|
newPos.Y = yShift switch
|
||||||
|
{
|
||||||
|
-1 => newZone.Height,
|
||||||
|
1 => 0,
|
||||||
|
_ => newPos.Y / CurrentZone.Height * newZone.Height
|
||||||
|
};
|
||||||
|
|
||||||
|
CurrentZone = newZone;
|
||||||
|
return newPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity AddAsteroid(Vector2 position, AsteroidSize size, Vector2? velocity = null)
|
||||||
|
{
|
||||||
|
var asteroid = CreateEntity("asteroid", position);
|
||||||
|
asteroid.SetTag(PauseFreezeTag);
|
||||||
|
asteroid.AddComponent(new Asteroid(size));
|
||||||
|
var so = asteroid.AddComponent(new SpaceObject());
|
||||||
|
so.TurnVelocity = Random.MinusOneToOne() * 3;
|
||||||
|
so.Velocity = velocity ?? Random.NextUnitVector() * 20;
|
||||||
|
return asteroid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HitAsteroid(Entity asteroid, Vector2 hitLocation)
|
||||||
|
{
|
||||||
|
var cur = asteroid.GetComponent<Asteroid>();
|
||||||
|
var angle = DakotaUtils.ToAngle(asteroid.Position - hitLocation) + (float) Math.PI;
|
||||||
|
// ~ 135 degrees
|
||||||
|
var angle1 = DakotaUtils.VecFromAngle(angle - 2.4f) * 50;
|
||||||
|
var angle2 = DakotaUtils.VecFromAngle(angle + 2.4f) * 50;
|
||||||
|
|
||||||
|
switch (cur.Size)
|
||||||
|
{
|
||||||
|
case AsteroidSize.HUGE:
|
||||||
|
AddAsteroid(asteroid.Position, AsteroidSize.LARGE, angle1);
|
||||||
|
AddAsteroid(asteroid.Position + angle2, AsteroidSize.LARGE, angle2);
|
||||||
|
break;
|
||||||
|
case AsteroidSize.LARGE:
|
||||||
|
AddAsteroid(asteroid.Position, AsteroidSize.MEDIUM, angle1);
|
||||||
|
AddAsteroid(asteroid.Position + angle2, AsteroidSize.MEDIUM, angle2);
|
||||||
|
break;
|
||||||
|
case AsteroidSize.MEDIUM:
|
||||||
|
AddAsteroid(asteroid.Position, AsteroidSize.SMALL, angle1);
|
||||||
|
AddAsteroid(asteroid.Position + angle2, AsteroidSize.SMALL, angle2);
|
||||||
|
break;
|
||||||
|
case AsteroidSize.SMALL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
var ec = new ParticleEmitterConfig();
|
||||||
|
ec.SourcePositionVariance = new Vector2(cur.Radius(), cur.Radius());
|
||||||
|
ec.Speed = 30;
|
||||||
|
ec.SpeedVariance = 1;
|
||||||
|
ec.ParticleLifespan = 10;
|
||||||
|
ec.ParticleLifespanVariance = 1;
|
||||||
|
ec.Angle = 90;
|
||||||
|
ec.AngleVariance = 360;
|
||||||
|
ec.StartColor = GameConstants.AsteroidColor;
|
||||||
|
ec.FinishColor = Color.Transparent;
|
||||||
|
ec.StartParticleSize = 4;
|
||||||
|
ec.FinishParticleSize = 0;
|
||||||
|
ec.MaxParticles = 200;
|
||||||
|
ec.EmitterType = ParticleEmitterType.Gravity;
|
||||||
|
var ee = CreateEntity("dust emitter");
|
||||||
|
ee.Position = asteroid.Position;
|
||||||
|
ee.AddComponent(new ParticleEmitter(ec)).Emit(100);
|
||||||
|
// TODO: ensure this gets removed?
|
||||||
|
|
||||||
|
asteroid.Destroy();
|
||||||
|
CurrentMission.OnAsteroidDestroyed(cur.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FirePrimary()
|
||||||
|
{
|
||||||
|
var playerHeading = DakotaUtils.VecFromAngle(Player.Rotation);
|
||||||
|
var bullet = CreateEntity("bullet", Player.Position + playerHeading * 20);
|
||||||
|
bullet.SetTag(PauseFreezeTag);
|
||||||
|
bullet.AddComponent(new Projectile(Primary.Projectile, true, Primary.Duration));
|
||||||
|
var so = bullet.AddComponent(new SpaceObject());
|
||||||
|
so.Velocity = playerHeading * Primary.Speed;
|
||||||
|
if (Primary.Projectile != ProjectileType.Beam)
|
||||||
|
so.Velocity += Player.GetComponent<SpaceObject>().Velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warp()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
Dakota/Dakota/Space/StarField.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
|
||||||
|
namespace Dakota.Space
|
||||||
|
{
|
||||||
|
public class Star
|
||||||
|
{
|
||||||
|
public Vector2 Position;
|
||||||
|
public Color StarColor;
|
||||||
|
|
||||||
|
public Star()
|
||||||
|
{
|
||||||
|
Position = new Vector2(Random.NextFloat() * 2, Random.NextFloat() * 2);
|
||||||
|
var intensity = Random.NextFloat(0.5f) + 0.7f;
|
||||||
|
StarColor = new Color(intensity, intensity, intensity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class StarField : RenderableComponent
|
||||||
|
{
|
||||||
|
private readonly Star[] _stars;
|
||||||
|
public override float Width => 1000;
|
||||||
|
public override float Height => 720;
|
||||||
|
|
||||||
|
public StarField()
|
||||||
|
{
|
||||||
|
_stars = new Star[500];
|
||||||
|
for (int i = 0; i < _stars.Length; i++)
|
||||||
|
_stars[i] = new Star();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
var pos = ((SpaceScene) (Entity.Scene)).Player.Position;
|
||||||
|
// TODO: scale by zone size
|
||||||
|
pos /= 3000;
|
||||||
|
// TODO: consider more parallax
|
||||||
|
|
||||||
|
foreach (var star in _stars)
|
||||||
|
{
|
||||||
|
batcher.DrawPixel((star.Position.X - pos.X) * Width, (star.Position.Y - pos.Y) * Height, star.StarColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
Dakota/Dakota/Utils/DakotaUtils.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Dakota.Utils
|
||||||
|
{
|
||||||
|
public static class DakotaUtils
|
||||||
|
{
|
||||||
|
public static float ToAngle(Vector2 v)
|
||||||
|
{
|
||||||
|
return (float) Math.Atan2(v.Y, v.X) + (float) (Math.PI / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 VecFromAngle(float angle)
|
||||||
|
{
|
||||||
|
return new Vector2((float) Math.Sin(angle), (float) -Math.Cos(angle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
Dakota/Dakota/app.manifest
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="Dakota"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on and is
|
||||||
|
is designed to work with. Uncomment the appropriate elements and Windows will
|
||||||
|
automatically selected the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor
|
||||||
|
</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</assembly>
|
23
Dakota/DakotaTests/DakotaTests.csproj
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||||
|
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Dakota\Dakota.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
48
Dakota/DakotaTests/TestDakotaUtils.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using Dakota.Utils;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace DakotaTests
|
||||||
|
{
|
||||||
|
public class DakotaUtilTests
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 UpVector = new(0, -1);
|
||||||
|
private Vector2 RightVector = new(1, 0);
|
||||||
|
private Vector2 DownVector = new(0, 1);
|
||||||
|
private Vector2 LeftVector = new(-1, 0);
|
||||||
|
private const float Epsilon = 0.00001f;
|
||||||
|
private const float UpAngle = 0f;
|
||||||
|
private const float RightAngle = (float) Math.PI / 2f;
|
||||||
|
private const float DownAngle = (float) Math.PI;
|
||||||
|
private const float LeftAngle = (float) Math.PI * 1.5f;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestToAngle()
|
||||||
|
{
|
||||||
|
// going around the clock
|
||||||
|
Assert.AreEqual(UpAngle, DakotaUtils.ToAngle(UpVector));
|
||||||
|
Assert.AreEqual(RightAngle, DakotaUtils.ToAngle(RightVector));
|
||||||
|
Assert.AreEqual(DownAngle, DakotaUtils.ToAngle(DownVector));
|
||||||
|
Assert.AreEqual(LeftAngle, DakotaUtils.ToAngle(LeftVector));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestFromAngle()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(UpVector.X, DakotaUtils.VecFromAngle(UpAngle).X, Epsilon);
|
||||||
|
Assert.AreEqual(UpVector.Y, DakotaUtils.VecFromAngle(UpAngle).Y, Epsilon);
|
||||||
|
Assert.AreEqual(RightVector.X, DakotaUtils.VecFromAngle(RightAngle).X, Epsilon);
|
||||||
|
Assert.AreEqual(RightVector.Y, DakotaUtils.VecFromAngle(RightAngle).Y, Epsilon);
|
||||||
|
Assert.AreEqual(DownVector.X, DakotaUtils.VecFromAngle(DownAngle).X, Epsilon);
|
||||||
|
Assert.AreEqual(DownVector.Y, DakotaUtils.VecFromAngle(DownAngle).Y, Epsilon);
|
||||||
|
Assert.AreEqual(LeftVector.X, DakotaUtils.VecFromAngle(LeftAngle).X, Epsilon);
|
||||||
|
Assert.AreEqual(LeftVector.Y, DakotaUtils.VecFromAngle(LeftAngle).Y, Epsilon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
Dakota/Sprites/Ship00.aseprite
Normal file
5
Inky/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
3
Inky/.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "Nez"]
|
||||||
|
path = Nez
|
||||||
|
url = git@github.com:prime31/Nez.git
|
11
Inky/.idea/.idea.Inky/.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/modules.xml
|
||||||
|
/.idea.Inky.iml
|
||||||
|
/contentModel.xml
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
4
Inky/.idea/.idea.Inky/.idea/encodings.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
8
Inky/.idea/.idea.Inky/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
Inky/.idea/.idea.Inky/.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
22
Inky/Inky.sln
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Inky", "Inky\Inky.csproj", "{807420D8-9B51-4BB4-9C79-B07CF1FB27A4}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nez.MG38", "Nez\Nez.Portable\Nez.MG38.csproj", "{4DEC583E-A7C7-4671-B977-EA999AE58C50}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{807420D8-9B51-4BB4-9C79-B07CF1FB27A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{807420D8-9B51-4BB4-9C79-B07CF1FB27A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{807420D8-9B51-4BB4-9C79-B07CF1FB27A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{807420D8-9B51-4BB4-9C79-B07CF1FB27A4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4DEC583E-A7C7-4671-B977-EA999AE58C50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4DEC583E-A7C7-4671-B977-EA999AE58C50}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4DEC583E-A7C7-4671-B977-EA999AE58C50}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4DEC583E-A7C7-4671-B977-EA999AE58C50}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
15
Inky/Inky/Content/Content.mgcb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
#----------------------------- Global Properties ----------------------------#
|
||||||
|
|
||||||
|
/outputDir:bin/$(Platform)
|
||||||
|
/intermediateDir:obj/$(Platform)
|
||||||
|
/platform:DesktopGL
|
||||||
|
/config:
|
||||||
|
/profile:Reach
|
||||||
|
/compress:False
|
||||||
|
|
||||||
|
#-------------------------------- References --------------------------------#
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------- Content ---------------------------------#
|
||||||
|
|
48
Inky/Inky/DemoControls.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public class DemoControls : SceneComponent, IUpdatable
|
||||||
|
{
|
||||||
|
private VirtualButton _left;
|
||||||
|
private VirtualButton _right;
|
||||||
|
private float _eyeDirection = 1;
|
||||||
|
|
||||||
|
public DemoControls()
|
||||||
|
{
|
||||||
|
_left = new VirtualButton();
|
||||||
|
_left.Nodes.Add(new VirtualButton.KeyboardKey(Keys.Left));
|
||||||
|
_right = new VirtualButton();
|
||||||
|
_right.Nodes.Add(new VirtualButton.KeyboardKey(Keys.Right));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
var lanky = Scene.Entities.FindEntity("inky").GetComponent<Lanky>();
|
||||||
|
if (_left.IsDown)
|
||||||
|
{
|
||||||
|
lanky.LegAlignment = Alignment.Left;
|
||||||
|
lanky.ArmAlignment = Alignment.Left;
|
||||||
|
lanky.HeadShift -= 1f * Time.DeltaTime;
|
||||||
|
}
|
||||||
|
else if (_right.IsDown)
|
||||||
|
{
|
||||||
|
lanky.LegAlignment = Alignment.Right;
|
||||||
|
lanky.ArmAlignment = Alignment.Right;
|
||||||
|
lanky.HeadShift += 1f * Time.DeltaTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lanky.EyeShift += _eyeDirection * Time.DeltaTime;
|
||||||
|
if (lanky.EyeShift < -0.99) _eyeDirection = 1;
|
||||||
|
else if (lanky.EyeShift > 0.99) _eyeDirection = -1;
|
||||||
|
lanky.MouthShift += _eyeDirection * Time.DeltaTime;
|
||||||
|
lanky.LegWobble += _eyeDirection * Time.DeltaTime;
|
||||||
|
|
||||||
|
lanky.LegAlignment = Alignment.Center;
|
||||||
|
lanky.ArmAlignment = Alignment.Center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Inky/Inky/Game1.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public class Game1 : Core
|
||||||
|
{
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
Scene = new InkyScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Inky/Inky/GameConstants.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public class GameConstants
|
||||||
|
{
|
||||||
|
public const int UiRenderLayerBg = 910;
|
||||||
|
public const int UiRenderLayerFg = 900;
|
||||||
|
public const int BackgroundRenderLayer = 50;
|
||||||
|
}
|
||||||
|
}
|
BIN
Inky/Inky/Icon.bmp
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
Inky/Inky/Icon.ico
Normal file
After Width: | Height: | Size: 144 KiB |
33
Inky/Inky/Inky.csproj
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
<TieredCompilation>false</TieredCompilation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Icon.ico" />
|
||||||
|
<None Remove="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Icon.ico" />
|
||||||
|
<EmbeddedResource Include="Icon.bmp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<MonoGameContentReference Include="Content\Content.mgcb" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<TrimmerRootAssembly Include="Microsoft.Xna.Framework.Content.ContentTypeReader" Visible="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Nez\Nez.Portable\Nez.MG38.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
36
Inky/Inky/InkyScene.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public class InkyScene : Scene
|
||||||
|
{
|
||||||
|
public InkyScene()
|
||||||
|
{
|
||||||
|
// set up screen & camera
|
||||||
|
SetDesignResolution(1280, 720, SceneResolutionPolicy.ShowAllPixelPerfect);
|
||||||
|
Screen.SetSize(1280, 720);
|
||||||
|
ClearColor = Color.White;
|
||||||
|
// render background, then everything else, then UI layers
|
||||||
|
AddRenderer(new ScreenSpaceRenderer(0, GameConstants.BackgroundRenderLayer));
|
||||||
|
AddRenderer(new RenderLayerExcludeRenderer(10, GameConstants.UiRenderLayerBg,
|
||||||
|
GameConstants.BackgroundRenderLayer, GameConstants.UiRenderLayerFg));
|
||||||
|
AddRenderer(new ScreenSpaceRenderer(100, GameConstants.UiRenderLayerBg, GameConstants.UiRenderLayerFg));
|
||||||
|
Core.ExitOnEscapeKeypress = false;
|
||||||
|
if (Environment.GetEnvironmentVariable("DEBUG_RENDERING") != null)
|
||||||
|
Core.DebugRenderEnabled = true;
|
||||||
|
|
||||||
|
var inky1 = CreateEntity("inky");
|
||||||
|
inky1.AddComponent<Lanky>().Color = Color.Black;
|
||||||
|
inky1.Position = new Vector2(300, 300);
|
||||||
|
|
||||||
|
var worm = CreateEntity("worm");
|
||||||
|
//worm.AddComponent<Skeletron.Skeletron>().Color = Color.Black;
|
||||||
|
worm.AddComponent<Lanky2>();
|
||||||
|
worm.Position = new Vector2(600, 400);
|
||||||
|
|
||||||
|
AddSceneComponent<DemoControls>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
156
Inky/Inky/Lanky.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using System;
|
||||||
|
using Nez;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public enum Alignment
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Center
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Lanky : RenderableComponent
|
||||||
|
{
|
||||||
|
public override float Height => BodyHeight + HeadHeight + LegLength;
|
||||||
|
public override float Width => BodyWidth;
|
||||||
|
|
||||||
|
public readonly int LegLength;
|
||||||
|
public readonly int ArmLength;
|
||||||
|
public readonly int BodyWidth;
|
||||||
|
public readonly int BodyHeight;
|
||||||
|
public readonly int HeadWidth;
|
||||||
|
public readonly int HeadHeight;
|
||||||
|
|
||||||
|
public Alignment LegAlignment;
|
||||||
|
public Alignment ArmAlignment;
|
||||||
|
|
||||||
|
private float _headShift;
|
||||||
|
public float HeadShift
|
||||||
|
{
|
||||||
|
get => _headShift;
|
||||||
|
set => _headShift = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _eyeShift;
|
||||||
|
public float EyeShift
|
||||||
|
{
|
||||||
|
get => _eyeShift;
|
||||||
|
set => _eyeShift = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _mouthShift;
|
||||||
|
public float MouthShift
|
||||||
|
{
|
||||||
|
get => _mouthShift;
|
||||||
|
set => _mouthShift = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _mouthWidth;
|
||||||
|
public float MouthWidth
|
||||||
|
{
|
||||||
|
get => _mouthWidth;
|
||||||
|
set => _mouthWidth = Math.Clamp(value, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _legWobble;
|
||||||
|
|
||||||
|
public float LegWobble
|
||||||
|
{
|
||||||
|
get => _legWobble;
|
||||||
|
set => _legWobble = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Lanky()
|
||||||
|
{
|
||||||
|
// readonly
|
||||||
|
BodyHeight = 100;
|
||||||
|
LegLength = (int)((Random.NextFloat(0.6f) + 0.6f) * BodyHeight);
|
||||||
|
ArmLength = (int)((Random.NextFloat(0.3f) + 0.3f) * BodyHeight);
|
||||||
|
BodyWidth = (int)((Random.NextFloat(0.5f) + 0.5f) * BodyHeight);
|
||||||
|
HeadWidth = 40;
|
||||||
|
HeadHeight = 40;
|
||||||
|
|
||||||
|
LegAlignment = Alignment.Center;
|
||||||
|
ArmAlignment = Alignment.Center;
|
||||||
|
MouthWidth = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
var thickness = 3f;
|
||||||
|
// body
|
||||||
|
batcher.DrawHollowRect(
|
||||||
|
Entity.Position.X - BodyWidth/2f,
|
||||||
|
Entity.Position.Y - BodyHeight/2f,
|
||||||
|
BodyWidth, BodyHeight, Color, thickness
|
||||||
|
);
|
||||||
|
|
||||||
|
// legs
|
||||||
|
var legInset = BodyWidth * 0.15f;
|
||||||
|
var legBodyY = Entity.Position.Y + BodyHeight / 2f;
|
||||||
|
// center positions
|
||||||
|
var leftLegX = Entity.Position.X - BodyWidth / 2f + legInset;
|
||||||
|
var rightLegX = Entity.Position.X + BodyWidth / 2f - legInset;
|
||||||
|
|
||||||
|
if (LegAlignment == Alignment.Left)
|
||||||
|
rightLegX = leftLegX + legInset;
|
||||||
|
else if (LegAlignment == Alignment.Right)
|
||||||
|
leftLegX = rightLegX - legInset;
|
||||||
|
|
||||||
|
var leftWobble = LegWobble * LegLength * 0.1f;
|
||||||
|
var rightWobble = -LegWobble * LegLength * 0.1f;
|
||||||
|
|
||||||
|
batcher.DrawLine(leftLegX, legBodyY, leftLegX, legBodyY + LegLength + leftWobble, Color);
|
||||||
|
batcher.DrawLine(rightLegX, legBodyY, rightLegX, legBodyY + LegLength + rightWobble, Color);
|
||||||
|
|
||||||
|
// arms
|
||||||
|
var armShift = 10;
|
||||||
|
var armY = Entity.Position.Y - BodyHeight / 2f + armShift;
|
||||||
|
float leftArmX = 0;
|
||||||
|
float rightArmX = 0;
|
||||||
|
switch (ArmAlignment)
|
||||||
|
{
|
||||||
|
case Alignment.Left:
|
||||||
|
leftArmX = Entity.Position.X - BodyWidth / 2f + armShift;
|
||||||
|
rightArmX = leftArmX + armShift;
|
||||||
|
break;
|
||||||
|
case Alignment.Right:
|
||||||
|
leftArmX = Entity.Position.X + BodyWidth / 2f - armShift * 2;
|
||||||
|
rightArmX = leftArmX + armShift;
|
||||||
|
break;
|
||||||
|
case Alignment.Center:
|
||||||
|
leftArmX = Entity.Position.X - armShift * 2;
|
||||||
|
rightArmX = Entity.Position.X + armShift * 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
batcher.DrawLine(leftArmX, armY, leftArmX, armY + ArmLength, Color);
|
||||||
|
batcher.DrawLine(rightArmX, armY, rightArmX, armY + ArmLength, Color);
|
||||||
|
|
||||||
|
// head
|
||||||
|
var headX = Entity.Position.X + (BodyWidth / 2f) * HeadShift - HeadWidth/2f;
|
||||||
|
var headY = Entity.Position.Y - BodyHeight / 2f - HeadHeight;
|
||||||
|
batcher.DrawHollowRect(
|
||||||
|
headX,
|
||||||
|
Entity.Position.Y - BodyHeight/2f - HeadHeight,
|
||||||
|
HeadWidth, HeadHeight, Color, thickness
|
||||||
|
);
|
||||||
|
var eyeInset = EyeShift * (HeadWidth * 0.3f);
|
||||||
|
var eyeSpace = HeadWidth * 0.15f;
|
||||||
|
var eyeWidth = 2;
|
||||||
|
batcher.DrawHollowRect(headX + HeadWidth/2f + eyeInset - eyeSpace - eyeWidth, headY + eyeSpace, eyeWidth, eyeWidth, Color, thickness);
|
||||||
|
batcher.DrawHollowRect(headX + HeadWidth/2f + eyeInset + eyeSpace - eyeWidth, headY + eyeSpace, eyeWidth, eyeWidth, Color, thickness);
|
||||||
|
|
||||||
|
var mouthCenterX = HeadWidth / 2f + MouthShift * HeadWidth / 2f;
|
||||||
|
var halfMouth = (HeadWidth * MouthWidth) / 2f;
|
||||||
|
batcher.DrawLine(
|
||||||
|
Math.Max(headX + mouthCenterX - halfMouth, headX),
|
||||||
|
headY + HeadHeight * 0.8f ,
|
||||||
|
Math.Min(headX + mouthCenterX + halfMouth, headX + HeadWidth),
|
||||||
|
headY + HeadHeight * 0.8f ,
|
||||||
|
Color
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
Inky/Inky/Lanky2.cs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using Inky.Skeletron;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
using Edge = Inky.Skeletron.Edge;
|
||||||
|
using Random = Nez.Random;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public class Lanky2 : RenderableComponent
|
||||||
|
{
|
||||||
|
public override float Height => 100;
|
||||||
|
public override float Width => 100;
|
||||||
|
|
||||||
|
public readonly int LegLength;
|
||||||
|
public readonly int ArmLength;
|
||||||
|
public readonly int BodyWidth;
|
||||||
|
public readonly int BodyHeight;
|
||||||
|
public readonly int HeadWidth;
|
||||||
|
public readonly int HeadHeight;
|
||||||
|
|
||||||
|
public Alignment LegAlignment;
|
||||||
|
public Alignment ArmAlignment;
|
||||||
|
|
||||||
|
private float _headShift;
|
||||||
|
public float HeadShift
|
||||||
|
{
|
||||||
|
get => _headShift;
|
||||||
|
set => _headShift = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _eyeShift;
|
||||||
|
public float EyeShift
|
||||||
|
{
|
||||||
|
get => _eyeShift;
|
||||||
|
set => _eyeShift = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _mouthShift;
|
||||||
|
public float MouthShift
|
||||||
|
{
|
||||||
|
get => _mouthShift;
|
||||||
|
set => _mouthShift = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _mouthWidth;
|
||||||
|
public float MouthWidth
|
||||||
|
{
|
||||||
|
get => _mouthWidth;
|
||||||
|
set => _mouthWidth = Math.Clamp(value, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _legWobble;
|
||||||
|
|
||||||
|
public float LegWobble
|
||||||
|
{
|
||||||
|
get => _legWobble;
|
||||||
|
set => _legWobble = Math.Clamp(value, -1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Skeletron.Rectangle _body;
|
||||||
|
|
||||||
|
public Lanky2()
|
||||||
|
{
|
||||||
|
BodyHeight = (int) ((Random.NextFloat(0.5f) + 0.5f) * 100);
|
||||||
|
_body = new Skeletron.Rectangle(100, BodyHeight);
|
||||||
|
var _head = new Skeletron.Rectangle(40, 40);
|
||||||
|
_body.Attach(Edge.Top, _head);
|
||||||
|
|
||||||
|
// readonly
|
||||||
|
LegLength = (int)((Random.NextFloat(0.6f) + 0.6f) * BodyHeight);
|
||||||
|
_body.Attach(Edge.Bottom, new Line(LegLength, true), 0.4f);
|
||||||
|
_body.Attach(Edge.Bottom, new Line(LegLength, true), -0.4f);
|
||||||
|
|
||||||
|
ArmLength = (int)((Random.NextFloat(0.3f) + 0.3f) * BodyHeight);
|
||||||
|
_body.Attach(Edge.Left, new Line(ArmLength, true), 0.4f);
|
||||||
|
_body.Attach(Edge.Right, new Line(ArmLength, true), -0.4f);
|
||||||
|
|
||||||
|
LegAlignment = Alignment.Center;
|
||||||
|
ArmAlignment = Alignment.Center;
|
||||||
|
MouthWidth = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
_body.Draw(batcher, Entity.Position.X, Entity.Position.Y, Color.Black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
Inky/Inky/Program.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Inky
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
using (var game = new Game1())
|
||||||
|
game.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
Inky/Inky/Skeletron/Head.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Inky.Skeletron
|
||||||
|
{
|
||||||
|
public class Head
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
29
Inky/Inky/Skeletron/Line.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky.Skeletron
|
||||||
|
{
|
||||||
|
public class Line : Shape
|
||||||
|
{
|
||||||
|
public override int HalfHeight => IsVertical ? Length / 2 : 1;
|
||||||
|
public override int HalfWidth => IsVertical ? 1 : Length / 2;
|
||||||
|
|
||||||
|
public int Length;
|
||||||
|
public bool IsVertical;
|
||||||
|
|
||||||
|
public Line(int length, bool isVertical)
|
||||||
|
{
|
||||||
|
Length = length;
|
||||||
|
IsVertical = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Batcher batcher, float x, float y, Color color)
|
||||||
|
{
|
||||||
|
if(IsVertical)
|
||||||
|
batcher.DrawLine(x, y-Length/2f, x, y+Length/2f, color);
|
||||||
|
else
|
||||||
|
batcher.DrawLine(x-Length/2f, y, x+Length/2f, y, color);
|
||||||
|
DrawChildren(batcher, x, y, Color.Black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Inky/Inky/Skeletron/Rectangle.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky.Skeletron
|
||||||
|
{
|
||||||
|
|
||||||
|
public class Rectangle : Shape
|
||||||
|
{
|
||||||
|
public override int HalfHeight => Height/2;
|
||||||
|
public override int HalfWidth => Width/2;
|
||||||
|
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
|
||||||
|
public Rectangle(int width, int height)
|
||||||
|
{
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Batcher batcher, float x, float y, Color color)
|
||||||
|
{
|
||||||
|
batcher.DrawHollowRect(x - Width/2f,y - Height/2f, Width, Height, color, 2f);
|
||||||
|
DrawChildren(batcher, x, y, Color.Black);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
70
Inky/Inky/Skeletron/Shape.cs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky.Skeletron
|
||||||
|
{
|
||||||
|
public enum Edge
|
||||||
|
{
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EdgeAttachment
|
||||||
|
{
|
||||||
|
public Edge OnEdge;
|
||||||
|
public float XOffset;
|
||||||
|
public float YOffset;
|
||||||
|
public Shape Shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Shape
|
||||||
|
{
|
||||||
|
public abstract int HalfHeight { get; }
|
||||||
|
public abstract int HalfWidth { get; }
|
||||||
|
|
||||||
|
private List<EdgeAttachment> _attachments;
|
||||||
|
|
||||||
|
protected Shape()
|
||||||
|
{
|
||||||
|
_attachments = new List<EdgeAttachment>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Draw(Batcher batcher, float x, float y, Color color);
|
||||||
|
|
||||||
|
public EdgeAttachment Attach(Edge on, Shape shape, float xOffset = 0, float yOffset = 0)
|
||||||
|
{
|
||||||
|
var ea = new EdgeAttachment() { OnEdge = on, Shape = shape, XOffset = xOffset, YOffset = yOffset};
|
||||||
|
_attachments.Add(ea);
|
||||||
|
return ea;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DrawChildren(Batcher batcher, float x, float y, Color color)
|
||||||
|
{
|
||||||
|
foreach (var att in _attachments)
|
||||||
|
{
|
||||||
|
var childX = x;
|
||||||
|
var childY = y;
|
||||||
|
|
||||||
|
switch (att.OnEdge)
|
||||||
|
{
|
||||||
|
case Edge.Top:
|
||||||
|
childY -= att.Shape.HalfHeight + HalfHeight;
|
||||||
|
break;
|
||||||
|
case Edge.Bottom:
|
||||||
|
childY += att.Shape.HalfHeight + HalfHeight;
|
||||||
|
break;
|
||||||
|
case Edge.Left:
|
||||||
|
childX -= att.Shape.HalfWidth + HalfWidth;
|
||||||
|
break;
|
||||||
|
case Edge.Right:
|
||||||
|
childX += att.Shape.HalfWidth + HalfWidth;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
att.Shape.Draw(batcher, childX + att.XOffset * HalfWidth, childY + att.YOffset * HalfHeight, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
Inky/Inky/Skeletron/Skeletron.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Inky.Skeletron
|
||||||
|
{
|
||||||
|
public class Skeletron : RenderableComponent, IUpdatable
|
||||||
|
{
|
||||||
|
public override float Height => 100;
|
||||||
|
public override float Width => 100;
|
||||||
|
|
||||||
|
public Shape _body;
|
||||||
|
private EdgeAttachment _neckJoint;
|
||||||
|
|
||||||
|
public Skeletron()
|
||||||
|
{
|
||||||
|
_body = new Rectangle(80, 200);
|
||||||
|
(_body as Rectangle).Attach(Edge.Left, new Rectangle(30, 10));
|
||||||
|
(_body as Rectangle).Attach(Edge.Right, new Rectangle(60, 10));
|
||||||
|
(_body as Rectangle).Attach(Edge.Right, new Rectangle(60, 10), 0, 0.3f);
|
||||||
|
var head = new Rectangle(80, 80);
|
||||||
|
head.Attach(Edge.Top, new Rectangle(100, 5), 0, 0);
|
||||||
|
_neckJoint = (_body as Rectangle).Attach(Edge.Top, head, -1, 0);
|
||||||
|
(_body as Rectangle).Attach(Edge.Bottom, new Line(40, true), -0.5f, 0);
|
||||||
|
(_body as Rectangle).Attach(Edge.Bottom, new Line(40, true), 0.5f, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
_neckJoint.XOffset += Time.DeltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(Batcher batcher, Camera camera)
|
||||||
|
{
|
||||||
|
_body.Draw(batcher, Entity.Position.X, Entity.Position.Y, Color.Black);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
Inky/Inky/app.manifest
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="Inky"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on and is
|
||||||
|
is designed to work with. Uncomment the appropriate elements and Windows will
|
||||||
|
automatically selected the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</assembly>
|
20
Inky/newproj.txt
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
- new monogame cross platform
|
||||||
|
- add Nez as submodule
|
||||||
|
git submodule add git@github.com:prime31/Nez.git Nez
|
||||||
|
- SLN -> add existing projeectt -> Nez.Portable.MG38
|
||||||
|
- Proj -> add reference -> Nez
|
||||||
|
- change Game1.cs to
|
||||||
|
|
||||||
|
using Nez;
|
||||||
|
|
||||||
|
namespace Dakota
|
||||||
|
{
|
||||||
|
public class Game1 : Core
|
||||||
|
{
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
Scene = new SomeScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
UPWG/.gitignore
vendored
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
BIN
UPWG/Content/jason.jpg
Executable file
After Width: | Height: | Size: 72 KiB |
39
UPWG/Data/moves.csv
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
Name,Type,Rank,PartsUtilized,PartsRestrained,BaseChance,BaseOffense,BasePopularity
|
||||||
|
Chop 1,Strike,1,Arms,0,0.8,3,1
|
||||||
|
Chop 2,Strike,2,Arms,0,0.85,6,2
|
||||||
|
Chop 3,Strike,3,Arms,0,0.9,9,3
|
||||||
|
Kick 1,Strike,1,Legs,0,0.7,4,1
|
||||||
|
Kick 2,Strike,2,Legs,0,0.8,8,3
|
||||||
|
Kick 3,Strike,3,Legs,0,0.85,12,5
|
||||||
|
Headbutt 1,Strike,1,Head,0,0.8,5,1
|
||||||
|
Headbutt 2,Strike,2,Head,0,0.9,9,1
|
||||||
|
Headbutt 3,Strike,3,Head,0,1.0,12,3
|
||||||
|
Bodystrike 1,Strike,1,All,0,0.75,6,1
|
||||||
|
Bodystrike 2,Strike,2,All,0,0.85,8,2
|
||||||
|
Bodystrike 3,Strike,3,All,0,0.9,10,3
|
||||||
|
Arm Hold 1,Hold,1,All,Arms,0.4,5,1
|
||||||
|
Arm Hold 2,Hold,2,All,Arms,0.5,8,2
|
||||||
|
Arm Hold 3,Hold,3,All,Arms,0.6,10,3
|
||||||
|
Leg Hold 1,Hold,1,All,Legs,0.4,5,1
|
||||||
|
Leg Hold 2,Hold,2,All,Legs,0.5,8,2
|
||||||
|
Leg Hold 3,Hold,3,All,Legs,0.6,10,3
|
||||||
|
Head Hold 1,Hold,1,All,Head,0.3,5,1
|
||||||
|
Head Hold 2,Hold,2,All,Head,0.5,8,2
|
||||||
|
Head Hold 3,Hold,3,All,Head,0.6,10,3
|
||||||
|
Body Hold 1,Hold,1,All,Body,0.5,5,1
|
||||||
|
Body Hold 2,Hold,2,All,Body,0.6,8,2
|
||||||
|
Body Hold 3,Hold,3,All,Body,0.7,10,3
|
||||||
|
Aerial Arm 1,Aerial,1,All,0,0.5,8,3
|
||||||
|
Aerial Arm 2,Aerial,2,All,0,0.6,12,4
|
||||||
|
Aerial Arm 3,Aerial,3,All,0,0.7,14,5
|
||||||
|
Aerial Leg 1,Aerial,1,All,0,0.4,8,3
|
||||||
|
Aerial Leg 2,Aerial,2,All,0,0.5,12,4
|
||||||
|
Aerial Leg 3,Aerial,3,All,0,0.6,14,5
|
||||||
|
Aerial Body 1,Aerial,1,All,0,0.4,9,4
|
||||||
|
Aerial Body 2,Aerial,2,All,0,0.5,14,5
|
||||||
|
Aerial Body 3,Aerial,3,All,0,0.7,17,6
|
||||||
|
Pin,Pin,1,All,0,0.3,0,1
|
||||||
|
Arms Pin,Pin,2,All,Arms,0.4,0,3
|
||||||
|
Legs Pin,Pin,2,All,Legs,0.4,0,3
|
||||||
|
Body Pin,Pin,2,All,Body,0.4,0,3
|
||||||
|
Super Pin,Pin,3,All,All,0.5,0,5
|
|
11
UPWG/Elite/Elite.csproj
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
81
UPWG/Elite/Engine.cs
Executable file
@ -0,0 +1,81 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
|
||||||
|
namespace Elite
|
||||||
|
{
|
||||||
|
public class Engine : Game
|
||||||
|
{
|
||||||
|
public static Engine Instance;
|
||||||
|
|
||||||
|
private GraphicsDeviceManager _graphicsDeviceManager;
|
||||||
|
private int _width;
|
||||||
|
private int _height;
|
||||||
|
private Color _clearColor;
|
||||||
|
|
||||||
|
private Scene _currentScene;
|
||||||
|
private Scene _nextScene;
|
||||||
|
|
||||||
|
private float _elapsed;
|
||||||
|
|
||||||
|
public static Scene Scene
|
||||||
|
{
|
||||||
|
get => Instance._currentScene;
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Instance._currentScene != null)
|
||||||
|
Instance._nextScene = value;
|
||||||
|
else
|
||||||
|
Instance._currentScene = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Elapsed => Instance._elapsed;
|
||||||
|
|
||||||
|
public Engine(int width, int height, Color clearColor)
|
||||||
|
{
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
_graphicsDeviceManager = new GraphicsDeviceManager(this);
|
||||||
|
Content.RootDirectory = "Content";
|
||||||
|
IsMouseVisible = true;
|
||||||
|
IsFixedTimeStep = false;
|
||||||
|
_clearColor = clearColor;
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
_graphicsDeviceManager.PreferredBackBufferWidth = _width;
|
||||||
|
_graphicsDeviceManager.PreferredBackBufferHeight = _height;
|
||||||
|
_graphicsDeviceManager.ApplyChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
base.Update(gameTime);
|
||||||
|
_elapsed = (float) gameTime.ElapsedGameTime.TotalSeconds;
|
||||||
|
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
|
||||||
|
Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||||
|
Exit();
|
||||||
|
|
||||||
|
_currentScene?.Update(_elapsed);
|
||||||
|
|
||||||
|
if (_nextScene != null)
|
||||||
|
{
|
||||||
|
_currentScene = _nextScene;
|
||||||
|
_nextScene = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
GraphicsDevice.Clear(_clearColor);
|
||||||
|
|
||||||
|
_currentScene.Draw(_elapsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
UPWG/Elite/Entity.cs
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
namespace Elite
|
||||||
|
{
|
||||||
|
public class Component
|
||||||
|
{
|
||||||
|
public Entity Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IUpdateable
|
||||||
|
{
|
||||||
|
void Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface
|
||||||
|
|
||||||
|
public class Entity
|
||||||
|
{
|
||||||
|
private static uint _nextId;
|
||||||
|
|
||||||
|
public string Name;
|
||||||
|
public readonly int Id;
|
||||||
|
private readonly FastList<Component
|
||||||
|
}
|
||||||
|
}
|
56
UPWG/Elite/Scene.cs
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Elite
|
||||||
|
{
|
||||||
|
public class Scene
|
||||||
|
{
|
||||||
|
public static int DefaultHeight = 800;
|
||||||
|
public static int DefaultWidth = 600;
|
||||||
|
public readonly int Width;
|
||||||
|
public readonly int Height;
|
||||||
|
public float Scale;
|
||||||
|
|
||||||
|
private SpriteBatch _batch;
|
||||||
|
private RenderTarget2D _target;
|
||||||
|
|
||||||
|
public Scene(int width, int height)
|
||||||
|
{
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
_batch = new SpriteBatch(Engine.Instance.GraphicsDevice);
|
||||||
|
_target = new RenderTarget2D(Engine.Instance.GraphicsDevice, Width, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scene() : this(DefaultWidth, DefaultHeight)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Draw(float elapsed)
|
||||||
|
{
|
||||||
|
Engine.Instance.GraphicsDevice.SetRenderTarget(_target);
|
||||||
|
Engine.Instance.GraphicsDevice.Clear(Color.SeaGreen);
|
||||||
|
|
||||||
|
/*
|
||||||
|
SpriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
|
||||||
|
|
||||||
|
foreach (var drawable in DrawList)
|
||||||
|
{
|
||||||
|
drawable.Draw(SpriteBatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpriteBatch.End();
|
||||||
|
_graphicsDevice.SetRenderTarget(null);
|
||||||
|
|
||||||
|
SpriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, SamplerState.PointClamp, null, null);
|
||||||
|
SpriteBatch.Draw(_target, Vector2.Zero, null, Color.LightBlue, 0.0f, Vector2.Zero, _scale,
|
||||||
|
SpriteEffects.None,
|
||||||
|
0.0f);
|
||||||
|
SpriteBatch.End();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Update(float elapsed)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
UPWG/Elite/Sprite.cs
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
using System.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Elite
|
||||||
|
{
|
||||||
|
public class Sprite
|
||||||
|
{
|
||||||
|
private Texture2D _texture;
|
||||||
|
|
||||||
|
public Sprite(GraphicsDevice device, string filename)
|
||||||
|
{
|
||||||
|
var fileStream = new FileStream(filename, FileMode.Open);
|
||||||
|
_texture = Texture2D.FromStream(device, fileStream);
|
||||||
|
fileStream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
batch.Draw(_texture, Vector2.Zero, Color.White);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
UPWG/Elite/TextElement.cs
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
|
||||||
|
namespace Elite
|
||||||
|
{
|
||||||
|
public class TextElement
|
||||||
|
{
|
||||||
|
public string Text;
|
||||||
|
public Vector2 Position;
|
||||||
|
public Color Color;
|
||||||
|
|
||||||
|
public TextElement(string text, Vector2 position, Color color)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
Position = position;
|
||||||
|
Color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
UPWG/Manhattan/Manhattan.cs
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using Elite;
|
||||||
|
|
||||||
|
namespace Manhattan
|
||||||
|
{
|
||||||
|
public class ManhattanGame : Engine
|
||||||
|
{
|
||||||
|
public ManhattanGame(int width, int height, Color clearColor) : base(width, height, clearColor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
Scene = new Flying();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Flying : Scene
|
||||||
|
{
|
||||||
|
public override void Draw(float elapsed)
|
||||||
|
{
|
||||||
|
base.Update(elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(float elapsed)
|
||||||
|
{
|
||||||
|
base.Update(elapsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
UPWG/Manhattan/Manhattan.csproj
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
<TieredCompilation>false</TieredCompilation>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Icon.ico"/>
|
||||||
|
<None Remove="Icon.bmp"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Icon.ico"/>
|
||||||
|
<EmbeddedResource Include="Icon.bmp"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<MonoGameContentReference Include="Content\Content.mgcb"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<TrimmerRootAssembly Include="Microsoft.Xna.Framework.Content.ContentTypeReader" Visible="false"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641"/>
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Elite\Elite.csproj"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
16
UPWG/Manhattan/Program.cs
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using Elite;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace Manhattan
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
using (var game = new ManhattanGame(1280, 720, Color.Bisque))
|
||||||
|
game.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
UPWG/Manhattan/app.manifest
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="Manhattan"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on and is
|
||||||
|
is designed to work with. Uncomment the appropriate elements and Windows will
|
||||||
|
automatically selected the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</assembly>
|
367
UPWG/UPWG.Core/Battle.cs
Executable file
@ -0,0 +1,367 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace UPWG.Core
|
||||||
|
{
|
||||||
|
public enum WrestlerPosition
|
||||||
|
{
|
||||||
|
InRing,
|
||||||
|
OnRopes,
|
||||||
|
OutsideRing,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MomentumLevel
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Low = 1,
|
||||||
|
Medium = 2,
|
||||||
|
High = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public enum HitResult
|
||||||
|
{
|
||||||
|
Miss,
|
||||||
|
Hit,
|
||||||
|
Critical,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoveResult
|
||||||
|
{
|
||||||
|
public HitResult Result;
|
||||||
|
|
||||||
|
// what did this do to the recipient?
|
||||||
|
public uint RecipientDamage;
|
||||||
|
public int RecipientMomentumDelta;
|
||||||
|
public BodyParts RecipientRestrained;
|
||||||
|
|
||||||
|
// and what did this do to us?
|
||||||
|
public uint SelfDamage;
|
||||||
|
public int SelfMomentumDelta;
|
||||||
|
public int SelfPopularityDelta;
|
||||||
|
|
||||||
|
public MoveResult(
|
||||||
|
HitResult result,
|
||||||
|
uint recipientDamage,
|
||||||
|
int recipientMomentumDelta = 0,
|
||||||
|
BodyParts restrained = 0,
|
||||||
|
uint selfDamage = 0,
|
||||||
|
int selfMomentumDelta = 0,
|
||||||
|
int selfPopularityDelta = 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Result = result;
|
||||||
|
RecipientDamage = recipientDamage;
|
||||||
|
RecipientMomentumDelta = recipientMomentumDelta;
|
||||||
|
RecipientRestrained = restrained;
|
||||||
|
SelfDamage = selfDamage;
|
||||||
|
SelfMomentumDelta = selfMomentumDelta;
|
||||||
|
SelfPopularityDelta = selfPopularityDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IGoal
|
||||||
|
{
|
||||||
|
public void ProcessMove(Move move, MoveResult result);
|
||||||
|
public bool IsComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MaxMomentumGoal : IGoal
|
||||||
|
{
|
||||||
|
public int GoalMomentum { get; }
|
||||||
|
private int _maxMomentum;
|
||||||
|
private int _curMomentum;
|
||||||
|
|
||||||
|
MaxMomentumGoal(int goalMomentum)
|
||||||
|
{
|
||||||
|
GoalMomentum = goalMomentum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessMove(Move move, MoveResult result)
|
||||||
|
{
|
||||||
|
_curMomentum += result.SelfMomentumDelta;
|
||||||
|
if (_curMomentum > _maxMomentum)
|
||||||
|
_maxMomentum = _curMomentum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsComplete()
|
||||||
|
{
|
||||||
|
return _maxMomentum >= GoalMomentum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MatchStatus
|
||||||
|
{
|
||||||
|
InProgress,
|
||||||
|
Pinfall,
|
||||||
|
Submission,
|
||||||
|
CountOut,
|
||||||
|
Disqualification,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MoveOptions
|
||||||
|
{
|
||||||
|
// this class represents the available moves
|
||||||
|
public string Strike { get; set; }
|
||||||
|
public string Grapple { get; set; }
|
||||||
|
public string Other { get; set; }
|
||||||
|
public string Special { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Battle
|
||||||
|
{
|
||||||
|
private static Random _random = new Random();
|
||||||
|
|
||||||
|
public enum ParticipantRole
|
||||||
|
{
|
||||||
|
LeftSingle,
|
||||||
|
RightSingle,
|
||||||
|
LeftTag1,
|
||||||
|
LeftTag2,
|
||||||
|
RightTag1,
|
||||||
|
RightTag2,
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Participant
|
||||||
|
{
|
||||||
|
public Wrestler Wrestler;
|
||||||
|
public WrestlerPosition Position;
|
||||||
|
public BodyParts Restrained;
|
||||||
|
public BodyParts Injured;
|
||||||
|
public MomentumLevel Momentum;
|
||||||
|
public uint MaxFatigue;
|
||||||
|
public uint CurFatigue;
|
||||||
|
|
||||||
|
public Participant(Wrestler wrestler)
|
||||||
|
{
|
||||||
|
Wrestler = wrestler;
|
||||||
|
Position = WrestlerPosition.InRing;
|
||||||
|
Restrained = 0;
|
||||||
|
Injured = 0;
|
||||||
|
Momentum = MomentumLevel.None;
|
||||||
|
CurFatigue = MaxFatigue = wrestler.Fortitude * 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint _turnClock;
|
||||||
|
private ParticipantRole _playerRole;
|
||||||
|
|
||||||
|
public Dictionary<ParticipantRole, Participant> Participants { get; }
|
||||||
|
public MatchStatus Status { get; private set; }
|
||||||
|
public ParticipantRole[] UpcomingTurns { get; set; }
|
||||||
|
public MoveOptions CurrentMoveOptions { get; private set; }
|
||||||
|
|
||||||
|
private void InitializeState()
|
||||||
|
{
|
||||||
|
_turnClock = 1;
|
||||||
|
Status = MatchStatus.InProgress;
|
||||||
|
UpcomingTurns = new ParticipantRole[5];
|
||||||
|
CalcUpcomingTurns();
|
||||||
|
CurrentMoveOptions = new MoveOptions();
|
||||||
|
CalcPlayerMoveOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Battle(Wrestler leftWrestler, Wrestler rightWrestler)
|
||||||
|
{
|
||||||
|
Participants = new Dictionary<ParticipantRole, Participant>
|
||||||
|
{
|
||||||
|
[ParticipantRole.LeftSingle] = new Participant(leftWrestler),
|
||||||
|
[ParticipantRole.RightSingle] = new Participant(rightWrestler)
|
||||||
|
};
|
||||||
|
_playerRole = ParticipantRole.LeftSingle;
|
||||||
|
InitializeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Battle(Wrestler leftOne, Wrestler leftTwo, Wrestler rightOne, Wrestler rightTwo)
|
||||||
|
{
|
||||||
|
Participants = new Dictionary<ParticipantRole, Participant>
|
||||||
|
{
|
||||||
|
[ParticipantRole.LeftTag1] = new Participant(leftOne),
|
||||||
|
[ParticipantRole.LeftTag2] = new Participant(leftTwo),
|
||||||
|
[ParticipantRole.RightTag1] = new Participant(rightOne),
|
||||||
|
[ParticipantRole.RightTag2] = new Participant(rightTwo)
|
||||||
|
};
|
||||||
|
_playerRole = ParticipantRole.LeftTag1;
|
||||||
|
InitializeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player Interaction
|
||||||
|
|
||||||
|
public void CalcPlayerMoveOptions()
|
||||||
|
{
|
||||||
|
// TODO: revisit for other match types
|
||||||
|
var player = Participants[_playerRole];
|
||||||
|
var target = Participants[ParticipantRole.RightSingle];
|
||||||
|
// TODO: revisit for other move types
|
||||||
|
CurrentMoveOptions.Strike = GetBestAvailableMove(player, MoveType.Strike, target);
|
||||||
|
CurrentMoveOptions.Grapple = GetBestAvailableMove(player, MoveType.Aerial, target);
|
||||||
|
CurrentMoveOptions.Special = "Pin";
|
||||||
|
CurrentMoveOptions.Other = "Enzugiri **";
|
||||||
|
}
|
||||||
|
|
||||||
|
public MoveResult ApplyMove(string moveName)
|
||||||
|
{
|
||||||
|
var move = MoveDatabase.Lookup(moveName);
|
||||||
|
return ApplyMove(_playerRole, move, ParticipantRole.RightSingle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPlayerTurn()
|
||||||
|
{
|
||||||
|
return UpcomingTurns[0] == _playerRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndTurn()
|
||||||
|
{
|
||||||
|
_turnClock += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPU Control
|
||||||
|
|
||||||
|
public void GetCpuMove(out string move, out ParticipantRole target)
|
||||||
|
{
|
||||||
|
move = "Chop 1";
|
||||||
|
target = ParticipantRole.LeftSingle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internals
|
||||||
|
|
||||||
|
private MoveResult ApplyMove(ParticipantRole performerPos, Move move, ParticipantRole recipientPos)
|
||||||
|
{
|
||||||
|
var performer = Participants[performerPos];
|
||||||
|
var recipient = Participants[recipientPos];
|
||||||
|
|
||||||
|
// can this move be done?
|
||||||
|
if (!MoveIsValid(performer, move, recipient))
|
||||||
|
throw new InvalidMoveException();
|
||||||
|
|
||||||
|
var hitResult = CheckForHit(performer, move, recipient);
|
||||||
|
|
||||||
|
// if move misses, no damage
|
||||||
|
if (hitResult == HitResult.Miss)
|
||||||
|
return new MoveResult(hitResult, 0);
|
||||||
|
|
||||||
|
uint damage = 0;
|
||||||
|
uint selfDamage = 0;
|
||||||
|
switch (move.Type)
|
||||||
|
{
|
||||||
|
case MoveType.Strike:
|
||||||
|
damage = (uint) (move.BaseOffense * performer.Wrestler.DamageMult);
|
||||||
|
break;
|
||||||
|
case MoveType.Aerial:
|
||||||
|
damage = (uint) (move.BaseOffense * performer.Wrestler.DamageMult);
|
||||||
|
selfDamage = 5;
|
||||||
|
break;
|
||||||
|
case MoveType.Hold:
|
||||||
|
break;
|
||||||
|
case MoveType.Throw:
|
||||||
|
damage = (uint) (move.BaseOffense * performer.Wrestler.DamageMult);
|
||||||
|
break;
|
||||||
|
case MoveType.Pin:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: how does momentum/popularity work?
|
||||||
|
|
||||||
|
return new MoveResult(hitResult, damage, 0, 0, selfDamage, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CalcUpcomingTurns()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < UpcomingTurns.Length; i++)
|
||||||
|
{
|
||||||
|
// TODO: use speed to determine turn order
|
||||||
|
if ((_turnClock + i) % 2 == 1)
|
||||||
|
{
|
||||||
|
UpcomingTurns[i] = ParticipantRole.LeftSingle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpcomingTurns[i] = ParticipantRole.RightSingle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly double[] HitMod = {0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4};
|
||||||
|
private static readonly double[] EvadeMod = {-0.1, -0.1, -0.05, -0.05, 0, 0.05, 0.05, 0.1, 0.1, 0.15};
|
||||||
|
|
||||||
|
private static HitResult CheckForHit(Participant performer, Move move, Participant recipient)
|
||||||
|
{
|
||||||
|
var critChance = 0.05;
|
||||||
|
uint attackStat = 0;
|
||||||
|
|
||||||
|
switch (move.Type)
|
||||||
|
{
|
||||||
|
case MoveType.Strike:
|
||||||
|
attackStat = performer.Wrestler.Strength;
|
||||||
|
break;
|
||||||
|
case MoveType.Aerial:
|
||||||
|
attackStat = performer.Wrestler.Agility;
|
||||||
|
break;
|
||||||
|
case MoveType.Pin:
|
||||||
|
attackStat = performer.Wrestler.Strength > performer.Wrestler.Agility
|
||||||
|
? performer.Wrestler.Strength
|
||||||
|
: performer.Wrestler.Agility;
|
||||||
|
break;
|
||||||
|
case MoveType.Hold:
|
||||||
|
attackStat = performer.Wrestler.Grappling;
|
||||||
|
break;
|
||||||
|
case MoveType.Throw:
|
||||||
|
attackStat = performer.Wrestler.Grappling;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hitChance = move.BaseChance * HitMod[attackStat] - EvadeMod[recipient.Wrestler.Agility];
|
||||||
|
|
||||||
|
var hitRoll = _random.NextDouble();
|
||||||
|
if (hitRoll < critChance)
|
||||||
|
return HitResult.Critical;
|
||||||
|
else if (hitRoll <= hitChance)
|
||||||
|
return HitResult.Hit;
|
||||||
|
else
|
||||||
|
return HitResult.Miss;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool MoveIsValid(Participant performer, Move move, Participant recipient)
|
||||||
|
{
|
||||||
|
// TODO: check position of performer and recipient
|
||||||
|
|
||||||
|
// is there an issue affecting the required body part
|
||||||
|
var requiredPartsRestrained = performer.Restrained & move.PartsUtilized;
|
||||||
|
if (requiredPartsRestrained != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// does wrestler have momentum?
|
||||||
|
if (performer.Momentum < (MomentumLevel) (move.Rank - 1))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetBestAvailableMove(Participant participant, MoveType type, Participant recipient)
|
||||||
|
{
|
||||||
|
List<Move> best = new();
|
||||||
|
var bestRank = -1;
|
||||||
|
foreach (var (moveName, expertise) in participant.Wrestler.MoveSet)
|
||||||
|
{
|
||||||
|
var move = MoveDatabase.Lookup(moveName);
|
||||||
|
// accumulate list of best valid moves of the type
|
||||||
|
if (move.Type == type && MoveIsValid(participant, move, recipient))
|
||||||
|
{
|
||||||
|
// for now just use rank, eventually this may be dynamic
|
||||||
|
if (move.Rank > bestRank)
|
||||||
|
{
|
||||||
|
bestRank = (int) move.Rank;
|
||||||
|
best.Clear();
|
||||||
|
best.Add(move);
|
||||||
|
}
|
||||||
|
else if (move.Rank == bestRank)
|
||||||
|
{
|
||||||
|
best.Add(move);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return best[_random.Next(best.Count)].Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
UPWG/UPWG.Core/Moves.cs
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using CsvHelper;
|
||||||
|
|
||||||
|
namespace UPWG.Core
|
||||||
|
{
|
||||||
|
public class InvalidMoveException : Exception
|
||||||
|
{
|
||||||
|
public InvalidMoveException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public InvalidMoveException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MoveType
|
||||||
|
{
|
||||||
|
Strike,
|
||||||
|
Aerial,
|
||||||
|
Hold,
|
||||||
|
Throw,
|
||||||
|
Pin,
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum BodyParts
|
||||||
|
{
|
||||||
|
Arms = 1,
|
||||||
|
Legs = 2,
|
||||||
|
Head = 4,
|
||||||
|
Body = 8,
|
||||||
|
All = Arms | Legs | Head | Body,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Move
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public MoveType Type { get; set; }
|
||||||
|
|
||||||
|
public uint Rank { get; set; }
|
||||||
|
|
||||||
|
// can it be done?
|
||||||
|
public double BaseChance { get; set; }
|
||||||
|
|
||||||
|
//public MomentumLevel RequiredMomentum { get; set; }
|
||||||
|
public BodyParts PartsRestrained { get; set; }
|
||||||
|
public BodyParts PartsUtilized { get; set; }
|
||||||
|
|
||||||
|
// what does it do?
|
||||||
|
public int BasePopularity { get; set; }
|
||||||
|
public int BaseOffense { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MoveDatabase
|
||||||
|
{
|
||||||
|
public static readonly Dictionary<string, Move> Moves = new();
|
||||||
|
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
using var reader = new StreamReader("Data/moves.csv");
|
||||||
|
using var csv = new CsvReader(reader, CultureInfo.InvariantCulture);
|
||||||
|
var records = csv.GetRecords<Move>();
|
||||||
|
foreach (var record in records)
|
||||||
|
{
|
||||||
|
Moves[record.Name] = record;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Move Lookup(string name)
|
||||||
|
{
|
||||||
|
return Moves[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
UPWG/UPWG.Core/StateMachine.cs
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace UPWG.Core
|
||||||
|
{
|
||||||
|
public class StateMachine<T>
|
||||||
|
where T : Enum
|
||||||
|
{
|
||||||
|
public T CurrentState { get; private set; }
|
||||||
|
public double TimeInState { get; private set; }
|
||||||
|
private Dictionary<T, (double, T)> _transitions;
|
||||||
|
|
||||||
|
public StateMachine(T initial)
|
||||||
|
{
|
||||||
|
CurrentState = initial;
|
||||||
|
TimeInState = 0;
|
||||||
|
_transitions = new Dictionary<T, (double, T)>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTransition(T from, T to, double after = 0)
|
||||||
|
{
|
||||||
|
_transitions[from] = (after, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetState(T newState)
|
||||||
|
{
|
||||||
|
CurrentState = newState;
|
||||||
|
TimeInState = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(double elapsed)
|
||||||
|
{
|
||||||
|
TimeInState += elapsed;
|
||||||
|
|
||||||
|
if (!_transitions.ContainsKey(CurrentState))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var (maxTime, nextState) = _transitions[CurrentState];
|
||||||
|
if (TimeInState > maxTime)
|
||||||
|
{
|
||||||
|
SetState(nextState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
UPWG/UPWG.Core/UPWG.Core.csproj
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CsvHelper" Version="27.1.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
61
UPWG/UPWG.Core/Wrestler.cs
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace UPWG.Core
|
||||||
|
{
|
||||||
|
public enum WeightClass
|
||||||
|
{
|
||||||
|
Light,
|
||||||
|
Normal,
|
||||||
|
Heavy,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Wrestler
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public uint Strength { get; } // used
|
||||||
|
public uint Grappling { get; }
|
||||||
|
public uint Agility { get; }
|
||||||
|
public uint Fortitude { get; }
|
||||||
|
public uint Charisma { get; }
|
||||||
|
public WeightClass Weight { get; }
|
||||||
|
public Dictionary<string, uint> MoveSet;
|
||||||
|
|
||||||
|
public Wrestler(string name, uint strength, uint grappling, uint agility, uint fortitude, uint charisma,
|
||||||
|
WeightClass weight
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Strength = strength;
|
||||||
|
Grappling = grappling;
|
||||||
|
Agility = agility;
|
||||||
|
Fortitude = fortitude;
|
||||||
|
Charisma = charisma;
|
||||||
|
Weight = weight;
|
||||||
|
MoveSet = new Dictionary<string, uint>();
|
||||||
|
foreach (var (move, _) in MoveDatabase.Moves)
|
||||||
|
{
|
||||||
|
MoveSet[move] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double DamageMult
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch (Strength)
|
||||||
|
{
|
||||||
|
case <= 2: return 0.5;
|
||||||
|
case <= 4: return 1.0;
|
||||||
|
case <= 6: return 1.2;
|
||||||
|
case <= 8: return 1.4;
|
||||||
|
default: return 1.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint GetExpertise(string moveName)
|
||||||
|
{
|
||||||
|
return MoveSet.ContainsKey(moveName) ? MoveSet[moveName] : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
160
UPWG/UPWG.Main/Animation.cs
Executable file
@ -0,0 +1,160 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Elite;
|
||||||
|
|
||||||
|
namespace UPWG.Main
|
||||||
|
{
|
||||||
|
internal enum MovementType
|
||||||
|
{
|
||||||
|
Run,
|
||||||
|
Jump,
|
||||||
|
Flip,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum RingPosition
|
||||||
|
{
|
||||||
|
// these use cardinal directions (picture a compass rose laid over the ring)
|
||||||
|
// they will be flipped when animations are reversed
|
||||||
|
SouthWest,
|
||||||
|
West,
|
||||||
|
NorthWest,
|
||||||
|
North,
|
||||||
|
NorthEast,
|
||||||
|
East,
|
||||||
|
SouthEast,
|
||||||
|
South,
|
||||||
|
Center,
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BattleAnimation
|
||||||
|
{
|
||||||
|
protected double ElapsedSeconds;
|
||||||
|
protected readonly double RunSeconds;
|
||||||
|
|
||||||
|
protected BattleAnimation(double runSeconds)
|
||||||
|
{
|
||||||
|
ElapsedSeconds = 0;
|
||||||
|
RunSeconds = runSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Done()
|
||||||
|
{
|
||||||
|
return ElapsedSeconds > RunSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Update(double elapsed, ref Vector2 pos, ref float rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Run : BattleAnimation
|
||||||
|
{
|
||||||
|
private Vector2 _start;
|
||||||
|
private Vector2 _end;
|
||||||
|
|
||||||
|
public Run(double runSeconds, RingPosition from, RingPosition to) : base(runSeconds)
|
||||||
|
{
|
||||||
|
_start = RingPositionToVector2(from);
|
||||||
|
_end = RingPositionToVector2(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double elapsed, ref Vector2 pos, ref float rotation)
|
||||||
|
{
|
||||||
|
ElapsedSeconds += elapsed;
|
||||||
|
pos = Vector2.Lerp(_start, _end, (float) (ElapsedSeconds / RunSeconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
private const float EastRopesX = 200;
|
||||||
|
private const float WestRopesX = 500;
|
||||||
|
private const float CenterX = (EastRopesX + WestRopesX) / 2;
|
||||||
|
private const float NorthRopesY = 100;
|
||||||
|
private const float SouthRopesY = 300;
|
||||||
|
private const float CenterY = (NorthRopesY + SouthRopesY) / 2;
|
||||||
|
|
||||||
|
public static Vector2 RingPositionToVector2(RingPosition position)
|
||||||
|
{
|
||||||
|
return position switch
|
||||||
|
{
|
||||||
|
RingPosition.North => new Vector2(CenterX, NorthRopesY),
|
||||||
|
RingPosition.NorthEast => new Vector2(EastRopesX, NorthRopesY),
|
||||||
|
RingPosition.East => new Vector2(EastRopesX, CenterY),
|
||||||
|
RingPosition.SouthEast => new Vector2(EastRopesX, SouthRopesY),
|
||||||
|
RingPosition.South => new Vector2(CenterX, SouthRopesY),
|
||||||
|
RingPosition.SouthWest => new Vector2(WestRopesX, SouthRopesY),
|
||||||
|
RingPosition.West => new Vector2(WestRopesX, CenterY),
|
||||||
|
RingPosition.NorthWest => new Vector2(WestRopesX, NorthRopesY),
|
||||||
|
RingPosition.Center => new Vector2(CenterX, CenterY),
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(position))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Spin : BattleAnimation
|
||||||
|
{
|
||||||
|
private float _angleFrom;
|
||||||
|
private float _angleTo;
|
||||||
|
|
||||||
|
public Spin(double runSeconds, float angleFrom, float angleTo) : base(runSeconds)
|
||||||
|
{
|
||||||
|
_angleFrom = angleFrom;
|
||||||
|
_angleTo = angleTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(double elapsed, ref Vector2 pos, ref float rotation)
|
||||||
|
{
|
||||||
|
ElapsedSeconds += elapsed;
|
||||||
|
rotation = MathHelper.Lerp(_angleFrom, _angleTo, (float) (ElapsedSeconds / RunSeconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BattleSprite : IBatchDrawable
|
||||||
|
{
|
||||||
|
private const int Width = 128;
|
||||||
|
private const int Height = 128;
|
||||||
|
|
||||||
|
private Texture2D _texture;
|
||||||
|
private Vector2 _origin;
|
||||||
|
private Vector2 _pos;
|
||||||
|
private float _rotation;
|
||||||
|
private BattleAnimation[] _animations;
|
||||||
|
private int _animationNum;
|
||||||
|
|
||||||
|
public BattleSprite(GraphicsDevice graphicsDevice, string filename)
|
||||||
|
{
|
||||||
|
var fileStream = new FileStream("Content/jason.jpg", FileMode.Open);
|
||||||
|
_texture = Texture2D.FromStream(graphicsDevice, fileStream);
|
||||||
|
fileStream.Dispose();
|
||||||
|
|
||||||
|
_pos = new Vector2(100, 200);
|
||||||
|
_origin = new Vector2(_texture.Width / 2, _texture.Height / 2);
|
||||||
|
|
||||||
|
_animations = new BattleAnimation[]
|
||||||
|
{
|
||||||
|
new Run(1, RingPosition.West, RingPosition.East),
|
||||||
|
new Run(1, RingPosition.East, RingPosition.West),
|
||||||
|
//new Run(1, RingPosition.West, RingPosition.East),
|
||||||
|
//new Run(1, RingPosition.East, RingPosition.Center),
|
||||||
|
//new Run(0.2, RingPosition.Center, RingPosition.Center),
|
||||||
|
new Spin(4, 0, 3.14f),
|
||||||
|
};
|
||||||
|
_animationNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(double elapsedSeconds)
|
||||||
|
{
|
||||||
|
if (_animationNum < _animations.Length)
|
||||||
|
{
|
||||||
|
_animations[_animationNum].Update(elapsedSeconds, ref _pos, ref _rotation);
|
||||||
|
if (_animations[_animationNum].Done())
|
||||||
|
_animationNum += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Draw(SpriteBatch batch)
|
||||||
|
{
|
||||||
|
batch.Draw(_texture, new Rectangle((int) _pos.X, (int) _pos.Y, Width, Height), null, Color.White,
|
||||||
|
_rotation, _origin, SpriteEffects.None, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
197
UPWG/UPWG.Main/BattleTest.cs
Executable file
@ -0,0 +1,197 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using UPWG.Core;
|
||||||
|
using Elite;
|
||||||
|
|
||||||
|
namespace UPWG.Main
|
||||||
|
{
|
||||||
|
public enum TurnState
|
||||||
|
{
|
||||||
|
WaitingForInput,
|
||||||
|
PlayerMoveAnimation,
|
||||||
|
PlayerMoveResult,
|
||||||
|
OpponentMoveAnimation,
|
||||||
|
OpponentMoveResult,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BattleTest : Game
|
||||||
|
{
|
||||||
|
private GraphicsDeviceManager _graphicsDeviceManager;
|
||||||
|
private SpriteFont _spriteFont;
|
||||||
|
private Wrestler _p1;
|
||||||
|
private Wrestler _p2;
|
||||||
|
private Battle _match;
|
||||||
|
private StateMachine<TurnState> _turnState;
|
||||||
|
private BattleSprite _sprite1;
|
||||||
|
private BattleSprite _sprite2;
|
||||||
|
private ScaledRenderTarget _target;
|
||||||
|
private Sprite _ring;
|
||||||
|
|
||||||
|
public BattleTest()
|
||||||
|
{
|
||||||
|
_graphicsDeviceManager = new GraphicsDeviceManager(this);
|
||||||
|
Content.RootDirectory = "Content";
|
||||||
|
IsMouseVisible = true;
|
||||||
|
MoveDatabase.Initialize();
|
||||||
|
|
||||||
|
_turnState = new StateMachine<TurnState>(TurnState.WaitingForInput);
|
||||||
|
_turnState.AddTransition(TurnState.PlayerMoveAnimation, TurnState.PlayerMoveResult, 1);
|
||||||
|
_turnState.AddTransition(TurnState.PlayerMoveResult, TurnState.OpponentMoveAnimation, 1);
|
||||||
|
_turnState.AddTransition(TurnState.OpponentMoveAnimation, TurnState.OpponentMoveResult, 1);
|
||||||
|
_turnState.AddTransition(TurnState.OpponentMoveResult, TurnState.WaitingForInput, 1);
|
||||||
|
|
||||||
|
_p1 = new Wrestler("CM Punk", 7, 9, 5, 8, 10, WeightClass.Normal);
|
||||||
|
_p2 = new Wrestler("John Cena", 8, 8, 5, 8, 8, WeightClass.Normal);
|
||||||
|
_match = new Battle(_p1, _p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Initialize()
|
||||||
|
{
|
||||||
|
_graphicsDeviceManager.PreferredBackBufferWidth = 1281;
|
||||||
|
_graphicsDeviceManager.PreferredBackBufferHeight = 720;
|
||||||
|
_graphicsDeviceManager.ApplyChanges();
|
||||||
|
base.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadContent()
|
||||||
|
{
|
||||||
|
_spriteFont = Content.Load<SpriteFont>("Arial");
|
||||||
|
_target = new ScaledRenderTarget(GraphicsDevice, 640, 360, 2.0f, _spriteFont);
|
||||||
|
_sprite1 = new BattleSprite(GraphicsDevice, "");
|
||||||
|
_sprite2 = new BattleSprite(GraphicsDevice, "");
|
||||||
|
_ring = new Sprite(GraphicsDevice, "Content/oga/ring_7.png");
|
||||||
|
|
||||||
|
_target.DrawList.Add(_ring);
|
||||||
|
_target.DrawList.Add(_sprite1);
|
||||||
|
_target.DrawList.Add(_sprite2);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UnloadContent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Update(GameTime gameTime)
|
||||||
|
{
|
||||||
|
var keyboardState = Keyboard.GetState();
|
||||||
|
MoveResult moveResult;
|
||||||
|
|
||||||
|
_turnState.Update(gameTime.ElapsedGameTime.TotalSeconds);
|
||||||
|
_sprite1.Update(gameTime.ElapsedGameTime.TotalSeconds);
|
||||||
|
_sprite2.Update(gameTime.ElapsedGameTime.TotalSeconds);
|
||||||
|
|
||||||
|
if (keyboardState.IsKeyDown(Keys.Escape))
|
||||||
|
Exit();
|
||||||
|
|
||||||
|
if (_match.IsPlayerTurn() && _turnState.CurrentState == TurnState.WaitingForInput)
|
||||||
|
{
|
||||||
|
if (keyboardState.IsKeyDown(Keys.A))
|
||||||
|
{
|
||||||
|
moveResult = _match.ApplyMove(_match.CurrentMoveOptions.Strike);
|
||||||
|
_turnState.SetState(TurnState.PlayerMoveAnimation);
|
||||||
|
}
|
||||||
|
else if (keyboardState.IsKeyDown(Keys.S))
|
||||||
|
{
|
||||||
|
moveResult = _match.ApplyMove(_match.CurrentMoveOptions.Grapple);
|
||||||
|
_turnState.SetState(TurnState.PlayerMoveAnimation);
|
||||||
|
}
|
||||||
|
else if (keyboardState.IsKeyDown(Keys.D))
|
||||||
|
{
|
||||||
|
moveResult = _match.ApplyMove(_match.CurrentMoveOptions.Other);
|
||||||
|
_turnState.SetState(TurnState.PlayerMoveAnimation);
|
||||||
|
}
|
||||||
|
else if (keyboardState.IsKeyDown(Keys.F))
|
||||||
|
{
|
||||||
|
moveResult = _match.ApplyMove(_match.CurrentMoveOptions.Special);
|
||||||
|
_turnState.SetState(TurnState.PlayerMoveAnimation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_match.GetCpuMove(out var move, out var target);
|
||||||
|
moveResult = _match.ApplyMove(move);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Update(gameTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawWrestler(Battle.ParticipantRole role, Battle.Participant participant)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Battle.ParticipantRole.LeftSingle:
|
||||||
|
x = 100;
|
||||||
|
y = 100;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
x = 1280 - 300;
|
||||||
|
y = 100;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_target.DrawString(
|
||||||
|
_spriteFont, $"{participant.Wrestler.Name}",
|
||||||
|
new Vector2(x, y), Color.Pink
|
||||||
|
);
|
||||||
|
_target.DrawString(
|
||||||
|
_spriteFont, $"Momentum: {participant.Momentum}",
|
||||||
|
new Vector2(x, y + 20), Color.Pink
|
||||||
|
);
|
||||||
|
_target.DrawString(
|
||||||
|
_spriteFont, $"Restrained: {participant.Restrained} Injured: {participant.Injured}",
|
||||||
|
new Vector2(x, y + 40), Color.Pink
|
||||||
|
);
|
||||||
|
_target.DrawString(
|
||||||
|
_spriteFont, $"{participant.CurFatigue} / {participant.MaxFatigue}",
|
||||||
|
new Vector2(x, y + 60), Color.Pink
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawMoveOptions(MoveOptions moveOptions)
|
||||||
|
{
|
||||||
|
_target.DrawString(_spriteFont, $"A: {moveOptions.Strike}",
|
||||||
|
new Vector2(200, 200), Color.Yellow);
|
||||||
|
_target.DrawString(_spriteFont, $"S: {moveOptions.Grapple}",
|
||||||
|
new Vector2(200, 210), Color.Yellow);
|
||||||
|
_target.DrawString(_spriteFont, $"D: {moveOptions.Special}",
|
||||||
|
new Vector2(200, 220), Color.Yellow);
|
||||||
|
_target.DrawString(_spriteFont, $"F: {moveOptions.Other}",
|
||||||
|
new Vector2(200, 230), Color.Yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
GraphicsDevice.Clear(Color.Red);
|
||||||
|
|
||||||
|
const int x = 300;
|
||||||
|
var y = 300;
|
||||||
|
var n = 1;
|
||||||
|
|
||||||
|
_target.Draw(gameTime);
|
||||||
|
_target.SpriteBatch.Begin();
|
||||||
|
foreach (var (key, value) in _match.Participants)
|
||||||
|
{
|
||||||
|
DrawWrestler(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
_target.DrawString(_spriteFont, $"{_turnState.CurrentState}", new Vector2(_target.Width / 2, 0),
|
||||||
|
Color.White);
|
||||||
|
foreach (var turn in _match.UpcomingTurns)
|
||||||
|
{
|
||||||
|
_target.DrawString(_spriteFont, $"{n}: {turn}", new Vector2(x, y), Color.Green);
|
||||||
|
n += 1;
|
||||||
|
y += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_match.IsPlayerTurn())
|
||||||
|
DrawMoveOptions(_match.CurrentMoveOptions);
|
||||||
|
_target.SpriteBatch.End();
|
||||||
|
|
||||||
|
base.Draw(gameTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
UPWG/UPWG.Main/Content/Arial.spritefont
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
This file contains an xml description of a font, and will be read by the XNA
|
||||||
|
Framework Content Pipeline. Follow the comments to customize the appearance
|
||||||
|
of the font in your game, and to change the characters which are available to draw
|
||||||
|
with.
|
||||||
|
-->
|
||||||
|
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
|
||||||
|
<Asset Type="Graphics:FontDescription">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Modify this string to change the font that will be imported.
|
||||||
|
-->
|
||||||
|
<FontName>Arial</FontName>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Size is a float value, measured in points. Modify this value to change
|
||||||
|
the size of the font.
|
||||||
|
-->
|
||||||
|
<Size>12</Size>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Spacing is a float value, measured in pixels. Modify this value to change
|
||||||
|
the amount of spacing in between characters.
|
||||||
|
-->
|
||||||
|
<Spacing>0</Spacing>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
UseKerning controls the layout of the font. If this value is true, kerning information
|
||||||
|
will be used when placing characters.
|
||||||
|
-->
|
||||||
|
<UseKerning>true</UseKerning>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
|
||||||
|
and "Bold, Italic", and are case sensitive.
|
||||||
|
-->
|
||||||
|
<Style>Regular</Style>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If you uncomment this line, the default character will be substituted if you draw
|
||||||
|
or measure text that contains characters which were not included in the font.
|
||||||
|
-->
|
||||||
|
<!-- <DefaultCharacter>*</DefaultCharacter> -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
CharacterRegions control what letters are available in the font. Every
|
||||||
|
character from Start to End will be built and made available for drawing. The
|
||||||
|
default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin
|
||||||
|
character set. The characters are ordered according to the Unicode standard.
|
||||||
|
See the documentation for more information.
|
||||||
|
-->
|
||||||
|
<CharacterRegions>
|
||||||
|
<CharacterRegion>
|
||||||
|
<Start> </Start>
|
||||||
|
<End>~</End>
|
||||||
|
</CharacterRegion>
|
||||||
|
</CharacterRegions>
|
||||||
|
</Asset>
|
||||||
|
</XnaContent>
|
20
UPWG/UPWG.Main/Content/Content.mgcb
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#----------------------------- Global Properties ----------------------------#
|
||||||
|
|
||||||
|
/outputDir:bin/$(Platform)
|
||||||
|
/intermediateDir:obj/$(Platform)
|
||||||
|
/platform:Windows
|
||||||
|
/config:
|
||||||
|
/profile:Reach
|
||||||
|
/compress:False
|
||||||
|
|
||||||
|
#-------------------------------- References --------------------------------#
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------- Content ---------------------------------#
|
||||||
|
|
||||||
|
#begin Arial.spritefont
|
||||||
|
/importer:FontDescriptionImporter
|
||||||
|
/processor:FontDescriptionProcessor
|
||||||
|
/processorParam:PremultiplyAlpha=True
|
||||||
|
/processorParam:TextureFormat=Compressed
|
||||||
|
/build:Arial.spritefont
|
BIN
UPWG/UPWG.Main/Icon.bmp
Executable file
After Width: | Height: | Size: 256 KiB |
BIN
UPWG/UPWG.Main/Icon.ico
Executable file
After Width: | Height: | Size: 144 KiB |
14
UPWG/UPWG.Main/Program.cs
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace UPWG.Main
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
using (var game = new BattleTest())
|
||||||
|
game.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
UPWG/UPWG.Main/UPWG.Main.csproj
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<PublishReadyToRun>false</PublishReadyToRun>
|
||||||
|
<TieredCompilation>false</TieredCompilation>
|
||||||
|
<PackageId>UPWG.Main</PackageId>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<ApplicationIcon>Icon.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Icon.ico"/>
|
||||||
|
<None Remove="Icon.bmp"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Icon.ico"/>
|
||||||
|
<EmbeddedResource Include="Icon.bmp"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<MonoGameContentReference Include="Content\Content.mgcb"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<TrimmerRootAssembly Include="Microsoft.Xna.Framework.Content.ContentTypeReader" Visible="false"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.0.1641"/>
|
||||||
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.0.1641"/>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Elite\Elite.csproj"/>
|
||||||
|
<ProjectReference Include="..\UPWG.Core\UPWG.Core.csproj"/>
|
||||||
|
<ProjectReference Include="..\UPWG.Utils\UPWG.Utils.csproj"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
43
UPWG/UPWG.Main/app.manifest
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="UPWG.BattleTest"/>
|
||||||
|
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||||
|
<security>
|
||||||
|
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||||
|
</requestedPrivileges>
|
||||||
|
</security>
|
||||||
|
</trustInfo>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on and is
|
||||||
|
is designed to work with. Uncomment the appropriate elements and Windows will
|
||||||
|
automatically selected the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows Vista -->
|
||||||
|
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
|
||||||
|
|
||||||
|
<!-- Windows 7 -->
|
||||||
|
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||||
|
|
||||||
|
<!-- Windows 8 -->
|
||||||
|
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||||
|
|
||||||
|
<!-- Windows 8.1 -->
|
||||||
|
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</assembly>
|
34
UPWG/UPWG.sln
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPWG.Core", "UPWG.Core\UPWG.Core.csproj", "{C8358627-AEAF-473B-B7B9-FD670A366095}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPWG.Main", "UPWG.Main\UPWG.Main.csproj", "{4D7C34FD-5B50-454C-93ED-E805F261F48B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elite", "Elite\Elite.csproj", "{090DD346-EFA7-4907-8ACB-757D63F9F4B5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Manhattan", "Manhattan\Manhattan.csproj", "{9FD7026A-D69B-40D8-AC7B-B77023CF5444}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{C8358627-AEAF-473B-B7B9-FD670A366095}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C8358627-AEAF-473B-B7B9-FD670A366095}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C8358627-AEAF-473B-B7B9-FD670A366095}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C8358627-AEAF-473B-B7B9-FD670A366095}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4D7C34FD-5B50-454C-93ED-E805F261F48B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4D7C34FD-5B50-454C-93ED-E805F261F48B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4D7C34FD-5B50-454C-93ED-E805F261F48B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4D7C34FD-5B50-454C-93ED-E805F261F48B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{090DD346-EFA7-4907-8ACB-757D63F9F4B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{090DD346-EFA7-4907-8ACB-757D63F9F4B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{090DD346-EFA7-4907-8ACB-757D63F9F4B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{090DD346-EFA7-4907-8ACB-757D63F9F4B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{9FD7026A-D69B-40D8-AC7B-B77023CF5444}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{9FD7026A-D69B-40D8-AC7B-B77023CF5444}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{9FD7026A-D69B-40D8-AC7B-B77023CF5444}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{9FD7026A-D69B-40D8-AC7B-B77023CF5444}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|