[No Limits 2] Tuto sur les scripts

Bon, je donnes ma langue aux chats ...
j'essaye en vain depuis quelques jours de réaliser une porte coulissante mais là, j'en peux plus !

Ce que j'ai compris c'est que tout les temps 't' sont pris sur la simulation or je pense avoir besoin d'une constante pour chaque déplacement. J'ai repris le script DoorScript et j'ai essayé de lui donner des translations dans un cycle(t) d'automate mais il reprend la position du simu pour les actions triggers (before/behind) du coup la porte fait n'importe quoi.

Je suis arrivé a faire passer la porte d'une position à une autre mais c'est juste un changement et c'est malheureusement instantané. C'est pour cette raison que j'aimerais utiliser la PolyRamp mais je suis plus sur de rien...


Il me semble avoir tout essayer autour de cette fonction 'translation' mais j'y arrives pô... :cry:



Code:
float cycle = 2.0f;
	float Max_Depl = 0.1f;
  
  
  public void onNextFrame(float fTickTime)
  {	
  	float t = (float)sim.getCurAbsSimulationTimeSec() % cycle;
   	float startDelay = 0;
   	
   	switch (state)
    {
    case STATE_IDLE:

     break; 
    case STATE_OPENING:
     { 
      	if (state == 1)
        {
          m_porte_pos.y =  PolyRamp(0, Max_Depl, 0+startDelay, 2+startDelay, t, 0, 1.5f, 1, -1.5f);
      		porte.setTranslation(m_porte_pos);
					break;
        }
     }
      
    case STATE_OPENING_REVERSED:
			{ 
      	if (state == 2)
        {
          m_porte_pos.y =  PolyRamp(0, Max_Depl, 0+startDelay, 2+startDelay, t, 0, 1.5f, 1, -1.5f);
      		porte.setTranslation(m_porte_pos);
					break;
        }
     }
      
     
    case STATE_CLOSING:
     { 
      	rot += fTickTime * t;
        if (state == 3)
        {
          m_porte_pos.y =  PolyRamp(Max_Depl, 0, 0+startDelay, 3+startDelay, rot, 0, 1.5f, 1, -1.5f);
      		porte.setTranslation(m_porte_pos);
					break;
        }
     }
     
    }
  }

Siouplais !

svp.jpg
 
J'ai déjà modifié ce script (DoorScript) pour obtenir exactement ce que tu veux, malheureusement je suis pas sur mon pc là, mais je peux te l'envoyer en fin d'aprem quand je serai chez moi  :wink:
 
DJ Julio a dit:
J'ai déjà modifié ce script (DoorScript) pour obtenir exactement ce que tu veux, malheureusement je suis pas sur mon pc là, mais je peux te l'envoyer en fin d'aprem quand je serai chez moi  :wink:

Pourrais tu le mettre sur ce sujet ? Qu'on puisse en profiter aussi ! Merci.
 
Voici le script complet  :wink:

Code:
import com.nolimitscoaster.*;
import nlvm.math3d.*;

public class DoorScriptModifie extends Script implements TrackTriggerListener
{
  private SceneObject sco;
  private SceneObjectElement leftDoor;
  private SceneObjectElement rightDoor;
  
  private static final int STATE_IDLE = 0;
  private static final int STATE_OPENING = 1;
  private static final int STATE_CLOSING = 2;
  
  // Ouverture limitée à 2m de chaque côté
  private static final float TRANSLATION = 2.0f;
  //Temps d'ouverture de 1,5s
  private static final float DUREE_OUVERTURE = 2.0f;
  //Temps d'accélération et de ralentissement
  private static final float DUREE_ACCELERATION = 0.5f;
  //Variable servant lors de l'ouverture ou la fermeture des portes
  private static float startTime = 0.0f;
  
  private int state; 
  private float trans;
  
  private TrackTrigger beforeDoorTrigger;
  private TrackTrigger behindDoorTrigger;
  
  private StaticSound doorSound;
  
  private static final String scriptName = "DoorScript";
  
  // must be constant string expression and marked as final so that the compiler will no complain with a warning when used for
  // StaticSound.loadFromFile
  private final static String doorSoundFile = "doorsound.ogg";
  
  public bool onInit()
  {
    sco = sim.getSceneObjectForEntityId(getParentEntityId());
    if (sco == null)
    {
      System.err.println(scriptName + ": the script is not part of a scene object");
      return false;
    }
    //Récupération du sous objet porte gauche
    leftDoor = sco.getElementForName("left");
    if (leftDoor == null) 
    {
      System.err.println(scriptName + ": element not found: left");
      return false;
    }    
    //Récupération du sous objet porte droite
    rightDoor = sco.getElementForName("right");
    if (rightDoor == null) 
    {
      System.err.println(scriptName + ": element not found: right");
      return false;
    }  
	//Initialisation du son d'ouverture de la porte
    doorSound = StaticSound.loadFromFile(doorSoundFile, 0);
    if (doorSound == null)
    {
      System.err.println(scriptName + ": could not load sound '" + doorSoundFile + "'");
      return false;
    }

	//Vecteur représentant la position de l'objet dans l'espace
    Vector3f pos = new Vector3f();
    sco.getTranslation(pos);

	//Déplacement du son au niveau de l'objet
    doorSound.setPosition(pos);

    // Setting to 'Local' will enable environmental (reverb) effects if this sound's position should be e.g. in a tunnel
    doorSound.setEnvironmentMode(StaticSound.E_ENVMODE_LOCAL);

    // These parameters affect the distance attenuation
    doorSound.setDistanceParameters(2.0f, 0.8f);

    final float range = 10;

    // create triggers...
    TrackPos trackPos = sim.findNearestCoasterTrack(pos, range);
    if (trackPos == null)
    {
      System.err.println(scriptName + ": no coaster found within a range of "+ range + " meters");
      return false;
    }
    else
    {
      Coaster coaster = trackPos.getCoaster();
      
      System.out.println(scriptName + ": Coaster found: " + coaster);

      System.out.println("Coaster Style is: " + coaster.getCoasterStyleId());
      
      // create a trigger 5 meters in front of the track pos
      beforeDoorTrigger = TrackTrigger.createTrackTriggerAtOffset(trackPos, -5.0);
      
      // create a trigger 5 meters after the track pos
      behindDoorTrigger = TrackTrigger.createTrackTriggerAtOffset(trackPos, +5.0);
      
      // tell the triggers that they should call our onTrainEntering/onTrainLeaving methods
      // We have to implement the TrackTriggerListener interface
      beforeDoorTrigger.addTrackTriggerListener(this);
      behindDoorTrigger.addTrackTriggerListener(this);
    }
    
    state = STATE_IDLE;
    trans = 0;
    
    return true;
  }
  
  public void onNextFrame(float fTickTime)
  {
    switch (state)
    {
    case STATE_IDLE:
      // do nothing
      break;
    case STATE_OPENING: //Etat gérant l'ouverture de la porte
      {
	    //Calcul de la position de la porte
		startTime += fTickTime;
        trans = (float)Tools.switchRampC1(DUREE_OUVERTURE, TRANSLATION, DUREE_ACCELERATION, startTime);
		//Si on atteint l'ouverture maximale autorisée, on bloque la translation
        if (trans >= TRANSLATION)
        {
          trans = TRANSLATION;
          state = STATE_IDLE;
		  startTime = 0;
        }
		//Construction de deux vecteurs
		Vector3f leftTrans = new Vector3f(-trans,0,0);//La translation se fait sur l'axe X
		Vector3f rightTrans = new Vector3f(trans,0,0);//La translation se fait sur l'axe X
		//On applique la translation aux sous objets porte gauche et porte droite
		leftDoor.setTranslation(leftTrans);
		rightDoor.setTranslation(rightTrans);
      }
      break;    
    case STATE_CLOSING: //Etat gérant la fermeture de la porte
      {
	    //Calcul de la position de la porte
		startTime += fTickTime;
        trans = TRANSLATION - (float)Tools.switchRampC1(DUREE_OUVERTURE, TRANSLATION, DUREE_ACCELERATION, startTime);
		//Si on atteint l'ouverture minimale, on bloque la translation
        if (trans <= 0)
        {
          trans = 0;
          state = STATE_IDLE;
		  startTime = 0;
        }
		//Construction de deux vecteurs
		Vector3f leftTrans = new Vector3f(-trans,0,0);//La translation se fait sur l'axe X
		Vector3f rightTrans = new Vector3f(trans,0,0);//La translation se fait sur l'axe X
		//On applique la translation aux sous objets porte gauche et porte droite
		leftDoor.setTranslation(leftTrans);
		rightDoor.setTranslation(rightTrans);
      }
      break;
    }
  }
  
  /**
   * This method is part of the TrackTriggerListener Interface implementation
   *
   * It will be called if the interface is registered for a trigger using the
   * addTrackTriggerListener method.
   */
  public void onTrainEntering(TrackTrigger trigger, Train train)
  {
    if (trigger == beforeDoorTrigger)
    {
      if (train.getSpeed() > 0)
      {
        state = STATE_OPENING;
        doorSound.play();

        //printTrainPositionAndRotation(train);
      }
    }
    else if (trigger == behindDoorTrigger)
    {
      if (train.getSpeed() < 0)
      {
        state = STATE_OPENING;
        doorSound.play();
      }
    }
  }
  
  /**
   * This method is part of the TrackTriggerListener Interface implementation
   *
   * It will be called if the interface is registered for a trigger using the
   * addTrackTriggerListener method.
   */  
  public void onTrainLeaving(TrackTrigger trigger, Train train)
  {
    if (trigger == beforeDoorTrigger)
    {
      if (train.getSpeed() < 0)
      {
        state = STATE_CLOSING;
        doorSound.play();
      }
    }
    else if (trigger == behindDoorTrigger)
    {
      if (train.getSpeed() > 0)
      {
        state = STATE_CLOSING;
        doorSound.play();
      }
    }
  }

  // This method demonstrates how to get the position and rotation of the first bogey
  private void printTrainPositionAndRotation(Train train)
  {
    if (train.getBogieCount() > 0)
    {
      Vector3f pos = new Vector3f();
      Vector3f front = new Vector3f();
      
      train.getBogieOrientationAndPosition(0, front, null, null, pos);

      System.out.println(scriptName + ": First bogey is at " + pos);

      double azimuthRad = Math.atan2(front.x, -front.z);
      double elevationRad = Math.atan2(front.y, Math.sqrt(front.x* front.x + front.z* front.z));

      System.out.println(scriptName + ": Yaw is " + Math.toDegrees(azimuthRad) + " degrees"); 
      System.out.println(scriptName + ": Pitch is " + Math.toDegrees(elevationRad) + " degrees"); 
    }
  }
}
 
Dans la lignée de mes recherches ...
Prenons un objet simple, un plan avec 4 points. Via un script, est-il modifiable, peut-il être copié un certain nombre de fois (une array x, y, z) ?

DJ Julio, quel méthode préconiserais-tu pour apprendre ce code, quel site de référence ?

Merci  :-)
 
Alors, un script peut te permettre de déplacer, appliquer une rotation ou modifier l'échelle d'un objet ou sous objet. Les scripts ne permettent pas la copie, si il y a plusieurs objets, ils doivent tous être présents dans le modèle 3d, et après avec les scripts tu peux choisir de les afficher ou pas (propriété Visible).

Après dans le cadre d'un plan par exemple, il me semble que les matériaux NL2 te permettent d'appliquer des déplacement de vertex pour les animer (j'ai vu une video postée sur NoLimits Exchange qui montre des drapeaux animés sans scripts), mais c'est indépendant des scripts du coup  :wink:

Pour l'apprentissage je recommenderai OpenClassrooms, avec notament ce cours :
http://fr.openclassrooms.com/informatique/cours/apprenez-a-programmer-en-java
 
Merci pour les infos  :mrgreen:

Et en passant par les particules, serait-il possible de bricoler quelque chose pour aligner les sous-objets ?
Je sais pas si c'est comme ça avec les autres logiciels que Blender mais quand j'exporte en 3ds, tout les points de pivot sont regroupés sur un vecteur.
Du coup si je voudrais faire une alignée de lampes, je dois les poser une à une avec l’éditeur NL2  :cry:
Est-ce quelqu'un s'est déjà intéressé a faire un chenillard autrement que l'exemple donné avec tango dont j'ai vraiment de la peine à m'en sortir avec toutes ces lumières ?  :?
 
Si tu veux faire une ligne de lampes, je te conseillerai de placer tes lampes dans ton logiciel de modélisation.
Par exemple sur 3ds max j'ai placé des lumières de type Omni et je leur ai donné un nom unique, et du coup quand je créé mon nl2sco dans NL2, je rajoute chaque lampe a partir du modèle. NL2 détecte automatiquement les lampes de type spot et omni présents dans le fichier 3ds, ce qui facilite les choses puisque du coup tu les places dans ton logiciel, et que nl2 rempli les coordonnées x, y et z tout seul  :-) Bon il faut quand meme rajouter les lampes une par une dans l'éditeur NL2, mais sans se soucier des coordonnées, y'a juste a sélectionner le nom de la lampe dans la liste  :wink:
 
DJ Julio a dit:
Bon il faut quand meme rajouter les lampes une par une dans l'éditeur NL2, mais sans se soucier des coordonnées, y'a juste a sélectionner le nom de la lampe dans la liste  :wink:
Oui je fais pareil mais si tu veux faire une rave, bonjour l'angoisse.  :-D

 
Serait-il possible d'avoir un tuto sur les lumières parce que c'est assez compliqué sur NL2 donc au niveau des scripts mais aussi au niveau du NL2sco editor ca serait cool merci  :-) .
 
Amis forumeurs, Modérateurs etc...

Il y a quelques jours, je me suis dit que nous aurons toujours les mêmes questions concernant les scripts. En effet, plus le sujet va s'allonger, plus les membres seront découragés de parcourir les innombrables posts afin de trouver leur(s) réponse(s).

Donc... Serait-il possible ( j'implore votre Grande Compréhension et Gentillesse ) de créer des sujets pour chaque groupe...

Je m'explique, scripted coasters, scripts objets, scripts lumières, scripts trains et autres ? Enfin, si c'est possible...  :-)
 
Bon, un premier jet.
Vous pourrez retrouver l'original chez moi => http://www.dawaweb.ch/dawa/?page_id=1646

Alors dans un premier temps :

Les lumières.

Il est possible d’ajouter un ou plusieurs point lumineux appelé ‘light’ sur tout les objets.
Pour mon exemple j’ai pris un simple cube de Blender que j’ai exporté en 3ds et que j’ai appelé
cube.nl2sco.

013.png


021.png


Je lui ai ajouté un point omnidirectionnel ‘light01' et je l’ai plongé dans un environnement dénudé de lumière que j’ai appelé nuit .-)

043.png


061.png


Résultat : Nuit !

081.png


Pourquoi ? Le point se trouve au point 0-0-0 du point de pivot de l’objet. Pour mon cube il se trouve en son centre et la distance d’éclairage (Range) n’est pas assez longue puisque mon cube fait 1 mètre et qu’il se trouve à 2 mètres du sol depuis ce point.
J’augmente le ‘Range’ à 2 mètres et le sol s’éclaire faiblement.

101.png


Je déplace le point ‘light’ en le montant sur l’axe Y d’un mètre afin qu’il soit visible.

121.png


J’ajoute un halo pour que cette fois-ci il soit visible pour nos yeux.

141.png

                                                           
161.png


Je lui ajoute du ‘Range’ pour éclairer le sol, et un peu d’intensité. Je le décale d’un mètre sur l’axe X.

181.png

                                                           
20.png
 

J’ajoute cette fois-ci un point identique que j’appelle ‘light02' et que je décale cette fois-ci à -1 sur l’axe X.

22.png

                                                           
24.png

                                                                                                                       
Je change le type d’éclairage que je passe en ‘spot’ et je lui indique d’éclairer le sol avec un -1 dans la direction Y .

28.png

                                                           
30.png


Le ‘Cutoff Angle’ est l’angle maximum de l’halo du spot.
Le Spot Exponent est la lumière diffusée par le spot depuis son centre.
Plus ils sont éloigné et plus le détail sera grand, comme quand on approche un spot d’un mur …
Exemple à 30 et 0 :

32.png

                                                           
34.png


Je lui ajoute un faisceaux (Volume effect):

36.png

                                                           
38.png


Je lui augmente sa distance d’éclairage ‘Range’ à deux mètres et son diamètre initial (point).

40.png

                                                                 
42.png


Si je lui ajoute une image avec les réglages comme ceci, je ne verrai rien.

43.png


Je passes la couleur de mon spot au blanc, je pousse le ‘Range’ à 3m pour qu’il atteigne la surface projetée.

44.png

                                                           
46.png


Résumons :

Général :

Setup :Custom = nous choisissons les position ici.
From model 3d = Les position des light sont donnée depuis le logiciel 3d.
Name : Son nom.
Type : Un point omnidirectionnel ou un spot.
Parent Element : Si l’on veux attribuer la light à un sous objet de l’objet.

Common:
Pos X, Y, Z : distance du point ‘light’ au point de pivot de l’objet.
Range : Distance d’éclairage.
Intensité : Intensité lumineuse (puissance).
Color : A changer le prix de l’entrée du parc …
Halo Z-offset : Offset à partir du halo ( avec un réglage à 10, il ne sera visible qu’à partir de 10 mètres, plus proche, il ne le sera pas).
Halo  Size : Diamètre.
Halo Intensity : Intensité du halo (puissance).

Spot-Light :
Direction X, Y, Z : Direction de l’éclairage.
Cutoff Angle : Angle d’ouverture en dégrés du spot
Spot Exponent : lumière diffusée par le spot depuis son centre
Custom Spot-Texture : image de projection (fond noir = masque)

Volume Effect (faisceaux) :
Range : Distance de projection.
Size : Diamètre du faisceaux à la base du spot.
Intensité : Intensité du faisceaux..


En résumé, on peut mettre autant de points light qui peuvent être à présent pilotées par scripts. (A venir)

Je pensais pas finir autant tard mais au moins, j'ai été jusqu'au bout. J’espère que ça vous aidera, un peu  :wink:

 
Super merci, ça va beaucoup m'aider, j'y connais rien du tout au niveau des lumières donc ça va bien m'aider  :mrgreen:
 
Petit ajout ...


44.png


L'éditeur de lumières est un peu rébarbatif a utiliser surtout quand il faut en régler plusieurs.
Pour se faciliter la tâche, on peu passer par un éditeur texte  de type notpad ou autre et on ouvre directement l'objet .nl2sco.

Si j'ouvre le cube.nl2sco
Code:
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <sceneobject>
    <model path="cube.3ds"/>
    <materialpath name="Material">cube.nl2mat</materialpath>
    
    <lightsource range="3" intensity="2" type="point">
      <name>light01</name>
      <position x="1" y="1" z="0"/>
      <color r="0.905882" g="1" b="0.105882"/>
      <halo zoffset="0" intensity="1" size="1"/>
    </lightsource>
    
    <lightsource range="3" intensity="5" type="spot" spotcutoff="30" spotexponent="0">
      <direction x="0" y="-1" z="0"/>
      <upvector x="0" y="1" z="0"/>
      <customcookietexturepath>testlogo.png</customcookietexturepath>
      <name>light02</name>
      <position x="-1" y="1" z="0"/>
      <color r="1" g="0.992157" b="0.992157"/>
      <halo zoffset="10" intensity="1" size="1"/>
      <volume range="3" intensity="1" size="0.1"/>
    </lightsource>
    
  </sceneobject>
</root>

Mes deux lumières se trouvent entre les balises '<lightsource></lightsource>' et a partir de là, je peux les modifier plus facilement, en ajouter des centaines.

Il suffit de sauvegarder le code et de ré-ouvrir le parc afin que NL recharge le code.

46.png


La prochaine fois,  je vais tenter de fournir les différents moyens de contrôler les lumières.