Olá
pessoal, meu nomé Luciano Augusto e sou Game Developer. Já
desenvolvi jogos de Entretenimento e Educacionais, tanto em 2D como 3D,
tenho projetos na Europa, USA e Brasil. Trabalho há mais de 8 anos
com isto e publiquei 3 livros, sendo 2 de Jogos Eletrônicos. Resumindo,
game é minha vida.
Este
game faz parte de um módulo que estou terminando do curso de jogos
avançado onde você irá programar um RPG on-line para
até 400 usuários, o curso avançado estará
no ar ainda em 2006, saiba mais dos meus cursos em: http://www.lucianoaugusto.com.br/ead
Minha
intenção com este tutorial é ensinar como projetar
e programar um game RPG em Flash com suporte a Action 2.0. Confesso que
eu não gostava do Flash nas versões anteriores, pois sempre
achei a programação muito fraca. Mas para minha surpresa
melhorou muito.
O
game que fiz, é baseado no RPG ZELDA. Tem um código fonte
rodando a internet com este game. Eu tenho ele aqui, mas é muito
mal escrito, não tem consistência de objetos nem definições
claras. Então escrevi o novo código em 4 horas e ficou 50%
menor comparando com o original. A única coisa que aproveitei do
arquivo original foram os gráficos.
Antes
de continuar olhe o game abaixo:
Está
muito simples de entender o código, mesmo os mais leigos irão
ter pouca ou nenhuma dificuldade para interpretar.
Antes
de continuar, baixe o código e o arquivo .FLA para Flash Professional
2004.
Lembre-se
de renomear este arquivo para .as e colocar na mesma pasta do .fla para
executar.
Eu
tenho o costume de programar o .as em separado, instanciar todos os objetos
e não programar nada dentro de Movie Clipes (com on(release) etc).
Quem programa assim, não por regra, é iniciante ou "newba".
Pois é muito fácil se perder na codificação
se ela está um pedaço no movie outro no quadro etc. Como
eu assumo projetos grandes e profissionais, acabei tendo de aprender a
programar de forma que facilitasse minha depuração futura.
O
código do Action Script está todo comentado, vou apenas
explicar o funcionamento do game e alguns segredos.
Se
olhar o código irá notar que tenho o costume de declarar
as variáveis antes de começar a programar, este costume
vem do Pascal que programei há muito tempo e não pense que
sou velho, tenho apenas 30 anos hehe.
//Definição
de todas as variáveis usadas no game.
var velocidade_personagem:Number = 5;
var estado_personagem:String = "";
Declarar
as variáveis no início facilita o controle sobre elas e
também você começa a ter uma boa noção
de quanto está usando de memória, afinal, variável
funciona como um ponteiro, e ocupa memória (RAM) quando declarada.
Não pense que isto é completamente inútil em Flash.
Qualquer programação, independente de tecnologia ocupa memória.
Aqui
começa o looping (rotina que fica testando algo direto) principal
do nosso game:
personagem_mc.onEnterFrame
= function() {
// O objeto Key é usado para testar as teclas, ia usar Listner,
mas como é um Tutorial básico
// resolvi fazer o controle de forma mais legível.
// Então: Key.DOWN é tecla para baixo e assim respectivamente.
if (Key.isDown(Key.DOWN)) {
this.gotoAndStop("walk_down");
// Estou fazendo um teste para ver se a personagem está na posição
Y que quero testar, caso esteja
// faço o terreno se mover, criando assim o efeito de câmera.
Na verdade usamos este macete em RPG
// para fazer o terreno se mover quando a personagem vai chegando perto
dos limites da tela, isto evita
if (this._y>180 && terreno_mc._y>-275) {
// Caso a personagem esteja no limite indicado, o terreno se move e não
ele, este efeito é muito utilizado
// em RPGs, pois simula a personagem andando normalmente e também,
uma câmera acompanhando. E a grande verdade
// é que neste caso quem se move é o terreno.
terreno_mc._y -= velocidade_personagem;
limites_mc._y -= velocidade_personagem;
} else {
// Caso esteja fora dos limites, quem se move é a personagem. Vocês
precisam entender que esta é a grande sacada
// para fazer um RPG, o jogo de personagem e cenário cria a ilusão
de câmera no mundo 2D.
personagem_mc._y += velocidade_personagem;
}
}
if (Key.isDown(Key.UP)) {
this.gotoAndStop("walk_up");
// Aqui também testo os limites antes de mover o terreno.
if (this._y<50 && terreno_mc._y<-3) {
terreno_mc._y += velocidade_personagem;
limites_mc._y += velocidade_personagem;
} else {
personagem_mc._y -= velocidade_personagem;
}
}
if (Key.isDown(Key.LEFT)) {
this.gotoAndStop("walk_left");
// Aqui também testo os limites antes de mover o terreno.
if (this._x<90 && terreno_mc._x<-3.5) {
terreno_mc._x += velocidade_personagem;
limites_mc._x += velocidade_personagem;
} else {
personagem_mc._x -= velocidade_personagem;
}
}
if (Key.isDown(Key.RIGHT)) {
this.gotoAndStop("walk_right");
// Aqui também testo os limites antes de mover o terreno.
if (this._x>190 && terreno_mc._x>-253.3) {
terreno_mc._x -= velocidade_personagem;
limites_mc._x -= velocidade_personagem;
} else {
personagem_mc._x += velocidade_personagem;
}
}
// Chamando a função para detectar a colisão e passando
os 2 objetos
// como parâmetro. O primeiro objeto é a personagem, repsresentado
por this
// o segundo objeto é a mascará de colisão. A grande
sacada de usar função é que
// você testa muitas colisões com pouco código
testaColisao(this, limites_mc);
// Estou usando o mesma função para testar colisão,
mas esperando um retorno de verdadeiro
// ou falso, por isto uso o IF(...) Retornando verdadeiro posso tratar
o objeto.
if (testaColisao(this, terreno_mc.npc_01_mc)) {
terreno_mc.npc_01_mc._xscale = -60;
terreno_mc.sombra_npc_01_mc._xscale = -60;
//Estou abrindo o balão e passando os parâmetros, o último,
3000 é em milisegundos, ou seja 3 segundos ele fica aberto.
abreBalaoNpc(403, 323, "Olá sou o npc deste game! Muito prazer,
meu nome é Lula!", 3000);
}
// Controle de ATAQUE usando a tecla SPACE e dependendo do estado do personagem,
ativa uma animação
// A variável estado_personagem é setada no arquivo principal
dentro do Movie do personagem
// Por falta de tempo não vou colocar um inimigo aqui, mas pode
ser um tutorial futuro
if (Key.isDown(Key.SPACE)) {
if (estado_personagem == "down") {
this.gotoAndStop("attack_down");
} else if (estado_personagem == "up") {
this.gotoAndStop("attack_up");
} else if (estado_personagem == "left") {
this.gotoAndStop("attack_left");
} else if (estado_personagem == "right") {
this.gotoAndStop("attack_right");
}
}
};
Ele
testa todas as ações da personagem, e controla posição
X/Y, Ataque, colisão etc.
Dentro
deste looping temos algumas funções fabricadas em casa (não
são do flash, eu que fiz), a principal é a :
testaColisao(this,
limites_mc);
Esta
função pega o objeto this como primeiro parâmetro,
ou seja a personagem, e também qual o objeto que será a
máscara de colisão. Usamos o sistema de colisão para
testar quando a personagem chega nos limites do cenário por exemplo,
onde ela não pode passar, ou em pedras e árvores onde ela
não pode passar por cima.
A
rotina de colisão que escrevi, está perfeita. Ela testa
a colisão pelos limites do objeto e não pelo quadrado do
MovieClip, abaixo vou explicar melhor:
Nesta
imagem a colisão está no limite do MovieClip na parte azul,
repare na bolinha acertando o limite (quadrado em volta do desenho). Isto
é o padrão do FLASH:
Agora
usando uma técnica de programação, pegamos os valores
X,Y mínimos e máximos do objeto e testamos a colisão
por vértice ou edges.
Com
isto o sistema de colisão fica perfeito para montar limites onde
as personagens podem andar ou não.
Abaixo
o código do sitema de colisão: // Função criada para testar
a colisão do personagem com os elementos
// do cenário que não podem ser ultrapassados ou que devam
fazer alguma coisa
// Esta função é vital para o RPG. Ela além
de segurar a persoangem para não passar
// por cima das coisas que há uma colisão, ela também
retorna verdadeiro (true) quando
// uma colisão acontece, com isto podemos tratar a colisão
e iniciar outra ação, se for
// o caso
function testaColisao(objeto:Object, objeto2:Object) {
with (eval(objeto)) {
// Esta sequência de Ifs aninhados testam os vértives (limites)
de colisão
// do objeto passado como parâmetro que vai impedir que sua personagem
ande
// onde não possa.
// Usar o getBounds retorna as coordenadas X e Y máximas em comparação
a um objeto
// e o Stage. Com isto sabemos exatamente onde tem um objeto desenhado
para fazer
// um teste de colisão mais preciso.
if (eval(objeto2).hitTest(getBounds(_root).xMax, _y, true)) {
// Caso eu encontre um limite eu volto meu personagem e não o deixo
ultrapassar
// É exatamente isto que está acontecendo na expressão
abaixo.
// Esta colisão testa o lado direito da personagem
_x = _x-velocidade_personagem;
return true;
}
if (eval(objeto2).hitTest(getBounds(_root).xMin, _y, true)) {
// Esta colisão testa o lado equerdo da personagem
_x = _x+velocidade_personagem;
return true;
}
if (eval(objeto2).hitTest(_x, getBounds(_root).yMax, true)) {
// Esta colisão testa a parte inferior da personagem
_y = _y-velocidade_personagem;
return true;
}
if (eval(objeto2).hitTest(_x, getBounds(_root).yMin, true)) {
// Esta colisão testa a parte superior da personagem
_y = _y+velocidade_personagem;
return true;
}
}
}
O
game na verdade se baseia nisto, não tem segredo. O lance de simulação
de câmera é mais simples ainda. No código lá
em cima do looping do personagem, fiz toda a simulação usando
para isto o deslocamento X,Y da personagem. Ou seja, se a personagem estiver
próximo do limite da tela, a tela rola para a direita ou para baixo.
só usei uma condicional IF para controlar isto e o efeito é
fantástico, parece que temos uma câmera seguindo a personagem.
if
(this._y>180 && terreno_mc._y>-275) {
// Caso a personagem esteja no limite indicado, o terreno se move e não
ele, este efeito é muito utilizado
// em RPGs, pois simula a personagem andando normalmente e também,
uma câmera acompanhando. E a grande verdade
// é que neste caso quem se move é o terreno.
terreno_mc._y -= velocidade_personagem;
limites_mc._y -= velocidade_personagem;
} else {
// Caso esteja fora dos limites, quem se move é a personagem. Vocês
precisam entender que esta é a grande sacada
// para fazer um RPG, o jogo de personagem e cenário cria a ilusão
de câmera no mundo 2D.
personagem_mc._y += velocidade_personagem;
}
Observem
que a área vermelha é o limite, então se a personagem
chegar nesta área ela para de andar e quem anda no caminho inverso
é o terreno. Isto simula uma câmera.
Agora
vou colocar os valores que usei no código para testar os limites,
com isto você entenderá melhor:
Agora
fica claro como funcionam os limites para ativar a rolagem do cenário
ou não.
Este
game se resume a deslocar a personagem e a tratar alguns eventos básicos,
acredito que vocês não tenham dificuldade de entendê-lo.
O
ratinho que está passando não programei, usei guide lines
apenas, e a programação do npc está no código
comentada.
Espero
que gostem, aguardo perguntas e tendo tempo ajudo a melhorar este código.
Luciano
Augusto da Silva
Game Developer
(41) 9193-4528 | contato@lucianoaugusto.com.br