Tile System [Enemy]

今日は皆-さん. Em fim dificuldade no nosso game, mas eu não estou falando de códigos avançados e complexos que vocês não entenderão, eu estou falando de inimigos. Como nosso grande amigos Ratysu (Dados Sujos) costumava dizer “A dificuldade valoriza o cumprimento da missão”. Pois bem um jogo com inimigos ganha muito mais emoção. E hoje daremos continuidade ao nosso tutorial tile system com a implementação de inimigos.

ssemeny

Clique aqui para jogar

Criando MovieClip Enemy:

Nosso movieclip enemy seguirá as mesmas proporções do player, com a diferença nos sprites e a propriedade linkage será definida como “Enemy”.

linkageenemy

Tipos de Inimigos:

Em nosso tutorial aprenderemos a montar 2 tipos de inimigos: os burros e os menos burros.

Burros: São aqueles inimigos que não se cansam de mover de um lado para o outro, anda anda anda , bate na parede, volta volta volta. Em nosso código chamaremos de inimigos tipo “Flip”.

Menos Burros: São aqueles inimigos que ao encostar em uma parede, escolhe uma direção aleatoriamente e segue ate o encontro da próxima parede. Chamaremos eles de tipo “Choose”.

Criando os objetos:

Nossos inimigos assim como criamos o jogador usaremos objetos com algumas propriedades pré definidas.

Enemy1 = {xtile:2, ytile:3, speed:2, enemy:true,  dirx:0, diry:-1, Type:"Flip"};
  • xtile,ytile (Number): Posição x e y inicial no tile system.
  • speed (Number): Velocidade do inimigo
  • enemy (Boolean): Esta propriedade especificara que o objeto é um inimigo, devemos implementar essa propriedade ao objeto Player também marcando como false.
  • dirx, diry (Number): Indica qual é a direção que nosso inimigo começará a percorrer. Seguindo as combinações:[1,0] direita, [-1,0] esquerda, [0,1] cima, [0,-1] baixo e [0,0] parado.
  • Type (“Choose” ou “Flip”): Indicará qual é o tipo do nosso inimigo

Junto com a criação dos objetos criaremos um vetor que armazenará todos os nosso objetos de inimigos. O código das declarações ficará mais ou menos assim:

char = {xtile:1,  ytile:1, speed:2, enemy:false};
Enemy1 = {xtile:2,  ytile:3, speed:2, enemy:true, dirx:0, diry:-1, Type:"Flip"};
Enemy2 = {xtile:6,  ytile:8, speed:2, enemy:true, dirx:-1, diry:0, Type:"Choose"};
Enemy3 = {xtile:2,  ytile:6, speed:2, enemy:true, dirx:0, diry:-1, Type:"Flip"};
arrayEnemy = [Enemy1, Enemy2, Enemy3];

Criando os MovieClips:

O processo de criação dos inimigos no field seguirá o mesmo padrão dos itens. Criaremos um loop que para cada índice fará referencia a um vetor para pegar as informações referentes as propriedades e logo em seguida substituirá o objeto do vetor pelo movieclip.

for (i = 0; i <  arrayEnemy.length; i++) {
  _root["Field"].attachMovie("Enemy","Enemy"  + i,5001 + i);
  _root["Field"]["Enemy"  + i]._x = arrayEnemy[i].xtile * TileP + 10;
  _root["Field"]["Enemy"  + i]._y = arrayEnemy[i].ytile * TileP + 10;
  _root["Field"]["Enemy"  + i].height = 7.5;
  _root["Field"]["Enemy"  + i].speed = arrayEnemy[i].speed;
  _root["Field"]["Enemy"  + i].enemy = arrayEnemy[i].enemy;
  _root["Field"]["Enemy"  + i].dirx = arrayEnemy[i].dirx;
  _root["Field"]["Enemy"  + i].diry = arrayEnemy[i].diry;
  _root["Field"]["Enemy"  + i].Type = arrayEnemy[i].Type;
  arrayEnemy[i] =  _root["Field"]["Enemy" + i];
}

Movendo os Inimigos:

O que difere os inimigos dos Playes? Ao meu ponto de vista o players você comanda e os inimigos andam sozinho. Vamos relembrar o funcionamento da estrutura de movimentação do Player.

Nos temos um loop que verifica quando pressionamos um botão. Depois se pressionarmos algo ele chama uma função passando os parâmetros da direção que o player vai ter que seguir. Na função armazenamos os valores de posicionamento em uma variável imagem fazemos cálculos com a velocidade, verificamos se depois do calculo se o tile no qual ele esta se dirigindo é walkable, senão deixamos o personagem parado.

Basicamente nosso inimigo também faz tudo isso com algumas mudanças, ao invés do jogador definir a direção com um botão, nosso inimigo já sabe qual é a direção que ele tem que seguir (dirx e diry), e ao invés dele ficar parado quando o destino não é permitido ele muda sua direção e segue o trajeto.

Pois bem no nosso loop criaremos um loop que percorrerá o vetor de inimigos e pedirá para todos andem suas respectivas direções, também aproveitaremos o loop para verificar se nosso player encostou em nosso inimigo, para o teste ficar perceptível colocaremos apenas para ele receber alpha 50 ao encostar. E na nossa função de movePlayer adicionaremos a verificação, se o objeto for encostar na parede ele criará uma variável wall e retornará true especificando o toque. Depois nós verificaremos. Se for um inimigo e encostou na parede mude de direção.

LoopFrame(){
   ..
 for (i in arrayEnemy) {
   movePlayer  (arrayEnemy[i],arrayEnemy[i].dirx,arrayEnemy[i].diry);
   if (arrayEnemy[i].hitTest  (Player)) {
     Player._alpha = 50;
   }
 }
 ..
..movePlayer (ob, dx, dy){
   ..
   if (_root["Field"][tileName].walk) {
     if ((dx == 1) or (dx == -1)) {
       ob._x += ob.speed * dx;
     }
   if ((dy == 1) or (dy == -1)) {
       ob._y += ob.speed * dy;
     }
   } else {
     hitwall = true;
   }
   ...

Nesta parte do código verificaremos se o inimigo é do tipo “Flip” ou “Choose”. Quando ele é Flip apenas multiplicamos as direções por -1 e quando for choose criamos um vetor com as 4 próximas possibilidades de movimento e usamos uma simples estrutura de random para escolher.

if (hitwall && ob.enemy) {
   if (ob.Type == "Flip")  {
     movePlayer (ob,dx * -1,dy *  -1);
     ob.dirx *= -1;
     ob.diry *= -1;
   } else if (ob.Type ==  "Choose") {
   var arraydir:Array = [[0, 1],  [1, 0], [0, -1], [-1, 0]];
   var rnddir = Math.round  (Math.random () * 4);
   movePlayer (ob,arraydir[rnddir][1],arraydir[rnddir][1]);
   ob.dirx = arraydir[rnddir][0];
   ob.diry = arraydir[rnddir][1];
   }
}

Código Final:

Agora vamos ver como ficou todo o código do na integra.

stop ();
arrayField = [[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
              [2, 0, 0, 0, 0, 0, 1, 0, 2, 2, 2, 2, 2, 2, 2],
              [2, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 1, 2, 2],
              [2, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 2, 2],
              [2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 2, 2],
              [2, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, 2],
              [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2],
              [2, 0, 0, 0, 1, 2, 0, 1, 0, 0, 2, 2, 2, 2, 2],
              [2, 2, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2],
              [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]];
itens = [[1, 2], [2, 8], [5, 6], [8, 7], [11, 4], [8, 4], [5, 1]];
var pontos:Number = 0;
_root.createEmptyMovieClip ("Field",1);
char = {xtile:1, ytile:1, speed:2, enemy:false};
Enemy1 = {xtile:2, ytile:3, speed:2, enemy:true, dirx:0,  diry:-1, Type:"Flip"};
Enemy2 = {xtile:6, ytile:8, speed:2, enemy:true, dirx:-1,  diry:0, Type:"Choose"};
Enemy3 = {xtile:2, ytile:6, speed:2, enemy:true, dirx:0,  diry:-1, Type:"Flip"};
arrayEnemy = [Enemy1, Enemy2, Enemy3];
Tile0 = {walk:true, frame:1};
Tile1 = {walk:false, frame:2};
Tile2 = {walk:false, frame:3};
TileP = 20;
indice = 0;
for (i = 0; i < arrayField[0].length; i++) {
  for (j = 0; j <  arrayField.length; j++) {
    indice += 1;
    newName =  "Tile_" + j + "_" + i;
    _root["Field"].attachMovie  ("Tile",newName,indice);
    _root["Field"][newName]._x = i * TileP;
    _root["Field"][newName]._y = j * TileP;
    _root["Field"][newName].walk = _root["Tile" + arrayField[j][i]].walk;
    _root["Field"][newName].gotoAndStop  (_root["Tile" + arrayField[j][i]].frame);
  }
}
for (i = 0; i < itens.length; i++) {
  var itemName =  "item_" + itens[i][1] + "_" + itens[i][0];
  _root["Field"].attachMovie  ("itens",itemName,i + 200);
  _root["Field"][itemName]._x  = itens[i][0] * TileP + 10;
  _root["Field"][itemName]._y  = itens[i][1] * TileP + 10;
}
_root["Field"].attachMovie  ("Player","Player",5000);
_root["Field"]["Player"]._x = char.xtile * TileP +  10;
_root["Field"]["Player"]._y = char.ytile * TileP +  10;
_root["Field"]["Player"].height = 7.5;
_root["Field"]["Player"].speed = char.speed;
_root["Field"]["Player"].enemy = char.enemy;
_root["Field"]["Player"].enemy = char.enemy;

for (i = 0; i < arrayEnemy.length; i++) {
  _root["Field"].attachMovie  ("Enemy","Enemy" + i,5001 + i);
  _root["Field"]["Enemy"  + i]._x = arrayEnemy[i].xtile * TileP + 10;
  _root["Field"]["Enemy"  + i]._y = arrayEnemy[i].ytile * TileP + 10;
  _root["Field"]["Enemy"  + i].height = 7.5;
  _root["Field"]["Enemy"  + i].speed = arrayEnemy[i].speed;
  _root["Field"]["Enemy"  + i].enemy = arrayEnemy[i].enemy;
  _root["Field"]["Enemy"  + i].dirx = arrayEnemy[i].dirx;
  _root["Field"]["Enemy"  + i].diry = arrayEnemy[i].diry;
  _root["Field"]["Enemy"  + i].Type = arrayEnemy[i].Type;
  arrayEnemy[i] =  _root["Field"]["Enemy" + i];
}

function loopFrame () {
  var Player =  _root["Field"]["Player"];
  if (Key.isDown  (Key.RIGHT)) {
    movePlayer  (Player,1,0);
  } else if  (Key.isDown (Key.LEFT)) {
    movePlayer  (Player,-1,0);
  } else if  (Key.isDown (Key.DOWN)) {
    movePlayer  (Player,0,1);
  } else if  (Key.isDown (Key.UP)) {
    movePlayer  (Player,0,-1);
  }
  for (i in itens)  {
    var  itemName = "item_" + itens[i][1] + "_" + itens[i][0];
    if  (_root["Field"][itemName].hitTest (Player)) {
      _root["Field"][itemName].removeMovieClip  ();
      pontos  += 100;
    }
  }
  for (i in  arrayEnemy) {
    movePlayer  (arrayEnemy[i],arrayEnemy[i].dirx,arrayEnemy[i].diry);
    if  (arrayEnemy[i].hitTest (Player)) {
      Player._alpha  = 50;
    }
  }
}
function movePlayer (ob, dx, dy) {
  var hitwall:Boolean  = false;
  ob.x = ob._x;
  ob.y = ob._y;
  ob.xtileIm =  Math.floor ((ob.x += ((ob.speed + ob.height) * dx)) / TileP);
  ob.ytileIm =  Math.floor ((ob.y += ((ob.speed + ob.height) * dy)) / TileP);
  var tileName:String  = "Tile_" + (ob.ytileIm) + "_" + (ob.xtileIm);
  if  (_root["Field"][tileName].walk) {
    if ((dx == 1) or  (dx == -1)) {
      ob._x  += ob.speed * dx;
    }
    if ((dy == 1) or  (dy == -1)) {
      ob._y  += ob.speed * dy;
    }
  } else {
    hitwall = true;
  }
  ob.xtile =  Math.floor (ob._x / TileP);
  ob.ytile =  Math.floor (ob._y / TileP);
  ob.xtileIm =  ob.xtile;
  ob.ytileIm =  ob.ytile;
  if (hitwall  && ob.enemy) {
    if (ob.Type ==  "Flip") {
      movePlayer  (ob,dx * -1,dy * -1);
      ob.dirx  *= -1;
      ob.diry  *= -1;
    } else if  (ob.Type == "Choose") {
      var  arraydir:Array = [[0, 1], [1, 0], [0, -1], [-1, 0]];
      var  rnddir = Math.round (Math.random () * 4);
      movePlayer  (ob,arraydir[rnddir][1],arraydir[rnddir][1]);
      ob.dirx  = arraydir[rnddir][0];
      ob.diry  = arraydir[rnddir][1];
    }
  }
}

Como vocês podem ver o código está bem rústico, quando eu tive a idéia de montar este tutorial era para seguir de maneira simples e pratica a criação de um jogo. Não me preocupei muito com modulação e estruturação. Por isso este será o tema do nosso próximo tutorial tile system. Vamos organizar este código e depois migrar para actionscript 3.0.até a próxima. Cya. また見てね.

Deixe um comentário