Papervision Tile

Olá pessoal, estava me preparando para montar um novo tutorial sobre tile system, já estou a algum tempo uma atualização para a estruturação de cenários isométricos, mas eu pensei “por que não criar um cenário 3D tile?”

swf

Clique na imagem para testar.

Gostou, este será o nosso produto final, pois bem vamos seguir com o tutorial.

Lógica:

A lógica é bem simples, usaremos 2 vetores diferentes, um deles será para mostrar qual será o tile que usaremos na posição e o outro vetor que indicara a altura. Criaremos os loops para percorrer o vetor e criar cubos num plano 3D. Como termos alguns cubos suspensos, completaremos os espaços vazios com cubos, e colocaremos uma função para rotacionar nosso Field.

Tiles:

linkage

Estes sãos os movieclips que usaremos no nosso arquivo .fla, todos eles com exceção do water são estáticos, não possuem nenhum freme alem do desenhado, já o water eu coloquei uma pequena movimentação para dar um efeito de água se movendo. Todos os movieclips estão com a propriedade linkage definidos.

Usaremos a classe MovieAssetMaterial para importarmos cada movieclip para um material diferente

 public var matGrass:MovieAssetMaterial = new MovieAssetMaterial("grass");
 public var matBase0:MovieAssetMaterial = new MovieAssetMaterial("base0");
 public var matBase1:MovieAssetMaterial = new MovieAssetMaterial("base1");
 public var matFlower:MovieAssetMaterial = new MovieAssetMaterial("flower");
 public var matWater:MovieAssetMaterial = new MovieAssetMaterial("water", true);

Tiles x Materiais

materiaislist

Como vocês podem ver na imagem acima montaremos cubos para usarmos como tile, por enquanto vamos nos focar em criar as listas de materiais para as respectivas faces dos cubos.

 public var w:MaterialsList = new MaterialsList(
    {front: matWater, back: matWater, left: matWater,
     right: matWater,  top: matWater,  bottom: matWater});
 public var g:MaterialsList = new MaterialsList(
    {front: matBase1,  back: matBase1,  left: matBase1,
     right: matBase1,  top: matGrass,  bottom: matBase1});
 public var f:MaterialsList = new MaterialsList(
    {front: matBase1,  back: matBase1,  left: matBase1,
     right: matBase1,  top: matFlower,  bottom: matBase1});
 public var b:MaterialsList = new MaterialsList(
    {front: matBase0,  back: matBase0,  left: matBase0,
     right: matBase0,  top: matBase0,   bottom: matBase0});

Assim nosso Tile ficara formatado da seguinte forma.

 public var arrayTile:Array = [
  [w,w,w,w,w,w,w,w,w,w],
  [w,w,w,g,g,g,g,w,w,w],
  [w,g,g,g,g,g,f,w,w,w],
  [w,f,g,f,g,g,g,g,w,w],
  [w,g,g,g,f,g,g,g,w,w],
  [w,w,g,g,w,g,g,g,w,w],
  [w,w,w,g,g,f,g,g,w,w],
  [w,w,w,g,g,g,g,w,w,w],
  [w,w,f,g,g,f,w,w,w,w],
  [w,w,w,w,w,w,w,w,w,w]];

Tile x Altura

Para não poluir o vetor de tile decidi usar um vetor separado para mostrar o posicionamento do bloco no plano R3.

 public var arrayTileHeight:Array = [
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,2,2,3,0,0,0],
  [0,3,2,0,1,1,2,0,0,0],
  [0,2,1,1,1,1,2,0,0,0],
  [0,0,1,1,1,1,1,0,0,0],
  [0,0,0,1,1,0,0,0,0,0],
  [0,0,0,0,1,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0]];

Nós usaremos cada cubo com o tamanho 30x30x30 analogamente para subir um nível os blocos temos que multiplicarmos a posição demonstrada no vetor por 30.

espaco

Com isso acabamos criando espaços vagos.para resolvermos isso criaremos um loop que criará blocos do tipo base da altura 0 ate a altura definida.

Criando Tiles

A diferença dos tiles que vimos em R2 para o R3 é que alteramos a propriedades x e z com os loops ao invés de (x,y) a propriedade y utilizamos para altura.

public function Objetos () {
  for (var i = 0; i < arrayTile.length; i++) {
      for (var j = 0; j <  arrayTile[0].length; j++) {
          //Criando blocos extras na altura
          if (arrayTileHeight[i][j]>0) {
             for (var k=0; k< arrayTileHeight[i][j]; k++){
                var obCubeb:Cube = new Cube(b,30,30,30);
                cena.addChild (obCubeb);
                obCubeb.x = i * 30 -150;
                obCubeb.z = j * 30 -150;
                obCubeb.y = k * 30;
             }
          }
          //Criando bloco Tile
          var obCube:Cube = new Cube(arrayTile[i][j],30,30,30);
          cena.addChild (obCube);
          obCube.x = i * 30 -150;
          obCube.z = j * 30 -150;
          obCube.y = arrayTileHeight[i][j] * 30;
      }
    }
    addEventListener (Event.ENTER_FRAME,Loop,false, 0, true);
 }

Código extra: Movimentando a câmera

Para fazer a movimentação da câmera utilizei a seguinte lógica, criei um objeto do tipo plano no centro de nosso cenário, e travei a câmera nele com o método.

obcamera.lookAt (centro);

Assim independente o posicionamento do x, y e z da câmera, ele sempre terá como foco o centro do mapa. Agora podemos movimentar o x e z da câmera para circular o cenário que ele nunca mudara seu foco.

A cada frame colocaremos as propriedades x e z somarem um valor, valor este que estará armazenado em um vetor. Se sempre somarmos valores nossa câmera sempre se afastará, com as possibilidades definidas em um vetor podemos manipular para ele alem de somar subtrair também para trazer a câmera de voltar.

Código Completo

Arquivo main.as

package {
   //flash
   import flash.display.MovieClip;
   import flash.events.*;
   //Papervision
   import org.papervision3d.objects.primitives.Plane;
   import org.papervision3d.objects.primitives.Cube;
   import org.papervision3d.scenes.Scene3D;
   import org.papervision3d.render.BasicRenderEngine;
   import org.papervision3d.cameras.Camera3D;
   import org.papervision3d.view.Viewport3D;
   import org.papervision3d.materials.MovieAssetMaterial;
   import org.papervision3d.materials.utils.MaterialsList;
   public class main extends MovieClip {
      //papervision
      public var cena:Scene3D;
      public var viewport:Viewport3D;
      public var camera:Camera3D;
      public var renderer:BasicRenderEngine;
      public var centro:Plane;
      //material
      public var matGrass:MovieAssetMaterial = new MovieAssetMaterial("grass");
      public var matBase0:MovieAssetMaterial = new MovieAssetMaterial("base0");
      public var matBase1:MovieAssetMaterial = new MovieAssetMaterial("base1");
      public var matFlower:MovieAssetMaterial = new MovieAssetMaterial("flower");
      public var matWater:MovieAssetMaterial = new MovieAssetMaterial("water", true);
      public var w:MaterialsList = new MaterialsList(
         {front: matWater, back: matWater, left: matWater,
          right: matWater, top: matWater, bottom: matWater});
      public var g:MaterialsList = new MaterialsList(
         {front: matBase1, back: matBase1, left: matBase1,
          right: matBase1, top: matGrass, bottom: matBase1});
      public var f:MaterialsList = new MaterialsList(
         {front: matBase1, back: matBase1, left: matBase1,
          right: matBase1, top: matFlower, bottom: matBase1});
      public var b:MaterialsList = new MaterialsList(
         {front: matBase0, back: matBase0, left: matBase0,
          right: matBase0, top: matBase0, bottom: matBase0});
       //tiles
       public var arrayTile:Array = [
        [w,w,w,w,w,w,w,w,w,w],
        [w,w,w,g,g,g,g,w,w,w],
        [w,g,g,g,g,g,f,w,w,w],
        [w,f,g,f,g,g,g,g,w,w],
        [w,g,g,g,f,g,g,g,w,w],
        [w,w,g,g,w,g,g,g,w,w],
        [w,w,w,g,g,f,g,g,w,w],
        [w,w,w,g,g,g,g,w,w,w],
        [w,w,f,g,g,f,w,w,w,w],
        [w,w,w,w,w,w,w,w,w,w]];
       public var arrayTileHeight:Array = [
        [0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,2,2,3,0,0,0],
        [0,3,2,0,1,1,2,0,0,0],
        [0,2,1,1,1,1,2,0,0,0],
        [0,0,1,1,1,1,1,0,0,0],
        [0,0,0,1,1,0,0,0,0,0],
        [0,0,0,0,1,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0],
        [0,0,0,0,0,0,0,0,0,0]];
       //Camera
       public var cam:int = 0
       public var a:int = 0;
       public var arrayCam:Array = [[-45,0],[0,-45],[45,-0],[0,45]];
       public function main () {
          Set ();
          Objetos ();
       }
       public function Set ():void {
          viewport = new Viewport3D(400,300,true,false,true,true);
          addChild (viewport);
          cena = new Scene3D ;
          renderer = new BasicRenderEngine ;
          camera = new Camera3D ;
          camera.focus = 100;
          camera.zoom = 10;
          camera.x = 650;
          camera.z = 450;
          camera.y = 700;
          centro = new Plane();
          centro.y = 0;
          centro.z = 0;
          centro.x = 0;
      }
      public function Objetos ():void {
          for (var i = 0; i < arrayTile.length; i++) {
             for (var j = 0; j <  arrayTile[0].length; j++) {
                //Criando blocos extras na altura
                if (arrayTileHeight[i][j]>0) {
                    for (var k=0; k< arrayTileHeight[i][j]; k++){
                       var obCubeb:Cube = new Cube(b,30,30,30);
                       cena.addChild (obCubeb);
                       obCubeb.x = i * 30 -150;
                       obCubeb.z = j * 30 -150;
                       obCubeb.y = k * 30;
                    }
                }
                //Criando bloco Tile
                var obCube:Cube = new Cube(arrayTile[i][j],30,30,30);
                cena.addChild (obCube);
                obCube.x = i * 30 -150;
                obCube.z = j * 30 -150;
                obCube.y = arrayTileHeight[i][j] * 30;
             }
          }
          addEventListener (Event.ENTER_FRAME,Loop,false, 0, true);
      }
      public function Loop (e:Event):void {
          a++ ;
          rotaionCamera (camera,arrayCam[cam][0],arrayCam[cam][1])
          if (a % 30 == 0){
             nextCamera()
          }
          renderer.renderScene (cena,camera,viewport);
      }
      public function nextCamera():void{
          cam= cam+1
          if (cam>=4){
             cam = 0
          }else if (cam<=-1){
             cam = 3
          }
      }
      public function rotaionCamera (obcamera:Camera3D,newx,newz):void {
          obcamera.x+= newx;
          obcamera.z+= newz;
          obcamera.lookAt (centro);
      }
   }
}

Obs: Lembrando que estamos fazendo um aplicativo utilizando as classes do papervision, não podemos esquecer-nos de importalas.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s


%d blogueiros gostam disto: