Orologio Analogico

24

Click here to load reader

Transcript of Orologio Analogico

Page 1: Orologio Analogico

Lezione di Build & Script

Come costruire un orologio analogico

Salahzar Stenvaag

Agosto 2008

La lezione non è difficile ma prevede la conoscenza almeno base della costruzione e dello scripting.

Per intenderci dovreste sapere come costruire box, cilindri tagliarli e linkarli assieme (lato build) e

come costruire uno script base e aver visto almeno la base della comunicazione llSay/listen.

Page 2: Orologio Analogico

0. Il progetto

1. la parte di build (3 lancette + la base)

2. lo script per le ore

3. per i minuti

4. per i secondi

5. lo script che fa ticcare il tutto

Page 3: Orologio Analogico

Scopo della lezione è insegnarvi a costruire un orologio analogico, utile da mettere in costruzioni (campanili), orologi da polso,

ed in genere per dimostrarvi:

la comunicazione all'interno di oggetti linkati (llMessageLinked/link_message)

istruzioni di movimentazione di oggetti linkati (llSetLocalRot)

accesso alle funzioni di data/ora utilizzo di un timer

Page 4: Orologio Analogico

0. Il progetto.

La nostra idea è semplice: costruiamo 3 lancette di dimensioni diverse e le poniamo sopra una base circolare.

Abbiamo un "ticker", un contatore che ogni secondo verifica l'ora e manda alle 3 lancette un segnale in modo che le lancette si dispongano in maniera conveniente.

Il ticker è un semplice timer che ogni secondo prende la data/ora, estra le informazioni relative a HH MM SS ed invia

HH => alla lancetta delle ore MM => alla lancetta dei minuti SS => alla lancetta dei secondi

Page 5: Orologio Analogico

1. la parte di build.

Le lancette devono poter essere facilmente ruotate attorno al perno centrale. Questo ci conduce ad un piccolo problema:

se le lancette le faccio con un box appiattito (es. 3m x 20cm x 1 cm) l'istruzione di rotazione lo muoverebbe attorno al suo centro e non avrei chiaramente indicazione di dove sta puntanto (si potrebbe mettere una texture trasparente per metà), ma io ho trovato una soluzione più elegante:

useremo dei box "tagliati" in modo che il centro stia ad una estremità.

Questo si ottiene con il seguente trucchetto:

Page 6: Orologio Analogico

- step 0: facciamo un normale box parallelepipoidale (10x.5x.5)

- step 1: se tagliamo il box fra 0.75 e 1.00 otteniamo una specie di spicchio.

- step 2: riducendo lo spessore lungo la Y al minimo possibile abbiamo una lamina rettangolare

Che può essere ruotata attorno all'asse Y facilmente per produrre le ore volute

La lancetta in questione la duplichiamo 3 volte cambiando la Z in modo da avere larghezza diversa.

Noi abbiamo utilizzato larghezza 0.10 per i secondi (lunghezza 4.9), 0.15 per i minuti (lunghezza 4.5) 0.25 per le ore (2.5). A questo punto le lancette vanno accostate con lo stesso centro, costruite un cilindro 5x5x0.01, usando

Page 7: Orologio Analogico

una texture opportuna linkiamo tutto assieme avendo cura di avere il cilindro come root prim (ultimo a essere cliccato) e voilà dal punto di vista costruttivo abbiamo fatto il nostro orologione. :)

2. Lo script per le ore

Come dicevo le lancette si limitano ad "ascoltare" sul canale dei messaggi interni finchè non compare un messaggio.

I messaggi vengono inviati come llMessageLinked all'intero oggetto linkato specificando "H" o "M" o "S" sul campo "key" e nel campo str il valore con la virgola di dove si deve mettere la lancetta es 5.4. Questo per avere uno spostamento molto

Page 8: Orologio Analogico

lineare delle lancette (eccetto la lancetta dei secondi che si muoverà a scatti).

Page 9: Orologio Analogico

Lo script per le ore è il seguente (TickHour):

default {

link_message(integer sendnum, integer channel, string str, key id) {

if((string)id=="H") {

// use str as the number to tick hour

float hour=(float)str;

vector myrotation=<90,270 -360 * (hour/12.0),0 >;

llSetLocalRot(llEuler2Rot(DEG_TO_RAD* myrotation));

} } }

* Come vedete risponde solo quando il parametro id vale "H" (così le lancette non si confondono).

* Prende il valore con la virgola estratta dal dato passato e lo mette in un float.

Page 10: Orologio Analogico

* Calcola la rotazione Euleriana in gradi lungo i 3 assi.

* In maniera empirica ho visto che se hour=0, la rotazione da fargli assumere è 270 gradi (verifica sul campo).

270-360*(hour/12.0) server per avere una rotazione espressa in gradi corretta, dove ogni incremento di hour corrisponde a 1/12 di angolo giro (360 gradi).

* la rotazione euleriana in gradi viene ricondotta in radianti e come di rotazione elementare

* Infine si setta la rotazione rispetto al root prim

Per provare questo script avevo messo:

1\ una llListen solo all'owner nello state_entry

2\ una listen che rimandava il dato ascoltato come message linked con chiave H

Page 11: Orologio Analogico

state_entry(){

llListen(0,"",llGetOwner(),"");

}

listen(integer channel,string name, key id, string data)

{

llMessageLinked(LINK_SET,0,data,"H");

}

ed alcuni llSay(0, ) in posizioni strategiche dello script :)

3. Lo script per i minuti

Avendo in mano lo script per le ore già testato, lo replichiamo per rispondere ai minuti. Attenzione che le ore sono espresse in dodicesimi di angolo, ma i minuti sono in sessantesimi.

Page 12: Orologio Analogico

Da qui lo script (TickMinute):

default {

link_message(integer sendnum, integer channel, string str, key id) {

if((string)id=="M") {

// use str as the number to tick hour

float minute=(float)str;

vector myrotation=<90,270-360*(minute/60.0),0>;

llSetLocalRot(llEuler2Rot(DEG_TO_RAD*myrotation)); }

}} Notate la divisione per 60.

Page 13: Orologio Analogico

4. Lo script per i secondi.

E' identico a quello dei minuti:

default {

link_message(integer sendnum, integer channel, string str, key id) {

if((string)id=="S") {

// use str as the number to tick hour

integer second=(integer)str;

vector myrotation= <90,270 – 360 * ((float) second/60.0),0>;

llSetLocalRot(llEuler2Rot(DEG_TO_RAD*myrotation));

}}}

Page 14: Orologio Analogico

5. Il cuore: il ticker centrale che istruisce le lancette:

default {

state_entry() {

llSetTimerEvent(1);

}

timer() {

// ottiene ora/minuti/secondi e calcola lo spostamento delle ore e minuti

list timestamp = llParseString2List( llGetTimestamp(), ["T",":","Z"] , [] );

float hour= llList2Float(timestamp,1) + llList2Float (timestamp,2) / 60.0;

float minutes= llList2Float(timestamp,2)+ llList2Float(timestamp,3) / 60.0;

Page 15: Orologio Analogico

// manda il segnale alle ore “H”, minuti “M” e secondif “S”

llMessageLinked(LINK_SET,0,(string)hour,(key)"H");

llMessageLinked(LINK_SET,0,(string)minutes,(key)"M");

llMessageLinked(LINK_SET,0,llList2String( timestamp, 3 ),(key)"S");

// visualizza comunque la data come testo flottante

llSetText(llList2String(timestamp,1)+":"+llList2String(timestamp,2)+":"+llGetSubString(llList2String(timestamp,3),0,2),<1,1,0>,1); }}

* Lo state_entry si limita ad impostare il timer ogni secondo

Page 16: Orologio Analogico

* il timer va a vedere che ore sono (llGetTimeStamp() espresso in tempo UTC (quello di Greenwich), anche chiamato ZULU time

* parsifica la data estraendone i vari pezzettini dentro una lista [ xx, v1, v2, v3 ]

* v1 contiene le ore, v2 i minuti, v3 i secondi

* l'ora viene calcolata come ora + minuti/60 per avere lo spostamento "dolce" delle ore

* i minuti vengono calcolati come minuti + secondi/60 analogamente

* le tre informazioni vengono inviate alle lancette che "obbediscono".

Page 17: Orologio Analogico

6. Conclusioni.

Avete in mano un freebie semplice e funzionale.

E' migliorabile in molti modi, a partire dalla texture per le ore.

Si potrebbe anche usare in luogo delle lancette dei cilindri con alpha channel con sopra dipinte le frecce.

Il problema però è che secondlife quando si usa troppa trasparenza non capisce più niente. :)

NOTA: A causa di alcuni problemi di refresh del Browser è possibile che non vediate le lancette dei minuti e delle ore muoversi se state immobili davanti. E’ comunque un ottimo esercizio per capire gli oggetti linkati e la comunicazione fra di essi.

Salahzar Stenvaag