Dear forum users! In compliance with the new European GDPR regulations, we'd just like to inform you that if you have an account, your email address is stored in our database. We do not share your information with third parties, and your email address and password are encrypted for security reasons.

New to the forum? Say hello in this topic! Also make sure to read the 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.
Post Reply
User avatar
Gurt
Lead Programmer
Lead Programmer
Posts: 1884
Joined: Sun Feb 28, 2016 3:22 pm
Title: Lead programmer
Started SFD: Made it!
Location: Sweden
Gender:
Age: 34

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

Post Reply