0votos

Crear un render de espacios isométricos sin usar z-buffer en JavaScript

por josejuan hace 4 años

Usando la estrategia comentada aquí (https://gist.github.com/josejuan/8e59c1aa8abee643ca0d) y la propiedad (estandar) de css que permite fijar una máscara basada en SVG. No se realizan optimizaciones (ej. se están renderizando todos los objetos en todas las celdas aunque no hace falta).

Crear un render de espacios isométricos sin usar z-buffer en el que los objetos deben poder tener múltiples alturas, anchuras mayores que la celda en la que están y tener partes transparentes (en que se ve lo que hay detrás).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<!DOCTYPE html> 
<html> 
  <head> 
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script> 
    <script type="text/javascript"> 
      $(function () { 
 
        // hardcoded 100x50 tiles 
        var COLS = 10, ROWS = 10; 
 
        // image preolading (to know sizes) 
        var img = { grass: 0, tree: 0, build1: 0, build2: 0, build3: 0, character: 0 }; 
        for(var p in img) 
          $('#preload').append(img[p] = $('<img />').attr('src', p + '.png')); 
 
        // tile ground construction 
        for(var col = 0; col < COLS; col++) 
            for(var row = 0; row < ROWS; row++) { 
              var x = 50 * (ROWS - row + col - 1), y = 25 * (row + col); 
              $('#ground').append( 
                $('<div />'). 
                  css({ position: 'absolute', left: x + 'px', top: y + 'px', width: '100px', height: '50px', overflow: 'hidden', mask: 'url(#tilemask)'}). 
                  attr('tx', x).attr('ty', y). 
                  append($('<img src="grass.png" style="position: absolute; z-index: -1" />')) 
              ); 
 
        // insert arbitrary size *static* object into ground (to move, update current tile and delta positions) 
        var insert = 
          function (col, row, image) { 
            var iw = image.width(), ih = image.height(); 
            var bx = 50 * (ROWS - row + col) - (iw >> 1), by = 25 * (row + col) + 50 - ih; // up/left image corner into ground world 
            $('#ground').find('div').each(function () { 
              var t = $(this), tx = ~~t.attr('tx'), ty = ~~t.attr('ty'); 
              t.append( 
                $('<img />'). 
                attr('src', image.attr('src')). 
                css({ position: 'absolute', left: (bx - tx) + 'px', top: (by - ty) + 'px', 'z-index': Math.max(col, row)}) 
              ); 
            }); 
          }; 
 
        { // random objects 
          var imgs = []; 
          for(var p in img) 
            imgs.push(p); 
          for(var col = 0; col < COLS; col++) 
            for(var row = 0; row < ROWS; row++) 
              insert(col, row, img[imgs[~~(Math.random() * imgs.length)]]); 
 
      }); 
    </script> 
  </head> 
  <body style="background: #c0c0c0"> 
    <div id="preload" style="height: 1px; overflow: hidden"></div> 
    <div id="ground"> 
    </div> 
    <svg height="0"> 
      <mask id="tilemask" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox"> 
        <polygon points="0,0.5 0.5,0 1,0.5 0.5,1" style="fill:white" /> 
      </mask> 
    </svg> 
  </body> 
</html> 
1 comentario

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.