20 March 2012
llResetScript
to switch to the destination owner key when the game is given away. Marketplace product will be updated since people may have had problems because the scripts used my own avatar key (bug, feature, idk… It is documented at llGetOwner
).This is the implementation of a very popular game, which appeared around the 70s and became a standard for Nokia phones in 1988. This is an implementation of the game in Second Life by using a HUD and a frame for the snake.
Soundtrack: Ulrich Schnauss - Passing By.
The game has 3 main components:
The task is to eat as much snake food as possible by moving around using the HUD and without colliding with the snake's body or going out of bounds. Any collision will end the game.
The full implementation may be found on marketplace.
This part goes in the snake frame.
////////////////////////////////////////////////////////// // WaS (c) grimore.org - 2012, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // ////////////////////////////////////////////////////////// integer _comChannel = 0; vector oPos = ZERO_VECTOR; vector sPos = ZERO_VECTOR; integer tItra = 0; integer fItra = 0; list tail = []; list food = []; integer TRAIL = 1; //pragma inline processFood(integer fIdx) { if(fIdx == -1) return; if(llVecDist(llList2Vector(food, fIdx), llGetPos() + oPos) > .5) jump next; ++TRAIL; food = llListReplaceList(food, (list)"", fIdx, fIdx); generateFood(1); llRegionSay(_comChannel, "EAT," + (string)(fIdx+1)); @next; processFood(--fIdx); } generateFood(integer num) { if(num == 0) return; vector fPos = <sPos.x + llFrand(5)*llList2Float([-1, 1], (integer)llFrand(2)), sPos.y, sPos.z + llFrand(5)*llList2Float([-1, 1], (integer)llFrand(2))>; food += fPos; llRezObject("[K] Snake Food", fPos, ZERO_VECTOR, ZERO_ROTATION, ++fItra); generateFood(--num); } default { state_entry() { sPos = llGetPos(); _comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llSetLinkPrimitiveParamsFast(2, [PRIM_POSITION, ZERO_VECTOR]); llRegionSay(_comChannel, "CLR"); generateFood(1+(integer)llFrand(10)); llListen(_comChannel, "", "", ""); } at_target(integer tnum, vector targetPos, vector ourPos) { llStopMoveToTarget(); } listen(integer chan,string name,key id,string mes) { if(llGetOwnerKey(id) != llGetOwner()) return; if(mes == "UP") state up; if(mes == "DOWN") state down; if(mes == "LEFT") state left; if(mes == "RIGHT") state right; } changed(integer change) { if(change & CHANGED_OWNER) state cleanup; } on_rez(integer param) { state cleanup; } } state up { state_entry() { llListen(_comChannel, "", "", ""); llSetTimerEvent(1); } listen(integer chan,string name,key id,string mes) { if(llGetOwnerKey(id) != llGetOwner()) return; if(mes == "UP") state up; if(mes == "DOWN") state down; if(mes == "LEFT") state left; if(mes == "RIGHT") state right; } timer() { processFood(llGetListLength(food)-1); if(llFabs(oPos.z + .5) > 5 || ~llListFindList(tail, (list)oPos)) { llOwnerSay("Game Over."); state cleanup; } llRegionSay(_comChannel, "DIE," + (string)(tItra-TRAIL)); if(llGetListLength(tail) == TRAIL) tail = llDeleteSubList(tail, 0, 0); llSetLinkPrimitiveParams(2, [PRIM_POS_LOCAL, (oPos+=<0,0,.5>) / llGetRootRotation()]); llRezObject("[K] Snake Body", llGetPos() + oPos - <0,0,.5>, ZERO_VECTOR, ZERO_ROTATION, tItra++); tail += oPos-<0,0,.5>; } } state down { state_entry() { llListen(_comChannel, "", "", ""); llSetTimerEvent(1); } listen(integer chan,string name,key id,string mes) { if(llGetOwnerKey(id) != llGetOwner()) return; if(mes == "UP") state up; if(mes == "DOWN") state down; if(mes == "LEFT") state left; if(mes == "RIGHT") state right; } timer() { processFood(llGetListLength(food)-1); if(llFabs(oPos.z - .5) > 5 || ~llListFindList(tail, (list)oPos)) { llOwnerSay("Game Over."); state cleanup; } llRegionSay(_comChannel, "DIE," + (string)(tItra-TRAIL)); if(llGetListLength(tail) == TRAIL) tail = llDeleteSubList(tail, 0, 0); llSetLinkPrimitiveParams(2, [PRIM_POS_LOCAL, (oPos-=<0,0,.5>) / llGetRootRotation()]); llRezObject("[K] Snake Body", llGetPos() + oPos + <0,0,.5>, ZERO_VECTOR, ZERO_ROTATION, tItra++); tail += oPos+<0,0,.5>; } } state left { state_entry() { llListen(_comChannel, "", "", ""); llSetTimerEvent(1); } listen(integer chan,string name,key id,string mes) { if(llGetOwnerKey(id) != llGetOwner()) return; if(mes == "UP") state up; if(mes == "DOWN") state down; if(mes == "LEFT") state left; if(mes == "RIGHT") state right; } timer() { processFood(llGetListLength(food)-1); if(llFabs(oPos.x - .5) > 5 || ~llListFindList(tail, (list)oPos)) { llOwnerSay("Game Over."); state cleanup; } llRegionSay(_comChannel, "DIE," + (string)(tItra-TRAIL)); if(llGetListLength(tail) == TRAIL) tail = llDeleteSubList(tail, 0, 0); llSetLinkPrimitiveParams(2, [PRIM_POS_LOCAL, (oPos-=<.5,0,0>) / llGetRootRotation()]); llRezObject("[K] Snake Body", llGetPos() + oPos + <.5,0,0>, ZERO_VECTOR, ZERO_ROTATION, tItra++); tail += oPos+<.5,0,0>; } } state right { state_entry() { llListen(_comChannel, "", "", ""); llSetTimerEvent(1); } listen(integer chan,string name,key id,string mes) { if(llGetOwnerKey(id) != llGetOwner()) return; if(mes == "UP") state up; if(mes == "DOWN") state down; if(mes == "LEFT") state left; if(mes == "RIGHT") state right; } timer() { processFood(llGetListLength(food)-1); if(llFabs(oPos.x + .5) > 5 || ~llListFindList(tail, (list)oPos)) { llOwnerSay("Game Over."); state cleanup; } llRegionSay(_comChannel, "DIE," + (string)(tItra-TRAIL)); if(llGetListLength(tail) == TRAIL) tail = llDeleteSubList(tail, 0, 0); llSetLinkPrimitiveParams(2, [PRIM_POS_LOCAL, (oPos+=<.5,0,0>) / llGetRootRotation()]); llRezObject("[K] Snake Body", llGetPos() + oPos - <.5,0,0>, ZERO_VECTOR, ZERO_ROTATION, tItra++); tail += oPos-<.5,0,0>; } } state cleanup { state_entry() { llRegionSay(_comChannel, "CLR"); llResetScript(); } }
This will have to be copied and modified for all directions: UP, DOWN, LEFT and RIGHT.
////////////////////////////////////////////////////////// // WaS (c) grimore.org - 2012, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // ////////////////////////////////////////////////////////// integer _comChannel; default { state_entry() { _comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(_comChannel, "", llGetOwner(), ""); } touch_start(integer total_number) { llRegionSay(_comChannel, "LEFT"); // Change this to either UP, DOWN, LEFT or RIGHT } on_rez(integer param) { llResetScript(); } }
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// default { state_entry() { integer comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(comChannel, "", "", ""); } listen(integer chan,string name,key id,string mes) { if(mes == "DIE," + llGetObjectDesc()) jump die; if(mes == "CLR") jump die; return; @die; llDie(); } on_rez(integer param) { llSetObjectDesc((string)param); llResetScript(); } }
////////////////////////////////////////////////////////// // WaS (c) grimore.org - 2012, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // ////////////////////////////////////////////////////////// default { state_entry() { integer comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(comChannel, "", "", ""); } listen(integer chan, string name, key id, string mes) { if(mes == "EAT," + llGetObjectDesc()) jump die; if(mes == "CLR") jump die; return; @die; llDie(); } on_rez(integer param) { llSetObjectDesc((string)param); llResetScript(); } }
This snippet will keep track of the food eaten by the snake. This script is optional and should be placed in the snake head.
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2011 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// integer eat = 0; default { state_entry() { llSetText("", <0,0,0>, .0); integer _comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; llListen(_comChannel, "", "", ""); } listen(integer chan,string name,key id,string mes) { if(~llSubStringIndex(mes, "EAT")) { llSetText("Eaten: " + (string)(++eat), <1,1,1>, 1); } if(~llSubStringIndex(mes, "CLR")) { llResetScript(); } } }