-
Notifications
You must be signed in to change notification settings - Fork 4
Advanced Animation
In this article you will learn how to combine animation properties, give them labels and trigger them via coaster trigger. Don´t get afraid. Its easily realizable with NoLimitsFramework. First I have to explain couple of things before we start. Its important to understand the layers behind the "scene" before using these techniques in the proper way.
I guess you already read the Basic animation wiki article . You should now be familiar with the com.nolimitsframework.animation.Animation class. The animation class contains transition for ONE scenery object or element inside of an object. Let me give you an example.
Imagine, we have a scenery object called House. House contains two doors. You want to define an "open door" and a "close door" animation. You have to instantiate two Animation classes:
Animation Door1 = new Animation("Scenery: House, Door1");
Animation Door2 = new Animation("Scenery: House, Door2");
Now you can define transitions for booth doors to open and close the same way we have learned in the Basic animation wiki article.
Let us define the close and open door transition. Important: Since we have 2 different door animation instances, we have to define the transition twice. Let us think about what happens if a door is opening. Yeah, well, the door is rotating on its Y-axis for 90 degrees. Lets do that. I guess, it should take 2 seconds for opening the door and we will use the "elastic in out" easing.
Door1.addAnimation(
SceneryObject.PROPERTY_ROTATION_Y, // Rotate on Y Axix
Math.toRadians(90.0f), // Roation Y to 90 Degrees
0.0f, // startTime, 0:00 sec
2.0f, // endTime, 0:02 sec
Easing.ELASTIC_IN_OUT // Easing: elastic in out
);
Good start. Lets define our "closing the door" transition. What is happening there? Well, its returning to 0° again on the same axis. Lets choose again 2 seconds of animation with the same easing, but this time, our StartTime should be 2sec and EndTime on 4 sec. We can later define in our timeline some labels like open the door from 0sec to 2sec and close the door from 2sec to 4sec. This sounds good right?
Door1.addAnimation(
SceneryObject.PROPERTY_ROTATION_Y, // Rotate on Y Axix
Math.toRadians(0.0f), // Roation Y to 90 Degrees
2.0f, // startTime, 0:02 sec
4.0f, // endTime, 0:04 sec
Easing.ELASTIC_IN_OUT // Easing: elastic in out
);
You have to do the same for Door2. Just copy and paste both transition definitions and rename from Door1 to Door2. You got it, I know it.
But we want to define a timeline, to execute both animations on the same time. For this purposes NoLimitsFramework is providing an other useful class.
After creating instances of the animation classe Door1 and Door2 we have to create a Timeline instance com.nolimitsframework.animation.Timeline.
Timeline DoorTimeline = new Timeline();
Now we have to add both animations to the timeline.
DoorTimeline.addAnimation(Door1);
DoorTimeline.addAnimation(Door2);
And now its getting interesting. Live mentioned above, you can define now labels. Our door opening animation is running from 0sec to 2sec. Let us define that.
setLabel("openDoor", 0.0f, 2.0f);
We want also define the label for closing the door which runs from 2sec to 4sec.
setLabel("closeDoor", 2.0f, 4.0f);
In fact we are done. Now you can start the animation with the start(label) method. You can leave label empty if you want to start from 0sec to the end. But NoLimitsFramework wouldn´t be cool, if you couldn´t connect your coaster triggers to these labels.
Just add these.
TriggerManager.addTrigger("ExepeditionGeforce, triggerOpenDoor", DoorTimeline, "openDoor");
TriggerManager.addTrigger("ExepeditionGeforce, triggerCloseDoor", DoorTimeline, "closeDoor");
Define two triggers on your coaster named triggerOpenDoor and triggerCloseDoor. Well, that´s it. You just connected your trigger with your timeline labels.
Please don´t forget to import the classes.
import com.nolimitsframework.*;
import com.nolimitsframework.trigger.*;
import com.nolimitsframework.animation.*;
import com.nolimitsframework.easing.*;
import com.nolimitsframework.scenery.*;
public class ExpditionGefore extends FrameworkScript {
public void init() {
Animation Door1 = new Animation("Scenery: House, Door1");
Animation Door2 = new Animation("Scenery: House, Door2");
Door1.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(90.0f), 0.0f, 2.0f, Easing.ELASTIC_IN_OUT);
Door1.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(0.0f), 2.0f, 4.0f, Easing.ELASTIC_IN_OUT);
Door2.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(90.0f), 0.0f, 2.0f, Easing.ELASTIC_IN_OUT);
Door2.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(0.0f), 2.0f, 4.0f, Easing.ELASTIC_IN_OUT);
Timeline DoorTimeline = new Timeline();
DoorTimeline.addAnimation(Door1);
DoorTimeline.addAnimation(Door2);
DoorTimeline.setLabel("openDoor", 0.0f, 2.0f);
DoorTimeline.setLabel("closeDoor", 2.0f, 4.0f);
TriggerManager.addTrigger("ExepeditionGeforce, triggerOpenDoor", DoorTimeline, "openDoor");
TriggerManager.addTrigger("ExepeditionGeforce, triggerCloseDoor", DoorTimeline, "closeDoor");
}
}
If you want to have a clean code, I would suggest to create a class which extends Timeline. In this case, I would create a class named HouseObject. Usually I am creating a folder inside CoasterScripts called objects. Our final code would end up for HouseObject.nlvm in:
package objects;
import com.nolimitsframework.*;
import com.nolimitsframework.trigger.*;
import com.nolimitsframework.animation.*;
import com.nolimitsframework.easing.*;
import com.nolimitsframework.scenery.*;
public class HouseObject extends Timeline implements Triggerable{
public HouseObject() {
Animation Door1 = new Animation("Scenery: House, Door1");
Animation Door2 = new Animation("Scenery: House, Door2");
Door1.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(90.0f), 0.0f, 2.0f, Easing.ELASTIC_IN_OUT);
Door1.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(0.0f), 2.0f, 4.0f, Easing.ELASTIC_IN_OUT);
Door2.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(90.0f), 0.0f, 2.0f, Easing.ELASTIC_IN_OUT);
Door2.addAnimation(SceneryObject.PROPERTY_ROTATION_Y, Math.toRadians(0.0f), 2.0f, 4.0f, Easing.ELASTIC_IN_OUT);
addAnimation(Door1);
addAnimation(Door2);
setLabel("openDoor", 0.0f, 2.0f);
setLabel("closeDoor", 2.0f, 4.0f);
}
}
And in your main coaster script, you have to instantiate the HouseObject and connect there your coaster triggers:
import com.nolimitsframework.*;
import objects.*;
public class ExpeditionGeforce extends FrameworkScript {
public void init() {
HouseObject house = new HouseObject();
TriggerManager.addTrigger("ExepeditionGeforce, triggerOpenDoor", house, "openDoor");
TriggerManager.addTrigger("ExepeditionGeforce, triggerCloseDoor", house, "closeDoor");
}
}
Well, this is how to keep everything clean.