Back-End

Publicidade

Olá, novamente, pessoal.

Na primeira parte deste artigo, vimos quais as vantagens e as características do NResponder. Caso ainda não tenha lido, confira aqui a primeira parte.

Nesta segunda parte, vamos ver o NResponder em ação em um exemplo real.

Agora você precisará dos arquivos fontes desse projeto. Você pode baixá-los aqui.

Rápida explicação

Neste exemplo vamos criar uma rotina de jogo de tiro bem simples, para mostrar como as características e os benefícios do NResponder podem mudar a sua forma de pensar, vamos refinar um pouco essa rotina.

Imagine que, nesse jogo, teremos uma arma velha, um tipo de revolver com tambor de 6 balas. Esse tipo de arma possui uma parte chamada “martelo” que precisa ser puxada para trás a cada tiro. Imagine que para fazer isso seja necessário algo em torno de 1,5 segundos. E mais, como o tambor tem apenas 6 balas, o usuário precisa recarregá-las toda vez que terminarem.

Primeiro, vamos imaginar o que seria necessário para construir isso utilizando a API Nativa de Eventos do Flash, quantos booleans, timers, travas, uma porção de “if then else” e mais uma porção de variáveis para contar tempo, tiros, etc.

Vou mostrar a vocês um caminho possível a se seguir, mas no meio desse caminho, antes que as coisas se tornem mais complexas com esse monte de amarras que acabei de falar, vamos mudar e utilizar o NResponder para resolver nossos problemas.

Agora, sobre os arquivos do projeto, é importante dizer que eu coloquei alguns comentários de mão-dupla. Você sabe, aquele tipo de bloco de comentário que você pode mudar facilmente entre um trecho e outro. Como este:

[as]
/*
...
/*/
The code here is activated.
//*/

---------

//*
The code here is activated.
/*/
...
//*/
[/as]

Assim você pode ver claramente a diferença de código entre a API Nativa de Eventos e o NResponder. Você pode facilmente alternar entre um trecho e o outro colocando apenas um “/” na primeira linha do bloco de comentário.

OK, vamos começar!

Construindo com a API Nativa de Eventos

A essa altura, você provavelmente já deu uma olhada nos arquivo do projeto. Então vou descrever rapidamente o que você encontrou no arquivo FLA:

Nada novo por aqui ainda, somente 3 MovieClips no palco: a área de tiro (shootArea), o botão de reload (reload) e as balas (bullets).

Dentro do MovieClip das balas você encontra outros seis, um para cada bala do revolver. Todos esses objetos possuem nomes de instância que iremos usar logo mais no arquivo AS.

E, como você pode ver, na livraria vamos exportar uma classe de view (MVC) chamada VShootAnimation. Essa classe de view apenas controla a animação dos tiros na tela baseada um “texture altas” (poof.png).

Agora vamos para o arquivo AS NResponderExample, mas utilizando apenas a API Nativa de Eventos.

[as]
/**
* NResponderExample class
*
* @version NResponderExample v1.0
* @author Diney Bomfim
*/
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;

/**
* Simple shoot game to illustrate the usage of NResponder.
*/
public dynamic class NResponderExample extends MovieClip
{

//**************************************************
// Protected / Private Properties
//**************************************************

private var shoots:int;

//**************************************************
// Initialization
//**************************************************

/**
* The initialization of NResponderExample class.
*/
public function NResponderExample():void
{
if (stage)
{
init(null);
}
else
{
addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
}
}

//**********************************************************************************************************
//
// Protected / Private Methods
//
//**********************************************************************************************************

/**
* Initiate the View of the application.
*
* @param e
*/
private function init(e:Event):void
{
// Remove the listener
removeEventListener(Event.ADDED_TO_STAGE, init);

// Definitions
doReload(null);

// Listeners
this.btReload.addEventListener(MouseEvent.MOUSE_DOWN, doReload, false, 0, true);
}

/**
* Make a Shoot on the valid stage area.
*
* @param e
*/
private function doShoot(e:MouseEvent):void
{
trace('a Shoot');

var shootAnim:VShootAnimation = new VShootAnimation();
shootAnim.x = stage.mouseX;
shootAnim.y = stage.mouseY;

addChild(shootAnim);

this.mcBullets['mcBullet' + shoots].visible = false;

++shoots;
}

/**
* Reload the gun.
*
* @param e
*/
private function doReload(e:MouseEvent):void
{
shoots = 1;

for (var i:int = 1; i <= 6; i++)
{
this.mcBullets['mcBullet' + i].visible = true;
}

// Listeners
this.mcShootArea.addEventListener(MouseEvent.MOUSE_DOWN, doShoot, false, 0, true);
}
}
}
[/as]

Bem, a classe acima será sua classe principal para compilar o arquivo FLA.

  • Primeiro, no construtor da classe (NResponderExample()), seguimos uma regra de boas práticas colocando Event.ADDED_TO_STAGE, para garantir que não haverá erros caso o SWF gerado seja posteriormente carregado em outra aplicação.
  • No método init(), nós removemos o Event.ADDED_TO_STAGE anterior, executamos o primeiro reload da arma e criamos o evento do botão de reload.
  • No método doReload(), fazemos com que todas as balas fiquem visíveis na tela e criamos o evento dos disparos da arma.
  • No método doShoot(), nós colocamos aquela classe de view VShootAnimation exatamente na mesma posição do mouse na tela e removemos uma bala da tela.

Até aqui o código está bem simples. Você pode testar e ver o resultado do código acima.

Mas ainda não temos o nosso comportamento minimamente refinado. As balas não se comportam como se o usuário puxasse o martelo, parecem mais uma metralhadora, e os tiros não terminam após a sexta bala, e, para completar, ainda temos um bug na linha this.mcBullets[‘mcBullet’ + shoots].visible = false; pois não existem mais balas para sumir da tela após a sexta.

Bem, tente imaginar a partir daqui o que seria necessário para resolver todos esses problemas e implantar aquele pequeno refinamento nessa rotina.

Gaste alguns minutos olhando para esse código e tente fazer isso da forma tradicional. Lembre-se dos problemas mencionados acima.

Para fazer isso, provavelmente teríamos um monte de “if then else”, criar alguns timers ou variáveis para contar o tempo, um monte de booleans para mim, isso é irritante!

Mas vamos PARAR por aqui agora, migrar tudo para NResponder e ver o que acontece.

Resolvendo os problemas com NResponder

Agora é o grande momento