OsTris

De DigiWiki.

Première étape: construction de la grille.

  • Rezzez un cube
  • Donnez-lui la taille X=0.050, Y=0.050, Z=0.050 (important!).
  • Renommez-le en l'appelant Cube.
  • Copiez Cube, et donnez un nom à la copie. Appelez-là SLTRis, par exemple.
  • Prenez Cube pour l'intégrer à votre inventaire.
  • Copier Cube depuis votre inventaire dans celui de SLTRis.
  • Faites glisser Cube vers SLTRis depuis votre inventaire en maintenant la touche.
  • CTRL enfoncée, puis quand le cube SLTRis apparait encadré de rouge, relâchez le bouton.
  • A présent, utilisez l'onglet Contenu de l'objet SLTRis pour vérifier si Cube s'y trouve.
  • Cliquez sur "Nouveau Script" pour créer un script.
  • Copier/Coller le code ci-dessous dans ce nouveau script.
// Position en cours de création dans la grille (X de 0 à 9, Y de 0 à 19)
integer X; integer Z;
 
// Position et taille du cube d'origine 
vector Pos; vector Scale;
 
// Rezze un cube
RezCube()
{
    llRezObject("Cube", Pos + <Scale.x * X, 0, Scale.z * Z>, ZERO_VECTOR, ZERO_ROTATION, 0);
}
 
default
{
    touch_start(integer total_number)
    {
        // Demande la permission de toucher aux liaisons
        llRequestPermissions(llGetOwner(), PERMISSION_CHANGE_LINKS);
    }
 
    // Des que la permission est accordée
    run_time_permissions(integer perm)
    {
        if (perm && PERMISSION_CHANGE_LINKS)
        {
            state build;
        }
    }
}
 
state build
{
    state_entry()
    {
        // Recupere position et taille du cube d'origine
        Pos = llGetPos();
        Scale = llGetScale();
 
        X = 0;
        Z = 0;
 
        // Deplace-le a sa position definitive : ce sera le prim 1
        llSetPos(Pos + <Scale.x * 9, 0, Scale.z * 19>);
 
        RezCube();
    }
 
    // Cet evenement se declenche quand un cube a été rezzé
    object_rez(key id)
    {
        // Le nouvel objet rezzé est lié à celui-ci, mais celui-ci reste le père. Le nouvel objet rezzé prendra donc le numéro 2. Les objets déja attachés suivront : 3, 4, 5...
        llCreateLink(id, TRUE);
 
        ++X;
 
        // Il faut bien s'arrêter un jour !
        if (X == 9 && Z == 19)
            state fin;
 
        if (X > 9)
        { 
            X = 0;
            ++Z; 
        }
        // Et on rezze le cube suivant...
        RezCube();
    }
}
 
state fin
{
    state_entry()
    {
        llOwnerSay("C'est fini !");
    }
}

Voilà... A présent, touchez SLTRis, accordez-lui la permission qu'il demande, puis patientez deux à trois bonnes minutes : SLTRis est en train de construire tout seul la grille de 200 cubes, alignés en 20 lignes de 10 colonnes. Le temps pour vous de lire la suite...

Deuxième étape: le moteur de jeu (mode démo).

  • Créer un nouveau script.
  • Copier/coller dans le script le code ci-dessous.
// Temporisation en seconde pour la chute d'une piece
float       INTERVALTIMERSTART           = 1.5;
float       INTERVALTIMERDEMO            = 0.5;
 
// Largeur et hauteur du terrain de jeu
integer     PLAYGROUNDWIDTH              = 10;
integer     PLAYGROUNDHEIGHT             = 20;
 
// Coordonnées relatives des carres occupes par les pieces par rapport au centre de rotation.
// Si 0,0 est specifie en premier, la piece ne doit pas tourner (le "O" par exemple")
list PIECES = [
<1.0, 0.0, 0.0>,  0, -1,  0,  0,  0,  1,  0,  2,    // "I" Rouge
<1.0, 1.0, 0.0>,  0, -1,  0,  0,  0,  1, -1,  1,    // "J" Jaune
<1.0, 0.0, 1.0>,  0, -1,  0,  0,  0,  1,  1,  1,    // "L" Magenta
<0.0, 0.0, 1.0>,  0,  0,  0,  1,  1,  0,  1,  1,    // "O" Bleu        <- Celle-ci ne tourne pas !
<0.0, 1.0, 0.0>, -1, -1, -1,  0,  0,  0,  0,  1,    // "S" Vert
<0.5, 0.5, 1.0>, -1,  0,  1,  0,  0,  0,  0,  1,    // "T" Brun
<0.5, 1.0, 1.0>, -1, -1,  0, -1,  0,  0,  1,  0     // "Z" Cyan
];
 
// Pieces
integer  gPieceType;
list     gPieceParams;
vector   gPieceColor;
 
// Caractéristiques de la piece en cours
integer  gPieceX;
integer  gPieceY;
integer  gPieceAngle;
list     gPieceCoordinates;
 
// Anciennes caractéristiques de la piece en cours
integer  gPieceOldX;
integer  gPieceOldY;
integer  gPieceOldAngle;
list     gPieceOldCoordinates;
 
// Grille
string   gPlayGroundContent;
string   gEmptyRow;
 
// Prisme plat
integer  FIRSTCUBELINKNUMBER             = 1;
 
DisplayCubes(list coordinates)
{
    integer i; integer Count = llGetListLength(coordinates);
    for (i = 0; i < Count; i += 2)
        DisplayCube(llList2Integer(coordinates, i), llList2Integer(coordinates, i + 1), gPieceColor);
}
 
// Efface les cubes qui composent une piece
EraseCubes(list coordinates)
{
    integer i; integer Count = llGetListLength(coordinates);
    for (i = 0; i < Count; i += 2)
        EraseCube(llList2Integer(coordinates, i), llList2Integer(coordinates, i + 1));
}
 
EraseCube(integer x, integer y)
{
    integer Idx = y * PLAYGROUNDWIDTH + FIRSTCUBELINKNUMBER + x;
    llSetLinkColor(Idx, <1, 1, 1>, ALL_SIDES);
    llSetLinkAlpha(Idx, .25, ALL_SIDES);
}
 
DisplayCube(integer x, integer y, vector color)
{
    integer Idx = y * PLAYGROUNDWIDTH + FIRSTCUBELINKNUMBER + x;
    llSetLinkColor(Idx, color, ALL_SIDES);
    llSetLinkAlpha(Idx, 1, ALL_SIDES);
}
 
// Initialise le jeu
InitGame()
{
    // Construit une ligne vide
    gEmptyRow = "";
 
    integer Idx;
    for (Idx = 0; Idx < PLAYGROUNDWIDTH; Idx += 1)
        gEmptyRow += "0";
}
 
// Initialise la grille
InitPlay()
{
    // Construit le playground
    gPlayGroundContent = "";
 
    integer Idx;
    for (Idx = 0; Idx < PLAYGROUNDHEIGHT; Idx += 1)
        gPlayGroundContent += gEmptyRow;
 
    RefreshPlayGround(0);
}
 
// Envoie un message sur le debug channel
Debug(list msg)
{
    llSay(DEBUG_CHANNEL, llList2CSV(msg));
}
 
// Affiche la piece en cours en effacant la position precedente
// On ne touche pas aux cellules qui "restent"
DisplayMovedPiece()
{
    list OldXYList = gPieceOldCoordinates;
    list NewXYList = gPieceCoordinates;
 
    integer Count = llGetListLength(OldXYList);
 
    integer i = 0;
    do
    {
        integer Idx = llListFindList(NewXYList, llList2List(OldXYList, i, i+1));
        if (Idx % 2)
        {
            i += 2;
        }
        else
        {
            OldXYList = llDeleteSubList(OldXYList, i, i+1);
            NewXYList = llDeleteSubList(NewXYList, Idx, Idx+1);
            Count -= 2;
        }
    }
    while(i < Count);
 
    // On efface seulement les cubes qui disparaissent...
    EraseCubes(OldXYList);
    // Pour n'afficher que les nouveaux
    DisplayCubes(NewXYList);
}
 
// Rotation
SetRotatedPieceParams()
{
    gPieceCoordinates = [];
 
    integer i;
    for (i = 0; i < 8; i += 2)
    {
        integer OffsetX = llList2Integer(gPieceParams, i);
        integer OffsetY = llList2Integer(gPieceParams, i + 1);
 
        // Neutralise la rotation pour les pieces symétriques comme "O" qui ne tournent pas.
        // Ce genre de pieces est repéré par les premieres coordonnees toujours à 0,0
        if (i == 0)
            if (OffsetX == 0 && OffsetY == 0)
                gPieceAngle = 0;
 
        if (gPieceAngle == 0)
            gPieceCoordinates += [gPieceX + OffsetX, gPieceY + OffsetY];
        else if (gPieceAngle == 1)
            gPieceCoordinates += [gPieceX - OffsetY, gPieceY + OffsetX];
        else if (gPieceAngle == 2)
            gPieceCoordinates += [gPieceX - OffsetX, gPieceY - OffsetY];
        else
            gPieceCoordinates += [gPieceX + OffsetY, gPieceY - OffsetX];
    }
}
 
// retourne TRUE si la la piece peut occuper la position suivante
integer IsPositionFree()
{
    integer i;
    for (i = 0; i < 8; i += 2)
    {
        integer X = llList2Integer(gPieceCoordinates, i);
        integer Y = llList2Integer(gPieceCoordinates, i + 1);
 
        if (X < 0  || Y < 0 || X >= PLAYGROUNDWIDTH || Y >= PLAYGROUNDHEIGHT)
            return FALSE;
 
        integer Idx = X + Y * PLAYGROUNDWIDTH;
 
        if (llGetSubString(gPlayGroundContent, Idx, Idx) != "0")
            return FALSE;
    }
 
    return TRUE;
}
 
// Valide la nouvelle position
StoreOldPosition()
{
    gPieceOldX = gPieceX;
    gPieceOldY = gPieceY;
    gPieceOldAngle = gPieceAngle;
    gPieceOldCoordinates = gPieceCoordinates;
}
 
// Invalide la nouvelle position
RetrieveOldPosition()
{
    gPieceX = gPieceOldX;
    gPieceY = gPieceOldY;
    gPieceAngle = gPieceOldAngle;
    gPieceCoordinates = gPieceOldCoordinates;
}
 
// Fige la piece dans sa position actuelle : elle ne bougera plus
FreezePiece()
{
    string Piece = (string) (gPieceType + 1);
    integer i;
    for (i = 0; i < 8; i += 2)
    {
        integer Idx = llList2Integer(gPieceCoordinates, i) + llList2Integer(gPieceCoordinates, i + 1) * PLAYGROUNDWIDTH;
        gPlayGroundContent = llDeleteSubString(llInsertString(gPlayGroundContent, Idx, Piece), Idx + 1, Idx + 1);
    }
}
 
// Redessine la grille à partir de la ligne rowStart
RefreshPlayGround(integer rowStart)
{
    integer X; integer Y;
    for (X = 0; X < PLAYGROUNDWIDTH; X += 1)
        for (Y = rowStart; Y < PLAYGROUNDHEIGHT; Y += 1)
        {
            integer Idx = X + Y * PLAYGROUNDWIDTH;
            integer CodeCube = (integer) llGetSubString(gPlayGroundContent, Idx, Idx);
 
            if (CodeCube == 0)
                EraseCube(X,Y);
            else
                DisplayCube(X,Y, llList2Vector(PIECES, (CodeCube - 1) * 9));
        }
}
 
// Retourne un nombre aleatoire entre min et max
integer Random(integer min, integer max)
{
    return (integer) llFrand((float) max + 1.0 - (float) min) + min;
}
 
// Affiche une nouvelle piece
PlaceNewPiece()
{
    gPieceType = Random(0, llGetListLength(PIECES) / 9 - 1);
    gPieceX = Random(4, PLAYGROUNDWIDTH - 4);
    gPieceY = 2;
    gPieceAngle = Random(0, 3);
 
    gPieceParams = llList2List(PIECES, gPieceType * 9 + 1, gPieceType * 9 + 8);
    gPieceColor = llList2Vector(PIECES, gPieceType * 9);
    SetRotatedPieceParams();
}
 
// Apres le deplacement d'un joueur
AfterPlayerMove()
{
    SetRotatedPieceParams();
 
    if (IsPositionFree())
    {
        DisplayMovedPiece();
        StoreOldPosition();
    }
    else
    {
        RetrieveOldPosition();
    }
}
 
integer gDemoMove;
 
default
{
    state_entry()
    {
        InitGame();
        state demo;
    }
}
 
state demo
{
    state_entry()
    {
        InitPlay();
 
        PlaceNewPiece();
        DisplayCubes(gPieceCoordinates);
        StoreOldPosition();
 
        llSetTimerEvent(INTERVALTIMERDEMO);
    }
 
    timer()
    {
        gDemoMove = !gDemoMove;
 
        if (gDemoMove)
        {
            gPieceY += 1;
            SetRotatedPieceParams();
 
            if (IsPositionFree())
            {
                DisplayMovedPiece();
                StoreOldPosition();
            }
            else
            {
                RetrieveOldPosition();
                FreezePiece();
 
                PlaceNewPiece();
 
                if (!IsPositionFree())
                {
                    llSetTimerEvent(0);
                    InitPlay();
                    PlaceNewPiece();
                    llSetTimerEvent(INTERVALTIMERDEMO);
                }
 
                DisplayCubes(gPieceCoordinates);
                StoreOldPosition();
            }
        }
        else
        {
            integer Move = Random(0, 4);
 
            if (Move == 0)
                gPieceX += 1;
            else if (Move == 1)
                gPieceX -= 1;
            else if (Move == 2)
                gPieceY += 1;
            else if (++gPieceAngle > 3)
                gPieceAngle = 0;
 
            AfterPlayerMove();
        }
    }
 
    state_exit()
    {
        llSetTimerEvent(0);
    }
}

Vous y voilà ! Aussitôt le script compilé et sauvegardé, regardez votre Tetris executer une démo. La grille est effacée, puis les pieces commencent à tomber, à tourner, puis à s'empiler jusqu'en haut. Une fois le haut de la grille atteint, la grille est de nouveau effacée et la démo recommence...


Deuxième étape: le moteur de jeu (mode jouable).

Voilà ci-dessous le script complet pour rendre ce jeu de Tétris jouable. Il vous suffit de remplacer le précédent par celui-ci:

// Temporisation en seconde pour la chute d'une piece
float       INTERVALTIMERSTART           = 1.5;
float       INTERVALTIMERDEMO            = 0.5;
 
// Largeur et hauteur du terrain de jeu
integer     PLAYGROUNDWIDTH              = 10;
integer     PLAYGROUNDHEIGHT             = 20;
 
// Coordonnées relatives des carres occupes par les pieces par rapport au centre de rotation.
// Si 0,0 est specifie en premier, la piece ne doit pas tourner (le "O" par exemple")
list PIECES = [
<1.0, 0.0, 0.0>,  0, -1,  0,  0,  0,  1,  0,  2,    // "I" Rouge
<1.0, 1.0, 0.0>,  0, -1,  0,  0,  0,  1, -1,  1,    // "J" Jaune
<1.0, 0.0, 1.0>,  0, -1,  0,  0,  0,  1,  1,  1,    // "L" Magenta
<0.0, 0.0, 1.0>,  0,  0,  0,  1,  1,  0,  1,  1,    // "O" Bleu        <- Celle-ci ne tourne pas !
<0.0, 1.0, 0.0>, -1, -1, -1,  0,  0,  0,  0,  1,    // "S" Vert
<0.5, 0.5, 1.0>, -1,  0,  1,  0,  0,  0,  0,  1,    // "T" Brun
<0.5, 1.0, 1.0>, -1, -1,  0, -1,  0,  0,  1,  0     // "Z" Cyan
];
 
// Pieces
integer  gPieceType;
list     gPieceParams;
vector   gPieceColor;
 
// Caractéristiques de la piece en cours
integer  gPieceX;
integer  gPieceY;
integer  gPieceAngle;
list     gPieceCoordinates;
 
// Anciennes caractéristiques de la piece en cours
integer  gPieceOldX;
integer  gPieceOldY;
integer  gPieceOldAngle;
list     gPieceOldCoordinates;
 
// Grille
string   gPlayGroundContent;
string   gEmptyRow;
 
// Prisme plat
integer  FIRSTCUBELINKNUMBER             = 1;
 
DisplayCubes(list coordinates)
{
    integer i; integer Count = llGetListLength(coordinates);
    for (i = 0; i < Count; i += 2)
        DisplayCube(llList2Integer(coordinates, i), llList2Integer(coordinates, i + 1), gPieceColor);
}
 
// Efface les cubes qui composent une piece
EraseCubes(list coordinates)
{
    integer i; integer Count = llGetListLength(coordinates);
    for (i = 0; i < Count; i += 2)
        EraseCube(llList2Integer(coordinates, i), llList2Integer(coordinates, i + 1));
}
 
EraseCube(integer x, integer y)
{
    integer Idx = y * PLAYGROUNDWIDTH + FIRSTCUBELINKNUMBER + x;
    llSetLinkColor(Idx, <1, 1, 1>, ALL_SIDES);
    llSetLinkAlpha(Idx, .25, ALL_SIDES);
}
 
DisplayCube(integer x, integer y, vector color)
{
    integer Idx = y * PLAYGROUNDWIDTH + FIRSTCUBELINKNUMBER + x;
    llSetLinkColor(Idx, color, ALL_SIDES);
    llSetLinkAlpha(Idx, 1, ALL_SIDES);
}
 
// Initialise le jeu
InitGame()
{
    // Construit une ligne vide
    gEmptyRow = "";
 
    integer Idx;
    for (Idx = 0; Idx < PLAYGROUNDWIDTH; Idx += 1)
        gEmptyRow += "0";
}
 
// Initialise la grille
InitPlay()
{
    // Construit le playground
    gPlayGroundContent = "";
 
    integer Idx;
    for (Idx = 0; Idx < PLAYGROUNDHEIGHT; Idx += 1)
        gPlayGroundContent += gEmptyRow;
 
    RefreshPlayGround(0);
}
 
// Envoie un message sur le debug channel
Debug(list msg)
{
    llSay(DEBUG_CHANNEL, llList2CSV(msg));
}
 
// Affiche la piece en cours en effacant la position precedente
// On ne touche pas aux cellules qui "restent"
DisplayMovedPiece()
{
    list OldXYList = gPieceOldCoordinates;
    list NewXYList = gPieceCoordinates;
 
    integer Count = llGetListLength(OldXYList);
 
    integer i = 0;
    do
    {
        integer Idx = llListFindList(NewXYList, llList2List(OldXYList, i, i+1));
        if (Idx % 2)
        {
            i += 2;
        }
        else
        {
            OldXYList = llDeleteSubList(OldXYList, i, i+1);
            NewXYList = llDeleteSubList(NewXYList, Idx, Idx+1);
            Count -= 2;
        }
    }
    while(i < Count);
 
    // On efface seulement les cubes qui disparaissent...
    EraseCubes(OldXYList);
    // Pour n'afficher que les nouveaux
    DisplayCubes(NewXYList);
}
 
// Rotation
SetRotatedPieceParams()
{
    gPieceCoordinates = [];
 
    integer i;
    for (i = 0; i < 8; i += 2)
    {
        integer OffsetX = llList2Integer(gPieceParams, i);
        integer OffsetY = llList2Integer(gPieceParams, i + 1);
 
        // Neutralise la rotation pour les pieces symétriques comme "O" qui ne tournent pas.
        // Ce genre de pieces est repéré par les premieres coordonnees toujours à 0,0
        if (i == 0)
            if (OffsetX == 0 && OffsetY == 0)
                gPieceAngle = 0;
 
        if (gPieceAngle == 0)
            gPieceCoordinates += [gPieceX + OffsetX, gPieceY + OffsetY];
        else if (gPieceAngle == 1)
            gPieceCoordinates += [gPieceX - OffsetY, gPieceY + OffsetX];
        else if (gPieceAngle == 2)
            gPieceCoordinates += [gPieceX - OffsetX, gPieceY - OffsetY];
        else
            gPieceCoordinates += [gPieceX + OffsetY, gPieceY - OffsetX];
    }
}
 
// retourne TRUE si la la piece peut occuper la position suivante
integer IsPositionFree()
{
    integer i;
    for (i = 0; i < 8; i += 2)
    {
        integer X = llList2Integer(gPieceCoordinates, i);
        integer Y = llList2Integer(gPieceCoordinates, i + 1);
 
        if (X < 0  || Y < 0 || X >= PLAYGROUNDWIDTH || Y >= PLAYGROUNDHEIGHT)
            return FALSE;
 
        integer Idx = X + Y * PLAYGROUNDWIDTH;
 
        if (llGetSubString(gPlayGroundContent, Idx, Idx) != "0")
            return FALSE;
    }
 
    return TRUE;
}
 
// Valide la nouvelle position
StoreOldPosition()
{
    gPieceOldX = gPieceX;
    gPieceOldY = gPieceY;
    gPieceOldAngle = gPieceAngle;
    gPieceOldCoordinates = gPieceCoordinates;
}
 
// Invalide la nouvelle position
RetrieveOldPosition()
{
    gPieceX = gPieceOldX;
    gPieceY = gPieceOldY;
    gPieceAngle = gPieceOldAngle;
    gPieceCoordinates = gPieceOldCoordinates;
}
 
// Fige la piece dans sa position actuelle : elle ne bougera plus
FreezePiece()
{
    string Piece = (string) (gPieceType + 1);
    integer i;
    for (i = 0; i < 8; i += 2)
    {
        integer Idx = llList2Integer(gPieceCoordinates, i) + llList2Integer(gPieceCoordinates, i + 1) * PLAYGROUNDWIDTH;
        gPlayGroundContent = llDeleteSubString(llInsertString(gPlayGroundContent, Idx, Piece), Idx + 1, Idx + 1);
    }
}
 
// Redessine la grille à partir de la ligne rowStart
RefreshPlayGround(integer rowStart)
{
    integer X; integer Y;
    for (X = 0; X < PLAYGROUNDWIDTH; X += 1)
        for (Y = rowStart; Y < PLAYGROUNDHEIGHT; Y += 1)
        {
            integer Idx = X + Y * PLAYGROUNDWIDTH;
            integer CodeCube = (integer) llGetSubString(gPlayGroundContent, Idx, Idx);
 
            if (CodeCube == 0)
                EraseCube(X,Y);
            else
                DisplayCube(X,Y, llList2Vector(PIECES, (CodeCube - 1) * 9));
        }
}
 
// Retourne un nombre aleatoire entre min et max
integer Random(integer min, integer max)
{
    return (integer) llFrand((float) max + 1.0 - (float) min) + min;
}
 
// Affiche une nouvelle piece
PlaceNewPiece()
{
    gPieceType = Random(0, llGetListLength(PIECES) / 9 - 1);
    gPieceX = Random(4, PLAYGROUNDWIDTH - 4);
    gPieceY = 2;
    gPieceAngle = Random(0, 3);
 
    gPieceParams = llList2List(PIECES, gPieceType * 9 + 1, gPieceType * 9 + 8);
    gPieceColor = llList2Vector(PIECES, gPieceType * 9);
    SetRotatedPieceParams();
}
 
// Apres le deplacement d'un joueur
AfterPlayerMove()
{
    SetRotatedPieceParams();
 
    if (IsPositionFree())
    {
        DisplayMovedPiece();
        StoreOldPosition();
    }
    else
    {
        RetrieveOldPosition();
    }
}
 
// Supprime les lignes completes
integer ReArrangeBricks()
{
    // Redétermine la toute premiere ligne non vide
    gRowStart = 0;
    while (IsEmptyRow(gRowStart) && gRowStart < PLAYGROUNDHEIGHT)
        gRowStart += 1;
 
    // Vide les lignes pleines
    integer DownLines;
 
    integer Row;
    for (Row = gRowStart; Row < PLAYGROUNDHEIGHT; Row += 1)
        if (IsFullRow(Row))
        {
            // Suprime la ligne concernée
            integer Idx = Row * PLAYGROUNDWIDTH;
            gPlayGroundContent = gEmptyRow + llDeleteSubString(gPlayGroundContent, Idx, Idx + PLAYGROUNDWIDTH - 1);
            DownLines += 1;
        }
 
    // Il y'a eu des lignes en moins
    if (DownLines)
    {
        RefreshPlayGround(gRowStart);
        gRowStart += DownLines;
    }
 
    return DownLines;
}
 
// Renvoie TRUE si la ligne est vide
integer IsEmptyRow(integer row)
{
    integer Idx =  row * PLAYGROUNDWIDTH;
    return (llGetSubString(gPlayGroundContent, Idx, Idx + PLAYGROUNDWIDTH - 1) == gEmptyRow);
}
 
// Renvoie TRUE si la ligne est pleine
integer IsFullRow(integer row)
{
    integer Idx = row * PLAYGROUNDWIDTH;
    return (llSubStringIndex(llGetSubString(gPlayGroundContent, Idx, Idx + PLAYGROUNDWIDTH - 1), "0") == -1);
}
 
integer gDemoMove;
float   gTimerEvent;
integer gRowStart;
 
default
{
    state_entry()
    {
        InitGame();
        state demo;
    }
}
 
state demo
{
    state_entry()
    {
        InitPlay();
 
        PlaceNewPiece();
        DisplayCubes(gPieceCoordinates);
        StoreOldPosition();
 
        llSetTimerEvent(INTERVALTIMERDEMO);
    }
 
    timer()
    {
        gDemoMove = !gDemoMove;
 
        if (gDemoMove)
        {
            gPieceY += 1;
            SetRotatedPieceParams();
 
            if (IsPositionFree())
            {
                DisplayMovedPiece();
                StoreOldPosition();
            }
            else
            {
                RetrieveOldPosition();
                FreezePiece();
 
                PlaceNewPiece();
 
                if (!IsPositionFree())
                {
                    llSetTimerEvent(0);
                    InitPlay();
                    PlaceNewPiece();
                    llSetTimerEvent(INTERVALTIMERDEMO);
                }
 
                DisplayCubes(gPieceCoordinates);
                StoreOldPosition();
            }
        }
        else
        {
            integer Move = Random(0, 4);
 
            if (Move == 0)
                gPieceX += 1;
            else if (Move == 1)
                gPieceX -= 1;
            else if (Move == 2)
                gPieceY += 1;
            else if (++gPieceAngle > 3)
                gPieceAngle = 0;
 
            AfterPlayerMove();
        }
    }
 
    touch_start(integer count)
    {
        llRequestPermissions(llDetectedKey(0), PERMISSION_TAKE_CONTROLS);
    }
 
    run_time_permissions(integer perms)
    {
        if (PERMISSION_TAKE_CONTROLS & perms)
        {
            llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_ROT_LEFT | CONTROL_ROT_RIGHT, TRUE, FALSE);
            state playing;
        }
    }
 
    state_exit()
    {
        llSetTimerEvent(0);
    }
}
 
state playing
{
    state_entry()
    {
        InitPlay();
 
        PlaceNewPiece();
        DisplayCubes(gPieceCoordinates);
        StoreOldPosition();
 
        gTimerEvent = INTERVALTIMERSTART;
        llSetTimerEvent(gTimerEvent);
    }
 
    timer()
    {
        gPieceY += 1;
 
        SetRotatedPieceParams();
 
        if (IsPositionFree())
        {
            DisplayMovedPiece();
            StoreOldPosition();
        }
        else
        {
            RetrieveOldPosition();
            FreezePiece();
 
            ReArrangeBricks();
            PlaceNewPiece();
 
            if (!IsPositionFree())
            {
                state demo;
            }
            else
            {
                DisplayCubes(gPieceCoordinates);
                StoreOldPosition();
            }
        }
    }
 
    control(key id, integer level, integer edge)
    {
        integer start = level & edge;
 
        if (CONTROL_BACK & start)
        {
            gPieceY += 1;
            AfterPlayerMove();
        }
        else if (CONTROL_FWD & start)
        {
            if (++gPieceAngle > 3) gPieceAngle = 0;
            AfterPlayerMove();
        }
        else if (CONTROL_ROT_LEFT & start)
        {
            gPieceX -= 1;
            AfterPlayerMove();
        }
        else if (CONTROL_ROT_RIGHT & start)
        {
            gPieceX += 1;
            AfterPlayerMove();
        }
    }
 
    state_exit()
    {
        llSetTimerEvent(0);
    }
}

Bon amusement!

Outils personnels
  • Cette page a été consultée 1 267 fois.
donate
Google Ads