Usando Diferentes “states”
LSL não é multithreaded. Isso quer dizer que não há como tratar a ocorrência de mais de um evento ao mesmo tempo, e um evento não pode interromper um outro. Ou seja: “timer” não interrompe um loop que acontece dentro de um “touch“. Além disso existem outras coisinhas, conhecidas como “annoyances” e seus conhecidos “hacks“. Uma annoyance bem conhecida e bem chata é que por LSL não ser multithreaded algumas coisas se sobrepõe: timers, permissionrequests, etc. Ou seja: chamando llSetTimerEvent() a segunda vez elemina o primeiro, chamando llRequestPermissions() a segunda vez desativa a primeira.
Não dá pra fazer 2 timers, ou setar permissões para coisas diferentes (como animar o avatar ou anexar algo a ele) em pontos diferentes do script, a menos que você saiba usar vários states.
Um “state” é uma condição ou situação dentro do script. Uma manira elegante de fazer o que muita gente faz com flags. Pense em uma lâmpada, que pode ficar acesa ou apagada. Há algumas maneiras de saber se a lâmpada está acesa, ou apagada:
- Usando polling: “lâmpada, você está acesa, ou apagada?”
- Usando flags: “menino, toda vez que aquela lâmpada acender, você grita, ok?”
- Por sobreposição de efeitos: “hm, a mesa está iluminada, isto é consequência da lâmpada estar acesa”
Mas você quer mais. Você quer que o interruptor saiba de alguma forma se a lâmpada está acesa ou apagada: se estiver acesa, apague a lâmpada, se estiver apagada, acenda, mas você não fica por aí falando com o interruptor, dizendo a ele o que fazer, e nem se preocupa se o interruptor precisa ou não perguntar à lâmpada se ela está acesa ou apagada…
É isso que um state faz, basicamente. Funciona como um flag que você não precisa se lembrar de setar, que guarda a informação de que parte o script se encontra. Isso faz com que você possa tratar de eventos de maneira diferenciada em diferentes sequências do script.
e SIM!! é possível criar (por exemplo) timers diferentes desde que eles estejam em states diferentes! Ou permite que você obtenha permissões com llRequestPermissions() para controlar os movimentos do avatar enquanto o anima.
No caso simples da lâmpada, vamos traduzir seus estados (states) para o LSL. Quero que a lâmpada inicie apagada. Depois que eu fizer alguma coisa, como tocá-la, ela deve acender. Se eu tocá-la quando acesa, quero que ela apague.
Todo script tem um estado “default“. Aaaaah !! Então é por isso que sempre tem um bloco desses:
default
{
//tudo que acontece vai aqui dentro
}
Sim! Exatamente por isso. É o estado padrão (default) do objeto que contém o script, ou seja, o estado inicial da coisa. Para nossa lâmpada, o default representa a lâmpada apagada. Então criaremos um tratamento para o “touch” que acenderá a lâmpada, dentro do “default”.
default
{
//nessa parte, a lâmpada está apagada
touch(integer number)
{
//aqui eu acendo a lâmpada
}
}
Agora, temos que criar um segundo estado, o estado da lâmpada acesa. A declaração é feita usando a tag “state”, e dando um nome ao estado. Faremos isso logo abaixo do final do estado default.
default
{
//nessa parte, a lâmpada está apagada
touch(integer number)
{
//aqui eu acendo a lâmpada
}
}
state acesa
{
//nessa parte, a lâmpada está acesa
}
Declaração feita, lembamos que quando a lâmpada está acesa, queremos apagá-la usando touch. Isso é feito tão fácil quando acender a lâmpada, oras, do jeito que sempre fizemos.
default
{
//nessa parte, a lâmpada está apagada
touch(integer number)
{
//aqui eu acendo a lâmpada
}
}
state acesa
{
//nessa parte, a lâmpada está acesa
touch(integer number)
{
//aqui eu apago a lâmpada
}
}
Pronto…! Ou quase… temos os dois estados, mas o script ainda não alterna entre eles. Basta adicionar as chamadas dos estados.
default
{
//nessa parte, a lâmpada está apagada
touch(integer number)
{
//aqui eu acendo a lâmpada
state acesa;
}
}
state acesa
{
//nessa parte, a lâmpada está acesa
touch(integer number)
{
//aqui eu apago a lâmpada
state default;
}
}
Digamos que sempre que a lâmpada entrar no estado acesa ela diga “me acenderam” e sempre que entrar no estado apagada, ela diga “me apagaram”. Oras, bastaria usar o state_entry().
default
{
//nessa parte, a lâmpada está apagada
state_entry()
{
llSay(0, "Me apagaram!");
}
touch(integer number)
{
//aqui eu acendo a lâmpada
state acesa;
}
}
state acesa
{
//nessa parte, a lâmpada está acesa
state_entry()
{
llSay(0, "Me acenderam!");
}
touch(integer number)
{
//aqui eu apago a lâmpada
state default;
}
}
É como se você escrevesse diferentes scripts para os diferentes comportamentos que você espera dos eventos durante cada parte da sequência do script, sem ter que se preocupar em saber em qual parte da execução o script está. Este último exemplo funciona! Pode copiar e colar dentro de um objeto qualquer dentro do SL e veja como funciona… Clique no objeto e observe a mágica!
Mágica? Não!! Cleverness!
nossa !
gostei mto desse tutorial
com isso eu tbm queria saber se dá pra fazer 2 tipos de script
no state desligado um tipo
no ligado outro tipo??
tbm gostaria que vc mostrasse um tutorial de como fazer o comando de voz
por exemplo
um comando pra particula começar
e outro pr desligar
tem como
brigado c tah ajudando mto noOois
Kisses naryuuu