sábado, 11 de fevereiro de 2012

[Tutorial] Criando jogo Top-Down - Avançado!

Iae galera, tudo tranquilo?

Bem... dessa vez eu vou criar um super tutorial de como criar seu jogo de Top-Down de aventura e batalha em tempo real. Para quem não sabe, Top-Down é quando você olha o personagem por cima e tem a liberdade de se movimentar para todas as direções (diferente de um jogo de plataforma, onde a gravidade é aplicada ao jogo).

Nesse projetos, vamos explorar muitas possibilidades, o que fará o tutorial ser bem extenso. Mas depois que completarmos, você irá me agradecer. Pode ter certeza x3 Só cuidado para não se perder no fluxo do tutorial. Se não entendeu uma parte, vá tentando até conseguir, não pule partes e leia atentamente ou tudo vai dar errado no final.

Para isso, vocês devem ter o GameMaker 8.0 ou o 8.1 Standard(não usem o 8.1 Lite/grátis pois ela coloca uma watermark  da Yoyo games no seu jogo).

Antes de começarmos, não se esqueca de ir no Menu e checar se a opção Advanced Mode está ativa.

0. Objetivo do tutorial
1. Iniciando
2. O Jogador
    2.1 Primeiros passos
    2.2 Movimentação
    2.3 Ataque
    2.3 Energia, Vidas e Game over
    2.4 Vida Extra
3. Nossa primeira room e a câmera
4. Obstáculos
5. Itens
6. Inimigos e sistema de batalha
7. Objetivo do jogo
8. Interface
9. Considerações finais

0. Objetivo do tutorial:

Criar um jogo Top-Down em que o jogador necessita pegar o diamante no final das fases, atacando os inimigos com socos e flechas se necessário. O jogo deverá apresentar uma interface básica também.

1. Iniciando:

Bom galera, primeiro vamos criar os objetos do jogo. Para os sprites, recomendo que por hora usem alguns básicos como quadrados de diferentes cores. Vamos criar alguns sprites e objetos vazios por hora para usarmos mais tarde:

Sprites: (Faça todos eles 32x32 de preferência)

- jogador_esquerda
- jogador_direita
- jogador_cima
- jogador_baixo
- jogador_ataque_esquerda
- jogador_ataque_direita
- jogador_ataque_cima
- jogador_ataque_baixo
- parede_sprite
- flecha_sprite
- tesouro_sprite
- mask_32_32 (Deve ser um quadrado cheio que ocupe toda a imagem, sem sobras)
- item_energia_sprite
- item_vida_sprite
- diamante_sprite
- vida_barra_sprite
- bola_de_fogo_sprite

Objetos:

- jogador
- ataque_principal
- ataque_1
- flecha
- inimigo_principal
- inimigo_1
- inimigo_2
- inimigo_3
- obstaculo_principal
- obstaculo_alto
- obstaculo_raso
- tesouro
- inimigo
- item_energia
- item_vida
- diamante
- jogador_posicao_inicial
- interface
- bola_de_fogo

Criem esses objetos com os mesmos nomes. Todos eles ficarão vazios, se quiser, você já pode especificar as sprites deles.

Já, já, iremos usar GML (Game Maker Language) para programas nossos jogos, então, copie e cole os códigos em verde e coloque-os nos eventos que eu irei especificar. Mas colar onde? Cole nas páginas do Execute Code.



2. O Jogador

Bem, aqui está o nosso herói da vez. Ele vai carregar em sí o foco principal da câmera do jogo e várias variáveis importantes, por isso, ele nunca poderá deixar de existir.

2.1 Primeiros passos:

Assim sendo, vamos deixá-lo Persistent. Assim, basta colocar ele apenas na primeira room do jogo que ele passará adiante em todas as outras Rooms.

Também deixaremos ele Sólid. Pois assim, os inimigos não vão passar por cima dele futuramente e interpretarão ele como um obstáculo em potêncial.

Para evitarmos bugs na colisão com obstáculos, adicionaremos uma Mask para o jogador. A Mask dele será a mask_32_32 que criamos anteriormente.

Agora no Create event, vamos dar ao nosso personagem algumas funções importantes. Coloque uma peça de código e vamos carregá-lo com algumas informações necessárias.
atacando =false
face =0
pontos =0
energia =100
energia_maximo =energia
vidas =3
2.2 Movimentação:

Agora vamos lhe dar movimentação, que é a parte mais importante. Para isso, vamos usar um código que checa se na direção não existe objetos sólidos, se o botão está sendo pressionado e, enquanto as duas estiverem satisfeitas, o jogador vai andar. Veja um exemplo:
if keyboard_check(vk_up) //Checa se o botão 'Direcional para Cima' está pressionado
{face = 90 //A direção do jogador, em graus. Não é obrigatório, mas será muito útil.
sprite_index = jogador_cima //Caso for verdade, o jogador mudará sua sprite.
if place_free(x,y-4){y -=4} //Agora, se quatro pixels acima estiver livres de obstáculos sólidos, o jogador andará quatro pixels acima. Se não, ele não anda nada.
}
Se você entendeu como funciona este código, será fácil programar as outras direções do personagem. Vamos colocar este código no step event do objeto jogador. Assim, usaremos as setas de direção para movermos nosso personagem.
//Movimentação para a direita
if keyboard_check(vk_right)
{face =0
sprite_index = jogador_direita
if place_free(x+4,y){x +=4}
}

//Movimentação para a esquerda
if keyboard_check(vk_left)
{face =180
sprite_index = jogador_esquerda
if place_free(x-4,y){x -=4}
}

//Movimentação para cima
if keyboard_check(vk_up)
{face =90
sprite_index = jogador_cima
if place_free(x,y-4){y -=4}
}

//Movimentação para baixo
if keyboard_check(vk_down)
{face =270
sprite_index = jogador_baixo
if place_free(x,y+4){y +=4}
}
Depois disso, vamos arrumar a velocidade visual de movimentação do personagem. Mas como assim? Bem, você provavelmente quer ver o seu personagem ''andando'' apenas quando ele tem certa velocidade, e não mechendo as pernas enquanto estiver parado.

Para isso, vamos utilizar o seguinte código, também no step event, e deve ser após o código anterior:
if keyboard_check (vk_down) or keyboard_check (vk_up) or keyboard_check (vk_right) or keyboard_check (vk_left) = true //Checa se algum direcional está sendo pressionado
{
image_speed=0.5 //A imagem do personagem se movimentará junto com ele
}
 else //Se não...
{
image_speed =0 //O desenho do personagem ficará parado
image_index =0 //e voltará para a primeira imagem
}
Agora, a movimentação de nosso personagem está completa.

2.3 Ataque

Bom, agora vamos trabalhar no ataque do nosso personagem. Para inovar, vamos fazer duas possibilidades: o ataque de curto alcance e atirar flechas. ''Atirar flechas'' pode ser facilmente substituido por tiros, então fique ligado!

Antes disso, vamos alterar um pouco os nossos objetos ataque_principal, ataque_1 e flecha. Faça o ataque_1 e a flecha ficarem Parent do ataque_principal.

O ataque_1 representará o ataque de curta distância do personagem, seja um soco ou coisa do tipo. Coloque qualquer sprite, de preferência 32x32 e de apenas uma subimagem. Você provavelmente vai querer que ele exista mais fique invisível aos olhos do jogador, então, vamos desmarcar a caixa de Visible dele. Agora, vá em Other events > Animation End e coloque apenas a função instance_destroy(). Isso fará com que ele se destrua quase instantaneamente. Mas porque isso é necessário? Simples, para ele ser destruído (o ataque) assim que acertar ou não acertar o inimigo.

Agora a flecha. Coloque no objeto uma sprite com 4 subimagens, cada uma com a flecha apontando para uma direção diferente. A primeira subimagem deve ser da flecha apontando para a direita (a segunda, para cima, a terceira para a esquerda e a ultima para baixo). Agora, coloque no create event o seguinte código:
direction = jogador.face //Faz com que ela vá na direção do jogador no momento que ela foi criada
speed =8 //Velocidade da flecha
image_speed =0
image_index=direction*image_number/360 //Este código faz com que a flecha escolha automáticamente a subimagem certa conforme sua direção.
Ainda no Create Event, coloque o alarm[0] para 150, e no evento do alarm[0], coloque instance_destroy(). Isso fará com que, em 5 segundos, a flecha se auto-destrua, para impedir que ela vá muito longe.
Agora coloque um evento de colisão com o objeto obstaculo_alto, instance_destroy() também, para ela ser destruida assim que bater em alguma parede ou coisa do gênero.

Agora que nós programamos os dois tipos de ataque, vamos programar para o jogador em criar ambos. O botão para o jogador atacar de perto será a letra A, e para o jogador atirar uma flecha, será a letra S.

Primeiro vamos programar o ataque curto/soco no jogador. Adicione o seguinte código na letra correspondente (neste caso, a letra A).
if atacando =false //Se ele ainda não estiver atacando no momento...
{atacando =true //Agora ele está.
if face = 0
instance_create(x+16,y,ataque_1)
if face =90
instance_create(y-16,y,ataque_1)
if face =180
instance_create(x-16,y,ataque_1)
if face = 270
instance_create(y+16,y,ataque_1)
}
Agora faça o mesmo com a flecha, só que em outra tecla (no nosso caso, S). Use o mesmo código acima, trocando apenas o ataque_1 por flecha. Se você preferir, troque também todos os 16 por 8, assim, evitará alguns bugs de colisão nas paredes e etc.

Muito bem! Agora nosso personagem ataca! Mas perái... ele pode até criar o ataque e a flecha, mas ele ainda não aparece atacando... Bom, para isso, vamos utilizar um código simples como o de andar, e de quebra, impediremos o jogador de andar enquanto ataca.

Coloque este código no step event, na mesma página do código do movimento, porém primeiro. Assim:
if atacando =true //Se o personagem estiver atacando...
{
image_speed =0.5
if face =0
sprite_index = jogador_atacando_direita
if face =90
sprite_index = jogador_atacando_cima
if face =180
sprite_index = jogador_atacando_esquerda
if face =270
sprite_index = jogador_atacando_baixo
}
else //Ou então... apartir daqui, ficará o código do movimento do personagem, assim, se ele NÃO estiver atacando, ele ficará livre para andar.
{Coloque o código de movimento aqui dentro e apague esta mensagem, ou seu jogo vai dar erro}
Agora, coloque isto no evento Other > Animation end:
atacando =false //Assim, o jogador vai parar de atacar assim que a animação de ataque dele terminar.
Ufa! Sei que essa parte foi extremamente cansativa e trabalhosa, mas posso lhe dizer: o pior já foi. Agora respire fundo e vamos continuar.

2.4 Energia, Vidas e Game over:

Agora vamos programar a parte da energia, vida e para nosso personagem morrer. O Próprio GameMaker oferece esse sistema, mas é, na verdade, bem limitado, fora isso, se você conseguir entender como funciona, você terá infinitas possibilidades!

No Create event do nosso personagem, vamos relembrar algumas coisas que nós especificamos:
energia =100
energia_maximo =energia 
vidas =3
Assim sendo, vamos fazer o seguinte: Quando a energia chegar em 0, o personagem perde uma vida. Se as vidas chegarem ao 0, o jogo acaba. Faça o seguinte, numa folha de código separada no step event do jogador:
if energia < 0 {energia =0} // Impede que a energia fique menos que 0
if energia > energia_maximo {energia = energia_maximo} //Impede que a energia fique mais que o limite que especificamos.

if energia =0 //Agora, se a energia chegar à 0...
{
show_message("Você morreu! Tente novamente!") //Mensagem de morte
vidas -=1 // Retira uma vida
room_restart() // Futuramente faremos com que isso faça o jogador voltar para a posição inicial
}
Muito bem, agora a nossa energia está programada e irá funcionar corretamente. Agora vamos programar as vidas. Você pode colocar este código na mesma folha da energia, depois ou antes:
if vidas <=0 {
show_message("Fim de Jogo!!") // Mensagem de Game over
game_restart() // Reinicia o jogo
}
Muito bem! Agora o nosso Game over também está programado.

2.5: Vida extra:

Nós ainda temos que pensar no que fazer com os pontos que o personagem vai pegar durante o jogo. Por que não colocamos, por exemplo, para cada 1000 pontos que ele obter, ele ganha uma nova vida?
Para isso, coloque outra folha de código no step event:
if pontos >=1000 // Se o jogador tiver mil ou mais pontos
{
vidas +=1 // Ele ganha mais uma vida
pontos -=1000 // Não se esqueça de descontar os mil pontos, ou ele ficará ganhando vidas infinitas toda hora
}
Ótimo! Agora nosso jogador está definitivamente completo! Agora que temos metade do jogo em nossas mãos, vamos aos outros aspectos necessário para o jogo rodar.

3. Nossa primeira room e a câmera:

Bom, agora, crie uma sala de cerca de 960x960 e coloque uma instância de jogador no centro dela.Você pode colocar um background legal.

Agora, vá na aba Views e marque a caixa Enable use of views e no View[0], marque a caixa Visible when room starts. Agora você pode alterar livremente os valores, mas considere muitas coisas antes:

View in room: Altera o tamanho da câmera da room. O padrão é 640x480 e é um bom tamanho, quase ideal. Não precisa alterar o X e Y pois não será uma câmera fixa, ela vai seguir o jogador.

Port on Screen: Altera o tamanha da tela do jogo no computador da pessoa. Se você colocar maior que o View in room, ele vai esticar os gráficos do seu jogo, e se for menor, vai comprimir. O ideal é deixar do mesmo tamanho que o view.

Object following: Coloque jogador. O Hsp (Horizontal Speed) e Vsp (Vertical Speed) é a velocidade da câmera ao seguir o jogador. De preferência deixe -1 como está. Já o Hbor e Vbor, coloque valores como 128/96, para centralizar um pouco o jogador na câmera.

4. Obstáculos:

Agora vamos criar os obstáculos do jogo. Eu pedi a vocês para criarem os objetos obstaculo_principal, obstaculo_raso e obstaculo_alto. Mas por quê isso? 

Bem, a explicação é muito simples: o obstaculo_alto não permitirá a passagem de flechas e coisas do gênero enquanto o obstaculo_raso sim, mas ambos não permitirão o jogador nem os inimigos passarem. Legal, né? Assim, você poderá fazer paredes não deixar flechas passarem, mas ao mesmo tempo possibilitar do jogador atirar flechas nos inimigos do outro lado de um rio ou por grades, por exemplo.

Bom, se você acompanhou o tutorial, já programamos a flecha para ser destruída no contato com o obstáculo_alto.

Agora, faça o obstaculo_alto e obstaculo_raso ficaram no Parent com o obstaculo_principal. Isso não terá uma utilidade definida, mas é somente por conveniência. Coloque também todos os três como Solid por motivos óbvios.

Agora, você pode criar todos os obstáculos que imaginar: árvores, pedras, rios e etc. Mas lembre-se sempre de ligar os obstáculos no Parent com o obstaculo_alto ou o obstaculo_raso, dependendo se ele deixa ou não flechas passarem por ele. Lembre-se: nenhum objeto além do obstáculo_raso e obstáculo_alto devem ser ligados diretamente no obstáculo_principal.

Lembre-se também de colocar a mask_32_32 como mask dos obstáculos para impedir bugs de colisão.

Então, coloque os obstáculos na sua room e faça um rápido teste. Atire flechas e tente andar sobre eles. Se nenhum deles deixar o jogador passar, e os rasos (provalmente rios, por exemplo) não destruirem as flechas, ótimo! Deu tudo certo!

Se você quiser colocar a room como Persistent, fique a vontade. Mas lembre-se: Se ela NÃO for Persistent, sempre que você voltar nela um novo jogador será criado, então, você pode:

- Deixar a room persistent
- Impedir do jogador voltar nessa room depois que sair dela

5. Itens:

Agora vamos criar nossos itens. Eu pedi para vocês criarem três itens: item_energia, item_vida e tesouro. São muito simples de serem programados, e todas suas funções eles serão especificadas via Collision event com o jogador.

item_energia:
jogador.energia +=25
instance_destroy()
item_vida:
jogador.vida +=1
instance_destroy()
item_tesouro:
jogador.pontos +=100
instance_destroy()
Se os itens tiverem uma animação básica em seus sprites, coloque um image_speed =0.5 no Create event para que ela não fique muito rápida.

Agora nós temos os itens para espalhar pelo nosso jogo. Agora vamos continuar que estamos quase acabando!

6. Inimigos e sistema de batalhas:

Bom, agora chegou a hora de colocar ameaças e desafios no nosso jogo. Existe infinitas possibilidades para programar uma IA de inimigos. Não vamos entrar em detalhes perfeccionistas nem uma IA tão inteligente, vamos apenas fazer um molde básico de inimigo.

Como o nosso jogo permite o personagem atacar, vamos ter que fazer inimigos mais agressivos e que saibam atacar o jogador também.

Eu pedi para vocês criarem quatro objetos: inimigo_principal, inimigo_1, inimigo_2, inimigo_3. Assim como nos obstáculos, o inimigo_1,2 e 3 serão ligados no inimigo_principal, e assim como os obstáculos, o inimigo_principal não fará parte do jogo diretamente, é apenas o molde que dará as informações mais necessárias para seus afiliados, por isso, faremos o principal nele, e para diferenciar um inimigo do outro, faremos pequenas alterações, como velocidade, sprite e etc. Se ficou difícil de entender, vamos por a mão na massa que se aprende mesmo é fazendo.

Vamos primeiro fazer o ataque deles, que será representado pelo objeto bola_de_fogo que já foi criado. No Create event da bola_de_fogo, coloque:
move_towards_point(jogador.x,jogador.y,4)
Na colisão com o jogador, coloque:
jogador.energia -10
instance_destroy()
E na colisão com o obstaculo_alto, coloque apenas:
instance_destroy()
No Create event do inimigo_principal, coloque:
velocidade =0
energia =0
delay =0
Então, no step event, vamos fazer uma IA básica:
if distance_to_object(jogador) <=160 //Se ele estiver a menos de 160 pixels de distância do jogador...
{
if distance_to_object(jogador) <=64 //Agora, se ele estiver ainda mais perto do jogador...
{
if delay <=0{
delay =100
instance_create(x,y,bola_de_fogo)  //Ele ataca
}
}
else //Se não...
mp_potential_step(jogador.x,jogador.y,velocidade,0) //Ele continua andando em direção ao jogador
}
else //Se não...
speed =0 //Para de andar

if delay >0{delay -=1}
if energia <=0 {instance_destroy()} //Se a energia acabar, ele é destruido.
Agora vamos fazer o inimigo perder energia quando é atacado. Para isso, crie um Collision event com o objeto ataque_principal:
energia -=irandom_range(10,25) //Faremos ele perder entre 10 e 25 pontos de energia quando atacado.
other.destroy_instance() //Destruir o ataque
Só para finalizar, vamos fazer com que os inimigos parem de andar no contato com a parede. Coloque um evento de colisão com o obstáculo_principal.
speed =0 //Apenas por conveniência, já que a IA dele impede que ele tente atravessar obstáculos
Agora, nosso inimigo_principal já está totalmente pronto. Agora, vamos fazer pequenas alterações no inimigo_1, inimigo_2 e inimigo_3.

No Create event do inimigo_1:
velocidade =1
energia =50
delay =0
No Create event do inimigo_2:
velocidade =4
energia =20
delay =0
No Create event do inimigo_3:
velocidade =2
energia =70
delay =0
Todo os outros eventos não precisam ser alterados, pois estão puxando informação da programação do inimigo_principal, já que estão de Parent nele. Agora que os inimigos estão totalmente programados, você nós podemos partir para o penúltimo passo do nosso mega tutorial.

7. Objetivo do jogo

Claro que todo jogo deve ter um objetivo. Então, vamos colocar como objetivo o jogador pegar o diamante. Você provavelmente deve ter colocado várias instâncias na sua primeira room, então, agora coloque alguns inimigos, faça um pequeno "labirinto" (mas não leve ao pé da letra, pois isso não é um jogo de maze) e coloque o diamante no fim dele. Agora vamos programar o diamante.

Coloque um Collision event do diamante com o Jogador.
if (room != room_last) //Se não for a última room do jogo
{
show_message("Você conseguiu! Vamos para a próxima fase!") //Mensagem de sucesso
room_goto_next() //Próxima fase
}
else //Mas se for...
{
show_message("Parabéns! Você conseguiu vencer a última fase! Obrigado por jogar!!") //Mensagem final
game_end() //O jogo fecha
}
Agora o diamante está programado para passar as fases e terminar o jogo. Mas quando você passa a fase, provavelmente perceberá que o seu jogador, que é Persistent, inicia a próxima no mesmo lugar que ele terminou a anterior. É aí que encontra nosso objeto especial: jogador_posicao_inicial.

Coloque o jogador_posicao_inicial no lugar que você quer que o jogador comece a fase. Então coloque no other > room_start do jogador_posicao_inicial e coloque o seguinte código:
jogador.x = x
jogador y =y
Agora sempre que o jogador entrar numa room ou morrer (lembra que programamos para a room reiniciar quando o personagem morrer?), ele é transportado automáticamente para o jogador_posicao_inicial. Não se esqueça de colocar um sprite qualquer nele e deixar o Visible dele desligado. E claro, lembre-se de colocar o jogador_posicao_inicial em todas as rooms do jogo.

8. Interface:

Agora que nosso jogo está praticamente completo, por que não deixá-lo mais bonito e com algumas informações? Para isso, criamos o sprite vida_barra_sprite. Faça dele um sprite cerca de 100x25 com cerca de 20 subimagens, cada uma menos cheia que a outra.

Salve esta imagem se desejar.
Agora, precisamos de um objeto para colocar nossa interface na tela. Para isso criamos o objeto interface. Deixe ele sempre Visible e Persistent, e coloque ele na mesma sala que o jogador. Além disso, coloque o Depth dela como -1000 (isso fará ela ficar acima de qualquer objeto).

Agora, acrescente o Draw Event e vamos fazer a interface básica do nosso joguinho.
draw_sprite(vida_barra_sprite,(jogador.energia*20/jogador.energia_maximo),view_xview[0]+4,view_yview[0]+4)
Este código colocará sua barra de energia no canto superior esquerdo da tela como mágica. Agora vamos adicionar algumas informações, como vidas restantes e a pontuação.

Coloque uma cor legal no draw event da interface (uma que não seja tão escura nem tão clara) e crie uma fonte legal, nem muito pequena nem muito grande e coloque-a também (ambos acima da folha de código).

Agora adicione o código na mesma folha da barra de vida.
draw_text(view_xview[0]+4,view_yview[0]+30,"Vidas: "+string(jogador.vidas))
draw_text(view_xview[0]+4,view_yview[0]+50,"Pontos: "+string(jogador.pontos))
Pronto! Agora sua interface está completa!

9. Considerações finais:

Pronto! Agora criamos todos os básicos que um jogo deve ter usando GML. Teste seu jogo e veja se funciona. Se algo no tutorial está dando errado, favor avisar!!

Logo, criarei uma engine com tudo pronto e disponibilizarei o Download para vocês verem como é nosso jogo pronto.

Copie, mas cite a fonte!!!

Até a próxima!

45 comentários:

  1. Excelente esse seu tutorial. Apenas duas dúvidas:
    COMO PODERIA MODIFICAR PARA:
    1) Queria que o personagem atirasse também andando. Tipo: aperto a seta up e tb o A(q atira) e ele fosse para frente e atirasse. Mesmo comportamento se fosse nas outras direcoes.
    2)No lugar de ataque a curta distancia, aparecer um escudo para ele se defender que iria se deteriorando quando fosse recebendo os ataques dos inimigos ate desaparecer. So voltando em outra fase.
    3) Eu poderia fazer todo esse processo sem usar codigos? apenas arrastando os comandos?

    GRATO GUSTAVO

    ResponderExcluir
    Respostas
    1. 1) Nesse caso, no comando da tecla A (ao ser pressionada ou liberada) você poderia colocar o código: (não se esqueça de criar a bala)

      {
      nnn=instance_create(personagem.x,personagem.y,obj_bala);
      nnn.direction=personagem.face;
      nnn.speed =8;
      }

      2) Ai basta criar um variável no Create_event do personagem que seria algo como:
      {
      energia_do_escudo=1000;
      }

      E na tecla de fazer aparecer o escudo:
      {
      if energia_do_escudo >0
      instance_create(obj_personagem.x,obj_personagem.y,obj_escudo)
      }

      E no Step_event do obj_escudo:
      {
      x = obj_personagem.x//Faz o escudo mover-se junto com o personagem
      y = obj_personagem.y//Complementa o de cima.

      minha_energia = obj_personagem.energia_do_escudo
      if minha_energia <=0//Se a minha energia acabou...
      instance_destroy()//Eu sumo :)
      }

      E ai você terá que fazer os inimigos se adaptarem para não denificarem o jogador enquanto ele possui escudo, e etc. Tente fazer do melhor jeito que lhe agrada!

      3) Sim... eu ja fiz vários jogos apenas arrastando os botões, porém eu recomendo que você comece a aprender utilizar os códigos por ser bem mais fácil trabalhar com a programação do jogo e praticamente obrigatório em jogos mais avançados. Sem contar também que existem milhões de coisas que só podem ser feitas perfeitamente através dos códigos.

      Lembre-se que isso é apenas um tutorial ensinando a criar elementos simples, para as pessoas entenderem como criar um jogo bem básico mesmo. Com certeza você, se levar a sério, irá encontrar a maneira que mais lhe agrada para programar seus jogos :)

      Excluir
  2. Muito legal seu tutorial. Também estou começando a aprender códigos e ele ta me ajudando muito. A ideia do amigo Gustavo tb veio a minha cabeça. Mas fiquei com umas dúvidas depois de sua explicação:
    1) Com esse código o escudo deve aparecer em qual posição junto do personagem? Como oriento isso?
    2)Esse nnn significa o que? é um comando?
    3)Vou abusar do seu conhecimento, mas vou perguntar: Como arrumo eu adapto os inimigos para não danificarem o jogador?
    Vc explica muito bem... vc tem outros tutoriais? Algum em video? Acho que vc deveria fazer outros de GM. Estou usando o novo GM STUDIO. AHHH... tutos sobre códigos seria muito legal!!! Precisamos muito de iniciativas como a sua... parabens!!!!!!

    Abração Marcus.

    ResponderExcluir
  3. Olá Marcus

    1) Bem, com o código que eu dei, o escudo automáticamente se ajusta ao personagem. A orientação sempre é com as coordenadas x e y. Para ter noção dessas medidas, você terá que ter duas bases: o tamanho das sprites e o tamanho da room.

    2) "nnn" é uma variável qualquer temporária. Ela não existe, mas eu sempre faço uso dela para "guardar" valores que eu considero importante para utilizá-los depois ou no exato momento. Por exemplo, eu utilizei:

    {
    nnn=instance_create(personagem.x,personagem.y,obj_bala);
    nnn.direction=personagem.face;
    nnn.speed =8;
    }

    Isso que dizer que sempre que eu me referir ao "nnn" o GM vai entender que eu quero dizer EXATAMENTE a instância que foi criada (instance_create(personagem.x,personagem.y,obj_bala)), por isso nas linhas seguintes eu pude alterar a direção(nnn.direction=personagem.face) e a velocidade da instância (nnn.speed =8)

    3) Bom, no GM existem infinitas possibilidades. Você pode fazer isso de infinitas maneiras, mas a mais simples que me vem a mente é colocar um:

    {
    if jogador.invencivel = false
    {
    jogador.energia -=5
    }
    }

    Traduzindo: "Se a jogador não estiver invencivel, energia -5, caso contrário, nada acontece".

    Legal cara, eu gosto bastante de usar o tempo livre para escrever tutoriais. Mais à frente talvez eu faça muitos outros, mas os únicos que eu possuo neste momento é os que estão na página GM Maker mesmo ;]
    (http://htplay.blogspot.com.br/p/adventuresmaker.html)

    ResponderExcluir
  4. Tenho uma dúvida que derrepente vc me esclarece. O meu obj_player está acumulando muitos eventos. Acredito que isso possa dificultar a execução do jogo. Explico melhor: Tenho vários tipos de objeto no jogo os quais ele colide. Se fossem os mesmo tudo bem, mas são diferentes, então preciso colocar um collision para cada um. Será que teria um jeito de colocar todas as colisões que apresentassem os mesmos efeitos num único comando evitando de ter que acumular um evento para cada uma.
    Valeu, aguardo... Ricardo.

    ResponderExcluir
    Respostas
    1. Simples... crie um "obj_parede_geral", e depois adicionar TODOS os obstáculos com o "Parent" no "obj_parede_geral".

      Depois, exclua todas as colisões com os obstáculos que você já criou no obj_jogador, e crie apenas uma colisão com o obj_parede_geral.

      Excluir
  5. Estou trabalhando com colisões e gostaria de saber como eu faço para que quando o obj_bolagigante encostar no obj_player ele pegue fogo: Tenho o objeto_fogo_vermelho criado. Seria algo assim: No momento da colisão o obj_player mudasse para o objeto_fogo_vermelho e se destruísse.
    Tentei fazer mas nao consegui mudar o sprite, apenas ele some sem ahaver mudança. Tentei colocar change instance e depois instance destroy no evento collision mas não dá certo. Que devo fazer?
    Gustavo

    ResponderExcluir
  6. Minha dúvida é parecida com a do amigo acima:
    Eu quero que:
    1) quando a flecha acertar o inimigo 3 vezes ele fique em chamas
    2) e logo depois as chamas desapareçam
    Para isso tenho: obj_fecha; obj_arqueiro; obj_inimigo; obj_chamas
    Minha dificuldade e fazer com que as chamas desapareçam:
    Usei: No creat do inimigo: vidas=3 no seu step: if vidas <=0 {instance_destroy()} OK FUNCIONOU MAS...
    Não sei usar os alarmes para o fogo sumir logo depois. Onde coloco e como?

    Obrigado Carlos Eduardo

    ResponderExcluir
    Respostas
    1. Decidi fazer um guia em breve explicando muitas das dúvidas aqui. Agurdem :)

      Excluir
  7. http://htplay.blogspot.com.br/2012/10/gamemaker-manual-criando-seu-primeiro.html

    Eu fiz os primeiros passos do Guia. Estarei atualizando ele constantemente. Se quiserem acompanhar, é só ir no link acima.

    ResponderExcluir
  8. Parabéns!! tá ficando ótimo!!
    Gustavo

    ResponderExcluir
  9. OLá amigo DORITOS.... nos deparamos com um problemão aqui e queria ver se pode me ajudar. Queria fazer aquele esquema:
    o player com 3 vidas. Cada vida que ele perdesse, a room voltava no começo.
    O problema é que quando ele é atingido por um inimigo e perde uma vida acontece um efeito de fogo. Precisaria que o room_restart() acontecesse pelo menos uns 2 segundos após esse efeito acontecer. O que consegui foi fazer o restart acontecer muito rápido, nem da tempo para o efeito acontecer.
    Tentei usar alarm na colisaõ, mas nao funcionou. Tentei usar o evento destroy mas tb nao deu.
    Nos salve dessa por favor!!!!
    Abraçao!!!

    GUSTAVO

    ResponderExcluir
    Respostas
    1. Nesse caso, coloque o room_restart() no Alarm 0 (ou qualquer outro) e quando o efeito do fogo COMEÇAR, coloque alarm[0]=60.

      Assim a room será reiniciada após 2 segundos que o efeito de fogo começar.

      Excluir
    2. Espero que funcione, pois como eu disse, sem o código fica difícil descobrir como as coisas funcionam :)

      Excluir
  10. Deixa eu explicar melhor: LEMBRANDO O JOGO É DO TIPO TOP DOWN... O cenário vem se deslocando para baixo.
    O jogo tá rolando. Derrepente o player morre. Ok.
    Não queria que a room se reiniciasse, queria mesmo é que o player aparecesse alguns metros abaixo de onde ele estava quando havia morrido. Assim deve aparecer aquela mensagem na tela (FASE 1) entao o jogo continuava desse ponto.
    Minhas dificuldades:
    O número de vidas deveria aparecer já debitando a que ele perdeu, o que nao acontece se usasse o room_restart().
    Para ele aparecer metros abaixo usei instance_create(xstart, ystart+300,obj_player). OK... MAS... a view nao retorna para baixo(apenas segue), ficando a mesma sem o player.
    Precisaria que a view tb descesse esses 300 de forma que o player aparecesse dentro dela.

    Outra dificuldade: Uso o Game maker studio... e nele já não aparecesse a opcao no drag de usar o highscore. Então teria que faze-lo em códigos.
    Gostaria de fazer um simples, tipo tabela com o nome dos melhores scores e um lugar para colocar o que a pessoa acabou de fazer. Já tenho uma room para ele, de forma que gostaria que ele aparecesse nessa room.

    ResponderExcluir
    Respostas
    1. Nesse caso recomendo você usar o 'global'.

      Vou te explicar melhor: 'global' é quando uma variável fica armazenada no próprio jogo, e não num objeto especifico. Sendo assim, ao invés de coloca vidas =3 no obj_jogador, crie uma room vazia atrás dessa e coloque no código create da própria room {global.vidas =3; room_goto_next()}. Assim, quando acontecer o room_restart(), as vidas estarão como devem ser.

      Vale lembrar de colocar, quando o jogador morre, global.vidas -=1

      Já os highscore: http://gmbr.forumeiros.com/t15837-como-fazer-highscores
      NOTA: você não precisa seguir todos os passos, só o código principal.

      Excluir
    2. Voltando ao assunto do jogador morrendo, já se você realmente quiser fazer o da outra maneira, sem room_restart()...

      Bem, não entendi muito bem o uso do seu "instance_create(xstart, ystart+300,obj_player)"

      Se você fizer isso, um obj_player será criado 300 pixels ABAIXO DO LOCAL ONDE O PRIMEIRO FOI CRIADO, ou seja, provavelmente FORA da room. E a view não segue objetos fora da room. Mude o código para: instance_create(xstart, ystart,obj_player)

      Excluir
  11. Ok... mas o highscore, que parecia o mais fácil, naõ to acertando. No obj_controle que ele disse coloquei:
    if vidas <1
    {highscore_show(pontos) // Mostra o número de pontos feitos
    highscore_set_background(Highscore) // Coloque o nome do background q vc criou antes
    highscore_set_colors(Highscore,c_green,c_red) // A cor das letras e do fundo
    highscore_set_font(fonte2,12,0) // Coloque a fonte que vc criou, numero da fonte, e o estilo.

    game_restart() //recomeça o jogo}

    MAS... ele dá erro me dizendo que essas funções estaõ obsoletas.
    Uso o GMS. Por isso não to conseguindo fazer, até já tinha visto esse link que me falou.

    ResponderExcluir
  12. Pelo que pesquisei no forum ga yoyogames apenas essas funcoes vao funcionar:
    highscore_add
    highscore_name
    highscore_value
    highscore_clear
    draw_highscore

    Então preciso entender como faco para criar um só com elas e nãoa cho em lugar nenhum.
    Já tenho o back e a room que quero que a tabela com os 10 melhores na pontuacao aparecam.

    ResponderExcluir
    Respostas
    1. Poxa cara, nisso eu realmente não posso te ajudar pois nunca usei essa função nos meus projetos... espero que o problema com a morte do player tenha sido resolvido ao menos...

      Desculpe :/

      Excluir
  13. Imagina.. muito grato por sua ajuda... Quanto a morte do player tudo OK.

    Mas abusando do seu conhecimento:

    Tenho uma room que indica as oito fases do jogo. Números de um a oito sendo do 2 ao 8 com cadeado(botoes inativos). Aquele esquema q vc já conhece.

    Queria saber como faria para que quando o player colidisse com algo o botão dois(por exemplo.) ficasse ativo para que que quando o tocasse já levasse para fase dois.

    Minha dúvida está no fato de que o player estaria em outra room. Então como faria para que esse botaõ ficasse ativo mesmo que ele estivesse na room dos botoes que indicam fases, e o player na room da fase 1?

    Outra questão é fazer o save e o load do game. (Aprender a faze-los 1°)
    Queria que quando o player morresse, por ex, o botao 2 da room que indica as fases ficasse ativo e que ao clicar num botao save abaixo o jogo fosse gravado. Assim quando carregar o mesmo novamente, no menu fases já apareceria ativo o botao 1 e 2, para que pudessem ser clicados e comecar o game na fase dois.

    ResponderExcluir
  14. Só complementando, mais uma vez me deparei com comandos que ficarem obsoletos no GMS. O GAME_SAVE E O GAME_LOAD. Caso contrário já teria resolvido. Perguntei no Game maker Brasil mas a resposta que obtive precisaria de uma explicaçao que talvez vc pudesse me dar:
    Criar variávei globais.. ok Mas como eu gravaria ?
    http://gmbr.forumeiros.com/t24883-como-fazer-para-salvar-o-game-e-depois-carregar#184501

    ResponderExcluir
    Respostas
    1. Bom cara, como o Game_save e o Game_load não funcionam mais, e você quer gravar algo simples como a tela de seleção de fazes, usaremos as funções .INI. Basicamente é um jeito de guardar variáveis num bloco de anotas (salvar), e depois executar ações dependendo dos valores no bloco de anotas (carregar). É um pouco complicado...

      No código da primeira room, logo que o jogo inicia, coloque:
      ini_open("saves.ini")
      {
      ini_read_string("Fases","Fase 1","Desbloqueado")
      ini_read_string("Fases","Fase 2","Bloqueado")
      ini_read_string("Fases","Fase 3","Bloqueado")
      ini_read_string("Fases","Fase 4","Bloqueado")
      ini_read_string("Fases","Fase 5","Bloqueado")
      ini_read_string("Fases","Fase 6","Bloqueado")
      ini_read_string("Fases","Fase 7","Bloqueado")
      ini_read_string("Fases","Fase 8","Bloqueado")
      }
      ini_close()

      No Step event de cada botão da fase, no menu, coloque:
      ini_open("saves.ini")
      {
      var_nnn = ini_read_string("Fases","Fase "+string(var_numero_da_fase),"")

      if var_nnn = "Desbloqueado"
      {
      var_bloqueado =false;
      image_index = 1;//Imagem da fase desbloqueada
      }
      else
      {
      var_bloqueado =true;
      image_index =0;//Imagem da fase bloqueada
      }

      }
      ini_close()

      No Create_event de cada botão da fase, coloque:
      var_numero_da_fase =1;//Coloque 1 na fase 1, 2 na fase 2, ...

      Agora, quando o jogador derrotar o chefão final de todas as fases, execute este código (de qualquer forma que desejar, geralmente quando o chefe é destruído ou o jogador é mandado de volta ao menu de seleção de fases):
      //Final da fase 1
      {
      ini_open("saves.ini")
      {
      ini_write_string("Fases","Fase 2","Desbloqueado")
      }
      ini_close()
      }

      //Final da fase 2
      {
      ini_open("saves.ini")
      {
      ini_write_string("Fases","Fase 3","Desbloqueado")
      }
      ini_close()
      }

      E assim por diante. Espero que funcione, eu testei e deu certo!

      Excluir
  15. Eu entendi bem, o botão da fase 1 inicia o jogo normalmente, mas o botao da fase 2 tb fica ativo em vez de ficar desativado.(SO TESTEI EM DOIS BOTÕES PRIMEIRAMENTE)
    Esquematizando p vc entender:
    Minha primeira room é a da tela inicial de apresentacao: nela eu aperto START e o game vai para a tela de FASES.
    Na tela dE FASES existem 8 botoes, cada um com um cadeado desenhado. Onde apenas o numero 1 é um cadeado aberto.
    É aí que está o problema. Como te disse acima( o botao 1 e o 2 ficam ativados). ERA PARA O BOTAO 2 FICAR INATIVO.
    Mesmo antes dele destruir o inimigo (onde coloquei o codigo q disse acima) os botoes ficam ativos.

    O QUE FIZ:

    Coloquei o 1 código nessa minha primeira room(da apresentacao(é a 1° do jogo)).
    Coloquei os códigos nos botões(no step deles)
    No create deles coloquei(var_numero_da_fase =1;//Coloque 1 na fase 1, 2 na fase 2, ...)

    Outra questão: tenho os objetos dos botoes com e sem cadeados. Como faria para que quando estiverem desbloqueados a imagem fosse trocada pela do cadeado aberto?

    ResponderExcluir
  16. Estou testando várias vezes. A questão que precisaria resolver é a de que quando termino o jogo, desligo o computador(por exemplo), horas depois quando vou jogar de novo, o botaõ da fase dois fica inativo, como se eu não tivesse já o liberado em meu jogo anterior. Pois eu havia passado de fase, ele abriu seu cadeado para que quando jogasse novamente não precisasse voltar a fase um, e começar tudo de novo. Mas tudo volta ao começo quando inicio o jogo novamente. Essa é minha dificuldade. Vejo que nos games, muitod deles, o que vc conquista fica gravado. No meu caso eu só preciso que fique gravado a room de fases, para que cada vez q se inicie(se anteriormente houvesse passado de fase) Os bot~es respectivos estivessem ativos.

    ResponderExcluir
    Respostas
    1. Bom cara, o código que eu te mandei faz tudo isso que vc disse: ele grava mesmo quando o computador desligado, e troca a imagem automáticamente quando vc destravar as fases.

      Tente mudar um detalhe que eu acho que você está se esquecendo:

      Ao clicar com o botão da fase 2, coloque no início de tudo:

      if var_bloqueado =false
      {
      //resto do código aqui, e provavelmente deve ser...
      room = rm_fase_2
      }

      Faça o mesmo nos outros botões, menos na fase 1 :)

      Excluir
  17. Teria como eu mandar p vc uma base para vc ver, se não for abusar muito de toda sua paciencia? Aí vc veria melhor os códigos. Me sugerindo. Como te enviaria?

    ResponderExcluir
    Respostas
    1. Tanto faz, faz um upload e me manda o Link. Se quiser me mandar privado, manda pro epilef_live@hotmail.com que eu dou uma olhada.

      Excluir
  18. Valeu amigo, muito obrigado pela sua imensa ajuda. Já arrumei tudo por aqui.

    Apenas mais uma coisa se puder me ajudar:

    Fiz um direcional na tela e mais dois botões.

    Para usar no Android.

    Funciona bem, só que no Android só funciona uma tecla por vez. Os direcionais até que fazem diagonal, sem problemas, mas se eu quero que o player avance para cima e atire simultaneamente, não dá.

    Pesquisei muito antes de te perguntar. Cheguei a vário lugares onde se falava em multitouch. Soube que o GMS aceita até 5 toques simultâneos. Mas que não se pode usar o EVENT MOUSE LEFT, pois ele só funciona com um toque de cada vez.
    Consegui um código assim:

    // check all possible touches
    for(btn_i=0; btn_i<=4; btn_i+=1) {
    // if there is a touch
    if (device_mouse_check_button(btn_i, mb_left)) {.......

    Acredito que deve ser usado no STEP DE CADA OBJETO(no meu caso os botõs de tiro, escudo e direcionais). Ma squando coloquei, e aperto um deles, todos funcionam ao memso tempo...

    Talvez possame ajudar? Nessa ou em outra maneira de gerar toques simultâneos.

    Grato.. UM ÓTIMO ANO PARA VC E SUA FAMÍLIA, ÓTIMA SAÚDE PARA TODOS NO ANO NOVO!!

    ResponderExcluir
    Respostas
    1. Eu não sou perito nessa tecnologia de android... mas ao toque, se todos funcionam ao mesmo tempo, garanto que se você puder encontrar uma maneiera de checar se o toque está encima do objeto DEPOIS de detectar um toque (usando o código acima) arrumaria o problema...

      Eu não sei ao certo que código você deve usar, você entrou numa área que eu não tenho conhecimento, me desculpe...

      No mais, Obrigado, e um Feliz Natal!

      Excluir
  19. Será que vc poderia me dar alguam dica a respeito disso:
    http://gmbr.forumeiros.com/t24999-multi-touch-para-android#185265

    Talvez saiba algo sobre virtualkeys?

    ResponderExcluir
  20. Consegui resolver!!! Como a gente aprende, mas e preciso dedicação... e muita!!
    Mias uma vez, mutio obrigado por sua ajuda... Apesar das dificuldades, sem essa sua força seria tudo muito mais complicado!!!

    ResponderExcluir
  21. o que significa inimigo1 , 2 ,3 ?

    ResponderExcluir
    Respostas
    1. São as variações dos inimigos. O inimigo_1 pode ser uma caveira, o inimigo_2 um zumbi, o inimigo_3 um dragão, por exemplo.

      Excluir
    2. A tem mais uma coisa quando eu ponho aquele codigo do delay , ele n reconhece o delay vc sabe pq?

      Excluir
    3. Provavelmente pq vc ñ colocou "delay=0" no Create Event. :)

      Excluir
  22. Os Inimigo_1 , 2 , 3 precisam de direita esquerda baixo cima , ou é de minha preferencia?
    Obrigado Ramon!

    ResponderExcluir
    Respostas
    1. Sua preferência, sempre. Não existe um jeito errado de programar.

      Excluir
  23. os inimigos nao se mechem e nem soltam a bola de fogo

    ResponderExcluir
    Respostas
    1. Faz tempo que eu criei o guia, talvez alguns códigos estejam desatualizados. Um dia irei refazer este guia, no momento não posso dizer o que está dando errado.

      Excluir
    2. Estou em duvida como fazer :
      Por exemplo quando eu passar por um NPC , aparecer uma mensagem tipo quadrinhos.
      E por exemplo fazer o dinheiro do jogo com 100 moedas = pode comprar o tal item etc

      Excluir
  24. 1 - Você sabe como faço pra fazer a vida do personagem e pra o inimigo? Obs : No personagem queria uma barra de vida indicando , como faço pra morrer quando a vida acabar?
    2- Como fazer meu personagem pular com animação ?

    ResponderExcluir
  25. Muito bom o tutorial!!!! Uma dúvida, por favor,eu estava usando 800x800 na room, 64x64 no personagem e tilesets, mas td em pixel art sem anti-aliasing, mas o que eu gostaria de fazer era dar um zoom na view para aproximar a área de jogo sem diminuir o seu tamanho, o que eu poderia fazer para chegar a isso?

    ResponderExcluir

Dúvidas? Pergunte!
Ajudou? Agradece!
:]