Compare commits

..

4 Commits

Author SHA1 Message Date
de41bbeb8d some other tests
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 20s
Create tag and build when new code gets to main / Export (push) Successful in 5m5s
2026-02-23 15:22:57 +01:00
a4873f183c back with more tests 2026-02-22 17:25:45 +01:00
d37ae8d26c remove tests from ci for now because the loading of the runtime is broken and 2dog might change that, but when it's available 2026-02-22 17:24:12 +01:00
5227fedf15 trying to fix CI
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 6m2s
Create tag and build when new code gets to main / Test (push) Failing after 8m46s
2026-02-22 17:13:51 +01:00
24 changed files with 758 additions and 34 deletions

View File

@@ -9,6 +9,7 @@ on:
env:
GODOT_VERSION: 4.6
DOTNET_VERSION: 'net9.0'
GAME_NAME: MovementTests
ITCHIO_USERNAME: Minimata
ITCHIO_GAMEID: MovementTests
@@ -38,33 +39,47 @@ jobs:
INITIAL_VERSION: 0.1.0
DEFAULT_BUMP: patch
Test:
runs-on: godot
# env:
# RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache
steps:
- name: Checkout with LFS
uses: https://git.game-dev.space/minimata/checkout-with-lfs.git@main
- name: Run tests
uses: godot-gdunit-labs/gdUnit4-action@v1
with:
godot-version: ${GODOT_VERSION}
godot-net: true
godot-force-mono: true
dotnet-version: 'net9.0'
paths: |
res://tests/
publish-report: false
upload-report: false
console-verbosity: 'normal'
arguments: "--verbose --headless --import"
- name: Upload test report
uses: actions/upload-artifact@v3-node20
with:
name: Test Report
path: ${{ github.workspace }}/reports/test-result.html
# Test:
# runs-on: godot
## env:
## RUNNER_TOOL_CACHE: /toolcache # Runner Tool Cache
# steps:
# - name: Checkout with LFS
# uses: https://git.game-dev.space/minimata/checkout-with-lfs.git@main
#
# - name: Setup Godot
# id: setup-godot
# uses: https://git.game-dev.space/minimata/setup-godot.git@main
# with:
# godot-version: ${GODOT_VERSION}
# dotnet-version: ${DOTNET_VERSION}
#
# - name: Run C# Tests
# env:
# GODOT_BIN: ${{ steps.setup-godot.outputs.godot_bin }}
# shell: bash
# run: |
# dotnet test --no-build --settings .runsettings --results-directory ./reports --logger "console;verbosity=normal" --logger "trx;LogFileName=results.xml" -- GdUnit4.Parameters="--verbose --headless --import"
#
## - name: Run tests
## uses: godot-gdunit-labs/gdUnit4-action@v1
## with:
## godot-version: ${GODOT_VERSION}
## godot-net: true
## godot-force-mono: true
## dotnet-version: ${DOTNET_VERSION}
## paths: |
## res://tests/
## publish-report: false
## upload-report: false
## console-verbosity: 'normal'
## arguments: "--verbose --headless --import"
#
# - name: Upload test report
# uses: actions/upload-artifact@v3-node20
# with:
# name: Test Report
# path: ${{ github.workspace }}/reports/test-result.html
Export:
runs-on: godot
@@ -79,8 +94,8 @@ jobs:
id: setup-godot
uses: https://git.game-dev.space/minimata/setup-godot.git@main
with:
godot-version: '4.6'
dotnet-version: 'net9.0'
godot-version: ${GODOT_VERSION}
dotnet-version: ${DOTNET_VERSION}
- name: Remove GDUnit addon
run: |

7
.gitignore vendored
View File

@@ -16,3 +16,10 @@
*.translation
.output.txt
*.suo
*.user
_ReSharper.*
bin
obj
packages

View File

@@ -0,0 +1,101 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.interfaces;
using Movementtests.systems.damage;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class DamageComponentUnitTest
{
[TestCase]
public void DamageModifierAppliesWhenTypeMatches()
{
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var modifier = new RDamageModifier(EDamageTypes.Normal, 2.0f);
var signalTriggered = false;
modifier.DamageTaken += (_, _) => signalTriggered = true;
var result = modifier.TakeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(20.0f);
AssertBool(signalTriggered).IsTrue();
}
[TestCase]
public void DamageModifierIgnoresWhenTypeDifferent()
{
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var modifier = new RDamageModifier(EDamageTypes.Fire, 3.0f);
var signalTriggered = false;
modifier.DamageTaken += (_, _) => signalTriggered = true;
var result = modifier.TakeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(0.0f);
AssertBool(signalTriggered).IsFalse(); // No damage actually taken
}
[TestCase]
public void DamageableSumsAllModifiers()
{
var mod1 = new RDamageModifier(EDamageTypes.Normal, 1.0f);
var mod2 = new RDamageModifier(EDamageTypes.Normal, 0.5f);
var damageable = new CDamageable();
damageable.DamageModifiers = new[] { mod1, mod2 };
var signalTriggered = false;
damageable.DamageTaken += (_, _) => signalTriggered = true;
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var result = damageable.TakeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(15.0f);
AssertBool(signalTriggered).IsTrue();
}
[TestCase]
public void ComputeDamageModifierAppliesWhenTypeMatches()
{
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var modifier = new RDamageModifier(EDamageTypes.Normal, 2.0f);
var signalTriggered = false;
modifier.DamageTaken += (_, _) => signalTriggered = true;
var result = modifier.ComputeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(20.0f);
AssertBool(signalTriggered).IsFalse();
}
[TestCase]
public void ComputeDamageModifierIgnoresWhenTypeDifferent()
{
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var modifier = new RDamageModifier(EDamageTypes.Fire, 3.0f);
var signalTriggered = false;
modifier.DamageTaken += (_, _) => signalTriggered = true;
var result = modifier.ComputeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(0.0f);
AssertBool(signalTriggered).IsFalse();
}
[TestCase]
public void ComputeDamageableSumsAllModifiers()
{
var mod1 = new RDamageModifier(EDamageTypes.Normal, 1.0f);
var mod2 = new RDamageModifier(EDamageTypes.Normal, 0.5f);
var cDamageable = new CDamageable();
cDamageable.DamageModifiers = new[] { mod1, mod2 };
var signalTriggered = false;
cDamageable.DamageTaken += (_, _) => signalTriggered = true;
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var result = cDamageable.ComputeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(15.0f);
AssertBool(signalTriggered).IsFalse();
}
}

View File

@@ -0,0 +1 @@
uid://db6rva7uccppc

View File

@@ -0,0 +1,55 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.interfaces;
using Movementtests.systems.damage;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class HealthComponentUnitTest
{
[TestCase]
public void ReadyInitializesCurrentHealth()
{
var cHealth = new CHealth();
cHealth.RHealth = new RHealth(150.0f);
cHealth._Ready();
AssertFloat(cHealth.CurrentHealth).IsEqual(150.0f);
}
[TestCase]
public void ReduceHealthDecreasesAndDoesNotDeplete()
{
var cHealth = new CHealth();
cHealth.RHealth = new RHealth(100.0f);
cHealth.CurrentHealth = 100.0f;
var damage = new DamageRecord(Vector3.Zero, new RDamage(25.0f, EDamageTypes.Normal));
var record = cHealth.ReduceHealth(source: null!, damageRecord: damage);
AssertFloat(cHealth.CurrentHealth).IsEqual(75.0f);
AssertFloat(record.CurrentHealth).IsEqual(75.0f);
AssertFloat(record.PreviousHealth).IsEqual(100.0f);
AssertFloat(record.MaxHealth).IsEqual(100.0f);
}
[TestCase]
public void ReduceHealthTriggersDepletionToZero()
{
var cHealth = new CHealth();
cHealth.RHealth = new RHealth(50.0f);
cHealth.CurrentHealth = 50.0f;
bool depleted = false;
cHealth.HealthDepleted += _ => depleted = true;
var damage = new DamageRecord(Vector3.Zero, new RDamage(100.0f, EDamageTypes.Normal));
var record = cHealth.ReduceHealth(source: null!, damageRecord: damage);
AssertBool(depleted).IsTrue();
AssertFloat(cHealth.CurrentHealth).IsEqual(0.0f);
AssertFloat(record.CurrentHealth).IsEqual(-50.0f);
AssertFloat(record.MaxHealth).IsEqual(50.0f);
}
}

View File

@@ -0,0 +1 @@
uid://bd52i51hncgmf

View File

@@ -0,0 +1,32 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.interfaces;
using Movementtests.systems.damage;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class KnockbackComponentUnitTest
{
[TestCase]
public void RegisterAndComputeKnockback()
{
var cKnock = new CKnockback();
cKnock.RKnockback = new RKnockback(2.0f);
cKnock.GlobalPosition = Vector3.Zero;
var damage = new DamageRecord(new Vector3(10, 0, 0), new RDamage(0, EDamageTypes.Normal));
var record = new KnockbackRecord(damage, 1.5f);
cKnock.RegisterKnockback(record);
var force = cKnock.ComputeKnockback();
// Direction from source(10,0,0) to target(0,0,0) is (-1,0,0), scaled by modifier(2) and multiplier(1.5) => (-3,0,0)
AssertVector(force).IsEqual(new Vector3(-3, 0, 0));
// Second call returns zero since internal state resets
var second = cKnock.ComputeKnockback();
AssertVector(second).IsEqual(Vector3.Zero);
}
}

View File

@@ -0,0 +1 @@
uid://bv0eionbgbig5

View File

@@ -0,0 +1,32 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.interfaces;
using Movementtests.scenes.movement;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class MovementSystemUnitTest
{
[TestCase]
public void GroundedMovementAcceleratesAndAppliesGravity()
{
var move = new CGroundedMovement();
move.RMovement = new RMovement(speed: 10.0f, acceleration: 1.0f, gravityModifier: 0.5f, targetHeight: 0.0f);
move.WallInFrontRayCast = new RayCast3D();
//move.GlobalPosition = Vector3.Zero;
var inputs = new MovementInputs(
Velocity: Vector3.Zero,
TargetLocation: new Vector3(10, 0, 0),
isOnFloor: false,
gravity: Vector3.Down * 9.8f,
delta: 1.0
);
var v = move.ComputeVelocity(inputs);
AssertVector(v).IsEqualApprox(new Vector3(10, -4.9f, 0), new Vector3(0.001f, 0.001f, 0.001f));
}
}

View File

@@ -0,0 +1 @@
uid://cofj5s4x74ay

View File

@@ -0,0 +1,30 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.interfaces;
using Movementtests.systems.damage;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class EnemyUnitTest
{
[TestCase]
public void ComputeDamageNoComponent()
{
var enemy = new Enemy();
var input = new DamageRecord(Vector3.Zero, new RDamage(10.0f, EDamageTypes.Normal));
var result = enemy.ComputeDamage(input);
AssertFloat(result.Damage.DamageDealt).IsEqual(0.0f);
}
[TestCase]
public void Unstun()
{
var enemy = new Enemy();
enemy.IsStunned = true;
enemy.Unstun();
AssertBool(enemy.IsStunned).IsFalse();
}
}

View File

@@ -0,0 +1 @@
uid://cojxgcs6xqqoq

View File

@@ -0,0 +1,55 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.systems;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class DashSystemUnitTest
{
private DashSystem _dashSystem;
[BeforeTest]
public void SetupTest()
{
_dashSystem = new DashSystem();
_dashSystem.DashCast3D = new ShapeCast3D();
_dashSystem.AddChild(_dashSystem.DashCast3D);
_dashSystem._dashCastDrop = new ShapeCast3D();
_dashSystem.AddChild(_dashSystem._dashCastDrop);
_dashSystem._dashTarget = new MeshInstance3D();
_dashSystem.AddChild(_dashSystem._dashTarget);
_dashSystem._dashDropIndicator = new MeshInstance3D();
_dashSystem.AddChild(_dashSystem._dashDropIndicator);
_dashSystem._dashDropLocationIndicator = new MeshInstance3D();
_dashSystem.AddChild(_dashSystem._dashDropLocationIndicator);
}
[AfterTest]
public void CleanupTest()
{
_dashSystem?.Free();
}
[TestCase]
public void TestStopPreparingDash()
{
_dashSystem.CanDashThroughTarget = true;
_dashSystem._dashTarget.Visible = true;
_dashSystem._dashDropIndicator.Visible = true;
_dashSystem._dashDropLocationIndicator.Visible = true;
_dashSystem.StopPreparingDash();
AssertBool(_dashSystem.CanDashThroughTarget).IsFalse();
AssertBool(_dashSystem._dashTarget.Visible).IsFalse();
AssertBool(_dashSystem._dashDropIndicator.Visible).IsFalse();
AssertBool(_dashSystem._dashDropLocationIndicator.Visible).IsFalse();
}
}

View File

@@ -0,0 +1 @@
uid://pv570go4cxws

View File

@@ -0,0 +1,91 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.systems;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class HeadSystemUnitTest
{
private HeadSystem _head;
[BeforeTest]
public void SetupTest()
{
_head = new HeadSystem();
_head._camera = new Camera3D();
_head.AddChild(_head._camera);
_head._cameraAnchor = new Marker3D();
_head.AddChild(_head._cameraAnchor);
_head._fpRig = new Node3D();
_head.AddChild(_head._fpRig);
_head._fpDisplacedRig = new Node3D();
_head.AddChild(_head._fpDisplacedRig);
}
[AfterTest]
public void CleanupTest()
{
_head?.Free();
}
[TestCase]
public void TestResetHeadBobbing()
{
_head._bobbingAccumulator = 10.0f;
_head.ResetHeadBobbing();
AssertFloat(_head._bobbingAccumulator).IsEqual(0.0f);
}
[TestCase]
public void TestComputeHowMuchInputForward()
{
Vector3 forwardInput = new Vector3(0, 0, -1);
AssertFloat(_head.ComputeHowMuchInputForward(forwardInput)).IsEqual(1.0f);
Vector3 backwardInput = new Vector3(0, 0, 1);
AssertFloat(_head.ComputeHowMuchInputForward(backwardInput)).IsEqual(-1.0f);
}
[TestCase]
public void TestComputeHowMuchInputSideways()
{
Vector3 rightInput = new Vector3(1, 0, 0);
AssertFloat(_head.ComputeHowMuchInputSideways(rightInput)).IsEqual(1.0f);
Vector3 leftInput = new Vector3(-1, 0, 0);
AssertFloat(_head.ComputeHowMuchInputSideways(leftInput)).IsEqual(-1.0f);
}
[TestCase]
public void TestGetForwardHorizontalVector()
{
Vector3 forward = _head.GetForwardHorizontalVector();
AssertVector(forward).IsEqualApprox(Vector3.Back, new Vector3(0.001f, 0.001f, 0.001f));
}
[TestCase]
public void TestLookAroundRotation()
{
var inputs = new HeadSystem.CameraParameters(
Delta: 0.016,
LookDir: new Vector2(1, 0),
PlayerInput: Vector3.Zero,
PlayerVelocity: Vector3.Zero,
WallContactPoint: Vector3.Zero,
SensitivitMultiplier: 1.0f,
WithCameraJitter: false,
WithCameraBobbing: false,
BobbingMultiplier: 1.0f,
FovMultiplier: 1.0f
);
float initialY = _head.Rotation.Y;
_head.LookAround(inputs);
AssertFloat(_head.Rotation.Y).IsEqual(initialY + 1.0f);
}
}

View File

@@ -0,0 +1 @@
uid://bp0xn8k3dmfkg

View File

@@ -0,0 +1,149 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.interfaces;
using Movementtests.systems.damage;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class PlayerControllerUnitTest
{
private PlayerController _player;
[BeforeTest]
public void SetupTest()
{
_player = new PlayerController();
_player._targetSpeed = 7.0f;
_player._gravity = 9.8f;
var rHealth = new RHealth(100.0f);
_player.RHealth = rHealth;
_player.CHealth = new CHealth { RHealth = rHealth, CurrentHealth = 100.0f };
}
[AfterTest]
public void CleanupTest()
{
_player?.Free();
}
[TestCase]
public void TestCalculateGravityForce()
{
_player.Weight = 3.0f;
// gravity is 9.8f
AssertFloat(_player.CalculateGravityForce()).IsEqualApprox(29.4f, 0.001f);
}
[TestCase]
public void TestIsPlayerInputtingForward()
{
// Test Keyboard Input
_player.InputDeviceChanged(false);
_player.OnInputMoveKeyboard(Vector3.Forward);
AssertBool(_player.IsPlayerInputtingForward()).IsTrue();
_player.OnInputMoveKeyboard(Vector3.Back);
AssertBool(_player.IsPlayerInputtingForward()).IsFalse();
// Test Gamepad Input
_player.InputDeviceChanged(true);
_player.OnInputMove(new Vector3(0, 0, -1));
AssertBool(_player.IsPlayerInputtingForward()).IsTrue();
}
[TestCase]
public void TestSetVerticalVelocity()
{
_player.Velocity = new Vector3(1, 0, 2);
_player.SetVerticalVelocity(5.0f);
AssertVector(_player.Velocity).IsEqual(new Vector3(1, 5, 2));
}
[TestCase]
public void TestComputeHVelocityGround()
{
_player.Velocity = Vector3.Zero;
_player.AccelerationFloor = 10.0f;
float delta = 0.1f;
Vector3 newVelocity = _player.ComputeHVelocity(delta, _player.AccelerationFloor, _player.DecelerationFloor, Vector3.Forward);
AssertVector(newVelocity).IsEqual(new Vector3(0, 0, -7.0f));
}
[TestCase]
public void TestComputeHVelocityAir()
{
_player.Velocity = new Vector3(5, 0, 0);
_player.AccelerationAir = 2.0f;
_player.DecelerationAir = 2.0f;
float delta = 0.5f;
Vector3 newVelocity = _player.ComputeHVelocity(delta, _player.AccelerationAir, _player.DecelerationAir, Vector3.Zero);
AssertVector(newVelocity).IsEqual(Vector3.Zero);
}
[TestCase]
public void TestReduceHealth()
{
var damageRecord = new DamageRecord(Vector3.Zero, new RDamage(25.0f, EDamageTypes.Normal));
_player.ReduceHealth(_player, damageRecord);
AssertFloat(_player.CHealth.CurrentHealth).IsEqual(75.0f);
}
[TestCase]
public void TestEmpoweredActionsLeft()
{
var mockUi = new PlayerUi();
var dashIcons = new TextureRect[3] { new TextureRect(), new TextureRect(), new TextureRect() };
mockUi._dashIcons = dashIcons;
_player.PlayerUi = mockUi;
_player.EmpoweredActionsLeft = 2;
AssertInt(_player.EmpoweredActionsLeft).IsEqual(2);
AssertBool(dashIcons[0].Visible).IsTrue();
AssertBool(dashIcons[1].Visible).IsTrue();
AssertBool(dashIcons[2].Visible).IsFalse();
}
[TestCase]
public void TestDashCooldownTimeout()
{
_player._canDash = false;
_player.DashCooldownTimeout();
AssertBool(_player._canDash).IsTrue();
}
[TestCase]
public void TestGetInputLocalHDirection()
{
_player.InputDeviceChanged(false);
_player.OnInputMoveKeyboard(new Vector3(1, 0, 1));
Vector3 expected = new Vector3(1, 0, 1).Normalized();
AssertVector(_player.GetInputLocalHDirection()).IsEqualApprox(expected, new Vector3(0.001f, 0.001f, 0.001f));
}
[TestCase]
public void TestComputeKnockback()
{
var cKnockback = new CKnockback();
cKnockback.RKnockback = new RKnockback(10.0f);
_player.CKnockback = cKnockback;
var damageRecord = new DamageRecord(new Vector3(10, 0, 0), new RDamage(0, EDamageTypes.Normal));
var knockbackRecord = new KnockbackRecord(damageRecord, 1.0f);
_player.GlobalPosition = Vector3.Zero;
cKnockback.GlobalPosition = Vector3.Zero;
_player.RegisterKnockback(knockbackRecord);
Vector3 knockback = cKnockback.ComputeKnockback();
AssertVector(knockback).IsEqual(new Vector3(-10, 0, 0));
}
}

View File

@@ -0,0 +1 @@
uid://kmphtu0ovixi

View File

@@ -0,0 +1,51 @@
using Godot;
using GdUnit4;
using static GdUnit4.Assertions;
using Movementtests.systems;
using Movementtests.systems.damage;
namespace Movementtests.tests;
[TestSuite, RequireGodotRuntime]
public class WeaponSystemUnitTest
{
private WeaponSystem _weapon;
[BeforeTest]
public void SetupTest()
{
_weapon = new WeaponSystem();
_weapon.RDamage = new RDamage(5.0f, EDamageTypes.Normal);
_weapon.WeaponMesh = new MeshInstance3D();
_weapon.AddChild(_weapon.WeaponMesh);
_weapon.WeaponLocationIndicator = new MeshInstance3D();
_weapon.AddChild(_weapon.WeaponLocationIndicator);
}
[AfterTest]
public void CleanupTest()
{
_weapon?.Free();
}
[TestCase]
public void TestWeaponLeftAndBackVisibility()
{
_weapon.Visible = false;
_weapon.WeaponLeft();
AssertBool(_weapon.Visible).IsTrue();
_weapon.WeaponBack();
AssertBool(_weapon.Visible).IsFalse();
}
[TestCase]
public void TestThrowWeaponOnCurveSetsUnfrozen()
{
_weapon.Freeze = true;
_weapon.ThrowWeaponOnCurve();
AssertBool(_weapon.Freeze).IsFalse();
}
}

View File

@@ -0,0 +1 @@
uid://vkv8aderakcb

View File

@@ -0,0 +1,50 @@
using System.Threading.Tasks;
using Godot;
using GodotStateCharts;
namespace Movementtests.tests;
using GdUnit4;
using static GdUnit4.Assertions;
[TestSuite, RequireGodotRuntime]
public class PlayerInteractionsTest
{
private ISceneRunner _runner;
private Node _scene;
private PlayerController _player;
private readonly float _tolerance = 0.01f;
private readonly Vector3 _vectorTolerance = new Vector3(0.01f, 0.01f, 0.01f);
[BeforeTest]
public void SetupTest()
{
_runner = ISceneRunner.Load("res://tests/player/interactions/player_interactions_scene.tscn");
_scene = _runner.Scene()!;
var player = _scene.FindChild("Player") as PlayerController;
_player = player!;
}
[AfterTest]
public void CleanupTest() {}
[TestCase("BaseLocation")]
public async Task PlayerMoveForward(string markerName)
{
var marker = _scene.FindChild(markerName) as Marker3D;
AssertObject(marker).IsNotNull();
_player.GlobalPosition = marker!.GlobalPosition;
await _runner.AwaitIdleFrame();
var startPos = _player.GlobalPosition;
_runner.SimulateKeyPress(Key.W);
await _runner.AwaitMillis(300);
_runner.SimulateKeyRelease(Key.W);
var endPos = _player.GlobalPosition;
var direction = startPos.DirectionTo(endPos);
AssertVector(direction).IsEqualApprox(Vector3.Forward, _vectorTolerance);
}
}

View File

@@ -0,0 +1 @@
uid://denedm5b8rmhh

View File

@@ -0,0 +1,35 @@
[gd_scene format=3 uid="uid://l0lflvsjbyvs"]
[ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/materials/greybox/m_greybox.tres" id="1_dv0re"]
[ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://scenes/player_controller/PlayerController.tscn" id="2_52d52"]
[node name="PlayerMovementScene" type="Node3D" unique_id=231040688]
[node name="CSGCombiner3D" type="CSGCombiner3D" parent="." unique_id=241909240]
use_collision = true
collision_layer = 256
collision_mask = 65553
[node name="Ground" type="CSGBox3D" parent="CSGCombiner3D" unique_id=432200143]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, -0.5, -3.25)
use_collision = true
collision_layer = 256
collision_mask = 65553
size = Vector3(1000, 1, 1000)
material = ExtResource("1_dv0re")
[node name="Ground2" type="CSGBox3D" parent="CSGCombiner3D" unique_id=854660236]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.75, 0.5, -1.75)
use_collision = true
collision_layer = 256
collision_mask = 65553
size = Vector3(1.5, 1, 1.5)
material = ExtResource("1_dv0re")
[node name="Player" parent="." unique_id=709076448 instance=ExtResource("2_52d52")]
TutorialDone = true
[node name="BaseLocation" type="Marker3D" parent="." unique_id=1793710692]
[node name="MantleLocation1" type="Marker3D" parent="." unique_id=550080845]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.75, 0, 0)

View File

@@ -1,5 +1,6 @@
using System.Threading.Tasks;
using Godot;
using GodotStateCharts;
namespace Movementtests.tests;
@@ -44,7 +45,7 @@ public class PlayerMovementTest
var startPos = _player.GlobalPosition;
_runner.SimulateKeyPress(Key.W);
await _runner.AwaitMillis(300);
await _runner.AwaitMillis(100);
_runner.SimulateKeyRelease(Key.W);
var endPos = _player.GlobalPosition;
@@ -63,17 +64,24 @@ public class PlayerMovementTest
var startPos = _player.GlobalPosition;
_runner.SimulateKeyPress(Key.Space);
await _runner.AwaitMillis(100);
_runner.SimulateKeyRelease(Key.Space);
await _runner.AwaitIdleFrame();
var jumping = StateChartState.Of(_player.GetNode("StateChart/Root/Movement/Jump"));
AssertBool(jumping.Active).IsTrue();
_runner.SimulateKeyRelease(Key.Space);
await _runner.AwaitIdleFrame();
var endPos = _player.GlobalPosition;
var direction = startPos.DirectionTo(endPos);
AssertVector(direction).IsEqualApprox(Vector3.Up, _vectorTolerance);
AssertVector(_player.Velocity.Normalized()).IsEqualApprox(Vector3.Up, _vectorTolerance);
await _runner.AwaitMillis(500);
await _runner.AwaitMillis(600);
endPos = _player.GlobalPosition;
AssertVector(endPos - startPos).IsEqualApprox(Vector3.Zero, _vectorTolerance);
var grounded = StateChartState.Of(_player.GetNode("StateChart/Root/Movement/Grounded"));
AssertBool(grounded.Active).IsTrue();
}
[TestCase("MantleLocation1")]
@@ -88,6 +96,9 @@ public class PlayerMovementTest
_runner.SimulateKeyPress(Key.Space);
await _runner.AwaitMillis(100);
var mantling = StateChartState.Of(_player.GetNode("StateChart/Root/Movement/Mantling"));
AssertBool(mantling.Active).IsTrue();
_runner.SimulateKeyRelease(Key.Space);
await _runner.AwaitMillis(500);