1

Criando um jogo Adobe Flash + Actionscript 3.0 (Prog) Part IV

Bem esse é o último post do jogo Quebra-Cabeça. Espero que esse seja o primeiro de muitos jogos a serem desenvolvidos e postados aqui no blog.

Conforme comentado anteriormente, nesse post falaremos mais de Actionscriot, mas antes de iniciarmos os códigos vamos criar o último item de Design do jogo que será as telas de “Start Game”, “Venceu” e “Perdeu”.

Então primeiro eu vou criar uma nova camada acima da Camada de Informações chamada de “Tela de Informações”.

Nova camada Tela de Inicio

Na sequência também já crio um novo keyframe no quadro  2 da camada Tela de Inicio, afinal não iremos precisar colocar nenhum conteúdo no quadro 1.

Crio um novo keyframe na camda

Depois com a ferramenta retângulo (Rectangle Tool) vou desenhar um retangulo de forma que ele cubra todos os demais objetos(a cor do retângulo é irrelevante, podendo usar quaisquer cores):

Desenho um retângulo

Converto o retângulo em símbolo do tipo MovieClip, para converter o retângulo, com o objeto selecionado:
Menu Modify, Convert to Symbol… ou uso o atalho F8.

Converto em simbolo do tipo MovieClip

Name: telainicio
Registration: Canto superior esquerdo

Vou dar um nome para o retângulo na instance name para que possa encontrá-lo através de Actionscript. Então seleciono o retângulo e coloco como nome na instance name.

Instance name inicio

Por último com a ferramenta de texto, vou criar uma caixa de texto vazia.

Ferramenta de texto(Text Tool)

Caixa de texto vazia

Com as seguintes configurações:

Dynamic Text

Dynamic Text

Character

Character
Family: _typewriter
Size: 25.0 pt
Cor: cinza (#CCCCCC)
Essas configurações de fonte, tamanho e cor são apenas uma sugestão, podendo se trabalhar com quaisquer outras fontes, tamanhos ou cores.

Paragraph

Centralizo o texto. E por ultimo coloco o seguinte nome da instance name da caixa de texto:

Instance name texto_inicio

Agora sim vamos para a parte de Actionscript, clico no quadro 2 da Layer Actionscript e em seguida abro o painel de Action:

Menu Windows, Action ou uso o atalho F9.

Quadro 2 da Layer Actionscript

Agora vamos começar a digitar o Actionscript de todo o jogo. Como o código final agora é bastante grande já vou colocá-lo comentado(ao copiar o código tome cuidado com as aspas, pois ele as inverte).

stop(); // para o script no quadro atual
import flash.utils.*; // importo uma galeria de utilidades do flash

texto_inicio.text=”Como jogar?\n\n\nMonte o quebra-cabeça encaixando as peças antes que o tempo acabe!\n\nPara começar apenas clique na tela.\n\nIniciar Jogo”; // adiciono o texto no texto_inicio;

var soma:Number = new Number(); // crio uma variável chamado soma e tipo ela como número(só pode receber números)

addEventListener(MouseEvent.MOUSE_DOWN, iniciar); //crio um ouvinte de evento quando houver o clique, inicia a função iniciar
function iniciar(Event:MouseEvent):void { //crio a função iniciar, com parâmetro de mouse com retorno nenhum (void)

tempo.text=”2:0″; // gravo dentro do tempo o valor de 2:0, lembrando que esse valor é apenas uma string
soma=0; // seto o valor inicial de soma para 0
pontos.text=”0″; // gravo dentro de pontos o valor de 0, lembrando que esse valor é apenas uma string

inicio.visible=false; //coloco o quadro do inicio como invisível
texto_inicio.visible=false; // faço o mesmo com o texto que está no inicio
inicio.mouseEnabled=false; //Essa função desabilita o mouse sobre o quadro inicio, para que não atrapalhe enquanto trabalho no quebra cabeças
texto_inicio.mouseEnabled=false; //faço o mesmo com o texto, pois se clicar no texto também ocorre o mesmo problema

for (var i = 1; i < 17; i++) { // crio uma repetição, dizendo que i deve iniciar em 1 e enquanto ele for menor que 17 (temos 16 peças),  ele aumenta 1
var Totalpecas=getChildByName(“peca”+i); /* crio uma nova variável com o nome de Totalpecas e pego o nome da peça, lembra que demos os nomes de peca1, peca2 e assim por diante, então ele vai pegar o nome “peca” + i(valor de i que vai se repetir 1, 2,3, até 16 */
Totalpecas.x = Math.floor( Math.random() * (stage.stageWidth-100) ); /* coloco cada peça em uma posição x randômica, para que as peças não fiquem sempre na mesma posição dentro do tamanho máximo do meu stage e subtraio o valor de 100, para que as peças não fiquem muito nos cantos, senão assim seria muito fácil  */
Totalpecas.y = Math.floor( Math.random() * (stage.stageHeight-100) ); //faço o mesmo com a posição y
Totalpecas.mouseEnabled=true; /* “ligo” a opção do mouse, agora vem a pergunta, porque fiz isso se o padrão é ser true? Simples, mais abaixo no script  eu desligo(seto como false) essa opção em determinado ponto e explicarei mais abaixo */
}

var segundos:Number=0;  // crio a variável segundos para criar o cronometro e coloco o valor de 0
var minuto:Number=2; // faço o mesmo para minutos, mais com o valor de 2, ou seja tem 2 minutos para montar o quebra-cabeças

var contador:Timer=new Timer(1000); /*crio uma variável chamada contador e tipo como sendo do tipo Timer e coloco o valor padrão de 1000 milisegundos, ou seja, 1 segundo. A cada um segundo ele volta a função para verificar como está o tempo atual */
contador.addEventListener(“timer”, funcTempo); // crio o ouvinte de evento do contator e chamo a função funcTempo
contador.start(); //inicio o Timer, quando se cria uma função do tipo Timer, é necessário que se inicie ela
function funcTempo(ObjTempo:TimerEvent) { /* crio a função funcTempo, passando o parâmetro como sendo do tipo TimerEvent, ou seja evento de tempo */
if (segundos>0) { // executo uma condição onde pergunto se segundos é maior que 0
segundos–; // se for, ele regride 1
} else { // senão
minuto–; //quem regride são os minutos
segundos+=59; //ao regredir um minuto, os segundos volta a valer 59
}
if (soma==80) { //executo uma segunda condição, se a soma for igual a 80(os pontos do jogador), caso o jogador ganhe!
texto_inicio.text=”Você Venceu, Parabéns\n\n\nVocê fez: “+soma+”pontos\n\n\n\nJogar Novamente?”; /* mudo o texto de texto_inicio, \n significa linha de baixo ou pular linha */
inicio.visible=true; //volto a visibilidade do quadro inicio
texto_inicio.visible=true; //também volto a visibilidade do texto
inicio.mouseEnabled=true; //também devolvo a função do mouse de clicar no quadro inicio
texto_inicio.mouseEnabled=true; // faço o mesmo com o texto
removeEventListener(MouseEvent.MOUSE_OVER, pecas); //removo o ouvinte pecas(veja mais abaixo)
removeEventListener(MouseEvent.MOUSE_DOWN, pegar); //também removo o ouvinte pegar
removeEventListener(MouseEvent.MOUSE_UP, soltar); //e o soltar (veja a explicação abaixo)
inicio.addEventListener(MouseEvent.MOUSE_DOWN, iniciar); // volto a adicionar o ouvinte de texto para o quadro inicio
texto_inicio.addEventListener(MouseEvent.MOUSE_DOWN, iniciar); //faço o mesmo com o texto
contador.stop(); //se o jogador ganhou, paro o contator
contador.removeEventListener(“timer”, funcTempo); /* e removo o ouvinte de evento, isso é necessário por dois motivos, 1 – descarrega da memoria, liberando espaço, 2 – irá zerar o contador, caso o jogador queira jogar novamente. */
}
if (minuto==0&&segundos==0) { // crio uma outra condição, caso o jogador não consiga montar as peças a tempo, ou seja, perdeu
texto_inicio.text=”Você perdeu, tente novamente\n\n\nVocê fez: “+soma+”pontos\n\n\n\nTentar Novamente?”; // adiciono o seguinte texto
inicio.visible=true; // devolvo a visibilidade do inicio
texto_inicio.visible=true; //faço o mesmo com o texto
inicio.mouseEnabled=true; // e também devolto a função de clicar no quadro inicio
texto_inicio.mouseEnabled=true; //faço o mesmo com o texto
removeEventListener(MouseEvent.MOUSE_OVER, pecas); //removo o ouvinte de evento pecas
removeEventListener(MouseEvent.MOUSE_DOWN, pegar); //também removo o ouvinte pegar
removeEventListener(MouseEvent.MOUSE_UP, soltar); // e o ouvinte soltar
contador.stop(); // paro o contator
contador.removeEventListener(“timer”, funcTempo); /* e removo o ouvinte de evento, isso é necessário por dois motivos, 1 – descarrega da memoria, liberando espaço, 2 – irá zerar o contaro, caso o jogador queira jogar novamente. */
inicio.addEventListener(MouseEvent.MOUSE_DOWN, iniciar); //volto a adicionar o ouvinte de texto para o quadro inicio
texto_inicio.addEventListener(MouseEvent.MOUSE_DOWN, iniciar); //também faço o mesmo com o texto_inicio
}
tempo.text=minuto+”:”+segundos; //retorno o valor para a caixa de tempo dos minutos e segundos restantes
}
removeEventListener(MouseEvent.MOUSE_DOWN, iniciar); /*enquanto não acontece nenhuma das condições acima, eu removo o ouvinte de evento iniciar */
addEventListener(MouseEvent.MOUSE_OVER, pecas); /*crio um novo ouvinte de evento, dessa vez com a propriedade MOUSE_OVER, ou seja quando o usuário passar o mouse sobre o(s) objeto(s) ele irá chamar a função pecas*/
}
function pecas(evt:Event):void { //crio a função pecas e passo o parâmetro evt do tipo Event
switch (evt.target.name) { // recupero o nome do objeto em qual o usuário está no momento passando o mouse por cima e pergunto:
case “tempo” : /* caso seja o tempo(campo dynamic de texto), ele não faz nada, imagina você puder ficar arrastanto a contagem de tempo, sem contar que isso poderia prejudicar o script, além de ocasionar erro. */
break; // pare aqui
case “pontos” : // caso seja pontos(campo dynamic de texto), ele também não irá fazer nada
break; //pare aqui
case “espaco1″ : //lembra das nossas peças invisiveis, não é porque elas estão invisiveis que não podem ser selecionadas, fiz isso para as 16.
break;
case “espaco2″ :
break;
case “espaco3″ :
break;
case “espaco4″ :
break;
case “espaco5″ :
break;
case “espaco6″ :
break;
case “espaco7″ :
break;
case “espaco8″ :
break;
case “espaco9″ :
break;
case “espaco10″ :
break;
case “espaco11″ :
break;
case “espaco12″ :
break;
case “espaco13″ :
break;
case “espaco14″ :
break;
case “espaco15″ :
break;
case “espaco16″ :
break;
default : //bem caso não seja nenhuma dessas opções, será o que precisamos
evt.target.addEventListener(MouseEvent.MOUSE_DOWN, pegar); /*não me importa qual peça ele pegou, o importante é que ele selecionou e ao selecionar, ele dispara a função pegar */
evt.target.addEventListener(MouseEvent.MOUSE_UP, soltar); // o mesmo irá ocorrer quando ele soltar a peça
break; //pare aqui
}
}

function pegar(Obj:Event):void { // crio a função pegar
Obj.target.startDrag(); // inicio a opção de poder arrastar a peça enquanto segura o botão do mouse apertado
Obj.target.alpha = 0.6; //também digo que a minha transparência é de 60%
}

function soltar(Obj:Event):void { //crio a função soltar
Obj.target.stopDrag(); //faço o objeto parar aonde o jogador soltou o botão do mouse
var espaco=”espaco”+Obj.target.name.substring(4,6); /*recupero os dois ultimos digitos do nome da peça(exemplo: seleciono a peca1, ele retorna 1, seleciono a peca15, ele retorna apenas 15, isso foi possivel graças ao substring, onde o valor 4, significa que eu quero que ignore os 4 primeiros caracteres pegue apenas a partir do quinto e o número 6 significa que eu quero que pare no máximo até o caracter 6 */
Obj.target.alpha = 1; //volto a transparencia da peça para 100%
var alvo = getChildByName(espaco); /* De posse da informação dos dois ultimos caracteres, eu crio uma variável que vai pegar a string acima “espaco” e vai adicionar os dois ultimos caracteres recuperados, formando assim o então espaco1, espaco2…. até o espaco16 */
if (Obj.target.hitTestPoint(alvo.x+50,alvo.y+50,true)) { /* Depois eu executo uma condição se a peça que o jogador está tentando encaixar está realmente sobre o espaço correto com uma margem de erro de 50, afinal acertar a posição exata de x e y poderia ser algo extremamente complicado */
soma+=5; //caso ele acerte soma +5 pontos
pontos.text = soma+”pts”; // retorno essa informação dentro do dynamic text pontos
Obj.target.mouseEnabled=false; /*a peça já foi encaixada, então desativo a opção de movimenta-la, para não ter um espertinho querendo fazer milhões de pontos */
Obj.target.x=getChildByName(espaco).x; //travo a peça na posição do espaço certo em x
Obj.target.y=getChildByName(espaco).y; //e no y
removeEventListener(MouseEvent.MOUSE_DOWN, pegar); // removo o ouvinte de evento pegar, descarregando da memoria
removeEventListener(MouseEvent.MOUSE_UP, soltar); //faço o mesmo com o ouvinte soltar
} else {
removeEventListener(MouseEvent.MOUSE_DOWN, pegar);  /* se ainda não conseguiu encaixar no espaço correto, eu também descarrego o ouvinte da memoria para tornar o jogo mais rápido */
removeEventListener(MouseEvent.MOUSE_UP, soltar); //faço o mesmo com o soltar
}
}

Assim finalizo a última parte do Jogo: Quebra-Cabeças, algumas outras informações:

O meu aquivo .fla ficou com 320Kb

O swf ficou com apenas: 17,9Kb

Ele consome entre 6352Kb e 6380Kb de memóra, ou seja é possivel rodar até mesmo em computadores muito lentos e com pouca memória ram.

Por último o size report do jogo:

quebra-cabecas.swf Movie Report
——————————–

Metadata
——–
Bytes    Value
—–    —–
1049    <rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”> <rdf:Description rdf:about=”" xmlns:xmp=”http://ns.adobe.com/xap/1.0/”> <xmp:CreatorTool>Adobe Flash CS4 Professional</xmp:CreatorTool> <xmp:CreateDate>2009-05-21T19:25:16-03:00</xmp:CreateDate> <xmp:MetadataDate>2009-05-28T22:12:13-03:00</xmp:MetadataDate> <xmp:ModifyDate>2009-05-28T22:12:13-03:00</xmp:ModifyDate> </rdf:Description> <rdf:Description rdf:about=”" xmlns:xmpMM=”http://ns.adobe.com/xap/1.0/mm/” xmlns:stRef=”http://ns.adobe.com/xap/1.0/sType/ResourceRef#”> <xmpMM:InstanceID>xmp.iid:E4D60591DE4BDE11B4A1AD2E7C4A877D</xmpMM:InstanceID> <xmpMM:DocumentID>xmp.did:E4D60591DE4BDE11B4A1AD2E7C4A877D</xmpMM:DocumentID> <xmpMM:OriginalDocumentID>xmp.did:6823CA215546DE11A3988B60EAE2E33E</xmpMM:OriginalDocumentID> <xmpMM:DerivedFrom rdf:parseType=”Resource”> <stRef:instanceID>xmp.iid:31407BC75F4ADE119D74E069E2B7B7C0</stRef:instanceID> <stRef:documentID>xmp.did:31407BC75F4ADE119D74E069E2B7B7C0</stRef:documentID> <stRef:originalDocumentID>xmp.did:6823CA215546DE11A3988B60EAE2E33E</stRef:originalDocumentID> </xmpMM:DerivedFrom> </rdf:Description> <rdf:Description rdf:about=”" xmlns:dc=”http://purl.org/dc/elements/1.1/”> <dc:format>application/x-shockwave-flash</dc:format> </rdf:Description> </rdf:RDF>

Frame #    Frame Bytes    Total Bytes    Scene
——-    ———–    ———–    —————-
1          15165          15165    Scene 1 (AS 3.0 Classes Export Frame)
2           3261          18426

Scene                        Shape Bytes    Text Bytes    ActionScript Bytes
————————-    ———–    ———-    ——————
Scene 1                              604           249                  3214

Symbol                       Shape Bytes    Text Bytes    ActionScript Bytes
————————-    ———–    ———-    ——————
telainicio                            34             0                     0
peca16                                72             0                     0
peca15                                88             0                     0
peca14                                88             0                     0
peca13                                69             0                     0
peca12                                98             0                     0
peca11                               109             0                     0
peca10                               104             0                     0
peca9                                 88             0                     0
peca8                                 87             0                     0
peca7                                103             0                     0
peca6                                 99             0                     0
peca5                                 83             0                     0
peca4                                 64             0                     0
peca3                                 82             0                     0
peca2                                 81             0                     0
peca1                                 65             0                     0
espaco16                               0             0                     0
espaco15                               0             0                     0
espaco14                               0             0                     0
espaco13                               0             0                     0
espaco12                               0             0                     0
espaco11                               0             0                     0
espaco10                               0             0                     0
espaco9                                0             0                     0
espaco8                                0             0                     0
espaco7                                0             0                     0
espaco6                                0             0                     0
espaco5                                0             0                     0
espaco4                                0             0                     0
espaco3                                0             0                     0
espaco2                                0             0                     0
espaco1                                0             0                     0
Mascara_quadrado                      32             0                     0
img_fundo                             37             0                     0

Font Name                 Bytes        Characters
———————-    ———    ————–
_typewriter                      35

ActionScript Bytes    Location
——————    ——–
3214    Scene 1:Frame 1

Bitmap                     Compressed    Compression
———————–    ———-  ——–  ———–
quebra-cabecas.jpg             10004      230400   JPEG Quality=80
Abraços e até o próximo jogo.

  1. admin disse:

    Olá, primeiramente obrigado por comentar no blog, A variável alvo recebe o valor: “espaco” + 1, 2 ou 3, confere se sua variável espaco está gravando corretamente o conteúdo e se a alvo está recebendo ela corretamente, para isso, entre os códigos:
    var espaco=”espaco”+Obj.target.name.substring(4,6);
    //digite aqui um trace(espaco); para ver o que está retornando(sem as barras de comentários)
    Obj.target.alpha = 1;
    var alvo = getChildByName(espaco);
    //faça o mesmo aqui com alvo, trace(alvo);
    Confira se na variavel espaco está sendo gravado: espaco1, espaco2, espaco3 e assim por diante, caso não esteja, confira se o nome das peças está corretamente colocado, pois os comandos: Obj.target.name.substring irá recuperar o nome das peças ao passar o mouse sobre elas e se não esqueceu nenhuma linha de código
    Qualquer outro problema volte a postar aqui e aproveite para postar a linha com erro, assim identifico o problema mais facilmente.

*