Menu

Tutorial de Unity 2D # 12 – Fase e GUI

E aê pessoal? Preparados para o penúltimo tutorial de Unity 2D? Hoje vamos ver como adicionar as fases (E telas) e muda-las no nosso jogo.

Bom, eu lembro que deixei um desafio para vocês a bastante tempo atrás de como fazer a bandeira se mover não é mesmo? Acredito que todos já conseguiram fazer depois do que passamos pelos inimigos, mas para quem não, aqui estará os passos: (Não vou entrar em detalhes para não fugir muito da aula, que será enorme)

1 – Importa a imagem abaixo para a pasta sprites:

sprite_flag

2 – Clique nela na aba Project e dentro da aba Inspector troque as opções Texture Type para Sprite (2D/uGUI) e em Spride Mode, troque para Multiple. Após isso realize um Slice automático no Sprite Editor.

3 – Crie um novo objeto chamado Bandeira.

4 – Adicione o componente Sprite Renderer (Rendering >> Sprite Renderer) com um dos sprites da bandeira.

5 – Clique sobre o objeto Bandeira na aba Hierarchy e dentro da aba Animation, jogue os demais sprites da bandeira. Será solicitado que salve a animação, então pode salva-la dentro de uma pasta na pasta animations (animations/bandeira ou animation/outros).

6 – Diminua a velocidade da bandeira, alterando o valor do sample para 20.

7 – Posicione o objeto no final a fase. E trabalho feito ^^

Pronto, com a nossa bandeira já no mapa, agora vamos iniciar de verdade o nosso tutorial. Nesse tutorial vamos criar 4 telas novas, de forma que o nosso jogo fique:

1 – Menu Inicial
2 – Fase 1 (Essa que já criamos)
3 – Fase 2 (Criar uma nova fase, sem nada demais, só para ter 2 fases)
4 – Créditos
5 – Game Over

O primeiro conteúdo que vamos criar será logo o mais chato. Ou seja, o menu principal. Por que mais chato? Porque para vocês, esse menu que eu vou criar será praticamente todo via script, ou seja, para quem não gosta, será a parte mais complicada. Mas relaxem, existe muuuuuuuita coisa mesmo para se ver, porém eu vou focar apenas na parte simples e direta. Em outro jogo (tutorial) se vocês quiserem eu exploro um post inteiro só para GUI ou faço um post a parte como fiz com programação, só voltado a GUI. Digo isso porque, essa parte é muito importante e muito rica. Através das opções de GUI você pode fazer:

Inventário

Menus

Toolbar (Aquela barra que fica ali em cima nos programas com as opções (Arquivo, Editar, ajuda…)

Campo para digitar nome

Campo de senha

Criar uma janela para digitar códigos para abrir bau/fechadura/tranca…

Opções

E por ai vai. Mas para o nosso tutorial só vou usar praticamente 4 coisas: Criar Grupo, criar uma caixa destaque, criar botões e inserir o título do jogo (imagem ou texto).

Deixando de conversa, bora para a pratica. A primeira coisa que eu vou pedir é que se vocês não criaram antes a pasta scenes (Não lembro se pedi ou não para vocês criarem antes), então criem, clicando na aba Project com o botão direito e escolhendo a opção Create >> Folder. Dê o nome dessa pasta de scenes. Será nessa pasta que vamos salvar cada cena (fase) do nosso jogo. Após criar jogue a cena já criada (A nossa fase atual) para dentro dessa pasta:

01 - Mudar de fase

Bom, agora vamos criar uma nova cena, que será nosso menu principal. Para isso vá no menu principal File >> New Scene.

02 - Mudar de fase

Logo em seguida, você já pode salvar logo a scene para ela ficar guardada. Salve ela na pasta scenes com o nome menu_principal.

03 - Mudar de fase

Pode aproveitar e trocar já o nome da antiga scene para fase01:

04 - Mudar de fase

Agora importe a seguinte imagem ou qualquer outra que vocês queiram para a pasta texture, para se o fundo do seu cenário:

desert

E troque a opção Texture Type para Texture:

05 - Mudar de fase

Vamos realizar o mesmo procedimento para o que será o título do seu jogo. No meu caso vou usar a logo do Jogos Indie:

jogos_indie

Importem para a pasta Texture e mude seu tipo para Texture.

Feito isto, criem um novo objeto chamado MenuPrincipal (GameObject >> Create Empty). Este objeto terá um Script que irá criar TODA a tela do menu principal. Sim o menu principal será criado todo através de script!

Então meus queridos é hora de pegar um café, por uma música light para relaxar e criar um novo Script (C# Script) na pasta Scripts com o nome MenuPrincipal, pois a loucura para quem não gosta de programação vai começar.

A primeira coisa que vocês ter que fazer nesse script é adicionar duas propriedades:

public Texture2D background;
public Texture2D titulo;

Background será a nossa imagem de fundo (desert.png) e titulo será a logo do seu jogo (No meu caso a logo do Jogos Indie).

Com as propriedades criadas, é hora de apresentar a vocês um novo método padrão do MonoBehaviour: OnGUI.

Como o próprio nome sugere, dentro deste método ficará a construção do HUD/GUI do nosso jogo. Dentro deste método vamos fazer as seguintes coisas:

1 – Inserir a imagem de fundo;

2 – Inserir o título do jogo;

3 – Inserir uma caixa com opções do menu;

4 – Inserir os botões do menu.

Bom, então a primeira coisa que vamos fazer é adicionar a seguinte linha no nosso OnGUI:

	void OnGUI() {
		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
	}

O que exatamente eu estou fazendo aqui? A Classe GUI é a responsável por criar todos os conteúdos GUI via script. O DrawTexture faz com que eu jogue uma imagem (textura) na tela, passando dois parâmetros, o primeiro sendo as informações de posição e tamanho (Rect) e a segunda é a imagem em si.

Os parâmetros do Rect significação: Rect(posição inicial de x, posição inicial de y, largura da imagem, altura da imagem).

As dimensões que estou usando no meu jogo para disponibiliza-lo aqui no Jogos Indie na página Índice é: 600×450. Isso significação dizer que a posição de cima do lado esquerdo é 0,0, enquanto a parte inferior do lado direito é 600,450:

posicao - screen

Pensem da seguinte forma, num papel quando estamos escrevendo, iniciamos da parte de cima, correto? Ou seja, a cada linha é um ponto, logo quanto maior o texto, mais distante da posição inicial de y vai estar e quanto mais caracteres por linha, mais distante ele vai estar na posição de x.

Vamos treinar um pouco isso, eu quero adicionar um botão que fique na parte inferior (Ou seja, mais distante de Y) no centro (No meio de X), qual será essa posição? A resposta é 300 (Metade de x = 600), 450 (parte mais distante de Y = 450).

Bom, com isso em mente, voltando ano nosso script, estamos dizendo que o nosso background irá iniciar na posição 0, 0 (Ou seja, na parte superior esquerda) e terá a largura da tela (Screen.width) e a altura da tela (Screen.height). Não é tão complicado assim, né?

Ah e só uma observação, toda posição que nós definirmos ser a posição que o nosso objeto será criado, equivale a posição da parte superior/esquerda desse objeto.

Sendo assim, se quisermos criar um menu com tamanho 120,120 e que ele fique no centro do nosso conteúdo, como devemos fazer? Se colocarmos a posição dele em 300,225 (No centro de uma tela 600,450), nosso menu ficará assim:

posicao errada

New Rect(300, 225, 120, 120) ou New Rect(Screen.width/2, Screen.height/2, 120, 120)

E não é isso que queremos não é mesmo? Se queremos o nosso menu centraliza-lo, teremos que subtrair a metade do valor do nosso menu na posição do objeto. Se o Menu tem 120 de largura, então a sua metade é 60. O mesmo vale para a altura. Logo:

300 – 60 = 240 (Posição Inicial de X)
225 – 60 = 165 (Posição Inicial de Y)

posicao correta

New Rect(240, 165, 120,120) ou new Rect((Screen.width/2 – 60), (Screen.height/2 – 60), 120, 120)

Conseguiram entender? Ou seja, para posicionar os nossos objetos via script (Quem um dia for mexer com Imagens e gráficos, vai ter quer que se acostumar com esses cálculos), vamos ter que fazer algumas dessas operações básicas.

Voltando ao nosso código, já adicionamos um background. Então caso você já queira visualizar como está ficando, pode adicionar o script ao objeto MenuPrincipal, e jogar a imagem desert no atributo e ver como ficou:

06 - Mudar de fase

Voltando ao código, é hora de adicionar uma nova linha, que ficará com o título:

	void OnGUI() {
		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);
	}

A segunda linha faz praticamente a mesma coisa do que o Background, só que ai iremos adicionar o título do jogo que terá largura 150 por altura de 40. Eu quero que o título fique centralizado (600/2 – 150/2 = 300 – 75 = 225) e um pouco distante do topo (50 de distância). Isso vai resultar em:

07 - Mudar de fase

Carlos, tem diferença eu por o titulo antes do background? Sim, tem. Se você inverter a ordem deixando:

	void OnGUI() {
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);
		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);	
	}

Significa dizer que primeiro você vai colocar o título e por cima do titulo você vai por o background, logo você não vai ver seu título, já que ele estará por trás da imagem do background.

Bom, até aqui tudo tranquilo, agora vamos criar um grupo. Esse grupo será as opções do nosso menu, ou seja, se eu mover o grupo de lugar, moverei tudo que estiver dentro dele. Assim se eu tiver 10 botões e quiser mudar a posição deles, só movo o grupo ao invés de sair movendo botão por botão. Bem mais prático.

Para criar um grupo, definimos um começo e um fim usando os métodos GUI.BeginGroup e GUI.EndGroup :

	void OnGUI() {
		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);
		
		GUI.BeginGroup (new Rect(240,150, 120, 120));
		GUI.EndGroup();
	}

Tudo que quisermos que fique dentro do grupo, vai ter que estar entre essas duas linhas. A primeira linha que define o começo do grupo, também é responsável por dizer o tamanho e a posição inicial do grupo.

Eu quero que ele fique centralizado (600/2 – 120/2 = 300 – 60 = 240) e um pouco mais distante do topo (150). Também defino que o seu tamanho será de 120×120. Todo conteúdo que fugir do tamanho do grupo (Exemplo, um conteúdo na posição 150,150) não será visível.

Bom, agora eu quero adicionar uma caixa nesse grupo, para dá um destaque maior ao meu menu. Posso fazer isso usando a opção GUI.Box:

void OnGUI() {

		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);

		GUI.BeginGroup (new Rect(240,150, 120, 120));
		GUI.Box(new Rect(0, 0, 120, 120), "Menu");
		GUI.EndGroup();
	}

No GUI.Box passamos a posição inicial e o tamanho dele um campo a mais. Se vocês reparem a posição inicial dele é 0, 0. O que significa dizer que a partir desse momento a sua posição não será mais em relação a tela do jogo, mas sim ao grupo que ele está. Com isso estou dizendo que o box será criado na parte superior/esquerda do grupo. E seu tamanho será o mesmo do grupo, logo ele vai ocupar todo o espaço do grupo. O outro atributo é o nome que será exibido na box:

08 - Mudar de fase

Eu poderia ao invés de usar um texto, usar um Texture, como fiz com o background e o titulo:

09 - Mudar de fase

GUI.Box(new Rect(0, 0, 120, 120), titulo);

Ou deixar em branco:

10 - Mudar de fase

GUI.Box(new Rect(0, 0, 120, 120), “”);

Após criar a Box do menu, eu quero criar 3 botões:

Iniciar

Continuar

Sair

Então adiciono os botões usando GUI.Button logo após a box dentro do meu grupo:

	void OnGUI() {

		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);

		GUI.BeginGroup (new Rect(240,150, 120, 120));
		GUI.Box(new Rect(0, 0, 120, 120), "Menu");
		GUI.Button (new Rect (20, 30, 50, 20), "Iniciar");
		GUI.Button (new Rect (20, 60, 70, 20), "Continuar");
		GUI.Button (new Rect (20, 90, 50, 20), "Sair");
		GUI.EndGroup();
	}

Aqui a ideia é exatamente igual a do Box, só que ao invés de criar um Box, ele cria um Botão. Criei os botões definindo uma iniciando em X = 20, para não ficar colado na box e com uma distância entre eles para não ficarem uma em cima do outro:

11 - Mudar de fase

Nosso menu já está quase pronto, falta adicionar ações para o nossos botões. Quando um botão é clicado ele retorna true no OnGUI, então só precisamos adicionar um if nos botões e fazer a ação:

	void OnGUI() {
		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);

		GUI.BeginGroup (new Rect(240,150, 120, 120));
		GUI.Box(new Rect(0, 0, 120, 120), "Menu");
		if (GUI.Button (new Rect (20, 30, 50, 20), "Iniciar")) {
			Application.LoadLevel("fase01");
		}
		if (GUI.Button (new Rect (20, 60, 70, 20), "Continuar")) {
			Debug.Log("Fica para o proximo tutorial de Save/Load");
		}
		if (GUI.Button (new Rect (20, 90, 50, 20), "Sair")) {
			Application.Quit();
		}
		GUI.EndGroup();
	}

if (GUI.Button (new Rect (20, 30, 50, 20), “Iniciar”)) {
       Application.LoadLevel(“fase01”);
}

No botão iniciar, colocamos uma condição para que quando o botão for apertado, ele carregue a Fase com o nome “fase01”.

A classe Application é responsável pelo controle das fases, encerrar o jogo, abrir conteúdos via browser… O LoadLevel é responsável por trocar de uma scene para outra. Aqui podemos chamar a fase de duas formas: Uma é a gente dizendo o nome exato dela e a segunda forma é a gente dizer a posição (index) dela.

Como assim posição? Toda fase que nosso jogo tem, precisa estar setada nas configurações do jogo, logo ela terá uma posição. Para adicionar uma fase ao seu jogo, vá em File >> Build Settings… e estando na fase, basta clicar em Add Current:

12 - Mudar de fase

13 - Mudar de fase

Ela vai adicionar a fase que você estiver editando. Se você tiver várias fases, pode clicar nelas na aba Project e arrasta para essa box ai de cima.
O index (posição) que eu me referir anteriormente é este nome ai ao lado das fases:

14 - Mudar de fase

Neste exemplo ai ao invés de chamar Application.LoadLevel(“fase01”), poderia chamar Application.LoadLevel(1).

A scene que tiver a posição (index) 0, será a primeira scene a ser chamada. Como nosso menu será a primeira scene a ser chamada, a arraste para cima da fase01, deixando ela na posição 0.

if (GUI.Button (new Rect (20, 60, 70, 20), “Continuar”)) {
       Debug.Log(“Fica para o proximo tutorial de Save/Load”);
}
O botão “continuar” será responsável para a gente continuar da ultima fase que paramos. Será o load do nosso save, mas isso fica para tutorial da semana que vem.

if (GUI.Button (new Rect (20, 90, 50, 20), “Sair”)) {
       Application.Quit();
}

O Application.Quit() é responsável por fechar o nosso jogo (Se ele for um jogo web ou nos nossos testes, não terá muita utilidade).

Com isto, terminamos o menu inicial!

Ficou grande não? Mas como falei, esta é a parte mais chata, o resto é mais tranquilo. Vamos criar uma nova scene (File >> New Scene) e salva-la (File >> Save Scene) com o nome gameover.

Vou pedir para que importem a seguinte imagem para a pasta Texture:

gameover

Troquem o Texture Type para GUI e criem um novo objeto chamado GameOver.

15 - Mudar de fase

Aproveitem para criar um script (C# Script) na pasta Scripts chamado GameOver (Botão direito na pasta scripts e Create >> C# Script).
Dentro deste Script, vamos adicionar três atributos:

public Texture2D background;
public float duracao;
private float contagem;

O background será essa imagem que acabamos de adicionar, enquanto o duracao será o tempo que ele vai permanecer na página de GameOver até voltar para o menu.

Bom, o primeiro passo aqui é adicionar a imagem de fundo através do OnGUI:

	void OnGUI() {
		GUI.DrawTexture (new Rect(0, 0, Screen.width, Screen.height), background);
	}

Aqui, estamos fazendo a mesma coisa que fizemos com o background do menu.

Após adicionar o background no Update, vamos fazer uma verificação, para ver se já atingiu o tempo que informamos para voltar ao MenuPrincipal.

	void Update () {
		contagem += Time.deltaTime;
		if (contagem >= duracao) {
			Application.LoadLevel(0);
		}
	}

Nossa atividade aqui é bem simples, a cada frame que o jogo roda, adicionar o tempo passado para a variável contagem. E depois verificamos se a contagem já atingiu o tempo que você definiu que deve permanecer nessa tela. Caso já o tenha, ele irá carregar o level de posição 0 (Nosso Menu).

Agora voltando ao Unity não se esqueça de adicionar esta scene para a fase (File >> Build Settings >>Add Current).

No objeto GameOver, adicione o Script GameOver e preencha os campos:

16 - Mudar de fase

Caso deseje, pode por uma música ai no fundo, já que já aprendemos como faz. (Add Component >> Audio >> Audio Source).

Com o GameOver pronto, vamos criar uma nova Scene (File >>New Scene) e a salve (File >> Save Scene) com o nome creditos.

Nesta nova cena vamos criar um novo objeto (GameObject >> Create Empty) com o nome Creditos e na pasta scripts vamos adicionar um novo script (Create >> C# Script) chamado Creditos.

Nesse script, vamos adicionar as 3 propriedades que usamos no game over, só que ao invés de ser background será a logo do jogo. E adicionaremos mais um, para edição do estilo do texto.

public Texture2D titulo;
public float duracao;
private float contagem;
private GUIStyle fonte;

Antes de tudo, precisamos agora definir no Start as informações da nossa fonte. Eu vou querer que minha fonte seja cinza e um pouco maior que o comum:

void Start () {
		fonte = new GUIStyle();
		fonte.fontSize = 20;
		fonte.normal.textColor = Color.gray;
	}

Ao iniciar a variável (fonte = new GUIStyle()), ele irá receber os dados padrões, ou seja fonte pequena e cor preta. Então em fonte.fonteSize estou aumentando o tamanho da minha fonte para 20 e em fonte.normal.textColor estou mudando a cor para cinza. Já vimos anteriormente que ao invés de usar a classe Color, poderíamos usar um Vector3 onde passaríamos os valores de RGB (Vermelho, Verde, Azul).

Em Update, vamos adicionar a verificação se o tempo atingiu a duração da cena. Caso sim, volta para a tela inicial.

	void Update () {
		contagem += Time.deltaTime;
		if (contagem >= duracao) {
			Application.LoadLevel(0);
		}
	}

Agora vamos adicionar algumas informações na tela:

void OnGUI() {
		GUI.DrawTexture (new Rect (225, 150, 150, 40), titulo);
		
		GUI.BeginGroup (new Rect(175,200, 250, 150));
		GUI.Label(new Rect(0, 0, 150, 20), "Tutorial de Unity 2D", fonte);
		GUI.Label(new Rect(0, 30, 150, 20), "Criador: Carlos W. Gama", fonte);
		GUI.Label(new Rect(0, 60, 150, 20), "Jogos Indie", fonte);
		GUI.EndGroup();
	}

Em DrawTexture e BeginGroup/EndGroup, já não existe mais nenhum mistério para a gente, já são conhecidos. O DrawTexture exibirá na tela a imagem do seu jogo. BeginGround irá iniciar um grupo onde todo o conteúdo que estiver entre este método e o EndGroup, vão receber a mesma posição.

O que temos de novo aqui é o GUI.Label. Nele passamos a informação da posição e tamanho através do Rect, um texto (Poderia ser uma imagem também, assim como vimos no GUI.Box) e opcionalmente podemos passar o estilo desse texto. Senão passarmos o estilo, ele ficará na cor branca e tamanho de fonte padrão.

Bom, bom. De volta ao Unity, clique sobre a Main Camera na aba Hierarchy e na opção Background, mude o fundo para preto, ao invés daquele azul.

17 - Mudar de fase

Agora clique no Creditos e adicione o Script Creditos, preenchendo os dados:

18 - Mudar de fase

Aproveite também para adicionar a scene ao projeto (File >> Build Settings >> Add Current).

Com os créditos feitos, agora vocês podem criar uma ou n fases que vocês quiserem. Eu vou criar apenas uma única fase chamada Fase02, bem simples usando os conteúdos que já usamos antes, por isso não vou explica-la, ok? Basta apenas criar uma fase simples como quiser e que tenha a bandeira no final da fase:

19 - Mudar de fase

Dica: Se você criar um prefab de Player e joga-lo, terá que jogar também a Vida. Para a câmera terá que adicionar o Script Camera e dar o Zoom. Alguns conteúdos não pegam bem com Prefabs, pois eles precisam colher o conteudo que estão no Hierarchy (Ex: a vida no objeto Player, player no objeto Ghost. Esses tem que setar novamente no script, nesta nova scene, para funcionar direito).

Após criar a sua segunda fase e adiciona-la ao jogo, volte para a Fase01 e vamos criar um novo script chamado Bandeira.
Para este script só vai existir uma única propriedade chamada:

public int proximaFase;

Nessa propriedade vamos passar o index (posição) da fase. Agora vamos criar um OnTriggerEnter2D (Se não tiver adicionar um Box Collider 2D com a poção Is trigger na sua bandeira, faça agora, pois vamos precisar).

void OnTriggerEnter2D(Collider2D colisor) {
		if (colisor.gameObject.tag == "Player") {
			Application.LoadLevel(proximaFase);
		}
	}

Caso seja o Player que toque na bandeira, ele vai seguir para a próxima fase. Com isso nosso tutorial está praticamente pronto, só falta voltar ao script do Player e onde reiniciamos a fase, vamos fazer com que ele vá para a fase de GameOver.

public void PerdeVida(int dano) {
		vidaAtual -= dano;

		if (vidaAtual <= 0) {
			Application.LoadLevel("gameover");
		} 

		if ((vidaAtual * 100 / maxVida) < 30) {
			vida.guiText.color = Color.red;
		}

		vida.guiText.text = "HP: " + vidaAtual + "/" + maxVida;
	}

E com isso finalmente chegamos ao final desse tutorial. Na ultima fase que você tiver criado, basta pedir para que a bandeira chame a fase créditos.

Foi meio intenso o de hoje, não é mesmo? Mas não foi difícil, foi apenas grande, pois inventei de juntar um pouco com as opções GUI dos créditos, menu principal e game over, quando o foco seria apenas a mudança de fase, mas como estamos no final do tutorial, achei legal passar essas informações para vocês.

Se algo não ficou claro, tem dúvidas, críticas ou sugestões? Deixem nos comentários. 😉
E semana que vem, chega o ultimo tutorial!

Player.cs

using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

	public float velocidade;
	public float forcaPulo;
	private bool estaNoChao;
	public Transform chaoVerificador;
	public Transform spritePlayer;
	private Animator animator;

	//Ataque Especial
	public GameObject ataqueEspecial;
	public float duracaoAtaque;
	private float contagemAtaque;

	//Vida
	public GameObject vida;
	public int maxVida;
	private int vidaAtual;

	//Tudo que ocorre quando o personagem e criado
	void Start () {
		animator = spritePlayer.GetComponent ();

		//Vida
		vidaAtual = maxVida;
		vida.guiText.color = new Vector4(0.25f, 0.5f, 0.25f, 1f);
		vida.guiText.text = "HP: " + vidaAtual + "/" + maxVida;
	}
	
	//Tudo que ocorre enquanto o personagem existe
	void Update () {
		Movimentacao();
		Ataque ();
	}

	//Responsavel pela movimentacao do personagem
	void Movimentacao() {

		//Seta no paramentro movimento, um valor 0 ou maior que 0. Ira ativar a condicao para mudar de animacao
		animator.SetFloat("movimento", Mathf.Abs (Input.GetAxisRaw ("Horizontal")));

		//Anda para a direita
		if (Input.GetAxisRaw("Horizontal") > 0 ) {
			transform.Translate (Vector2.right * velocidade * Time.deltaTime);
			transform.eulerAngles = new Vector2(0, 0);
		}

		//Anda para a esquerda
		if (Input.GetAxisRaw("Horizontal") < 0 ) {
			transform.Translate (Vector2.right * velocidade * Time.deltaTime);
			transform.eulerAngles = new Vector2(0, 180);
		}

		//Verifica se esta no chao
		estaNoChao = Physics2D.Linecast(transform.position, chaoVerificador.position, 1 << LayerMask.NameToLayer("Piso"));
		animator.SetBool ("chao", estaNoChao);

		//Responsavel pelo pulo
		if (Input.GetButtonDown("Jump") && estaNoChao) {
			rigidbody2D.AddForce(transform.up * forcaPulo);
		}
	}

	public void PerdeVida(int dano) {
		vidaAtual -= dano;

		if (vidaAtual <= 0) {
			Application.LoadLevel("gameover");
		} 

		if ((vidaAtual * 100 / maxVida) < 30) {
 			vida.guiText.color = Color.red;
 		}
 		vida.guiText.text = "HP: " + vidaAtual + "/" + maxVida;
 	}
 
	public void RecuperaVida(int recupera) {
 		vidaAtual += recupera;
 		if (vidaAtual > maxVida) {
			vidaAtual = maxVida;
		}

		if ((vidaAtual * 100 / maxVida) >= 30) {
			vida.guiText.color = new Vector4(0.25f, 0.5f, 0.25f, 1f);
		}

		vida.guiText.text = "HP: " + vidaAtual + "/" + maxVida;
	}

	void Ataque() {
		if (Input.GetButtonDown ("Fire1")) {
			ataqueEspecial.SetActive(true);
			contagemAtaque = 0f;
			PerdeVida(20);
		}

		if (Input.GetButton ("Fire1")) {
			contagemAtaque += Time.deltaTime;
			if (contagemAtaque >= duracaoAtaque) {
				ataqueEspecial.SetActive(false);
			}
		}

		if (Input.GetButtonUp ("Fire1")) {
			ataqueEspecial.SetActive(false);
		}
	}
}

GameOver.cs

using UnityEngine;
using System.Collections;

public class GameOver : MonoBehaviour {

	public Texture2D background;
	public float duracao;
	private float contagem;

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
		contagem += Time.deltaTime;
		if (contagem >= duracao) {
			Application.LoadLevel(0);
		}
	}

	void OnGUI() {
		GUI.DrawTexture (new Rect(0, 0, Screen.width, Screen.height), background);
	}
}

MenuPrincipal.cs

using UnityEngine;
using System.Collections;

public class MenuPrincipal : MonoBehaviour {

	public Texture2D background;
	public Texture2D titulo;


	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	void OnGUI() {

		GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
		GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);

		GUI.BeginGroup (new Rect(240,150, 120, 120));
		GUI.Box(new Rect(0, 0, 120, 120), "Menu");
		if (GUI.Button (new Rect (20, 30, 50, 20), "Iniciar")) {
			Application.LoadLevel("fase01");
		}
		if (GUI.Button (new Rect (20, 60, 70, 20), "Continuar")) {
			Debug.Log("Fica para o proximo tutorial de Save/Load");
		}
		if (GUI.Button (new Rect (20, 90, 50, 20), "Sair")) {
			Application.Quit();
		}
		GUI.EndGroup();
	}
}

Bandeira.cs

using UnityEngine;
using System.Collections;

public class Bandeira : MonoBehaviour {
	public int proximaFase;

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	void OnTriggerEnter2D(Collider2D colisor) {
		if (colisor.gameObject.tag == "Player") {
			Debug.Log ("Tocou");
			Application.LoadLevel(proximaFase);
		}
	}
}

Creditos.cs

using UnityEngine;
using System.Collections;

public class Creditos : MonoBehaviour {

	public Texture2D titulo;
	public float duracao;
	private float contagem;
	private GUIStyle fonte;	
	// Use this for initialization
	void Start () {
		fonte = new GUIStyle();
		fonte.fontSize = 20;
		fonte.normal.textColor = Color.gray;
	}
	
	// Update is called once per frame
	void Update () {
		contagem += Time.deltaTime;
		if (contagem >= duracao) {
			Application.LoadLevel(0);
		}
	}

	void OnGUI() {
		GUI.DrawTexture (new Rect (225, 150, 150, 40), titulo);
		
		GUI.BeginGroup (new Rect(175,200, 250, 150));
		GUI.Label(new Rect(0, 0, 150, 20), "Tutorial de Unity 2D", fonte);
		GUI.Label(new Rect(0, 30, 150, 20), "Criador: Carlos W. Gama", fonte);
		GUI.Label(new Rect(0, 60, 150, 20), "Jogos Indie", fonte);
		GUI.EndGroup();
	}
}

Parte 11 – Áudio

Índice Unity 2D

Parte 13 – Save e Load

Criador do Jogos Indie, amante de jogos, terror, música, anime e programação. Estudante de mestrado com foco em jogos na educação. Louco por Resident Evil e... sei lá, acho que é isso O.o

41 comments

  1. Paulo disse:

    Muitos parabéns e Obrigado por mais um ótimo tutorial.

  2. Romério disse:

    Ai cara no final deste incrível tutorial você vai disponibilizar o jogo para nós?

  3. Victor Hugo disse:

    Fala ae Carlos!!! Você vai mesmo fazer um post inteiro só para GUI? *-*
    =D faz! =D faz! =D faz! =D

  4. Karfann Nacif disse:

    Bom d+!!! Aprendi mto!
    parabens Carlos!

  5. Matheus disse:

    Passando só para dar meus parabéns pela sua dedicação!!! =]

  6. Bruno disse:

    Olá, n sei se lembra de mim(eu estava transformando os tutorias em videos(estou demorando um pouco)), quando eu comecei a fazer os videos me interessei mais por jogo 2D, assim levando com q eu pedisse este favor! Será que não teria como abrir tutorias para rpg maker! seria muito bom 🙂

  7. Antonio disse:

    Ola Carlos! Obrigado por mais um excelente tutorial!!

    Uma duvida, se quisermos aumentar o tamanho das letras “Menu”, “Iniciar”, “Continuar”, “Sair”, como fazemos?

    Obrigado!

    • Opa, Antonio.

      É da mesma forma que a gente fez com os créditos ou seja:

      var fonte = new GUIStyle ();
      fonte.fontSize = 20;

      GUI.Button (new Rect (20, 30, 50, 20), “Iniciar”, fonte);

      Porém, se você fizer isso, vai estar resetando o padrão de botão (Box, fonte branca…). Se você quiser manter o padrão e só aumentar a fonte, ao iniciar o GUIStyle você diz para ele usar o padrão de template do botão, assim:

      var fonte = new GUIStyle (GUI.skin.button);
      fonte.fontSize = 20;

      GUI.Button (new Rect (20, 30, 50, 20), “Iniciar”, fonte);

      ^^

  8. christian disse:

    Oii eu não estou conseguindo passar de fase a minha bandeira fica se mexendo e quendo vc passa por ela eu não consigo passar de fase, por que será?

    • Alvaro disse:

      Bem eu mexi altura e largura na hora da divisão do sprite ajudou bastante ela parou de se mover só da umas tremidinhas mas nem da para perceber durante o jogo. Você colocou o box colider2d na bandeira, verifica se setou o is trigger e se o script esta adicionado a bandeira. Há e não esqueça de adicionar a cena no build. Se não for nada disto espera pelo Carlos.

      • Bom trabalho Alvaro ^^

        Quando as suas tremidinhas provavelmente é por conta do tamanho dos sprites cortados. Eles tem que ficar mais ou menos do mesmo tamanho (width e height no sprite editor), do contrário se o sprite_flag_0 e o sprite_flag_1 tiverem tamanhos diferentes, ele vai dar esse tremidinha porque o ponto central da imagem já não será o mesmo.

    • Vixe, foi mal não tinha visto seu comentário =S

      Só vi agora por causa do Alvaro. Como o servidor não atual não esta me mandando email, nem sempre vejo os comentários de vocês foi mal >.< Verifica essas coisas ai que o Alvaro falou, que está tudo certinho ^^

  9. thawan disse:

    opa! então, aqui deu um pequeno erro falando o seguinte: “Assets/Scripts/Menu.cs(16,17): error CS0029: Cannot implicitly convert type `void’ to `bool'”

    de acordo com ele o erro está aqui: ” if (GUI.DrawTexture (new Rect (175, 180, 50, 45), btnPlay)) {

    Application.LoadLevel(“level1″);

    }”

    mas não encontrei nenhum erro ‘–

  10. thawan disse:

    falta de atenção é foda ‘– button e não drawtexture

  11. thawan disse:

    Então, meu problema é o seguinte, no meu projeto tem um GameObject com um GUItext recorde, mas agora que coloquei o GameObject com o menu, o meu recorde não aparece mais, o que eu faço?

  12. carloswgama disse:

    eu não entendi o que quis dizer com GameObject com o menu O.o

  13. thawan disse:

    kkkkkkkkkkkk teria alguma rede social que eu poderia entrar em contato pra mostrar exatamente meu problema?

  14. João Oliveira disse:

    Iae Carlos, Tranquilo ? Como eu faço para deixar a tela GameOver mais tempo, pq tipo, ela fica meio-segundo e troca para o menu, queria deixa-la mais tempo, pelo menos uns 7 segundos. Como eu faço isso ?

  15. carloswgama disse:

    altera o valor da variável duracao para 7 lá no objeto que tiver com o script de GameOver

  16. Gutemberg disse:

    Quando eu adiciono a img desert ao background e a img jogos indie no titulo não aparece nada na tela scene nem na game,isso acontece tbm com o gameover e creditos.Tem como resolver?

    • Então Gutemberg. Atualmente a gente não usa mais esses comandos na versão, embora ela ainda seja ativa.

      Utilizamos o Canvas que é beeeeem melhor que o GUI.O próximo tutorial já será com o canvas.

      Mas em relação a esse caso, a solução é bem simples:

      Basta você por o código do titulo após o background assim:
      GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background); //Vem primeiro
      GUI.DrawTexture(new Rect(225, 50, 150, 40), titulo); //Fica por cima dos anteriores

      O código que estiver abaixo sempre vai ficar por cima dos anteriores

  17. Gutemberg disse:

    Meu código não deu erro ta igual ao do site porem nada aparece nem na aba scene ou game tem como me enviar esse codigo com canvas?
    using UnityEngine;
    using System.Collections;

    public class MenuPrincipal : MonoBehaviour {

    public Texture2D background;
    public Texture2D titulo;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    void OnGUI() {

    GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), background);
    GUI.DrawTexture (new Rect (225, 50, 150, 40), titulo);

    GUI.BeginGroup (new Rect(240,150, 120, 120));
    GUI.Box(new Rect(0, 0, 120, 120), “Menu”);
    if (GUI.Button (new Rect (20, 30, 50, 20), “Iniciar”)) {
    Application.LoadLevel(“fase01”);
    }
    if (GUI.Button (new Rect (20, 60, 70, 20), “Continuar”)) {
    Debug.Log(“Fica para o proximo tutorial de Save/Load”);
    }
    if (GUI.Button (new Rect (20, 90, 50, 20), “Sair”)) {
    Application.Quit();
    }
    GUI.EndGroup();
    }
    }

  18. Onde eu acho a scene já criada pra jogar dentro da pasta scene?

    • Não tem um local exato. Isso vai depender de onde você a salvou. Você a salva em File >> Save Scene. Caso tenha criado outra scene sem salvar a anterior, então você perdeu tudo.

  19. Fiz o que você disse mas o background e o logo não apareceu na tela, pq? Na nova versão do unity é diferente? Tem que adicionar algo a +? Need Help, pls..

  20. posso usar esse background em meu jogo?

    • Então. Se você for fazer ele de graça, provavelmente não terá problema. Inclusive já vi jogos usando essa imagem.

      Agora se você quiser comercializar seu jogo, é bom dá uma buscada por ela no google e ver se acha os direitos autorais dela.

  21. rafoso disse:

    Vlws!!!

  22. Jose Soares Ramos Junior disse:

    Opa Carlos, amigo será se vc pode me ajudar…. fui abrir o unity e ele estava com o esquema de cores totalmente alterado, tanto o programa como as sprits ficaram com cores invertidas o que era vermelho esta azul, onde posso arrumar isso?

  23. Jose Soares Ramos Junior disse:

    Não é paga, já desinstalei e reinstalei e continuou,,, desinstalei e limpei tudo para ver, qualquer coisa formato o pc rsr

Deixe uma resposta

Parceiros

Steam Brasil LoboLimão Centro RPG Lab Indie
Mundo Gamer PodTerror

Anunciantes

Aglomerando - Agregador de conteúdo
Uêba - Os Melhores Links GeraLinks - Agregador de links Piadas Idiotas - São idiotas mas o faz rir Tedioso: Os melhores links LinkLog MeusLinks.com - Informação e conteúdo todos os dias para você! Agregador de Links - Madruga Links 4Blogs - Agregador de conteúdo Está no seu momento de descanso né? Entao clique aqui!