[No Limits 2] Tuto sur les scripts

gabifou a dit:
641778Capture.png
Il faut que ton Fichier soit en .nlvm , pour ça , dans Bloc notes , dans type de fichier tu fait tous et tu ajoute a la fin du nom du fichier " .nlvm "

:mrgreen:
 
Bon alors j'ai fait un script qui permet de mettre de l'audio dans tous les wagons de tous les trains d'un coaster en utilisant les StaticSound, et la possibilité d'avoir plusieurs musiques différentes par train. Le script tient en fait dans 2 scripts différents.

Alors avant toute chose, je vais lister les quelques inconvénients et problème qu'il est impossible de résoudre avec les fonctions de l'API. Comme je créé plusieurs sons diffusant la même musique (un par wagon de chaque train), j'ai du mettre le flag des musiques à FLAG_SHARED, pour être sur que toutes les musiques des différentes sources sont bien synchronisées entre elles. La première conséquence, c'est qu'il est nécessaire d'avoir des fichiers audio destinés pour chaque train, y compris si c'est exactement la même musique pour tous les train (5 trains = 5 musiques). La deuxième conséquence concerne la durée de la musique, il faut qu'elle soi assez longue pour tenir jusqu'au trigger arrêtant la musique ou un trigger permettant de changer de musique, mais il faut aussi qu'elle soi suffisamment courte pour que le train, lors de son passage au tour suivant, puisse avoir sa musique qui redémarre de zéro, parce que sinon la musique continue en mémoire (bien qu'on ne l'entende pas), et reprend à sa position en mémoire.

Remarque importante :
Les fichiers audio sont chargés sous forme de ressource associée au script et non directement depuis le nom du fichier.

Le premier fichier représente une classe permettant de définir des fichiers audio pour un train. En principe ce fichier n'est pas à modifier, sauf les 3 constantes au début, qui représentent respectivement le volume, le temps de fondu au lancement de la musique en secondes, et le temps de fondu à l'arrêt de la musique en secondes aussi.
OnboardMusicTrain :
Code:
import com.nolimitscoaster.*;
import nlvm.math3d.*;

public class OnboardMusicTrain 
{
	//Constantes
	private static final float GAIN = 1.0f;
	private static final float START_FADE_TIME = 1.0f;
	private static final float STOP_FADE_TIME = 1.0f;
	
	//Variables membres
	private Train mTrain;
	private int mCarCount;
	private int mMusicCount;
	private StaticSound[][] mMusics;
	private int mIndexOfCurrentMusic;

	//Constructeur
	public OnboardMusicTrain(Train train, int MusicCount)
	{
		mTrain = train;
		mMusicCount = MusicCount;
		mCarCount = mTrain.getCarCount();
		mMusics = new StaticSound[mMusicCount][mCarCount];
		mIndexOfCurrentMusic = -1;
	}
	
	//Fonction permettant d'ajouter une musique
	public final bool SetMusic(int index, String MusicId)
	{
		if(index < 0 || index >= mMusicCount)
		{
			System.err.println("Index out of limits");
			return false;
		}
		
		for(int i = mCarCount - 1; i >= 0; i--)
		{
			StaticSound newSS = StaticSound.loadFromResourceId(MusicId, StaticSound.FLAG_SHARED);
			if(newSS == null)
			{
				System.err.println("Music file cannot be found or opened: '" + MusicId + "'");
				return false;
			}
			newSS.setEnvironmentMode(StaticSound.E_ENVMODE_SAME_AS_LISTENER);
			
			mMusics[index][i] = newSS;
		}
		
		return true;
	}
	
	public final void UpdatePosition()
	{
		Vector3f fo = new Vector3f();
		Vector3f to = new Vector3f();
		Vector3f ro = new Vector3f();
		Vector3f pos = new Vector3f();
		for(int i = mCarCount - 1; i >= 0; i--)
		{
			mTrain.getCarOrientationAndPosition(i, fo, to, ro, pos);
			for(int j = mMusicCount - 1; j >= 0 ; j--)
			{
				mMusics[j][i].setPosition(pos);
			}
		}
	}
	
	public final Train getTrain()
	{
		return mTrain;
	}
	
	public final void playMusic(int index)
	{
		if(index < 0 || index >= mMusicCount) return;
		
		for(int i = mCarCount - 1; i >= 0; i--)
		{
			mMusics[index][i].stop();
			mMusics[index][i].setGain(0);
			mMusics[index][i].play();
			mMusics[index][i].setGainFaded(GAIN, START_FADE_TIME);
			
			if(mIndexOfCurrentMusic != -1)
			{
				mMusics[mIndexOfCurrentMusic][i].stopFaded(STOP_FADE_TIME);
			}
		}
		mIndexOfCurrentMusic = index;
	}
	
	public final void stopMusic()
	{
		if(mIndexOfCurrentMusic != -1)
		{
			for(int i = mCarCount - 1; i >= 0; i--)
			{
				mMusics[mIndexOfCurrentMusic][i].stopFaded(STOP_FADE_TIME);
			}
		}
		mIndexOfCurrentMusic = -1;
	}
}

La deuxième classe est la classe associée au coaster et permettant l'initialisation de la classe OnboardMusicTrain pour chaque train, mais aussi de gérer les trigger.
OnboardMusicCoaster :
Code:
import com.nolimitscoaster.*;

public class OnboardMusicCoaster extends Script implements TrackTriggerListener
{
	//Constantes
	private static final String Music1Train1Id = "Music1Train1"; //Id de la ressource, à définir dans l'éditeur
	private static final String Music2Train1Id = "Music2Train1";
	private static final String Music3Train1Id = "Music3Train1";
	private static final String Music4Train1Id = "Music4Train1";
	private static final String Music1Train2Id = "Music1Train2";
	private static final String Music2Train2Id = "Music2Train2";
	private static final String Music3Train2Id = "Music3Train2";
	private static final String Music4Train2Id = "Music4Train2";
	private static final String startMusic1TriggerName = "TestTrigger1";
	private static final String startMusic2TriggerName = "TestTrigger2";
	private static final String startMusic3TriggerName = "TestTrigger3";
	private static final String startMusic4TriggerName = "TestTrigger4";
	
	//Variables membres
	private TrackTrigger startMusic1Trig;
	private TrackTrigger startMusic2Trig;
	private TrackTrigger startMusic3Trig;
	private TrackTrigger startMusic4Trig;
	private int mTrainCount;
	private OnboardMusicTrain[] mMusicTrains;

	//Initialisation
	public bool onInit()
	{
		Coaster coaster = sim.getCoasterForEntityId(getParentEntityId());
		if (coaster == null)
		{
			System.err.println("This script must be attached to a coaster");
			return false;
		}
		startMusic1Trig = coaster.getTrackTrigger(startMusic1TriggerName);
		if (startMusic1Trig == null)
		{
			System.err.println("TrackTrigger not found: '" + startMusic1TriggerName + "'");
			return false;
		}
		startMusic1Trig.addTrackTriggerListener(this);
		
		startMusic2Trig = coaster.getTrackTrigger(startMusic2TriggerName);
		if (startMusic2Trig == null)
		{
			System.err.println("TrackTrigger not found: '" + startMusic2TriggerName + "'");
			return false;
		}
		startMusic2Trig.addTrackTriggerListener(this);
		
		startMusic3Trig = coaster.getTrackTrigger(startMusic3TriggerName);
		if (startMusic3Trig == null)
		{
			System.err.println("TrackTrigger not found: '" + startMusic3TriggerName + "'");
			return false;
		}
		startMusic3Trig.addTrackTriggerListener(this);
		
		startMusic4Trig = coaster.getTrackTrigger(startMusic4TriggerName);
		if (startMusic4Trig == null)
		{
			System.err.println("TrackTrigger not found: '" + startMusic4TriggerName + "'");
			return false;
		}
		startMusic4Trig.addTrackTriggerListener(this);
		
		mTrainCount = coaster.getTrainCount();
		mMusicTrains = new OnboardMusicTrain[mTrainCount];
		OnboardMusicTrain musicTrain;
		Train train;
		//Train 1
		train = coaster.getTrainAt(0); //On récupère le premier train
		musicTrain = new OnboardMusicTrain(train, 4); //On initialise sa classe OnboardMusicTrain qui contiendra 4 musiques
		if(!musicTrain.SetMusic(0, Music1Train1Id)) return false; //Ajout de la première musique (index = 0)
		if(!musicTrain.SetMusic(1, Music2Train1Id)) return false; //Ajout de la deuxième musique (index = 1)
		if(!musicTrain.SetMusic(2, Music3Train1Id)) return false;
		if(!musicTrain.SetMusic(3, Music4Train1Id)) return false;
		mMusicTrains[0] = musicTrain;
		
		//Train 2
		train = coaster.getTrainAt(1); //On refait la même chose que pour le premier train avec le train n°2
		musicTrain = new OnboardMusicTrain(train, 4);
		if(!musicTrain.SetMusic(0, Music1Train2Id)) return false;
		if(!musicTrain.SetMusic(1, Music2Train2Id)) return false;
		if(!musicTrain.SetMusic(2, Music3Train2Id)) return false;
		if(!musicTrain.SetMusic(3, Music4Train2Id)) return false;
		mMusicTrains[1] = musicTrain;
		
		return true;
	}
	
	//Mise à jour de la position des sons
	public void onNextFrame(float tick)
	{
		for(int i = 0; i < mTrainCount; i++)
		{
			mMusicTrains[i].UpdatePosition();
		}
	}
	
	public void onTrainEntering(TrackTrigger trigger, Train train)
	{
		OnboardMusicTrain musicTrain = null;
		for(int i = 0; i < mTrainCount; i++)
		{
			if(mMusicTrains[i].getTrain() == train)
			{
				musicTrain = mMusicTrains[i];
				break;
			}
		}
		
		if (trigger == startMusic1Trig && musicTrain != null)
		{
			musicTrain.playMusic(0);
		}
		else if (trigger == startMusic2Trig && musicTrain != null)
		{
			musicTrain.playMusic(1);
		}
		else if (trigger == startMusic3Trig && musicTrain != null)
		{
			musicTrain.playMusic(2);
		}
		else if (trigger == startMusic4Trig && musicTrain != null)
		{
			musicTrain.playMusic(3);
		}
	}
	
	public void onTrainLeaving(TrackTrigger trigger, Train train)
	{
	}
}

Alors dans le code je ne l'ai pas fait là, mais on peut rajouter un trigger qui ne gère que l'arrêt de la musique en cours. Il suffit pour celà d'initialiser un nouveau trigger dans la classe OnboardMusicCoaster et de rajouter ce bout de code dans la fonction onTrainEntering en dessous des autres :
Code:
if (trigger == stopMusicTrig && musicTrain != null)
		{
			musicTrain.stopMusic();
		}
 
Bonjour.
J'ai une erreur qui vient lors d'un packaging.
error C8: Class not found: RotEffect
...1 error(s), 0 warning(s)


J'ai edité tout les *.nlvm du dossier = aucune chaine trouvée .. ?

Étrange ?  :-(
 
yoyo212 a dit:
Bonjour.
J'ai une erreur qui vient lors d'un packaging.
error C8: Class not found: RotEffect
...1 error(s), 0 warning(s)


J'ai edité tout les *.nlvm du dossier = aucune chaine trouvée .. ?

Étrange ?  :-(

Vérifie que le nom du fichier non trouvé est bien RotEffect.nlvm et qu'à l'intérieur le nom de la classe est bien RotEffect.

Meletou1 a dit:
Super Travail DJ Julio, on voit que tu connais bien le langage Java !!!! :mrgreen: :mrgreen: :mrgreen: :-D

Merci  :-) En effet j'utilise le C# au quotidien dans mon boulot, qui est très très proche du Java  :wink:
 
DJ Julio a dit:
Vérifie que le nom du fichier non trouvé est bien RotEffect.nlvm et qu'à l'intérieur le nom de la classe est bien RotEffect.
En effet, c'était bien le fichier qui manquait. Pas très indicative comme message d'erreur  :?
En tout cas, reste par ici ! :mrgreen:
Merci
 
Je comprends pas, quel logiciel faut-il avoir pour lire des ficiers.NLVM ? Je n'arrive pas a les éditer une fois que j'ai changé le .text en .nlvm et lorsque je met d'abord le nom de la musique dans le script puis que je modifie le .text en .nlvm, il ne se passe rien dans NL quand j'ai chargé le script et j'ai un message d'erreur:

Waiting for scripts to finish...
error C14: Invalid class name or package: expected: onboardmusic in root package, found: OnboardMusic in root package
...1 error(s), 0 warning(s)

Quelqu'un pourrait m'aider svp ?  :|
 
Pour éditer les fichiers nlvm tu as juste besoin du bloc note en faisant un clic droit, puis "ouvrir avec". Si tu n'as pas cette option dans le menu, tu peux toujours aller dans les propriétés, puis modifier le programme par défaut avec lequel ouvrir ce type de fichier. Après je te conseille de passer par un éditeur de code comme Notepad++, qui te permettra d'éditer le fichier avec le code mis en couleur, ce qui facilite sa lecture et son édition. Pour mettre le code en couleur, le mieux c'est de définir le language du fichier sur Java dans Notepad++  :wink:

Ensuite pour ton erreur, il faut savoir que les scripts sont sensibles à la casse, tout doit être écrit à l'identique au niveau des noms de classes, de variables ... Là tu doit avoir ton fichier qui s'appelle onboardmusic.nlvm, et ta classe à l'intérieur du fichier qui s'appelle OnboardMusic, pour le code c'est du coup 2 noms différents. Essaye d'appeler ton fichier OnboardMusic.nlvm, ca devrait résoudre ton problème  :wink:
 
D'accord merci pour ta réponse, j'ai réussi il fallait changer le nom en effet et merci pour tes conseils  :-)
 
Désolé pour le double post mais maintenant j'ai ce message:
XInput not installed
SoundLayer: cannot open stream Armored Player - Gears Of War 2 Original Soundtrack.ogg'

:cry:  J'ai essayé plein de méthode pour tenter de faire apparaitre le son mais impossible quel est ce Xinput not installed ?

Faut-il mettre le fichier musique en .ogg dans le répertoire du parc ?
EDIT: problème réglé
 
coucou tout le monde, j'ai jamais fait de script de ma vie et la je doit avoué je suis perdu déjà j'ai essayer le script pour l audio  jusque la tout vas bien mais quand je fait add script ect dans class pass rien ne ce met et donc après ça me met erreur script ect bref je suis en galère si quelqu'un pourrais m'aider c'est gentil 0:)
 
adrien0210 a dit:
coucou tout le monde, j'ai jamais fait de script de ma vie et la je doit avoué je suis perdu déjà j'ai essayer le script pour l audio  jusque la tout vas bien mais quand je fait add script ect dans class pass rien ne ce met et donc après ça me met erreur script ect bref je suis en galère si quelqu'un pourrais m'aider c'est gentil 0:)
VOILA le petit message super cool que je me tape a chaque fois que je comprend totalement  (
..\..\Users\Adrien\Documents\com.nolimitscoaster.nolimits2\Bolliger et Mabliard\BlockScript.nlvm : error C14: Invalid class name or package: expected: BlockScript in root package, found: OnboardMusic in root package
...1 error(s), 0 warning(s)
)
 
Règle N°1 : Jamais d'espaces pour nommer un fichier, dossier, un lien, etc ...
Bolliger et Mabliard => Bolliger_et_Mabliard

Règle N°2 : Un petit tour par la case membres du forum pour une petite présentation sommaire. :-)
 
Alors explication du message :
Erreur dans le fichier BlockScript.nlvm : le nom de la classe est inccorect, il recherche une classe nommée BlockScript et il ne trouve qu'une classe nommée OnboardMusic. La classe doit avoir le même nom que le fichier dans laquelle elle est présente.
Deux solutions pour corriger le problème :
- renommer ton fichier en OnboardMusic.nlvm
- renommer ta classe dans le fichier en BlockScript :
Code:
public class BlockScript extends Script
{
...
}

Si tu n'as jamais fait de scripts, je te conseille vivement de suivre un tuto sur les bases dun language de programmation orientée objet : Java ou C#.

Au passage j'ai eu assez de mal à lire ton post, un peu de ponctuation pour de belles phrases facilite la compréhension de ton problème  :wink:
 
bonjour, jai un probleme avec le block script jai ce message quand j'ouvre mon coaster:

BlockScript: Block 'Lift' not found

Exception: NullPointerException
                at private void BlockScript.updateControlPanel() in line 414
                at public void BlockScript.onAutoMode(com.nolimitscoaster.Coaster)
                at void com.nolimitscoaster.Coaster.handleScriptedBlockSystemEvents()

merci si quelqu'un a la réponse
 
adrien0210 a dit:
bonjour, jai un probleme avec le block script jai ce message quand j'ouvre mon coaster:

BlockScript: Block 'Lift' not found

merci si quelqu'un a la réponse

Dans l'éditeur, il faut que le nom du bloc lift est le même que dans ton script... Càd "Lift" dans le propriétés de celui ci..
Voilà...