Bubble Breaker
De DigiWiki.
Bubble Breaker v0.2
- Rezzer une baballe de taille 0.25, 0.25, 0.25
- Lui insérer ce petit script (ci-dessous).
default { link_message(integer p, integer i, string s, key k) { llSetText(s, <1,1,1>, 1); } }
- Dupliquer cette sphère 80 fois, puis lier l'ensemble sans vous fatiguer à les positionner précisément. Au final, vous devez vous retrouver avec un objet composés de 81 sphères.
- Insérez le script ci-dessous dans l'objet une fois qu'il est lié
// Copyright (c) 2008 - Forest Klaar (Second Life) // // Redistribution and use in source forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Bubble Breaker v0.2 list gBubbles; list gColors = [<1,1,1>, <1,0,0>,<0,1,0>,<0,0,1>,<1,1,0>,<1,0,1>]; list gSelect; integer gScore; string gPlayer; list gBest; integer gLastSelected; // Magic numbers integer TEXT_PRIM = 45; // This prim is responsible of text display integer Ran() { return llFloor(llFrand(4))+1; } BubbleText(integer n, string s) { llMessageLinked(n, 0, s, NULL_KEY); } integer IsGameOver() { integer i; for(i=0; i<81; i++) { integer Type = llList2Integer(gBubbles, i); if (Type != 0) { if (i/9 != 8) { if (Type == llList2Integer(gBubbles, i+9)) return FALSE; } if (i%9 != 8) { if (Type == llList2Integer(gBubbles, i+1)) return FALSE; } } } return TRUE; } Refresh(float alpha) { integer i; for(i=0; i<81; i++) { integer Type = llList2Integer(gBubbles, i); if (Type == 0) llSetLinkAlpha(i+1, 0, ALL_SIDES); else { llSetLinkColor(i+1, llList2Vector(gColors, Type), ALL_SIDES); llSetLinkAlpha(i+1, alpha, ALL_SIDES); } } } Shift(integer n) { integer Col = n/9; if (n%9 == 8) { gBubbles = llListReplaceList(gBubbles, [0], Col*9+8, Col*9+8); return; } list Zone = llList2List(gBubbles, n+1, Col*9+8); gBubbles = llListReplaceList(gBubbles, Zone + [0], n, Col*9+8); } Roll() { integer i; for(i=0; i<9; i++) if (llDumpList2String(llList2List(gBubbles, i*9, i*9+8),"") == "000000000") gBubbles = [0,0,0,0,0,0,0,0,0] + llListReplaceList(gBubbles, [], i*9, i*9+8); } Select(integer n, integer type) { if (n < 0 || n > 80) return; if (llList2Integer(gBubbles, n) != type) return; if (llListFindList(gSelect, [n]) != -1) return; gSelect += n; if (n/9 != 0) Select(n-9, type); if (n/9 != 8) Select(n+9, type); if (n%9 != 0) Select(n-1, type); if (n%9 != 8) Select(n+1, type); } Build() { llSay(0, "Building bubbles.."); float Radius = .25; integer i; integer j; for(i=0; i<9; i++) for(j=0; j<9; j++) if (i+j != 0) llSetLinkPrimitiveParams(i*9+j+1, [PRIM_POSITION, <0, Radius * (float) i, Radius * (float) j>]); llSay(0, "Finished !"); } Demo() { gBubbles = []; integer i; integer c = 1; for (i=0; i<81; i++) { gBubbles += [c++]; if (c > 5) c = 1; } Refresh(1); } Init() { BubbleText(gLastSelected, ""); gBubbles = []; integer i; for (i=0; i<9; i++) gBubbles += [Ran(),Ran(),Ran(),Ran(),Ran(),Ran(),Ran(),Ran(),Ran()]; Refresh(1); } string DisplayScores() { string Display; integer i; integer n=llGetListLength(gBest)/2; for(i=0; i<n; i++) Display += llList2String(gBest, i*2+1) + " : " + llList2String(gBest, i*2) + "\n"; return Display; } SelectHightlight(float alpha) { integer i; integer cn = llGetListLength(gSelect); for (i=0; i<cn; i++) llSetLinkAlpha(llList2Integer(gSelect, i)+1, alpha, ALL_SIDES); } default { state_entry() { Demo(); state waiting; } } state waiting { state_entry() { BubbleText(TEXT_PRIM, "Bubble Breaker\n" + DisplayScores() + "\nTouch me to start a game"); llListen(5, "", llGetOwner(), ""); } listen(integer c, string n, key k, string m) { if (m == "build") Build(); } touch_start(integer c) { gPlayer = llDetectedName(0); Init(); state game; } } state game { state_entry() { gScore = 0; BubbleText(TEXT_PRIM, gPlayer + " is playing\nScore: " + (string) gScore); } touch_start(integer c) { integer n = llDetectedLinkNumber(0)-1; integer Type = llList2Integer(gBubbles, n); if (Type == 0) return; BubbleText(gLastSelected, ""); integer i; if (llListFindList(gSelect, [n]) != -1) { gSelect = llListSort(gSelect, 1, FALSE); integer ct = llGetListLength(gSelect); for (i=0; i<ct; i++) Shift(llList2Integer(gSelect, i)); Roll(); gScore += ct * (ct - 1); if (IsGameOver()) { Refresh(.5); string Text = "* Game Over *\n" + gPlayer + " scored " + (string) gScore; list ScoreEntry = [gScore, gPlayer]; gBest += ScoreEntry; gBest = llListSort(gBest, 2, FALSE); gBest = llList2List(gBest, 0, 9); if (llListFindList(gBest, ScoreEntry) != -1) Text += "\nCongratulations ! You are in the top 5!"; BubbleText(n+1, Text); state waiting; } Refresh(1); gSelect = []; BubbleText(TEXT_PRIM, gPlayer + " is playing\nScore: " + (string) gScore); return; } SelectHightlight(1); gSelect = []; Select(n, Type); integer cn = llGetListLength(gSelect); if (cn < 2) { BubbleText(TEXT_PRIM, gPlayer + " is playing\nScore: " + (string) gScore); gSelect = []; return; } BubbleText(TEXT_PRIM, gPlayer + " is playing\nScore: " + (string) gScore + "\n" + (string) cn + " bubbles selected"); BubbleText(n+1, (string) (cn * (cn-1))); gLastSelected = n+1; SelectHightlight(.5); } }
Voilà. Donc le jeu se lance...
Ne cliquez rien encore: l'ordre dans lequel les primitives est primordial pour son bon fonctionnement.
Pour vous épargner ce travail fastidieux, un bout de script se chargera de ce sale boulot une bonne fois pour toutes.
Tapez dans le tchat la commande suivante:
/5 build
Après ça, les petites boules que vous avez entassé en vrac vont comme par magie se ranger toutes seules, et vous pourrez ranger Bubble Breaker dans votre inventaire!
Bubble Breaker v0.5
Text Controller:
vector DEFAULT_COLOR = <1,1,1>; integer ALPHA = 1; default { link_message(integer s, integer n, string m, key k) { integer Idx = llSubStringIndex(m, "|"); if (Idx == -1) llSetText(llGetSubString(m, 0, Idx-1), DEFAULT_COLOR, ALPHA); else llSetText(llGetSubString(m, 0, Idx-1), (vector) llGetSubString(m, Idx+1, -1), ALPHA); } }
Bubble Breaker Controller:
// Copyright (c) 2008 - Forest Klaar (Second Life) // // Redistribution and use in source forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * The name of Forest Klaar name must not be used to endorse or promote // products derived from this software without specific prior written // permission. // // THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Bubble Breaker v0.5 list gBubbles; list gSelect; integer gScore; string gPlayer; list gBest; integer gLastSelected; integer gIsFlatVersion; list COLORS = [<1,1,1>, <1,0,0>,<0,1,0>,<0,0,1>,<1,1,0>,<1,0,1>]; list PRIM_ORDER = [4,0,2]; // Choose a random color, dont take the first one integer Ran() { return llFloor(llFrand(llGetListLength(COLORS)-1)) + 1; } EraseText(integer n) { llMessageLinked(n, 0, "", NULL_KEY); } MessageText(string s, vector c) { if (gIsFlatVersion) BubbleText(15, s, c); else BubbleText(45, s, c); } // We want this bubble to display a text BubbleText(integer n, string s, vector c) { llMessageLinked(n, 0, s + "|" + (string) c, NULL_KEY); } // Check for game end situation integer IsGameOver() { integer i; for(i=0; i<81; i++) { integer Type = llList2Integer(gBubbles, i); if (Type != 0) { if (i/9 != 8) { if (Type == llList2Integer(gBubbles, i+9)) return FALSE; } if (i%9 != 8) { if (Type == llList2Integer(gBubbles, i+1)) return FALSE; } } } return TRUE; } // Refresh the gameboard Ref(float alpha1, float alpha2) { if (gIsFlatVersion) RefreshFlat(alpha1, alpha2); else RefreshNorm(alpha1, alpha2); } RefreshNorm(float alpha1, float alpha2) { integer i; for(i=0; i<81; i++) { integer Type = llList2Integer(gBubbles, i); llSetLinkColor(i+1, llList2Vector(COLORS, Type), ALL_SIDES); if (Type == 0) llSetLinkAlpha(i+1, alpha2, ALL_SIDES); else llSetLinkAlpha(i+1, alpha1, ALL_SIDES); } } RefreshFlat(float alpha1, float alpha2) { integer i; for(i=0; i<81; i++) { integer Type = llList2Integer(gBubbles, i); integer Prim = i / 3 + 1; integer Face = llList2Integer(PRIM_ORDER, i % 3); llSetLinkColor(Prim, llList2Vector(COLORS, Type), Face); if (Type == 0) llSetLinkAlpha(Prim, alpha2, Face); else llSetLinkAlpha(Prim, alpha1, Face); } } // Shift remaining bubbles up to down Shift(integer n) { integer Col = n/9; if (n%9 == 8) gBubbles = llListReplaceList(gBubbles, [0], Col*9+8, Col*9+8); else gBubbles = llListReplaceList(gBubbles, llList2List(gBubbles, n+1, Col*9+8) + [0], n, Col*9+8); } // Roll left bubbles to right Roll() { integer i; for(i=0; i<9; i++) if (llDumpList2String(llList2List(gBubbles, i*9, i*9+8),"") == "000000000") gBubbles = [0,0,0,0,0,0,0,0,0] + llListReplaceList(gBubbles, [], i*9, i*9+8); } // Recursive bubble selection Sel(integer n) { if (n < 0 || n > 80) return; if (llListFindList(gSelect, [n]) != -1) return; gSelect += n; integer Type = llList2Integer(gBubbles, n); if (n/9 != 0) if (llList2Integer(gBubbles, n-9) == Type) Sel(n-9); if (n/9 != 8) if (llList2Integer(gBubbles, n+9) == Type) Sel(n+9); if (n%9 != 0) if (llList2Integer(gBubbles, n-1) == Type) Sel(n-1); if (n%9 != 8) if (llList2Integer(gBubbles, n+1) == Type) Sel(n+1); } Demo() { gBubbles = []; integer i; integer c = 1; for (i=0; i<81; i++) { gBubbles += [c++]; if (c > 5) c = 1; } Ref(1, 0); } Init() { gBubbles = []; integer i; for (i=0; i<9; i++) gBubbles += [Ran(),Ran(),Ran(),Ran(),Ran(),Ran(),Ran(),Ran(),Ran()]; Ref(1, 0); } string DisplayScores() { string Display; integer i; integer n=llGetListLength(gBest)/2; for(i=0; i<n; i++) Display += llList2String(gBest, i*2+1) + " : " + llList2String(gBest, i*2) + "\n"; return Display; } RefScore() { MessageText(gPlayer + " is playing\nScore: " + (string) gScore, <1,1,0>); } HighLightSelection(float f) { if (gIsFlatVersion) HighLightSelectionFlat(f); else HighLightSelectionNorm(f); } HighLightSelectionFlat(float f) { integer i; integer cn = llGetListLength(gSelect); for (i=0; i<cn; i++) { integer Idx = llList2Integer(gSelect, i); integer Prim = Idx / 3 + 1; integer Face = llList2Integer(PRIM_ORDER, Idx % 3); llSetLinkAlpha(Prim, f, Face); } } HighLightSelectionNorm(float f) { integer i; integer cn = llGetListLength(gSelect); for (i=0; i<cn; i++) llSetLinkAlpha(llList2Integer(gSelect, i)+1, f, ALL_SIDES); } SelectBubbles() { HighLightSelection(.5); } UnselectBubbles() { HighLightSelection(1); } // Make bubbles disappear before shift and roll PopBubbles() { HighLightSelection(0); } default { state_entry() { gIsFlatVersion = (llGetNumberOfPrims() == 27); Demo(); state waiting; } } state waiting { state_entry() { MessageText("* Bubble Breaker *\n" + DisplayScores() + "\nTouch me to start !", <0,1,0>); } touch_start(integer c) { EraseText(LINK_SET); gPlayer = llDetectedName(0); Init(); state game; } } state game { state_entry() { gScore = 0; RefScore(); } touch_start(integer c) { integer Prim = llDetectedLinkNumber(0); integer n = Prim - 1; // Flat version requires a specific index number calculation if (gIsFlatVersion) { integer Face = llListFindList(PRIM_ORDER, [llDetectedTouchFace(0)]); if (Face == -1) return; n = n * 3 + Face; } // No bubble ? if (llList2Integer(gBubbles, n) == 0) return; gPlayer = llDetectedName(0); EraseText(gLastSelected); // Break bubbles ? if (llListFindList(gSelect, [n]) != -1) { PopBubbles(); gSelect = llListSort(gSelect, 1, FALSE); integer i; integer ct = llGetListLength(gSelect); for (i=0; i<ct; i++) Shift(llList2Integer(gSelect, i)); Roll(); gScore += ct * (ct - 1); // Are we stuck ? if (!IsGameOver()) { RefScore(); Ref(1, 0); gSelect = []; return; } gBest += [gScore, gPlayer]; gBest = llListSort(gBest, 2, FALSE); gBest = llList2List(gBest, 0, 9); string Text = "* Game Over *\n" + gPlayer + " scored " + (string) gScore; if (llListFindList(gBest, [gScore, gPlayer]) != -1) Text += "\nCongratulations ! You are in the top 5!"; BubbleText(Prim, Text, <1,0,0>); Ref(1, .5); state waiting; } UnselectBubbles(); gSelect = []; Sel(n); integer cnt = llGetListLength(gSelect); // No bubbles selected if (cnt < 2) { gSelect = []; return; } RefScore(); // Display selected bubbles BubbleText(Prim, (string) cnt + " bubbles selected\nClick again to get " + (string) (cnt * (cnt - 1)) + " points", llList2Vector(COLORS, llList2Integer(gBubbles, n))); gLastSelected = Prim; SelectBubbles(); } }