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”.
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.
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):
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.
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.
Por último com a ferramenta de texto, vou criar uma caixa de texto vazia.
Com as seguintes configurações:
Dynamic Text
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.
Centralizo o texto. E por ultimo coloco o seguinte nome da instance name da caixa de texto:
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.
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 < totalpecas="getChildByName(”peca”+i);" x =" Math.floor(" y =" Math.floor(" mouseenabled="true;">
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
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.