Tetris

Répondre
Partager Rechercher
Je m'intéresse au Tetris depuis quelques jours. Ca serait intéressant d'en construire un avec de vraies primitives mais c'est un gros chantier que j'ai commencé mais dont j'ignore où il ira. En attendant je vous livre une version "web on prim". Je trouve qu'on n'utilise pas suffisamment cette fonctionnalité, pour une raison que j'ignore. Pour le tetris mettez ce script dans une primitive :

Code PHP:

//----------------------------------------------------------------------------------
//                                 Tetris web V1.0
//----------------------------------------------------------------------------------
//    Source du Javascript : https://github.com/jakesgordon/javascript-tetris
//----------------------------------------------------------------------------------

//----------------------------------------------
//                  PARAMETRES
//----------------------------------------------
integer FACE 4;
string VERSION "1.00";

//----------------------------------------------
//                  VARIABLES
//----------------------------------------------
string myURL;

//----------------------------------------------
//                  FIN
//----------------------------------------------

browse(integer facestring url) {
    
llClearLinkMedia(LINK_THISface);
    
llSetLinkMedia(LINK_THISface, [
        
PRIM_MEDIA_CONTROLSPRIM_MEDIA_CONTROLS_MINI,
        
PRIM_MEDIA_AUTO_PLAYTRUE,
        
PRIM_MEDIA_AUTO_LOOPTRUE,
        
PRIM_MEDIA_AUTO_SCALETRUE,
        
PRIM_MEDIA_CURRENT_URLurl,
        
PRIM_MEDIA_HOME_URLurl,
        
PRIM_MEDIA_HEIGHT_PIXELS512,
        
PRIM_MEDIA_WIDTH_PIXELS512]);
}

string getPage() {
    return 
"<!DOCTYPE html>
<html>
<head>
  <title>Javascript Tetris</title>
  <style>
    body { font-family: Helvetica, sans-serif; }
    #tetris { margin: 1em auto; padding: 1em; border: 4px solid black; border-radius: 10px; background-color: #F8F8F8; }
    #canvas { display: inline-block; vertical-align: top; background: url(http://www.scriptol.fr/design/paint/images/nuage-bleu.png); box-shadow: 10px 10px 10px #999; border: 2px solid #333; }
    #menu { display: inline-block; vertical-align: top; position: relative; }
    #menu p { margin: 0.5em 0; text-align: center; }
    #menu p a { text-decoration: none; color: black; }
    #upcoming { display: block; margin: 0 auto; background-color: #E0E0E0; }
    #score { color: red; font-weight: bold; }
    #rows { color: blue; font-weight: bold; }
    @media screen and (min-width: 0px) and (min-height: 0px) { #tetris { font-size: 0.75em; width: 250px; } #menu { width: 100px; height: 200px; } #upcoming { width: 50px; height: 50px; } #canvas { width: 100px; height: 200px; } } /* 10px chunks */
    @media screen and (min-width: 400px) and (min-height: 400px) { #tetris { font-size: 1.00em; width: 350px; } #menu { width: 150px; height: 300px; } #upcoming { width: 75px; height: 75px; } #canvas { width: 150px; height: 300px; } } /* 15px chunks */
    @media screen and (min-width: 500px) and (min-height: 500px) { #tetris { font-size: 1.25em; width: 450px; } #menu { width: 200px; height: 400px; } #upcoming { width: 100px; height: 100px; } #canvas { width: 200px; height: 400px; } } /* 20px chunks */
    @media screen and (min-width: 600px) and (min-height: 600px) { #tetris { font-size: 1.50em; width: 550px; } #menu { width: 250px; height: 500px; } #upcoming { width: 125px; height: 125px; } #canvas { width: 250px; height: 500px; } } /* 25px chunks */
    @media screen and (min-width: 700px) and (min-height: 700px) { #tetris { font-size: 1.75em; width: 650px; } #menu { width: 300px; height: 600px; } #upcoming { width: 150px; height: 150px; } #canvas { width: 300px; height: 600px; } } /* 30px chunks */
    @media screen and (min-width: 800px) and (min-height: 800px) { #tetris { font-size: 2.00em; width: 750px; } #menu { width: 350px; height: 700px; } #upcoming { width: 175px; height: 175px; } #canvas { width: 350px; height: 700px; } } /* 35px chunks */
    @media screen and (min-width: 900px) and (min-height: 900px) { #tetris { font-size: 2.25em; width: 850px; } #menu { width: 400px; height: 800px; } #upcoming { width: 200px; height: 200px; } #canvas { width: 400px; height: 800px; } } /* 40px chunks */
  </style>
</head>

<body>

  <div id=\"tetris\">
    <div id=\"menu\">
      <p id=\"start\"><a href=\"javascript:play();\">Espace pour jouer</a></p>
      <p><canvas id=\"upcoming\"></canvas></p>
      <p>Score <span id=\"score\">00000</span></p>
      <p>Lignes <span id=\"rows\">0</span></p>
    </div>
    <canvas id=\"canvas\">
      Sorry, this example cannot be run because your browser does not support the &lt;canvas&gt; element
    </canvas>
  </div>

<script>
     //-------------------------------------------------------------------------
    // base helper methods
    //-------------------------------------------------------------------------

    function get(id) { return document.getElementById(id); };
    function hide(id) { get(id).style.visibility = 'hidden'; };
    function show(id) { get(id).style.visibility = null; };
    function html(id, html) { get(id).innerHTML = html; };

    function timestamp() { return new Date().getTime(); };
    function random(min, max) { return (min + (Math.random() * (max - min))); };
    function randomChoice(choices) { return choices[Math.round(random(0, choices.length-1))]; };

    if (!window.requestAnimationFrame) { // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
      window.requestAnimationFrame = window.webkitRequestAnimationFrame ||
                                     window.mozRequestAnimationFrame ||
                                     window.oRequestAnimationFrame ||
                                     window.msRequestAnimationFrame ||
                                     function(callback, element) {
                                       window.setTimeout(callback, 1000 / 60);
                                     }
    }

    //-------------------------------------------------------------------------
    // game constants
    //-------------------------------------------------------------------------

    var KEY = { ESC: 27, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40 },
        DIR = { UP: 0, RIGHT: 1, DOWN: 2, LEFT: 3, MIN: 0, MAX: 3 },
        canvas = get('canvas'),
        ctx = canvas.getContext('2d'),
        ucanvas = get('upcoming'),
        uctx = ucanvas.getContext('2d'),
        speed = { start: 0.6, decrement: 0.005, min: 0.1 }, // how long before piece drops by 1 row (seconds)
        nx = 10, // width of tetris court (in blocks)
        ny = 20, // height of tetris court (in blocks)
        nu = 5; // width/height of upcoming preview (in blocks)

    //-------------------------------------------------------------------------
    // game variables (initialized during reset)
    //-------------------------------------------------------------------------

    var dx, dy, // pixel size of a single tetris block
        blocks, // 2 dimensional array (nx*ny) representing tetris court - either empty block or occupied by a 'piece'
        actions, // queue of user actions (inputs)
        playing, // true|false - game is in progress
        dt, // time since starting this game
        current, // the current piece
        next, // the next piece
        score, // the current score
        vscore, // the currently displayed score (it catches up to score in small chunks - like a spinning slot machine)
        rows, // number of completed rows in the current game
        step; // how long before current piece drops by 1 row

    //-------------------------------------------------------------------------
    // tetris pieces
    //
    // blocks: each element represents a rotation of the piece (0, 90, 180, 270)
    // each element is a 16 bit integer where the 16 bits represent
    // a 4x4 set of blocks, e.g. j.blocks[0] = 0x44C0
    //
    // 0100 = 0x4 << 3 = 0x4000
    // 0100 = 0x4 << 2 = 0x0400
    // 1100 = 0xC << 1 = 0x00C0
    // 0000 = 0x0 << 0 = 0x0000
    // ------
    // 0x44C0
    //
    //-------------------------------------------------------------------------

    var i = { id: 'i', size: 4, blocks: [0x0F00, 0x2222, 0x00F0, 0x4444], color: 'cyan' };
    var j = { id: 'j', size: 3, blocks: [0x44C0, 0x8E00, 0x6440, 0x0E20], color: 'blue' };
    var l = { id: 'l', size: 3, blocks: [0x4460, 0x0E80, 0xC440, 0x2E00], color: 'orange' };
    var o = { id: 'o', size: 2, blocks: [0xCC00, 0xCC00, 0xCC00, 0xCC00], color: 'yellow' };
    var s = { id: 's', size: 3, blocks: [0x06C0, 0x8C40, 0x6C00, 0x4620], color: 'green' };
    var t = { id: 't', size: 3, blocks: [0x0E40, 0x4C40, 0x4E00, 0x4640], color: 'purple' };
    var z = { id: 'z', size: 3, blocks: [0x0C60, 0x4C80, 0xC600, 0x2640], color: 'red' };

    //------------------------------------------------
    // do the bit manipulation and iterate through each
    // occupied block (x,y) for a given piece
    //------------------------------------------------
    function eachblock(type, x, y, dir, fn) {
      var bit, result, row = 0, col = 0, blocks = type.blocks[dir];
      for(bit = 0x8000 ; bit > 0 ; bit = bit >> 1) {
        if (blocks & bit) {
          fn(x + col, y + row);
        }
        if (++col === 4) {
          col = 0;
          ++row;
        }
      }
    };

    //-----------------------------------------------------
    // check if a piece can fit into a position in the grid
    //-----------------------------------------------------
    function occupied(type, x, y, dir) {
      var result = false
      eachblock(type, x, y, dir, function(x, y) {
        if ((x < 0) || (x >= nx) || (y < 0) || (y >= ny) || getBlock(x,y))
          result = true;
      });
      return result;
    };

    function unoccupied(type, x, y, dir) {
      return !occupied(type, x, y, dir);
    };

    //-----------------------------------------
    // start with 4 instances of each piece and
    // pick randomly until the 'bag is empty'
    //-----------------------------------------
    var pieces = [];
    function randomPiece() {
      if (pieces.length == 0)
        pieces = [i,i,i,i,j,j,j,j,l,l,l,l,o,o,o,o,s,s,s,s,t,t,t,t,z,z,z,z];
      var type = pieces.splice(random(0, pieces.length-1), 1)[0];
      return { type: type, dir: DIR.UP, x: Math.round(random(0, nx - type.size)), y: 0 };
    };


    //-------------------------------------------------------------------------
    // GAME LOOP
    //-------------------------------------------------------------------------

    function run() {

      addEvents(); // attach keydown and resize events

      var last = now = timestamp();
      function frame() {
        now = timestamp();
        update(Math.min(1, (now - last) / 1000.0)); // using requestAnimationFrame have to be able to handle large delta's caused when it 'hibernates' in a background or non-visible tab
        draw();
        last = now;
        requestAnimationFrame(frame, canvas);
      }

      resize(); // setup all our sizing information
      reset(); // reset the per-game variables
      frame(); // start the first frame

    };

    function addEvents() {
      document.addEventListener('keydown', keydown, false);
      window.addEventListener('resize', resize, false);
    };

    function resize(event) {
      canvas.width = canvas.clientWidth; // set canvas logical size equal to its physical size
      canvas.height = canvas.clientHeight; // (ditto)
      ucanvas.width = ucanvas.clientWidth;
      ucanvas.height = ucanvas.clientHeight;
      dx = canvas.width / nx; // pixel size of a single tetris block
      dy = canvas.height / ny; // (ditto)
      invalidate();
      invalidateNext();
    };

    function keydown(ev) {
      var handled = false;
      if (playing) {
        switch(ev.keyCode) {
          case KEY.LEFT: actions.push(DIR.LEFT); handled = true; break;
          case KEY.RIGHT: actions.push(DIR.RIGHT); handled = true; break;
          case KEY.UP: actions.push(DIR.UP); handled = true; break;
          case KEY.DOWN: actions.push(DIR.DOWN); handled = true; break;
          case KEY.ESC: lose(); handled = true; break;
        }
      }
      else if (ev.keyCode == KEY.SPACE) {
        play();
        handled = true;
      }
      if (handled)
        ev.preventDefault(); // prevent arrow keys from scrolling the page (supported in IE9+ and all other browsers)
    };

    //-------------------------------------------------------------------------
    // GAME LOGIC
    //-------------------------------------------------------------------------

    function play() { hide('start'); reset(); playing = true; };
    function lose() { show('start'); setVisualScore(); playing = false; };

    function setVisualScore(n) { vscore = n || score; invalidateScore(); };
    function setScore(n) { score = n; setVisualScore(n); };
    function addScore(n) { score = score + n; };
    function clearScore() { setScore(0); };
    function clearRows() { setRows(0); };
    function setRows(n) { rows = n; step = Math.max(speed.min, speed.start - (speed.decrement*rows)); invalidateRows(); };
    function addRows(n) { setRows(rows + n); };
    function getBlock(x,y) { return (blocks && blocks[x] ? blocks[x][y] : null); };
    function setBlock(x,y,type) { blocks[x] = blocks[x] || []; blocks[x][y] = type; invalidate(); };
    function clearBlocks() { blocks = []; invalidate(); }
    function clearActions() { actions = []; };
    function setCurrentPiece(piece) { current = piece || randomPiece(); invalidate(); };
    function setNextPiece(piece) { next = piece || randomPiece(); invalidateNext(); };

    function reset() {
      dt = 0;
      clearActions();
      clearBlocks();
      clearRows();
      clearScore();
      setCurrentPiece(next);
      setNextPiece();
    };

    function update(idt) {
      if (playing) {
        if (vscore < score)
          setVisualScore(vscore + 1);
        handle(actions.shift());
        dt = dt + idt;
        if (dt > step) {
          dt = dt - step;
          drop();
        }
      }
    };

    function handle(action) {
      switch(action) {
        case DIR.LEFT: move(DIR.LEFT); break;
        case DIR.RIGHT: move(DIR.RIGHT); break;
        case DIR.UP: rotate(); break;
        case DIR.DOWN: drop(); break;
      }
    };

    function move(dir) {
      var x = current.x, y = current.y;
      switch(dir) {
        case DIR.RIGHT: x = x + 1; break;
        case DIR.LEFT: x = x - 1; break;
        case DIR.DOWN: y = y + 1; break;
      }
      if (unoccupied(current.type, x, y, current.dir)) {
        current.x = x;
        current.y = y;
        invalidate();
        return true;
      }
      else {
        return false;
      }
    };

    function rotate(dir) {
      var newdir = (current.dir == DIR.MAX ? DIR.MIN : current.dir + 1);
      if (unoccupied(current.type, current.x, current.y, newdir)) {
        current.dir = newdir;
        invalidate();
      }
    };

    function drop() {
      if (!move(DIR.DOWN)) {
        addScore(10);
        dropPiece();
        removeLines();
        setCurrentPiece(next);
        setNextPiece(randomPiece());
        clearActions();
        if (occupied(current.type, current.x, current.y, current.dir)) {
          lose();
        }
      }
    };

    function dropPiece() {
      eachblock(current.type, current.x, current.y, current.dir, function(x, y) {
        setBlock(x, y, current.type);
      });
    };

    function removeLines() {
      var x, y, complete, n = 0;
      for(y = ny ; y > 0 ; --y) {
        complete = true;
        for(x = 0 ; x < nx ; ++x) {
          if (!getBlock(x, y))
            complete = false;
        }
        if (complete) {
          removeLine(y);
          y = y + 1; // recheck same line
          n++;
        }
      }
      if (n > 0) {
        addRows(n);
        addScore(100*Math.pow(2,n-1)); // 1: 100, 2: 200, 3: 400, 4: 800
      }
    };

    function removeLine(n) {
      var x, y;
      for(y = n ; y >= 0 ; --y) {
        for(x = 0 ; x < nx ; ++x)
          setBlock(x, y, (y == 0) ? null : getBlock(x, y-1));
      }
    };

    //-------------------------------------------------------------------------
    // RENDERING
    //-------------------------------------------------------------------------

    var invalid = {};

    function invalidate() { invalid.court = true; }
    function invalidateNext() { invalid.next = true; }
    function invalidateScore() { invalid.score = true; }
    function invalidateRows() { invalid.rows = true; }

    function draw() {
      ctx.save();
      ctx.lineWidth = 1;
      ctx.translate(0.5, 0.5); // for crisp 1px black lines
      drawCourt();
      drawNext();
      drawScore();
      drawRows();
      ctx.restore();
    };

    function drawCourt() {
      if (invalid.court) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        if (playing)
          drawPiece(ctx, current.type, current.x, current.y, current.dir);
        var x, y, block;
        for(y = 0 ; y < ny ; y++) {
          for (x = 0 ; x < nx ; x++) {
            if (block = getBlock(x,y))
              drawBlock(ctx, x, y, block.color);
          }
        }
        ctx.strokeRect(0, 0, nx*dx - 1, ny*dy - 1); // court boundary
        invalid.court = false;
      }
    };

    function drawNext() {
      if (invalid.next) {
        var padding = (nu - next.type.size) / 2; // half-arsed attempt at centering next piece display
        uctx.save();
        uctx.translate(0.5, 0.5);
        uctx.clearRect(0, 0, nu*dx, nu*dy);
        drawPiece(uctx, next.type, padding, padding, next.dir);
        uctx.strokeStyle = 'black';
        uctx.strokeRect(0, 0, nu*dx - 1, nu*dy - 1);
        uctx.restore();
        invalid.next = false;
      }
    };

    function drawScore() {
      if (invalid.score) {
        html('score', (\"00000\" + Math.floor(vscore)).slice(-5));
        invalid.score = false;
      }
    };

    function drawRows() {
      if (invalid.rows) {
        html('rows', rows);
        invalid.rows = false;
      }
    };

    function drawPiece(ctx, type, x, y, dir) {
      eachblock(type, x, y, dir, function(x, y) {
        drawBlock(ctx, x, y, type.color);
      });
    };

    function drawBlock(ctx, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x*dx, y*dy, dx, dy);
      ctx.strokeRect(x*dx, y*dy, dx, dy)
    };

    //-------------------------------------------------------------------------
    // FINALLY, lets run the game
    //-------------------------------------------------------------------------

    run();

  </script>

</body>
</html>"
;
}
 
default
{
    
changed(integer change) {
        if (
change & (CHANGED_REGION_START CHANGED_REGION CHANGED_TELEPORT))
            
llResetScript();
    }

    
state_entry() {
        
llOwnerSay("Web Tetris " VERSION);
        
llRequestURL();
    }

    
on_rez(integer start_param) {
        
llResetScript();
    }

    
http_request(key idstring methodstring body) {
        if (
method == URL_REQUEST_GRANTED) {
            
myURL body;
            
browse(FACEbody);
        }
        else if (
method == "GET") {
            
string path_info llGetHTTPHeader(id"x-path-info");
            
// Appel url de base
            
if (path_info == "") {
                
// Réponse
                
llSetContentType(idCONTENT_TYPE_HTML);
                
llHTTPResponse(id200getPage());
            }
        }
    }

Et cliquez dessus, au bout d'un moment (le temps que le serveur se crée et le programme se charge) vous devez obtenir le jeu :

tetris.JPG

J'ai juste intégré un programme open source un peu adapté pour SL dans un script.

Si ce n'était le temps de chargement il y aurait une piste intéressante pour élargir les possibilités de nos scripts en faisant directement appel à des librairies Javascript externes sans impacter la mémoire disponible...
Merci Bestmomo , super jeu . J'ai juste une question . Est ce qu'on peut tourner les pièces ? et si oui avec quelle commande

Et si quelqu'un sait ou trouver le vieux mahjong freebie qui existait en 2006 , je suis preneuse ....... je ne retrouve pas le mien
Citation :
Publié par Cat.of.Library
J'ai juste une question . Est ce qu'on peut tourner les pièces ? et si oui avec quelle commande
Comme sur tous les Tetris, avec la flèche vers le haut .
Citation :
Publié par black cats
C'est vrai qu'un tetris avec des prims qui tombent, ç'aurait de la gueule.
Oui ça aurait de la gueule . Le problème réside dans l'optimisation du nombre de primitives utilisées. Une pièce peut facilement se créer avec un équivalent prim. Par contre les box qui restent en bas posent problème. Dans un traitement un peu bourrin on peut utiliser une primitive par box, et avec un jeu qui se remplit le nombre grimpe vite ! On peut optimiser tout ça mais c'est plus délicat à coder, je suis sur l'affaire .
Ca a l'air sympa.
Mais ça ne résout pas le problème soulevé par Best : 200 prims, ça fait mal !

Bon, il propose aussi une "version plate" à 41 prims.
Mais c'est moins marrant du coup.

Après, sur son opensim perso, les 200 prims posent moins de problèmes.
Citation :
Publié par djphil
SLTris (fonctionne sur OpenSim)
J'avais déjà analysé ce code quand il est sorti en 2007 . Il y a d'ailleurs un bug au niveau de la matrice des pièces. Les 200 primitives sont rédhibitoires et jouer sur des textures ne me satisfait pas. J'ai envie de "vraies" primitives qui "tombent" et d'optimiser tout ça pour ne pas dépasser une cinquantaine de primitives en tout quand la grille est presque pleine.

J'ai bien avancé mais je suis tombé sur un bug d'affichage qui pose problème. Et puis je dois gérer en même temps quelques projets dans d'autres domaines qui m'occupent. Mais je présenterai quand même bientôt une première version qui commence à ressembler à quelque chose.
Ah oui, j'avais pas vu que ça marchait avec des textures.
En effet, ça perd beaucoup d'intérêt. L'intérêt de faire ça sur SL, c'est de voir tomber des briques 3D.

Une cinquantaine de primitives, ça devient raisonnable. Et bien plus encore, dans la mesure où ce n'est que temporaire, et que la majorité des prims disparaissent quand on arrête de jouer.
Je suis curieux de voir quels artifices tu utilises pour optimiser ça.

En tout cas, j'attends avec impatience de pouvoir tester.

J'espère qu'on n'aura pas besoin de chaussures de sécurité quand les briques se mettront à tomber.
Voici un peu où j'en suis sur cette vidéo :



J'ai toujours mon problème de bug du viewer quand on est un peu trop éloigné, des objets ne s'affichent pas et il faut zoomer, on le voit à un moment sur la vidéo. Si quelqu'un a une astuce pour régler ça. J'ai aussi un bug dans un cas de figure bien particulier, mais je n'ai pas réussi à bien le cerner .

Au niveau de l'équivalent prims voici un instantané des boxes :

tetris_impact.jpg

On voit un impact de 20 pour 68 boxes présentes, donc dans ce cas là un gain de 70% par rapport à un traitement de base une box = une primitive. La question est : mais comment est-ce que je fais ?

Dernière modification par bestmomo ; 14/11/2013 à 12h54.
Bravo Bestmomo, c'est très beau.
Pour la "disparition" visuelle des cubes, cela ne vient pas d'un réglage trop "faible" de tes préférences graphiques?
Les formes qui tombent sont générées par un site internet de tetris ou bien sont-elles générées par ton script?
On déplace latéralement les cubes avec le clavier?
Citation :
Publié par Poisson.Soluble
Pour la "disparition" visuelle des cubes, cela ne vient pas d'un réglage trop "faible" de tes préférences graphiques?
J'ai réglé le problème en obligeant l'avatar à s'asseoir et en fixant la caméra. Ma carte graphique est vieillote et je ne dois pas être le seul dans ce cas.

Citation :
Publié par Poisson.Soluble
Les formes qui tombent sont générées par un site internet de tetris ou bien sont-elles générées par ton script?
Tout est généré en LSL.

Citation :
Publié par Poisson.Soluble
On déplace latéralement les cubes avec le clavier?
Oui, avec les flèches comme dans les Tetris classiques.
Citation :
Publié par bestmomo
La question est : mais comment est-ce que je fais ?
Bon, je tente quelques hypothèses

- les pièces, lorsqu'elles tombent sont faites de soit une, soit deux primitives, selon leur complexité, de manière à pouvoir les faire à partir de prims parallélépipédiques

- une fois tombées, la prim disparait, et est remplacée par un autre système :
tu rezzes des barres horizontales, de n fois la longueur d'une box, pour chaque succession de n box de même couleur. Chaque ligne est constitué uniquement de ces barres. De la gauche vers la droite : une nouvelle barre à chaque fois qu'on change de couleur.

- pour faire bonne mesure, tu linkes les barres d'une même ligne au fur et à mesure qu'elles arrivent, et les passes en convex hull. Ce qui fait que chaque prim a un impact de 0,5 seulement (arrondi à l'entier supérieur pour le linkset).
Un linkset par ligne, donc.

Ce qui donnerait, pour ce qu'on voit sur ton image :
la ligne tout en bas : 4 prims ---> 2 PE (Prim Equivalent)
la ligne juste au dessus : 5 prims ---> 3 PE
etc

En comptant d'après ton image, j'arrive à un impact de 19, ce qui n'est pas loin de ce que tu obtiens.
En revanche, mon système donnerait 1 linkset par ligne entamée, soit 9 objets, ce qui n'est pas en accord avec les 20 objets indiqués dans ta fenêtre d'édition.
Tu as presque tout bon .


  • Les pièces sont toutes faites de deux primitives (1 équivalent prim). Ca m'arrange pour le positionnement et les rotations.
  • Une fois tombée la pièce est remplacée par des barres horizontales faites aussi de deux primitives (1 équivalent prim). Ces barres peuvent gérer deux couleurs. Donc à mesure que ça tombe je gère selon l'existant l'apparence des barres (je fais apparaître une ou deux couleurs et j'absorbe ce qui tombe une couleur est disponible ou si les couleurs sont les mêmes).
  • Je peux pas linker "en vol" (il faut la permission et en plus ça plante le script 1 seconde) donc je gère comme ça et je n'ai pas un linkset pour chaque ligne mais plusieurs objets (d'ou les 20 objets de mon exemple). Mais en équivalent prim c'est presque pareil, ça dépend de la configuration des pièces.
Je me suis donc empressé de tester le tetris que tu as installé au café JOL.

Très sympa de voir de "vraies" pièces 3D tomber les unes sur les autres.

Malheureusement, le bug d'affichage dont tu as parlé plusieurs fois est très fréquent chez moi. Je ne sais pas si ça se manifeste à ce point là chez tout le monde, si ma carte graphique assez basique a un rapport...

Pas de vrai problème pour les pièces qui tombent.
En revanche, lorsqu'elles se transforment en ligne, il y a quasiment un problème d'affichage à chaque fois. Du coup, c'est quasi injouable.

J'imagine que tu as déjà du essayer de bidouiller pour contourner ce bug.
Peut-être en passant l'opacité de la texture à 0.999 pendant un instant, juste après le rez ?
Ça dépend vraiment de la sim où on se trouve, si elle est pas trop chargée il n'y a aucun problème. Je vais essayer de bidouiller l'alpha, là je me contente de mettre à 1 quand je les ai placées et déformées parce que je stocke en permanence 4 box prêtes à l'emploi avec un alpha à 0.
Citation :
Publié par bestmomo
Ça dépend vraiment de la sim où on se trouve
Apparemment, le problème serait donc côté serveur, et non pas client.
Donc, ni liée au viewer, ni à la carte graphique.

Il faudrait voir si le problème vient plutôt du fait que les pièces nouvellement rezzées ne sont pas prises en compte du tout pour l'affichage (indépendamment du alpha), ou si c'est le passage invisible/visible qui ne se fait pas.

Je n'ai pas constaté de problème avec les pièces qui tombent, uniquement avec les pièces déjà tombées. Ce qui laisse penser que le problème d'affichage est bien lié à leur caractère initialement invisible.
Tu as testé si ça change quelque chose quand tu rezzes les pièces avec un alpha de 1 au lieu de zéro ? Ou avec un alpha très faible, mais non nul ?
(les pièces invisibles que tu stockes, c'est uniquement celles qui restent en bas, ou aussi celles qui tombent ?).
Ah oui, j'ai testé aussi.
J'adore.
Très fluide, et sans le bug d'affichage, c'est franchement agréable à jouer.

Quand quatre lignes disparaissent d'un coup, et qu'il y a tout un empilage de briques qui tombent, il y a un petit coup de lag, celles du dessus prennent un léger retard, qui donne un effet de réalisme supplémentaire assez sympa
.

Dernière modification par Compte #393338 ; 11/01/2014 à 01h03.
@Yongho

Oui le jeu est pas folichon mais je me suis concentré sur le fonctionnement, je ferai mieux pour la prochaine version. Le clignotement des pièces en bas est dû au fait qu'il y a une substitution de primitives et selon le lag ça se voit. Le biais est effectivement pour mettre en relief l'aspect 3D, on s'y habitue vite pour les alignements.

*****************************************************

Sinon je vous annonce deux choses :

  • J'ai créé une page sur mon site sur ce sujet. Avec en particulier la possibilité de télécharger un manuel au format PDF qui explique la création du jeu et comporte toutes les informations nécessaires pour en créer un (build et scripts). Vous pouvez donc avec ça vous faire un joli Tetris. Les scripts sont réservés à un usage personnel.
  • Pour ceux qui voudraient un truc tout prêt j'ai aussi mis une version en vente sur le market. Celle-ci comporte quelques fonctionnalités supplémentaires, en particulier elle est en relation avec un serveur externe. Si le jeu a du succès je compte mettre en place des compétitions entre tous les possesseurs, je collecte donc toutes les informations que je range soigneusement dans une base de données (c'est mon côté big brother !). Les acquéreurs recevront également automatiquement les mises à jour.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés