[débat] Scratch Vs LSL direct

Répondre
Partager Rechercher
Qu'est ce que scratch?
C'est une interface graphique qui permet de générer du LSL, voici ci dessous une video montrant certaines de ses possibilités


Maintenant il y a pas mal de questions à se poser sur ces deux d'approche du script.
Notamment des dilemmes insolubles.
D'un coté un code obtenu avec un grande productivité sans ou peu de connaissance en script mais avec un code répugnant et impossible à maintenir.
De l'autre de la performance, des possibilités beaucoup plus larges, mais nécessitant un apprentissage.

L'objectif n'est pas d'obtenir une victoire par KO sur l'une des deux méthodes, mais de voir comment tirer le meilleur parti des deux et laquelle est le plus adeptée et pour qui
C'est comme du HTML directe VS Frontpage des années 1990

Je dirait, tout dépends de ce que l'on veux.

Pour un petit gadget qu'on fait comme son premier t-shirt dans SL et qu'on va pas vendre, c'est sympa comme tout de réussir a faire son scripte avec scratch (j'imagine )

Dès qu'on veux aller plus loin, il faut passer du côté code de la force

Et une dernière analogie pour la route: Lance Armstrong a sûrement commencé le vélo avec les petites roulettes de côté, mais il n'aurait jamais rien gagné avec, selon la légende.
Scratch c'est le "Flaubert" du script. Enormément de lignes inutiles (à moins qu'il n'ai évolué depuis peu).

Voici le code obtenu avec Scratch pour faire dire "Hello, avatar!" à une prim au démarrage du script, et "Touched!" si on clique sur elle.

Code:
// The code below was generated by
// SCRATCH FOR SECOND LIFE (S4SL)
// alpha release October 19, 2007
//
// by Eric Rosenbaum (ericr@media.mit.edu)
// MIT Media Lab
// Lifelong Kindergarten group
//
// S4SL is a modified version of Scratch,
// a graphical programming language for kids
// see scratch.mit.edu
//
//
// USER VARIABLES
//
 
//
//  INTERNAL VARIABLES
//
vector home;
integer penState;
float penColor;
float color;
float ghost;
vector originalScale;
float sizePercent;
integer numAvatarsNearby;
vector nearestAvPosition;
key ownerKey;
vector ownerPosition;
//
//   INTERNAL FUNCTIONS
//
// move(steps)
// move object a number of steps (meters) along its current heading
// forward is along the positive x axis
// if the pen is down, create a line segment along the path traveled
// the line is positioned by its center, which is placed halfway back along the path
move(float steps)
{
    vector fwd = llRot2Fwd(llGetRot()) * steps;
    llSetPos(llGetPos() + fwd);
    if (penState == TRUE) {
        if (llGetInventoryType("lineSegment") == INVENTORY_NONE) {
            llSay(0, "Oops! To draw a line, my inventory needs a lineSegment. You can get one from the Scratch Inventory Box.");
        } else {
                integer randomID = llRound(llFrand(99999999));
            llRezObject("lineSegment", llGetPos()-fwd/2, <0,0,0>, llGetRot(), randomID);
            llSay(1, (string)randomID + ":set length:"+ (string)llFabs(steps));
            llSay(1, (string)randomID + ":set color:" + (string)penColor);
        }
    }
}
// turnRight(float angle)
// turn angle degrees clockwise around the local z axis
turnRight(float angle)
{
    angle *= -1;
    rotation newRot = llEuler2Rot(<0,0,angle> * DEG_TO_RAD);
    llSetRot(newRot*llGetRot());
}
// turnLeft(float angle)
// turn angle degrees counterclockwise around the local z axis
turnLeft(float angle)
{
    rotation newRot = llEuler2Rot(<0,0,angle> * DEG_TO_RAD);
    llSetRot(newRot*llGetRot());
}
//up(float steps)
//move up along the global z axis by steps meters
//does not leave a line segment
up(float steps)
{
    llSetPos(llGetPos()+<0,0,steps>);
}
//down(float steps)
//move down along the global z axis by steps meters
//does not leave a line segment
down(float steps)
{
    llSetPos(llGetPos()+<0,0,-1*steps>);
}
// turnPitch(float angle)
// turn angle degrees upward around the local y axis
turnPitch(float angle)
{
    angle *= -1;
    rotation newRot = llEuler2Rot(<0,angle,0> * DEG_TO_RAD);
    llSetRot(newRot*llGetRot());
}
// float getHeading()
// return the current heading in the xy plane in degrees
float getHeading() {
    return llRot2Angle(llGetRot())*RAD_TO_DEG;
}
// setHeading(float angle)
// set the heading in the xy plane in degrees
setHeading(float angle) {
    vector newVec = <0, 0, angle*DEG_TO_RAD>;
    rotation newRot = llEuler2Rot(newVec);
    llSetRot(newRot);
}
// turnRoll(float angle)
// turn angle degrees clockwise around the local x axis
turnRoll(float angle)
{
    rotation newRot = llEuler2Rot(<angle,0,0> * DEG_TO_RAD);
    llSetRot(newRot*llGetRot());
}
// changePenColorBy(float num)
// change the pen color by an amount
changePenColorBy(float num)
{
    penColor += num;
    setPenColorTo(penColor);
}
// setPenColorTo(float num)
// set the pen to a particular color
setPenColorTo(float num)
{
    penColor = (integer)num % 100;
}
// penDown()
// put the pen down, so that when the object moves it will draw
penDown() {
    penState = TRUE;
}
// penUp()
// put the pen up, so that the object will not draw when it moves
penUp() {
    penState = FALSE;
}
// clear()
// broadcast a message to nearby line segments that will cause them to
// delete themselves
clear() {
    llSay(1, "clearLineSegments");
}
// pointTowardNearestAv()
// turn to point toward the nearest avatar
pointTowardNearestAv()
{
    vector myPos = llGetPos();
    float xdiff = myPos.x - nearestAvPosition.x;
    float ydiff = myPos.y - nearestAvPosition.y;
    float angle = llAtan2(xdiff, ydiff) * RAD_TO_DEG;
    setHeading(270 - angle);
}
// pointTowardOwner()
// turn to point toward the owner
pointTowardOwner()
{
    vector myPos = llGetPos();
    float xdiff = myPos.x - ownerPosition.x;
    float ydiff = myPos.y - ownerPosition.y;
    float angle = llAtan2(xdiff, ydiff) * RAD_TO_DEG;
    setHeading(270 - angle);
}
// float distanceToNearestAv()
// returns the distance in meters to the nearest avatar
float distanceToNearestAv()
{
    return llVecDist(llGetPos(), nearestAvPosition);
}
// float distanceToOwner()
// returns the distance in meters to the owner
float distanceToOwner()
{
    return llVecDist(llGetPos(), ownerPosition);
}
// float randomMinToMax(float min, float max)
// returns a random number between min and max
integer randomMinToMax(float min, float max)
{
    return llRound(llFrand(max - min) + min);
}
// say(string text)
// say the text on the public chat channel 0 so all nearby avatars and objects will hear it
say(string text)
{
    llSay(0, text);
}
// broadcast(string message)
// say the message on channel 1.  No avatars will hear it.
// all nearby objects will hear it.
broadcast(string message)
{
    llSay(1, message);
}
// setText(string text)
// create opaque white floating text above the object
setText(string text)
{
    llSetText(text, <1,1,1>, 1);
}
// vector hueToRGB(float h)
// take a color represented as a hue value between 1 and 100 and
// return an RGB vector representing the same color.
vector hueToRGB(float h)
{
    integer i;
    float f;
    float p;
    float q;
    float t;
    float r;
    float g;
    float b;
    float s = 1;
    float v = 1;
    h *= 5;            // sector 0 to 5
    i = llFloor(h);
    f = h - i;            // factorial part of h
    p = v * ( 1 - s );
    q = v * ( 1 - s * f );
    t = v * ( 1 - s * ( 1 - f ) );
    if (i == 0) {
        r = v;
        g = t;
        b = p;
    } else if (i == 1) {
            r = q;
        g = v;
        b = p;
    } else if (i == 2) {
            r = p;
        g = v;
        b = t;
    } else if (i == 3) {
            r = p;
        g = q;
        b = v;
    } else if (i == 4) {
            r = t;
        g = p;
        b = v;
    } else {
            r = v;
        g = p;
        b = q;
    }
    return <r,g,b>;
}
// setColor(float num)
// set the color of the object using a number between 1 and 100 representing a hue
setColor(float num)
{
    color = (integer)num % 100;
    llSetColor(hueToRGB(color / 100), ALL_SIDES);
    if (llGetObjectName() == "Scratch Bug") {
        llSetLinkColor(2, hueToRGB(color / 100), ALL_SIDES);
    } else {
            //llSetLinkColor(LINK_SET, hueToRGB(color / 100), ALL_SIDES);
        }
}
// changeColorBy(float num)
// change the hue of the object by a number
changeColorBy(float num)
{
    float newColor = color + num;
    if (newColor < 0) {
        newColor = 0;
    }
    if (newColor > 100) {
        newColor = 100;
    }
    setColor(newColor);
}
// setGhost(float num)
// set the ghost effect of the object to a value between 0 (opaque) and 100 (transparent)
setGhost(float num)
{
    ghost = (integer)num % 101;
    llSetAlpha(((100 - ghost) / 100), ALL_SIDES);
    llSetLinkAlpha(LINK_SET, ((100 - ghost) / 100), ALL_SIDES);
}
// changeGhostBy(float num)
// change the ghost effect on an object by a number
changeGhostBy(float num)
{
    setGhost(ghost + num);
}
// setSize(float newSize)
// set the size of the object to a percentage of its original size
setSize(float newSize)
{
    sizePercent = newSize;
    vector newScale = originalScale*(sizePercent/100);
    llSetScale(newScale);
}
// changeSizeBy(float change)
// change the size of an object by a percentage of its original size
changeSizeBy(float change)
{
    sizePercent += change;
    vector newScale = originalScale*(sizePercent/100);
    llSetScale(newScale);
}
// playSound(string snd)
// play a sound at full volume
// snd can be the name of a sound in the inventory of the object, or the
// UUID of a sound which exists somewhere else
playSound(string snd)
{
    llPlaySound(snd, 1);
}
// playSoundNamed(string snd)
// play a sound at full volume
// snd can be the name of a sound in the inventory of the object, or the
// UUID of a sound which exists somewhere else
// this is the version for text input of the name of a sound in a scratch block
// so it checks the inventory and gives an error if the sound is missing
playSoundNamed(string snd)
{
    if (llGetInventoryType(snd) == INVENTORY_NONE) {
        llSay(0, "Oops! My inventory does not contain the sound " + snd);
    } else {
            llPlaySound(snd, 1);
    }
}
// wait(float secs)
// pause all execution of this script for some number of seconds
wait(float secs)
{
    llSleep(secs);
}
// levelOut()
// remove the x and y rotation components, so that the object is
// level with respect to the ground
levelOut()
{
    vector myVec = llRot2Euler(llGetRot());
    vector newVec = <0, 0, myVec.z>;
    rotation newRot = llEuler2Rot(newVec);
    llSetRot(newRot);
}
// goHome()
// move the object back to its home position
// home is set the the position of the object when it is created,
// and can be set to a new position using setHomeHere()
goHome()
{
    llSetPos(home);
    //levelOut();
}
// setHomeHere()
// set the home position to the current position
setHomeHere()
{
    home = llGetPos();
}
// startListening()
// listen for messages on both channel 0, the public channel,
// and channel 1, where broadcasts are sent
startListening()
{
    llListen(0, "", "", "");
    llListen(1, "", "", "");
}
// initInternal()
// do some setup for internal functions
// this includes setting various variables to their defaults
// clearing text on the object, and turning on
// the repeating sensor and timer events
initInternal()
{
    setHomeHere();
    penState = FALSE;
    penColor = 0;
    color = 0;
    ghost = 0;
    sizePercent = 100;
    originalScale = llGetScale();
    ownerKey = llGetOwner();
    llSetText("", <1,1,1>, 0);
    llSensorRepeat("", "", AGENT, 96, PI, .1);
    llSetTimerEvent(.1);
    startListening();
}
initAll() {
    initInternal();
    created1();
}
touch1(){
    say("Touched!");
}
created1(){
    say("Hello Avatar!");
}
default
{
    state_entry()
    {
        initAll();
    }
    on_rez(integer start_param)
    {
        initAll();
    }
    sensor(integer n)
    {
        numAvatarsNearby = n;
        nearestAvPosition = llDetectedPos(0);
        integer i;
        for (i=0; i<n; i++) {
            if (llDetectedKey(i) == ownerKey) {
                ownerPosition = llDetectedPos(i);
            }
        }
    }
    touch_start(integer n) {
        touch1();
    }
    collision_start(integer n) {
    }
    listen(integer channel, string name, key id, string msg) {
    }
    timer() {
    }
}
//<?xml version="1.0" encoding="UTF-8" ?><scratchScript><block event="Scratch-MouseClickEvent"/><block selector="say:"><argument>Hello!</argument></block></scratchScript>
//<?xml version="1.0" encoding="UTF-8" ?><scratchScript><block event="Scratch-created"/><block selector="say:"><argument>Hello!</argument></block></scratchScript>

Je préfère nettement la version de base de l'éditeur interne à SL.

Par contre il est clair que celui qui ne connaît pas du tout le LSL va trouver cet outil pratique, mais il risque d'être très vite écoeuré s'il essaye de comprendre le fonctionnement d'un script généré avec Scratch.
Encore un truc pour dire "si vous voulez commencer le LSL et bien ne le faites pas". Ce scratch est un véritable pollueur de code, comme la plupart des générateurs. Mais il ne s'arrête pas là, il pollue également ceux qui s'intéressent à l'aspect dynamique de SL. Et ce n'est pas l'explication bateau "c'est bien pour celui qui veut juste faire bouger un truc sans se poser de question et sans songer à le vendre" qui me fera changer d'avis sur l'intérêt de ce machin (désolée pour ceux qui ont passé du temps à le développer).
Je peu souscrire au côté immorale d'apporter des burger frittes pour enrayer la malnutrition... dans le cas de la malnutrition.

Mais ici, même si tout codeur s'accordera sur l'aspect parfaitement beurk de ce code, qu'y a-t-il de si malsain à laisser cette "malboufe du scripte" à disposition de ceux qui n'ont pas accès à la gastronomie du code moléculaire? Si ce n'est en entretenant la gangrène du "tout tout de suite" qui fait tant de mal par ailleurs à notre société...
[Modéré par Biouby : Les voyages des sujets forment la jeunesse, désolée pour le dérangement. (Ouaisss j'ai modéré Oklyshhh) ]

[Modéré par Oklysh: Je te hais Biouby.]

[Encore un fan! <3]
Vous tous trop manichéens scratch a plein d'avantage.

Le premier de permettre d'avoir une première approche de la programmation en douceur sans avoir à se soucier de la syntax

De comprendre ce qu'est de l'évènementiel, notion par forcément évidente quand on commence.

Travailler sur des rotations et des déplacements fixe comme le ferait un puppeter n'est pas une chose évidente pour un débutant et c'est tellment simple avec scratch

je suis clairement un defenseur du code "propre" mais peut etre un plus grand défenseur de la pédagogie et de la vulgarisation.

Il n'existe pas aujourd'hui de programme capable de générer du code optimiser, vous avez deja regarder le code générer par les macros EXCEL ?

Mais scratch présente cet avantage de faire de chose simple rapidement.

Combien de scripteur se sont cassé les dents sur crée une simple porte?
Alors que c'est si simple avec scratch.
Ok c'est dégueulasse mais au moins c'est simple et fonctionel et sans connaissance.

Très vite par contre on est limité avec scratch et si on veut aller plus loin il faut absolument faire sur LSL à la main
Mais peut etre que cette transition se fera plus en douceur que de commencer par l'aspect rebutant et rigide de la syntaxe du LSL


Sinon, quelqu'un a essayer de le comprendre ce simple script hello avatar , ben essayez et vous comprendrez comment ca marche tout ca
Ouch. J'ai jamais compris l'intérêt d'un tel logiciel.

Premièrement parce qu'il génère du code horrible, un script d'une centaine de ligne pour un "Hello avatar" et "touched" c'est vraiment moyen je trouve.

Deuxièmement un débutant n'y apprend rien pour la même raison évoquée sur le premier point : script dégueulasse et vite illisible. Au final le LSL va le repousser et il continuera à l'utiliser sans essayer de comprendre comment ça se passe derrière.

Et un petit troisièmement, il ne faut pas abuser non plus le LSL a justement été crée pour être très simple et accessible par tout le monde. L'apprentissage peut se faire en quelques jours pour créer des scripts basiques :
- déplacements
- rotations (simples)
- faire parler un objet
- les évènements comme touch_start, state_entry etc

On arrive donc vite à 30% de ce que fait ce fameux scratch. Après bien sûr il y a aussi la catégorie de personnes qui ne veulent tout simplement pas apprendre le LSL mais c'est différent.
Bonsoir,

Ce n'est pas mal du tout pour moi qui ne sais même pas faire une porte qui s'ouvre quand je lui dit "sésame". Là c'est fait en deux coup de cuillère à pot.

Bon, de là à faire un script pour un avion... Y'a un pas

C'est juste un avis de nul en programmation.
Bonjour

il me fait penser a l'époque a Dreamweaver, le pollueur de code html,
une plaie a l'époque pour les gens qui désiraient du code propre et optimisés surtout au temps de la préhistoire ou on regardais la taille d'une page html pour passer dans les goulot des modems a 36,6k o

avec le temps Dream c'est améliorer (je ne dis pas parfait) mais le code nettement mieux adapté et plus compréhensible.

perso je ne pense pas accroché par scratch, mais il trouvera sa place voir même au delà , avec le temps le développeur de scratch saura surement modifier le code pour que lorsque l'on demande un simple "hello avatar" il evitera d'intégrer les fonction de rotation etc

Je ne ferais donc pas la même erreur qu'avec dream que j'assassinais en disant que c'était nul , pourri et anti développeur..
je ne pense pas non plus d'adopté, mais après tout "bonne chance scratch"

P.S je serais curieux de connaitre le taux de lag généré par un simple mouvement afin de savoir si je doit raler après les utilisateurs de script générer avec scratch
__________________
Paris 1900
http://www.paris1900.net
Bon je vais continuer à me faire l'avocat du diable et défendre scratch

Au lieu de critiqué les centaines de ligne généré par scratch pour un hello avatar LISEZ LE !!! C'est une structure de base, c'est tout

Citation :
Deuxièmement un débutant n'y apprend rien pour la même raison évoquée sur le premier point : script dégueulasse et vite illisible. Au final le LSL va le repousser et il continuera à l'utiliser sans essayer de comprendre comment ça se passe derrière.
Parce que tu pars sur le postulat que le débutant doit lire le code?
Il est clair que pour les débutants je déconseille de lire le code, d'ailleurs ca ne sert à rien il n'y comprendrons rien.

Une approche en douceur de la programmation en utilisant que l'aspect visuel uniquement permettant d'etre plus parlant

Un gain de productivité aussi pour ceux qui débute.
l'intervention de peuk est interessante, car il n'est a première vu pas un scripteur ou un programmeur ce qui je ne crois pas que se soit votre cas

Une variable, c'est une notion simple, évidente, non?
Ben allez l'expliquer ca à une personne qui n'a jamais vu de script ou qui n'a aucune notion dans le domaine.
Peut être alors que vous remettrez en cause votre conception de l'apprentissage du LSL
OUI ca permet au debutant d'avoir une approche en douceur de la programmation.

NON ca ne permet pas au debutant d'avoir une approche (meme en douceur) du LSL.

D'apres moi, ce logiciel permet au neophyte d'entrer dans le monde de la programmation en général sur un coussin mais pas dans le LSL spécifiquement car le script généré n'est pas instructif et représentatif du LSL.

Par contre, ca permet de ne pas rentrer dans la programmation LSL aussi ! (dans ce sens c'est fait expres) donc ca permet a l'utilisateur occasionnel de faire un script fonctionnel rapidemment sans connaissances en LSL.

Pour conclure je dirais que ce logiciel est bien pour montrer qu'il n'est pas bien ^^ ou pour maintenir loin les debutants du LSL. Je suis peut etre un peu rude mais c'est ma (la?) vérité.
Oui Scratch est une horreur: à mon avis, pour ceux qui veulent apprendre, il ne peut que les dégouter, les dérouter, leur faire croire que scripter est compliqué.

Bon pour ceux qui ne veulent pas apprendre il peut dépanner; mais faut pas s'étonner si ça lag après: je le répéte c'est une horreur.

Je suis surprise que toi Magic, un scripteur de ton niveau, tente de promouvoir cette cochonnerie.
ben elenia, je crois que vais répondre à ta question en faisant carrément un wiki

/me fouille au fin fond de son inventaire pour retrouver ses cours de LSL avec scratch comme prérequis
Désolé de revenir sur cet ancien post .

Personnelement , je ne trouve pas le code affreux .

Peut etre que les gens ne savent pas lire correctement un script .
Certes il y a beaucoup de lignes pour faire les fonctions mais lsl est gèré par les évenements . C est le code a l intérieur des evenements qui détermine la complexité du script
De plus , si vous avez un viewer comme phoenix emergence ou autre , vous pouvez checker "enable preprocessing" puis "optimize"
Vous avez comme résultat un script de taille très correcte dans le résultat post-processed

Code PHP:

float sizePercent;
integer penState;
float penColor;
vector ownerPosition;
key ownerKey;
vector originalScale;
integer numAvatarsNearby;
vector nearestAvPosition;
vector home;
float ghost;
float color;
 
say(string text)
{
    
llSay(0text);
}
created1(){
    
say("Hello Avatar!");
}
touch1(){
    
say("Touched!");
}
 
 
startListening()
{
    
llListen(0"""""");
    
llListen(1"""""");
}
 
setHomeHere()
{
    
home llGetPos();
}
 
 
 
initInternal()
{
    
setHomeHere();
    
penState FALSE;
    
penColor 0;
    
color 0;
    
ghost 0;
    
sizePercent 100;
    
originalScale llGetScale();
    
ownerKey llGetOwner();
    
llSetText("", <1,1,1>, 0);
    
llSensorRepeat(""""AGENT96PI.1);
    
llSetTimerEvent(.1);
    
startListening();
}
initAll() {
    
initInternal();
    
created1();
}
default
{
    
state_entry()
    {
        
initAll();
    }
    
on_rez(integer start_param)
    {
        
initAll();
    }
    
sensor(integer n)
    {
        
numAvatarsNearby n;
        
nearestAvPosition llDetectedPos(0);
        
integer i;
        for (
i=0i<ni++) {
            if (
llDetectedKey(i) == ownerKey) {
                
ownerPosition llDetectedPos(i);
            }
        }
    }
    
touch_start(integer n) {
        
touch1();
    }
    
collision_start(integer n) {
    }
    
listen(integer channelstring namekey idstring msg) {
    }
    
timer() {
    }

En revanche , le principal souci est l initialisation d un timer et d un listener qui ecoute tout le monde .
Je suppose que la personne dans le post qui a utilisé scratch a oublié d enlever cela
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés