This forum is locked and will eventually go offline. If you have feedback to share you can find us in our Discord channel "MythoLogic Interactive" https://discord.gg/nECKnbT7gk

Forum rules

Scripting 14 - RayCast and HitTest

A smaller forum with a few tutorials how to get started with the ScriptAPI.
Forum rules
By using the forum you agree to the following rules.
Locked
User avatar
Gurt
Lead Programmer
Lead Programmer
Posts: 1887
Joined: Sun Feb 28, 2016 3:22 pm
Title: Lead programmer
Started SFD: Made it!
Location: Sweden
Gender:
Age: 36

Scripting 14 - RayCast and HitTest

Post by Gurt » Mon Jul 29, 2019 1:59 pm

Scripting 14 - RayCast and HitTest

Scripting in SFD assumes you have a fair knowledge of C#.

The following code demonstrates how to perform RayCasts in the world between two points. Available in v.1.3.0.

Code: Select all


// Example script how to RayCast in the world from a player and show some debugging information about the hit objects while testing the map in the editor.
public void OnStartup()
{
	Events.UpdateCallback.Start(OnUpdate, 0);	
}

public void OnUpdate(float ms)
{
	IUser[] users = Game.GetActiveUsers();
	IPlayer plr = (users != null && users.Length > 0 ? users[0].GetPlayer() : null); // any player instance
	
	if (plr != null) {
		Vector2 worldPos = plr.GetWorldPosition() + Vector2.UnitY * 12f;
		Vector2 worldPosEnd = worldPos + plr.AimVector * 100f;
		
		if (Game.IsEditorTest) {
			Game.DrawLine(worldPos, worldPosEnd, Color.Red);
		}
		
		// RayCastInput offers some filtering capabilities, for now just filter on everything with a set CategoryBit (effectively ignoring background objects).
		RayCastInput rci = new RayCastInput() { IncludeOverlap = true, MaskBits = 0xFFFF, FilterOnMaskBits = true };
		// You can also filter on specific types. If you only want to raycast players you would add the IPlayer type to the Types array property: rci.Types = new Type[1] { typeof(IPlayer) };
		RayCastResult[] results = Game.RayCast(worldPos, worldPosEnd, rci);
		foreach(RayCastResult result in results)	{
		
			if (Game.IsEditorTest) {
				Game.DrawCircle(result.Position, 1f, Color.Yellow);
				Game.DrawLine(result.Position, result.Position + result.Normal * 5f, Color.Yellow);
				Game.DrawArea(result.HitObject.GetAABB(), Color.Yellow);
				Game.DrawText(result.HitObject.UniqueID.ToString(), result.Position, Color.Yellow);
			}
			
			// Destroy nearby glass that the player is looking at
			if (result.Fraction < 0.3f && result.HitObject.Name.IndexOf("glass", StringComparison.OrdinalIgnoreCase) >= 0) {
				result.HitObject.Destroy();
			}
			
		}
	}

}
To perform a HitTest on any IObject simply use the bool IObject.HitTest(Vector2 position) function. You can also perform RayCasts on individual IObjects.

Code: Select all

IObject obj = ... // any IObject instance

if (obj.HitTest(Vector2.Zero)) {
	// Object overlaps the center of the world
}
Vector2 pA = Vector2.Zero;
Vector2 pB = Vector2.UnitX * 100f;
if (obj.RayCast(pA, pB, true).Hit) {
	// Object hit between pA and pB
}


ScriptAPI Implementation for RayCast and HitTest:
► Show Spoiler
6 x
Gurt

Locked