[v1.0] Fully 3D moving platform

Post your example zscripts/ACS scripts/etc here.
Forum rules
The Projects forums are only for projects. If you are asking questions about a project, either find that project's thread, or start a thread in the General section instead.

Got a cool project idea but nothing else? Put it in the project ideas thread instead!

Projects for any Doom-based engine (especially 3DGE) are perfectly acceptable here too.

Please read the full rules for more details.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

[v1.0] Fully 3D moving platform

Post by Apeirogon »

Well, as title say. One of the realization of fully 3D platform, which uses specific actor as platform.
A little video demonstration

Github
https://github.com/MekBoss/fully_3d_platform
How to download it from Github
viewtopic.php?f=39&t=70332

It have some "advanced" features, for now only one. If you jump down from the platform you save you momentum from movement on the platform. Speed of the platform have influence on your speed when you jump down from it, in other words. Turn on in example for testing purpose.

If someone have some tips for improvement, feel free to say it here or on Github.
Last edited by Apeirogon on Wed Oct 21, 2020 1:01 pm, edited 2 times in total.
User avatar
AFADoomer
Posts: 1346
Joined: Tue Jul 15, 2003 4:18 pm

Re: [Proof of concept] Fully 3D moving platform

Post by AFADoomer »

Nice!

Not sure if this will help at all, but here's a stripped down version of my generic moving platforms that I put together a while back:

Code: Select all

// Moving Platforms
class Platform : Actor
{
	Array<Actor> touchers;
	Vector3[64] offsets;

	double moveangle, moved, user_movedist;

	Default
	{
		Radius 46;
		Height 12;
		MaxStepHeight 0;
		Speed 4;
		+CANPASS
		+DONTTHRUST
		+NOGRAVITY
		+SOLID
	}

	States
	{
		Spawn:
			MDLA A -1;
			Stop;
		Active:
			MDLA A -1;
			Stop;
		Inactive:
			MDLA A -1;
			Stop;
	}

	override void Touch(Actor toucher)
	{
		if (toucher == self || toucher.bNoGravity || toucher is "Platform" || toucher.pos.z == toucher.floorz) { return; }
		if (toucher.pos.z > pos.z + 32.0 || toucher.pos.z < pos.z - 16) { return; }
		if (touchers.Find(toucher) == touchers.Size()) { touchers.Push(toucher); }
	}

	override void PostBeginPlay()
	{
		moveangle = angle;

		bDormant = SpawnFlags & MTF_DORMANT;

		if (bDormant) { Deactivate(self); }
		else { Activate(self); }

		Super.PostBeginPlay();
	}

	override void Tick()
	{
		if (IsFrozen() || bDormant)
		{
			Actor.Tick();

			return;
		}

		CheckTouchers();

		Vector2 newpos = pos.xy + RotateVector((Speed, 0), moveangle);
		moved += Speed;

		if (CheckMove(newpos, 0) && (user_movedist <= 0 || moved <= user_movedist))
		{
			SetOrigin((newpos, pos.z), true);

			MatchMovement();
			Actor.Tick();
		}
		else
		{
			moveangle = (moveangle + 180) % 360;
			moved = 0;
			Actor.Tick();
		}
	}

	override bool CanCollideWith(Actor other, bool passive)
	{
		if (other.player || other.bIsMonster)
		{
			Touch(other);
			return true;
		}

		return true;
	}

	void CheckTouchers()
	{
		for (int i = 0; i < min(touchers.Size(), 64); i++)
		{
			if (touchers[i])
			{
				if (
					Distance3D(touchers[i]) > (Radius + touchers[i].radius) * 1.4 ||
					touchers[i].pos.z < pos.z + height ||
					!touchers[i].bOnMobj
				)
				{
					touchers.Delete(i);
					offsets[i] = (0, 0, 0);
				}
				else { offsets[i] = touchers[i].pos - pos; }
			}
			else { touchers.Delete(i); touchers.ShrinkToFit(); }
		}
	}

	void MatchMovement()
	{
		for (int i = 0; i < min(touchers.Size(), 64); i++)
		{
			if (
				touchers[i] && 
				(
					(Distance2D(touchers[i]) < (Radius + touchers[i].radius) * 1.4 && touchers[i].pos.z == pos.z + height) ||
					absangle(angle, AngleTo(touchers[i])) < 45 ||
					((touchers[i].bOnMobj || (touchers[i].player && touchers[i].player.jumptics == 0)) && Distance3D(touchers[i]) < radius * 2)
				) &&
				offsets[i] != (0, 0, 0)
			)
			{
				if (touchers[i].TryMove(pos.xy + offsets[i].xy, true))
				{
					touchers[i].SetOrigin(pos + offsets[i], true);
				}
			}
		}
	}

	override void Activate(Actor activator)
	{
		bDormant = false;
		Super.Activate(activator);
	}

	override void Deactivate(Actor activator)
	{
		bDormant = true;
		Super.Deactivate(activator);
	}
}
These handle 'bouncing' back and forth between endpoints (or a user-defined max move distance), and take their movement angle and speed from the actor. The effect works best with a 3D model for the platform. This particular one only moves on the x/y axis, but I have another variant that follow the path of a tracer, so can move on any axis.

You could also make the platform able to carry other actors by using a BlockThingsIterator to find touching objects, instead of just CanCollideWith.
User avatar
Enjay
 
 
Posts: 27679
Joined: Tue Jul 15, 2003 4:58 pm
Location: Scotland

Re: [Proof of concept] Fully 3D moving platform

Post by Enjay »

Very nice, very smooth. I can see that it has some issues (for example, I rode the platform right to the end and got stuck in the wall) but the travelling part of the ride seemed very solid.
User avatar
Apeirogon
Posts: 1606
Joined: Mon Jun 12, 2017 12:57 am

Re: [v1.0] Fully 3D moving platform

Post by Apeirogon »

Now platform should not push player through walls into the void, I added the necessary restrictions.
Also was added basic physics. Now you store you momentum from moving on platform when you jump down. But it easily can be turned off, since its only a function flag.

Return to “Script Library”