This commit is contained in:
GoaLitiuM
2021-08-31 20:03:02 +03:00
parent 995e9bdbce
commit 8bde0a7f18
11 changed files with 511 additions and 259 deletions

2
.gitignore vendored
View File

@@ -17,3 +17,5 @@ Output/*
Source/obj/ Source/obj/
.idea/* .idea/*
*.DotSettings.user *.DotSettings.user
Tests/bin/
Tests/obj/

View File

@@ -5,19 +5,31 @@
"Data": { "Data": {
"ProductName": "Goake", "ProductName": "Goake",
"CompanyName": "GoaLitiuM", "CompanyName": "GoaLitiuM",
"CopyrightNotice": "ddc",
"Icon": null,
"FirstScene": "194e05f445ece24ec5448d886e1334df", "FirstScene": "194e05f445ece24ec5448d886e1334df",
"NoSplashScreen": true, "NoSplashScreen": true,
"SplashScreen": null,
"Time": "a55dc3c04da4ea3744b7f1994565beac", "Time": "a55dc3c04da4ea3744b7f1994565beac",
"Audio": "492a33824049ba25a8bdcdb148179e67", "Audio": "492a33824049ba25a8bdcdb148179e67",
"LayersAndTags": "60078f6a489f7c57e47fce83afaada66", "LayersAndTags": "60078f6a489f7c57e47fce83afaada66",
"Physics": "4bd8a4cc460399b5f1975fbe0a668e3f", "Physics": "4bd8a4cc460399b5f1975fbe0a668e3f",
"Input": "8ec53dba4c238bfbea1d62922e612a4d", "Input": "8ec53dba4c238bfbea1d62922e612a4d",
"Graphics": "f94d5aae457aeba67033a8a4ca753214", "Graphics": "f94d5aae457aeba67033a8a4ca753214",
"Navigation": null,
"Localization": null,
"GameCooking": "af2e52554f7faed7b4937181dd22d166", "GameCooking": "af2e52554f7faed7b4937181dd22d166",
"Streaming": "3a6ffc3a43e684f77cfed1a1f8f6bd0e", "Streaming": "3a6ffc3a43e684f77cfed1a1f8f6bd0e",
"CustomSettings": { "CustomSettings": {
"BrushMaterials": "29a0b0c54b40eb3e6857ffb4c9cab71e" "BrushMaterials": "29a0b0c54b40eb3e6857ffb4c9cab71e"
}, },
"WindowsPlatform": "4a5eec97484253fed72934860ae62c40" "WindowsPlatform": "4a5eec97484253fed72934860ae62c40",
"UWPPlatform": null,
"LinuxPlatform": null,
"PS4Platform": null,
"XboxOnePlatform": null,
"XboxScarlettPlatform": null,
"AndroidPlatform": null,
"SwitchPlatform": null
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"ID": "0c0af24c4fafa9c72af2c08723321976", "ID": "0c0af24c4fafa9c72af2c08723321976",
"TypeName": "FlaxEngine.SceneAsset", "TypeName": "FlaxEngine.SceneAsset",
"EngineBuild": 6219, "EngineBuild": 6224,
"Data": [ "Data": [
{ {
"ID": "0c0af24c4fafa9c72af2c08723321976", "ID": "0c0af24c4fafa9c72af2c08723321976",
@@ -25,103 +25,53 @@
} }
}, },
{ {
"ID": "4ef1f38b4569142b55b0ff935525d47a", "ID": "c28e12a74ac7d87cf078c6a52bf696e0",
"TypeName": "FlaxEngine.RigidBody", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "0c0af24c4fafa9c72af2c08723321976", "PrefabObjectID": "999a202c47de967d2bdfd09abcc6df4e",
"Name": "PlayerPrefab", "ParentID": "0c0af24c4fafa9c72af2c08723321976"
"Transform": {
"Translation": {
"X": -167.25045776367188,
"Y": -10.409317016601563,
"Z": 61.111427307128909
}
},
"OverrideMass": true,
"Mass": 10.0,
"LinearDamping": 0.0,
"AngularDamping": 0.0,
"Constraints": 56,
"IsKinematic": true,
"EnableGravity": false
}, },
{ {
"ID": "e3bab01a4912873fc2e9ff855a214bf7", "ID": "26ae32e2418882abc15d568692fdd97f",
"TypeName": "Game.PlayerMovement", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "4ef1f38b4569142b55b0ff935525d47a", "PrefabObjectID": "b29a58f545071ca393afaab21faa83ad",
"ParentID": "c28e12a74ac7d87cf078c6a52bf696e0",
"V": {} "V": {}
}, },
{ {
"ID": "08ed03be4d537814ba01edb88f6801e1", "ID": "ddcf668e46d6c73d5d0d258822f24594",
"TypeName": "FlaxEngine.EmptyActor", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "4ef1f38b4569142b55b0ff935525d47a", "PrefabObjectID": "a67383834fc3f6f1106e8099e5557e32",
"Name": "RootActor" "ParentID": "c28e12a74ac7d87cf078c6a52bf696e0"
}, },
{ {
"ID": "499cfa784579b58bba713daa0983d705", "ID": "9b502ff34a9bee27cf23aabd9cf1da91",
"TypeName": "FlaxEngine.Camera", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "08ed03be4d537814ba01edb88f6801e1", "PrefabObjectID": "b8fc420f4efe96fa2b4042bd98fd3e74",
"Name": "Camera", "ParentID": "ddcf668e46d6c73d5d0d258822f24594"
"Transform": {
"Translation": {
"X": 0.0,
"Y": 28.7337646484375,
"Z": 0.0
}
},
"Near": 1.0
}, },
{ {
"ID": "b59df4764594c5ee84a759b5e65bfc5a", "ID": "7a0c2f7648daf4b52776858dd302d509",
"TypeName": "FlaxEngine.AudioListener", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "08ed03be4d537814ba01edb88f6801e1", "PrefabObjectID": "226bdb004e72848777178a9d1f207cbf",
"Name": "AudioListener" "ParentID": "9b502ff34a9bee27cf23aabd9cf1da91"
}, },
{ {
"ID": "fbaa6db24f0a2a9db36bc6a043fc2572", "ID": "320c57c5499ef1692820f28954142720",
"TypeName": "FlaxEngine.CapsuleCollider", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "4ef1f38b4569142b55b0ff935525d47a", "PrefabObjectID": "8bd80bca49ac35da66aabaa2e473851d",
"IsActive": false, "ParentID": "c28e12a74ac7d87cf078c6a52bf696e0"
"Name": "CapsuleCollider",
"Transform": {
"Orientation": {
"X": 0.0,
"Y": 0.0,
"Z": 0.7071068286895752,
"W": 0.7071068286895752
}
},
"ContactOffset": 0.0,
"Material": "d99b8b6f40198beea4703dadd642150e",
"Radius": 16.0,
"Height": 52.0
}, },
{ {
"ID": "9677298d46e5d5d7021f7cb607bd3023", "ID": "deef0a234d3a14fad95b50b822e9f096",
"TypeName": "FlaxEngine.BoxCollider", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "4ef1f38b4569142b55b0ff935525d47a", "PrefabObjectID": "d9d61d314ad79d49ba08059cef50f802",
"Name": "BoxCollider", "ParentID": "c28e12a74ac7d87cf078c6a52bf696e0"
"ContactOffset": 0.0,
"Material": "ffe0e84c49607480f67a3994a7fe11a8",
"Size": {
"X": 32.0,
"Y": 84.0,
"Z": 32.0
}
}, },
{ {
"ID": "f472490345bbfe282aefa2aa027e0138", "ID": "fc1310c843e3136b468f83947df3566d",
"TypeName": "FlaxEngine.MeshCollider", "PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
"ParentID": "4ef1f38b4569142b55b0ff935525d47a", "PrefabObjectID": "b377cc03418270d87e8a5b92cb5374ea",
"IsActive": false, "ParentID": "c28e12a74ac7d87cf078c6a52bf696e0"
"Name": "CylinderCollider",
"Transform": {
"Scale": {
"X": 0.3199999928474426,
"Y": 0.8399999737739563,
"Z": 0.3199999928474426
}
},
"CollisionData": "593d92914c4bd54679ddec9e539bba80"
}, },
{ {
"ID": "b5d566374477944e69bdc2b86249883b", "ID": "b5d566374477944e69bdc2b86249883b",
@@ -168,13 +118,13 @@
"Transform": { "Transform": {
"Translation": { "Translation": {
"X": 0.0, "X": 0.0,
"Y": 733.0, "Y": 735.0,
"Z": 0.0 "Z": 0.0
} }
}, },
"Control": "FlaxEngine.GUI.Label", "Control": "FlaxEngine.GUI.Label",
"Data": { "Data": {
"Text": "uFPS: 120\nrFPS: 120\npFPS: 30\nCon: NaNms\nDirectX11\nGC memory: 15.30202MB", "Text": "eFPS: 121\nuFPS: 120\nrFPS: 120\npFPS: 30\nCon: NaNms\nDirectX11\nGC memory: 9.235704MB",
"TextColor": { "TextColor": {
"R": 1.0, "R": 1.0,
"G": 1.0, "G": 1.0,
@@ -194,6 +144,7 @@
"Font": "4508d98f4aa1f0bd59362b81d47e38f4", "Font": "4508d98f4aa1f0bd59362b81d47e38f4",
"Size": 10 "Size": 10
}, },
"Material": null,
"Margin": { "Margin": {
"Left": 0.0, "Left": 0.0,
"Right": 0.0, "Right": 0.0,
@@ -222,7 +173,7 @@
"Left": 0.0, "Left": 0.0,
"Right": 143.0, "Right": 143.0,
"Top": -80.0, "Top": -80.0,
"Bottom": 96.0 "Bottom": 112.0
}, },
"Scale": { "Scale": {
"X": 1.0, "X": 1.0,
@@ -260,8 +211,8 @@
"Name": "ContainerControl 0", "Name": "ContainerControl 0",
"Transform": { "Transform": {
"Translation": { "Translation": {
"X": 45644.0, "X": 44861.0,
"Y": 0.5, "Y": 1.5,
"Z": 0.0 "Z": 0.0
} }
}, },

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using FlaxEngine.Assertions;
namespace Cabrito namespace Cabrito
{ {
@@ -32,13 +31,12 @@ namespace Cabrito
instance = new ConsoleInstance(); instance = new ConsoleInstance();
} }
private static void Destroy() public static void Destroy()
{ {
if (instance != null) if (instance != null)
{ {
instance.Dispose(); instance.Dispose();
instance = null; instance = null;
FlaxEngine.Debug.Log("Console.Destroy");
} }
} }
@@ -139,7 +137,10 @@ namespace Cabrito
assemblyName.StartsWith("Mono.") || assemblyName.StartsWith("Mono.") ||
assemblyName == "mscorlib" || assemblyName == "mscorlib" ||
assemblyName == "Newtonsoft.Json" || assemblyName == "Newtonsoft.Json" ||
assemblyName.StartsWith("FlaxEngine.")) assemblyName.StartsWith("FlaxEngine.") ||
assemblyName.StartsWith("JetBrains.") ||
assemblyName.StartsWith("Microsoft.") ||
assemblyName.StartsWith("nunit."))
{ {
continue; continue;
} }

View File

@@ -1,6 +1,7 @@
using FlaxEngine; using FlaxEngine;
using Cabrito; using Cabrito;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
namespace Game namespace Game
{ {

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using FlaxEngine; using FlaxEngine;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -1082,6 +1083,16 @@ namespace Game
} }
} }
public class BrushGeometry
{
public MapBrush brush;
public Vector3[] vertices;
public uint[] indices;
public Vector2[] uvs;
public Vector3[] normals;
public Model model = null;
public MaterialBase brushMaterial = null; // FIXME: brush can have multiple textures
}
public class Q3MapImporter : Script public class Q3MapImporter : Script
@@ -1103,7 +1114,7 @@ namespace Game
void QuickHull(Vector3[] points, out Vector3[] outVertices) static void QuickHull(Vector3[] points, out Vector3[] outVertices)
{ {
var verts = new List<Vector3>(); var verts = new List<Vector3>();
var tris = new List<int>(); var tris = new List<int>();
@@ -1424,7 +1435,7 @@ namespace Game
return brushVertices.ToArray(); return brushVertices.ToArray();
} }
void TriangulateBrush3(MapBrush brush, out Vector3[] vertices) static public void TriangulateBrush3(MapBrush brush, out Vector3[] vertices)
{ {
float cs = 3000f; float cs = 3000f;
@@ -1638,13 +1649,13 @@ namespace Game
//uniqPoints.Add(new Vector3((float)Math.Round(v.X, 3), (float)Math.Round(v.Y, 3), (float)Math.Round(v.Z, 3))); //uniqPoints.Add(new Vector3((float)Math.Round(v.X, 3), (float)Math.Round(v.Y, 3), (float)Math.Round(v.Z, 3)));
} }
debugPoints = new List<Vector3>(uniqPoints); //debugPoints = new List<Vector3>(uniqPoints);
Vector3[] hullPoints; Vector3[] hullPoints;
QuickHull(uniqPoints.ToArray(), out hullPoints); QuickHull(uniqPoints.ToArray(), out hullPoints);
var ms = new MeshSimplifier(); var ms = new MeshSimplifier(1f, 7f);
var optimizedVerts = ms.Simplify(hullPoints); var optimizedVerts = ms.Simplify(hullPoints);
brushVertices.Clear(); brushVertices.Clear();
@@ -1652,7 +1663,7 @@ namespace Game
} }
else else
{ {
debugPoints = new List<Vector3>(faceVertices); //debugPoints = new List<Vector3>(faceVertices);
var hullPoints = faceVertices; var hullPoints = faceVertices;
@@ -1669,37 +1680,87 @@ namespace Game
vertices = brushVertices.ToArray(); vertices = brushVertices.ToArray();
} }
/*
Development (game)
cube3: 8.1ms + 123ms
aerowalk: 78ms + 1372ms
Development (editor)
cube3: 4.6ms + 77.3ms
aerowalk: 74ms + 1328ms
Release
cube3: 4.4ms + 61.4ms
aerowalk: 17ms + 511ms
UnitTest release:
aerowalk: 8ms + 267ms
aero unit:
.net6: 667 + 229
.net5: 704 + 237
.net5win7: 697 + 237
.net48 809 + 242
.net472 810 + 246
.net462 810 + 243
.net452 808 + 244
*/
public override void OnStart() public override void OnStart()
{ {
byte[] mapChars = File.ReadAllBytes(mapPath); byte[] mapChars = File.ReadAllBytes(mapPath);
Stopwatch sw = Stopwatch.StartNew();
root = MapParser.Parse(mapChars); root = MapParser.Parse(mapChars);
sw.Stop();
Console.Print("Map parsing time: " + sw.Elapsed.TotalMilliseconds + "ms");
bool oneMesh = false; bool oneMesh = false;
bool convexMesh = true; bool convexMesh = true;
if (!oneMesh) if (!oneMesh)
{ {
Dictionary<string, MaterialBase> materials = null; Dictionary<string, MaterialBase> materials = null;
var mapRootActor = Actor.AddChild<Actor>(); var mapRootActor = Actor.AddChild<Actor>();
mapRootActor.Name = "MapRootActor"; mapRootActor.Name = "MapRootActor";
List<BrushGeometry> brushGeometries = new List<BrushGeometry>(root.entities[0].brushes.Count);
// pass 1: triangulation
sw.Restart();
int brushIndex = 0; int brushIndex = 0;
foreach (var brush in root.entities[0].brushes) foreach (var brush in root.entities[0].brushes)
{ {
try try
{ {
List<Vector3> vertices = new List<Vector3>(); BrushGeometry geom = new BrushGeometry();
List<Vector2> uvs = new List<Vector2>();
List<Vector3> normals = new List<Vector3>();
TriangulateBrush3(brush, out Vector3[] brushVertices); TriangulateBrush3(brush, out geom.vertices);
geom.brush = brush;
brushGeometries.Add(geom);
}
catch (Exception e)
{
Console.Print("Failed to triangulate brush " + brushIndex.ToString() + ": " + e.Message);
}
brushIndex++;
}
sw.Stop();
Console.Print("Pass 1: triangulation: " + sw.Elapsed.TotalMilliseconds + "ms");
// pass 2: texturing
sw.Restart();
foreach (var geom in brushGeometries)
{
var brushVertices = geom.vertices;
Vector2[] brushUvs = new Vector2[brushVertices.Length]; Vector2[] brushUvs = new Vector2[brushVertices.Length];
Vector3[] brushNormals = new Vector3[brushVertices.Length]; Vector3[] brushNormals = new Vector3[brushVertices.Length];
// FIXME: brush can have multiple textures var textureName = geom.brush.planes[0].texture;
MaterialBase brushMaterial;
var textureName = brush.planes[0].texture;
if (materials == null) if (materials == null)
{ {
@@ -1717,7 +1778,8 @@ namespace Game
} }
} }
if (!materials.TryGetValue(textureName, out brushMaterial)) // FIXME: brush can have multiple textures
if (!materials.TryGetValue(textureName, out geom.brushMaterial))
{ {
Console.Print("Material '" + textureName + "' not found for brush"); Console.Print("Material '" + textureName + "' not found for brush");
materials.Add(textureName, material); materials.Add(textureName, material);
@@ -1736,7 +1798,7 @@ namespace Game
float uvRotation = 0f; float uvRotation = 0f;
Vector2 uvOffset = new Vector2(0f); Vector2 uvOffset = new Vector2(0f);
bool found = false; bool found = false;
foreach (var brushPlane in brush.planes) foreach (var brushPlane in geom.brush.planes)
{ {
if ((brushPlane.plane.Normal - normal).Length < 0.01f) if ((brushPlane.plane.Normal - normal).Length < 0.01f)
{ {
@@ -1760,6 +1822,7 @@ namespace Game
// Attempt to workaround most rounding errors at 45-degree angles which causes bias towards one axis. // Attempt to workaround most rounding errors at 45-degree angles which causes bias towards one axis.
// This behaviour is seemingly random in different engines and editors, so let's not bother. // This behaviour is seemingly random in different engines and editors, so let's not bother.
Vector3 textureNormal = new Vector3((float)Math.Round(normal.X, 4), Vector3 textureNormal = new Vector3((float)Math.Round(normal.X, 4),
(float)Math.Round(normal.Y, 4), (float)Math.Round(normal.Z, 4)); (float)Math.Round(normal.Y, 4), (float)Math.Round(normal.Z, 4));
@@ -1808,38 +1871,78 @@ namespace Game
brushNormals[i + 2] = normal; brushNormals[i + 2] = normal;
} }
vertices.AddRange(brushVertices); geom.vertices = brushVertices;
uvs.AddRange(brushUvs); geom.uvs = brushUvs;
normals.AddRange(brushNormals); geom.normals = brushNormals;
geom.indices = new uint[geom.vertices.Length];
for (uint i = 0; i < geom.vertices.Length; i++)
geom.indices[i] = i;
if (vertices.Count > 0) if (geom.vertices.Length > 0)
{ {
uint[] triangles = new uint[vertices.Count]; geom.model = Content.CreateVirtualAsset<Model>();
for (uint i = 0; i < vertices.Count; i++) geom.model.SetupLODs(new int[] { 1 });
triangles[i] = i; geom.model.LODs[0].Meshes[0].UpdateMesh(geom.vertices, geom.indices, geom.normals,
null, geom.uvs);
Model model = Content.CreateVirtualAsset<Model>();
model.SetupLODs(new int[] { 1 });
model.LODs[0].Meshes[0].UpdateMesh(vertices.ToArray(), (int[])(object)triangles, normals.ToArray(),
null, uvs.ToArray());
/*
StaticModel childModel = Actor.AddChild<StaticModel>(); StaticModel childModel = Actor.AddChild<StaticModel>();
childModel.Name = "Brush_" + brushIndex; childModel.Name = "Brush_" + brushIndex;
childModel.Model = model; childModel.Model = geom.model;
childModel.SetMaterial(0, brushMaterial); childModel.SetMaterial(0, geom.brushMaterial);
childModel.Parent = mapRootActor; childModel.Parent = mapRootActor;
CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>(); CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>();
if (collisionData.CookCollision(convexMesh ? CollisionDataType.ConvexMesh : CollisionDataType.TriangleMesh, vertices.ToArray(), if (collisionData.CookCollision(convexMesh ? CollisionDataType.ConvexMesh : CollisionDataType.TriangleMesh, geom.vertices.ToArray(),
triangles.ToArray())) geom.indices.ToArray()))
{ {
bool failed = true; bool failed = true;
if (convexMesh) if (convexMesh)
{ {
// fallback to triangle mesh // fallback to triangle mesh
failed = collisionData.CookCollision(CollisionDataType.TriangleMesh, failed = collisionData.CookCollision(CollisionDataType.TriangleMesh,
vertices.ToArray(), geom.vertices.ToArray(),
triangles.ToArray()); geom.indices.ToArray());
if (!failed)
Console.PrintWarning("Hull brush " + brushIndex.ToString() + " is not convex");
}
if (failed)
throw new Exception("failed to cook final collision");
}
var meshCollider = childModel.AddChild<MeshCollider>();
meshCollider.CollisionData = collisionData;
*/
}
//brushGeometries.Add(geom);
}
sw.Stop();
Console.Print("Pass 2: texturing: " + sw.Elapsed.TotalMilliseconds + "ms");
// pass 3: collision
sw.Restart();
foreach (var geom in brushGeometries)
{
StaticModel childModel = Actor.AddChild<StaticModel>();
childModel.Name = "Brush_" + brushIndex;
childModel.Model = geom.model;
childModel.SetMaterial(0, geom.brushMaterial);
childModel.Parent = mapRootActor;
CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>();
if (collisionData.CookCollision(convexMesh ? CollisionDataType.ConvexMesh : CollisionDataType.TriangleMesh, geom.vertices,
geom.indices))
{
bool failed = true;
if (convexMesh)
{
// fallback to triangle mesh
failed = collisionData.CookCollision(CollisionDataType.TriangleMesh,
geom.vertices,
geom.indices);
if (!failed) if (!failed)
Console.PrintWarning("Hull brush " + brushIndex.ToString() + " is not convex"); Console.PrintWarning("Hull brush " + brushIndex.ToString() + " is not convex");
} }
@@ -1850,14 +1953,8 @@ namespace Game
var meshCollider = childModel.AddChild<MeshCollider>(); var meshCollider = childModel.AddChild<MeshCollider>();
meshCollider.CollisionData = collisionData; meshCollider.CollisionData = collisionData;
} }
} sw.Stop();
catch (Exception e) Console.Print("Pass 3: collision: " + sw.Elapsed.TotalMilliseconds + "ms");
{
Console.Print("Failed to hull brush " + brushIndex.ToString() + ": " + e.Message);
}
brushIndex++;
}
} }
else else
{ {

View File

@@ -0,0 +1,32 @@
using System;
using Flax.Build;
public class GoakeTestsTarget : Target
{
/// <inheritdoc />
public GoakeTestsTarget()
{
Name = ProjectName = OutputName = "GoakeTests";
}
/// <inheritdoc />
public override void Init()
{
base.Init();
IsPreBuilt = false;
Type = TargetType.DotNet;
OutputType = TargetOutputType.Library;
/*Platforms = new[]
{
Flax.Build.Platform.BuildPlatform.Target,
};
Configurations = new[]
{
TargetConfiguration.Debug,
TargetConfiguration.Release,
};*/
CustomExternalProjectFilePath = System.IO.Path.Combine("Tests/GoakeTests.csproj");
}
}

View File

@@ -0,0 +1,43 @@
using NUnit.Framework;
using Cabrito;
using Console = Cabrito.Console;
namespace GoakeTests.ConsoleTests
{
public class ConsoleTests
{
[SetUp]
public void Setup()
{
Console.Init();
}
[TearDown]
public void CleanUp()
{
Console.Destroy();
}
[Test]
public void Test1()
{
string testPrint = "Hello world!";
Console.OnPrint += delegate(string s) { Assert.True(s == testPrint); };
Console.Print(testPrint);
}
[Test]
public void Test2()
{
string testPrint = "Hello world2!";
Console.OnPrint += delegate(string s) { Assert.True(s == testPrint); };
Console.Print(testPrint);
}
}
}

20
Tests/GoakeTests.csproj Normal file
View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
<TargetFrameworks>net452;net462;net472;net48;net5.0;net5.0-windows;net6.0</TargetFrameworks>
</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.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Source\Game.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,74 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using NUnit.Framework;
using Cabrito;
using FlaxEngine;
using Game;
namespace GoakeTests.MapParser
{
public class MapParserTests
{
private byte[] aerowalkBytes;
private MapEntity aerowalkRoot;
[SetUp]
public void Setup()
{
aerowalkBytes = File.ReadAllBytes(@"C:\dev\Goake\maps\aerowalk\aerowalk.map");
aerowalkRoot = Game.MapParser.Parse(aerowalkBytes);
}
[TearDown]
public void CleanUp()
{
}
[Test]
public void Perf_LoadAerowalk()
{
List<Game.MapEntity> mapEntities = new List<Game.MapEntity>(100);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
{
var root = Game.MapParser.Parse(aerowalkBytes);
mapEntities.Add(root);
}
sw.Stop();
var elapsedMs = sw.Elapsed.TotalMilliseconds;
TestContext.Out.WriteLine("Map parsing time: " + elapsedMs/100 + "ms");
}
[Test]
public void Perf_TriangulateAerowalk()
{
// warmup?
//var roott = Game.MapParser.Parse(aerowalkBytes);
List<Game.MapEntity> mapEntities = new List<Game.MapEntity>(100);
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1; i++)
{
foreach (var ent in aerowalkRoot.entities)
foreach (var brush in ent.brushes)
{
Q3MapImporter.TriangulateBrush3(brush, out Vector3[] verts);
Assert.IsTrue(verts.Length > 0);
}
}
sw.Stop();
var elapsedMs = sw.Elapsed.TotalMilliseconds;
TestContext.Out.WriteLine("Triangulation time: " + elapsedMs + "ms");
}
}
}

19
lore.md Normal file
View File

@@ -0,0 +1,19 @@
- overall tone should be fantasy-like (medieval) with hints of future/alien technology
- (year 4xxx in the future,) earth is dead, humankind is mostly dead, only ruins are left of the civilization
- previously technologically advanced civilization died thousands years ago
-
- goat-like humanoid creatures are waking up from deep sleep around the earth
- levels a mix of future and historical architecture (imagine ancients depicted artifacts but clearly technological in nature)
- old stone ruins mixed with a sparkle of futuristic tech
- crashed space ships with mostly futuristic texturing and materials
-
- weapons
- rocket launcher: technologically infused glove with engraved rune writing on it, basically a fireball thrower. possibly something everyone is carrying already but lacks power/ammo which can be found in the levels.
- nailgun: a homage to quake's super nailgun, looks like it was built in current day (early 2000) technology. has a heating element which can provide more punch to the nails making them more lethal (basic nailgun = starter weapon, ammo promotes it to super nailgun).
- crossbow: ancient looking crossbow capable of firing huge bolts that can be used to gain leverage around the levels, has a slot for a power crystal (battery) but is missing one or has a depleted one. adding power to this would increase the damage by tenfold, making it capable of instagibbing targets.
- shotgun: very powerful and inaccurate shotgun which shoots shrapnel that can ricochet from walls and still hit the target. possibly homage to flak cannon in unreal series. packs enough punch to even push the player backwards while in mid-air.
- lightning gun: ?
- melee weapon: can be almost anything from swords to hammers to laser sword and tasers. no pummel. can push back the player a bit when hitting floor or walls.
-