Players in games have been obliged to jump on moving platforms since the dawn of gaming. Even with the incredibly advanced games of today, it's not uncommon to encounter this most primitive game mechanic albeit with better graphics. There's also a popular retro genre that calls for the same, not the least for mobile games.
How do we do that in jMonkeyEngine? One way is, of course, to simply use move or setLocalTranslation
on geometries. This can quickly get complex if we want to make sequenced paths. A better option is to use MotionPaths and MotionEvents.
A MotionPath
object is basically a set of waypoints through which an object will move in an interpolated way meaning the movement will be smooth. The MotionEvent
is the control class defining when and how the object should move along the MotionPath
object. It can define how an object should be rotated along the path and if and how the path should be cycled through.
In this recipe, we'll check out how to use them for a game, which could be a side-scrolling 2D game, but the same principles can be used to create advanced cinematic cutscenes.
Let's begin by creating a platform object to move, by performing the following steps:
Geometry
called platform
and apply the Unshaded
material to it, as shown in the following code:platform = new Geometry("Platform", new Box(1f, 0.1f, 1f)); platform.setMaterial(new Material(assetManager, "MatDefs/Misc/Unshaded.j3md"));
platform
object to rootNode
.MotionPath
object called path
.for(inti = 0 ; i< 8; i++){ path.addWayPoint(new Vector3f(0, FastMath.sin(FastMath.QUARTER_PI * i) * 10f, FastMath.cos(FastMath.QUARTER_PI * i) * 10f)); }
path.setCycle(true)
to make it connect the first and last waypoints.MotionEvent
called event
and supply platform
and path
in the constructor.event.setInitialDuration(10f)
and setSpeed(1f)
.event.setLoopMode(LoopMode.Loop)
.path.enableDebugShape(assetManager, rootNode);
event.play()
to start the event!The for
loop creates eight waypoints along a circle at 45 degrees distance from each other. However, to make a complete circle the first and last waypoints need to be connected or the path will stop at the final one. This is why setCycle(true)
must be set. This is treated as the ninth waypoint at the same position as the first.
MotionEvent's initialDuration
is the time it should take to complete the path. The speed defines the factor at which the initialDuration
should be completed. So, setting the speed to 2f will halve the actual time it takes for the object to complete its movement. The loopMode
, not surprisingly, defines whether the object should stop once it has completed the path, or continue. There's also an option to make it go back the same path again with LoopMode.Cycle
. This is not related to MotionPath's setCycle
method.
While this recipe doesn't explore the option, it's possible to have the spatial in MotionPath
perform various types of rotation. By default, no rotation will be applied. By calling setDirectionType
it is possible to, for example, let the object follow the path's rotation (face the direction of the path) or rotate by a fixed amount or always face a certain point. Some of the direction types require a rotation to be supplied with the setRotation
method.
Now, the object is moving along its given path and we can add several platforms moving in different patterns. Let's say we want something to happen once a platform reaches the end of its path. Maybe it should start the next one or trigger one of our ScriptObjects from the previous recipes.
In that case, we can use MotionPathListener
. This is an interface with a callback method called onWayPointReached
, which will be called every time the path passes a waypoint. It will supply both the MotionEvent
and the index
of the waypoint. If we want to trigger something at the end of the path, it might look like the following code snippet:
path.addListener(new MotionPathListener() { public void onWayPointReach(MotionEvent control, intwayPointIndex) { if (path.getNbWayPoints() == wayPointIndex + 1) { nextMotionEvent.play(); } } });
3.135.191.86