import com.nolimitscoaster.*;
import nlvm.math3d.*;
public class FerrisWheelScript extends Script
{
private static final byte OPEN = 0;
private static final byte CLOSE = 1;
private static final float[] ANGLE = {-1.5707963267948966192313216916398f, 0.0f};
private static final byte CABINS = 64;
private static final byte NO_DOOR = CABINS;
private static final float MAX_ACCELERATION = 1.5f;
private static final float MAX_VELOCITY = 2;
private static final float DOOR_COMPARE = 0.001f;
private SceneObject m_sco;
private SceneObjectElement m_mainwheel;
private SceneObjectElement[] m_cabin = new SceneObjectElement[CABINS];
private SceneObjectElement[] m_door = new SceneObjectElement[CABINS];
private bool[] doorPrevOpen = new bool[CABINS];
private float[] cabinAngle = new float[CABINS];
private float m_angle;
private float[] doorAngle = new float[2];
private float[] doorRandomOffset = new float[2];
private byte[] doorMoving = new byte[2];
private byte[] lastDoorMoving = {NO_DOOR, NO_DOOR};
private float[] velocityDoor = new float[2];
public bool onInit()
{
m_sco = sim.getSceneObjectForEntityId(getParentEntityId());
m_mainwheel = m_sco.getElementForName("Wheel");
Vector3f cabinTrans;
for (byte i=CABINS-1; i>=0; --i)
{
m_cabin[i] = m_sco.getElementForName("Cabin" + i);
m_door[i] = m_sco.getElementForName("Door" + i);
m_sco.getElementForName("Windows" + i).setEntityColor(new Vector4f(10.0f, 10.0f, 10.0f, 0.2f));
m_sco.getElementForName("WindowDoor" + i).setEntityColor(new Vector4f(10.0f, 10.0f, 10.0f, 0.2f));
doorPrevOpen[i] = false;
cabinTrans = m_cabin[i].getMatrix().getTrans();
cabinAngle[i] = (float)Math.atan2(-cabinTrans.x, -cabinTrans.z);
}
return true;
}
public void onNextFrame(float tick)
{
m_angle += tick * 0.00654498469497873591346384038183f;
turnWheel();
for (byte i=1; i>=0; --i)
{
animateDoor(i, tick);
}
for (byte i=CABINS-1; i>=0; --i)
{
handleCabin(i);
}
}
private void turnWheel()
{
if(m_angle > Math.PI)
{
m_angle -= (float)Math.PI * 2;
}
else if(m_angle < -Math.PI)
{
m_angle += (float)Math.PI * 2;
}
m_mainwheel.setRotation(0, 0, m_angle);
}
private void animateDoor(byte state, float tick)
{
if(doorMoving[state] != NO_DOOR)
{
if (velocityDoor[state] * velocityDoor[state] / MAX_ACCELERATION / 2 >= Math.abs(ANGLE[state] - doorAngle[state]))
{
velocityDoor[state] = (velocityDoor[state] + MAX_ACCELERATION * tick * ((velocityDoor[state] < 0) ? 1 : -1));
}
else
{
float pos = (ANGLE[state] > doorAngle[state]) ? 1 : -1;
if (Math.abs(velocityDoor[state]) < MAX_VELOCITY)
{
velocityDoor[state] = velocityDoor[state] + MAX_ACCELERATION * tick * pos;
}
if (Math.abs(velocityDoor[state]) >= MAX_VELOCITY)
{
velocityDoor[state] = MAX_VELOCITY * pos;
}
}
doorAngle[state] += velocityDoor[state] * tick;
if(doorAngle[state] <= ANGLE[state] + DOOR_COMPARE && doorAngle[state] >= ANGLE[state] - DOOR_COMPARE)
{
doorAngle[state] = ANGLE[((state + 1) % 2)];
m_door[doorMoving[state]].setRotation(0, ANGLE[state], 0);
doorMoving[state] = NO_DOOR;
}
else
{
m_door[doorMoving[state]].setRotation(0, doorAngle[state], 0);
}
}
}
private void handleCabin(byte cabin)
{
m_cabin[cabin].setRotation(0, 0, -m_angle);
float realAngle = cabinAngle[cabin] - m_angle;
if(realAngle < 0.1f && realAngle > -0.1f)
{
checkDoor(OPEN, cabin, true);
}
else
{
checkDoor(CLOSE, cabin, false);
}
}
private void checkDoor(byte state, byte i, bool open)
{
if(doorMoving[state] == NO_DOOR && lastDoorMoving[state] != i)
{
if(doorPrevOpen[i] == !open)
{
doorRandomOffset[state] = (float)((Math.random() - 0.5f) / 10);
doorMoving[state] = i;
lastDoorMoving[state] = i;
doorPrevOpen[i] = open;
velocityDoor[state] = 0;
}
}
}
}
Return to NoLimits Coaster 2 Scripting