Danielle Teixeira
Desenvolvedora front-end e mobile intusiasta IoT e UX/UI Design, compartilho minhas experiências profissionais
Alunos:
Alex Costa
Danielle Teixeira
Paulo
Professor: Arivan
Esp: Desenvolvimento de aplicações para Dispositivos móveis
using UnityEngine;
using System.Collections;
/**
* Componente para fazer a câmera seguir o jogador.
* Necesário acoplar esse script a camera e definir o objeto follow.
*/
public class CameraController : MonoBehaviour {
public GameObject follow;
// LateUpdate é chamado após todo processamento da
// física ser realizado.
void LateUpdate () {
// Posição do objeto seguido.
Vector3 followPosition = follow.transform.position;
// Nova posição da câmera.
Vector3 cameraPosition = new Vector3 (followPosition.x, followPosition.y,
transform.position.z);
// Atualiza a posição da câmera.
transform.position = cameraPosition;
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
/**
* Controla o fluxo do jogo (navegação entre fases e menu).
*/
public class GameManager : MonoBehaviour
{
// Total de fases no jogo.
const int TOTAL_LEVELS = 3;
// Fase atual do jogador.
private int level;
// Interface de fim de jogo.
private GameObject endGameMenu = null;
// Implementa o padrão SINGLETON.
// Precisamos de apenas uma instância do GameManager acessível
// em todo o jogo.
public static GameManager instance = null;
private int totalPickups = 0;
private int totalPontos = 0;
private Text totalPontosText = null;
int totalLife = 3;
void Awake ()
{
//Check if instance already exists
if (instance == null) {
//if not, set instance to this
instance = this;
}
//If instance already exists and it's not this:
else if (instance != this) {
//Then destroy this. This enforces our singleton pattern, meaning there can only ever be one instance of a GameManager.
Destroy (gameObject);
}
//Sets this to not be destroyed when reloading scene
DontDestroyOnLoad (gameObject);
}
// Chamado pela unity sempre que uma cena acaba
// de ser carregada.
void OnLevelWasLoaded (int level)
{
// Cria o menu de fim de jogo.
CreateEndGameMenu ();
// Oculta o menu de fim de jogo.
endGameMenu.SetActive (false);
}
// Cria dinamicamente o menu de fim de jogo.
// Um Prefab do menu foi previamente criado e
// encontra-se na pasta Prefabs.
private void CreateEndGameMenu ()
{
// Recupera uma referência ao modelo do prefab.
GameObject EndMenu = Resources.Load<GameObject> ("Prefabs/EndMenu");
// Instancia o modelo (adicionando a cena) e guardando uma referência
// para ele na variável engGameMenu.
endGameMenu = Instantiate (EndMenu, new Vector3 (1, 1, 1), Quaternion.identity) as GameObject;
// Recupera referências aos botões do menu associando as respectivas
// ações de clique.
Button nextLevelBtn = GameObject.Find ("NextLevelBtn").GetComponent<Button> ();
nextLevelBtn.onClick.AddListener (() => NextLevel ());
Button restartLevelBtn = GameObject.Find ("RestartLevelBtn").GetComponent<Button> ();
restartLevelBtn.onClick.AddListener (() => RestartLevel ());
Button menuPrincipalBtn = GameObject.Find ("MenuPrincipalBtn").GetComponent<Button> ();
menuPrincipalBtn.onClick.AddListener (() => MenuPrincipal ());
this.totalPontosText = GameObject.Find ("pontosText").GetComponent<Text> ();
totalPontosText.text = "Total de Pontos : " + totalPontos.ToString ();
}
// -----------------------------------------totalPickups
// Inicia um novo jogo.
public void NewGame ()
{
level = 0;
NextLevel ();
}
// Reinicia a fase atual.
public void RestartLevel ()
{
SceneManager.LoadScene ("mapload");
this.totalPontos -= totalPickups;
}
// Avança para a próxima fase.
public void NextLevel ()
{
level++;
if (level <= TOTAL_LEVELS) {
SceneManager.LoadScene ("mapload");
}
}
// Encerra a fase atual, exibindo
// o menu de fim de jogo.
public void EndLevel (int timeLeft)
{
if (level >= TOTAL_LEVELS)
SceneManager.LoadScene ("menu");
else if (endGameMenu != null) {
totalPontos = (50 * (totalPickups)) + ((30 - timeLeft) * 10);
this.totalPontosText.text = "Total de Pontos : " + totalPontos.ToString ();
endGameMenu.SetActive (true);
}
}
public void MenuPrincipal ()
{
SceneManager.LoadScene ("menu");
this.totalLife = 3;
}
// Sai do jogo.
public void QuitGame ()
{
Application.Quit ();
}
public int CurrentLevel ()
{
return this.level;
}
public bool OnCollision (Collision2D other, int pickupsCounter)
{
// Se todos pickups foram coletados encerra a fase.
// Isso deve ser removido, visto que a fase deverá
// ser encerrada quando o UFO for direcionado para o
// portal.
if (pickupsCounter >= totalPickups) {
return true;
} else {
return false;
}
}
public void SetTotalPickups (int length)
{
this.totalPickups = length;
}
public void decrementLife ()
{
this.totalLife--;
}
public int lifes ()
{
return this.totalLife;
}
}
using UnityEngine;
using System.Collections;
using System.Text.RegularExpressions;
/**
* Cria um level dinamicamente a partir de um arquivo de texto.
* O arquivo representa uma matriz onde cada elemento representa
* um tile que irá compor o cenário.
*/
public class MapLoader : MonoBehaviour
{
void Start ()
{
CreateLevel (GameManager.instance.CurrentLevel ());
// Identifica quantos pickups a fase tem.
GameManager.instance.SetTotalPickups (GameObject.FindGameObjectsWithTag ("Pickups").Length);
}
// Cria os tiles do level a partir
// da matriz carregada do arquivo de texto.
void CreateLevel (int level)
{
string[][] data = LoadLevelData (level);
for (int y = 0; y < data.Length; y++) {
for (int x = 0; x < data [0].Length; x++) {
switch (data [y] [x]) {
case "1":
CreateTile ("Wall" + Random.Range (0, 3), x, y);
break;
case "0":
CreateTile ("Floor" + Random.Range (0, 3), x, y);
break;
case "+":
CreateTile ("Portal", x, y);
break;
case "-":
CreateTile ("FloorPortal", x, y);
break;
case "x":
CreateTile ("Trap", x, y);
break;
case "@":
CreateTile ("Floor" + Random.Range (0, 3), x, y);
CreateTile ("Pickup", x, y);
break;
}
}
}
}
// Cria um tile de um dado tipo em uma dada
// posição.
// Sugere-se altear o parâmetro "string prefab"
// para um array de prefabs, e selecionar um
// prefab aleatório dentro desse array.
// Assim a fase fica mais diversificada.
GameObject CreateTile (string prefab, int x, int y)
{
GameObject Prefab = Resources.Load<GameObject> ("Prefabs/" + prefab);
Instantiate (Prefab, new Vector3 (x - 4, y, 0), Quaternion.identity);
return Prefab;
}
// Retorna a matriz que representa o level informado.
// Por padrão os arquivos de level devem se chamar
// level1, level2, etc.
string[][] LoadLevelData (int level)
{
// Caminho do arquivo dentro da pasta "Resources".
string path = "Maps/level" + level;
// Carrega o arquivo.
TextAsset textFile = (TextAsset)Resources.Load (path);
// Recupera o texto do arquivo.
string text = textFile.text;
// Realiza splits transformando o texto em
// uma matriz.
string[] lines = Regex.Split (text, "\n");
int rows = lines.Length;
string[][] data = new string[rows][];
for (int i = 0; i < rows; i++) {
string[] lineParts = Regex.Split (lines [i], " ");
data [(rows - 1) - i] = lineParts;
}
return data;
}
}
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
/**
* Script de controle do UFO.
*/
public class Player : MonoBehaviour
{
// Velocidade de movimentação do UFO.
public float speed;
// Guarda o total de pickups na fase, para verificar
// se a fase foi concluída. Na versão final do jogo/
// isso deve ser removido (a fase será concluída quando
// o jogador acessar o portal).
private int totalPickups;
// Conta quantos pickups o jogador pegou.
private int pickupsCounter;
// Guarda uma referência ao componente Rigidbody2d do jogador,
// utilizado para movimentação.
private Rigidbody2D rb2d;
// Guarda uma referência ao componente Animator do jogador,
// usado para animação.
// Atenção: o animator funcionará apenas na cena "animation",
// onde ele foi configurado no UFO!
private Animator animator;
// Guarda uma referência ao AudioSOurce que emite o som
// de coleta de pickups.
// public AudioSource collectAudio;
public AudioSource collectAudio;
// Guarda uma referência ao componente de interface
// que exibe a quantidade de pickups coletados.
public Text countText;
public Text timerText;
private float timeLeft = 30;
bool freezerLevel = false;
// Use this for initialization
void Start ()
{
// Recupera as referências.
rb2d = GetComponent<Rigidbody2D> ();
animator = GetComponent<Animator> ();
// Inicia com 0 pickups.
pickupsCounter = 0;
// Atualiza o texto de exibição da quantidade de pickups.
updatePickupsText ();
for (int f = 3; f > GameManager.instance.lifes (); f--) {
Image manLife = GameObject.Find ("manLife" + f).GetComponent<Image> ();
manLife.enabled = false;
}
}
void Update ()
{
if (!this.freezerLevel) {
timeLeft -= Time.deltaTime;
timerText.text = "Tempo: " + Mathf.RoundToInt (timeLeft).ToString ();
if (timeLeft < 0) {
this.freezerLevel = true;
// GameOver();
Image manLife = GameObject.Find ("manLife" + GameManager.instance.lifes ()).GetComponent<Image> ();
GameManager.instance.decrementLife ();
manLife.enabled = false;
if (GameManager.instance.lifes () > 0) {
GameManager.instance.RestartLevel ();
} else {
GameManager.instance.MenuPrincipal ();
}
}
}
}
// Chamado em intervalos fixos.
// Uso: atualizacao física.
void FixedUpdate ()
{
if (rb2d) {
// Armazena o vetor direção do movimento do UFO.
Vector2 movement;
// Diretivas de compilãção.
#if UNITY_STANDALONE || UNITY_WEBPLAYER
// Compilação PC/Desktop
// Recupera as direções horizontal/vertical
// dos dispositivos de entrada.
float vHorizontal = Input.GetAxis ("Horizontal");
float vVertical = Input.GetAxis ("Vertical");
movement = new Vector2 (vHorizontal, vVertical);
// Bônus!
// Forma alternativa de mover o UFO.
// Descomente e teste! Use o mouse!
/*
if (Input.GetMouseButtonDown (0))
{
Vector3 newPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
newPosition.z = transform.position.z;
MoveTo (newPosition);
}
*/
#elif UNITY_IOS || UNITY_ANDROID || UNITY_WP8 || UNITY_IPHONE
// Compilação Mobile
// Recupera as direções horizontal/vertical do
// acelerômetro.
movement = new Vector2(Input.acceleration.x, Input.acceleration.y);
#endif
rb2d.AddForce (movement * speed);
}
}
// Chamado quando o UFO colide com algum objeto
// que possua um Collider setado como isTrigger.
void OnTriggerEnter2D (Collider2D other)
{
// Verifica se o objeto colidido possui a tag
// "Pickups".
if (other.gameObject.CompareTag ("Pickups")) {
animator.SetTrigger ("damage");
// Remove o pickup
other.gameObject.SetActive (false);
// Incrementa o contado de pickups.
pickupsCounter++;
// Reproduz o som de pickups.
collectAudio.volume = 1;
collectAudio.Play ();
// Atualiza o texto com a contagem de pickups
// coletados.
updatePickupsText ();
}
}
// Chamado quando o UFO colide com algum objeto
// que possua um Collider não setado como isTrigger.
void OnCollisionEnter2D (Collision2D other)
{
if (GameManager.instance.OnCollision (other, pickupsCounter) && other.gameObject.CompareTag ("Portal")) {
{
// Fim de fase.
// Remove o rb2d do UFO. Assim
// ele não se moverá mais.
Destroy (rb2d);
// Inicia um método em uma coroutine.
// Uma coroutine pode ser interrompida e
// continuada a partir de condições que determinamos.
StartCoroutine (EndLevel ());
this.freezerLevel = true;
}
}
Debug.Log (other.gameObject.tag);
// Dispara a animação de dano.
// Assim a animação é disparada sempre
// que o UFO colide com uma parede.
// Atenção: o animator funcionará apenas na cena "animation",
// onde ele foi configurado no UFO!
animator.SetTrigger ("damage");
}
// Coroutine de fim de level.
IEnumerator EndLevel ()
{
// Aguarda 1 segundos.
yield return new WaitForSeconds (1);
// Exibe o menu.
GameManager.instance.EndLevel (Mathf.RoundToInt (timeLeft));
}
// Atualiza o texto de interface.
void updatePickupsText ()
{
countText.text = "Ouros: " + pickupsCounter;
}
// Bônus!
// Forma alternativa de mover o UFO.
// Descomente e teste! Use o mouse!
/*
void MoveTo(Vector3 position)
{
StopCoroutine ("MoveToC");
StartCoroutine ("MoveToC", position);
}
IEnumerator MoveToC(Vector3 target)
{
while (Vector3.Distance (transform.position, target) > 0.1f)
{
// Lerp gera uma interpolação baseada na distância
// e no tempo passado.
transform.position = Vector3.Lerp (transform.position, target, Time.deltaTime);
// Ao retornar null a partir de uma Coroutine, ela será
// continuada automaticamente no próximo Game Loop!
yield return null;
}
}
*/
}
using UnityEngine;
using System.Collections;
public class Portal : MonoBehaviour
{
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
void OnCollisionEnter (Collision col)
{
Debug.Log (col.gameObject.tag);
}
}
ROTATor
using UnityEngine;
using System.Collections;
/**
* Gira um objeto na velocidade informada.
* Util para pickups do jogo!
*/
public class Rotator : MonoBehaviour {
public float speed = 45;
// Update is called once per frame
void Update ()
{
// Aplica a rotação apenas no eixo Z.
// Usa o tempo como referência pois desejamos
// que a rotação possua a velocidade de
// speed graus por segundo!
transform.Rotate (new Vector3(0,0,speed)*Time.deltaTime);
}
}
using UnityEngine;
using System.Collections;
/**
* Componente para fazer a câmera seguir o jogador.
* Necesário acoplar esse script a camera e definir o objeto follow.
*/
public class CameraController : MonoBehaviour {
public GameObject follow;
// LateUpdate é chamado após todo processamento da
// física ser realizado.
void LateUpdate () {
// Posição do objeto seguido.
Vector3 followPosition = follow.transform.position;
// Nova posição da câmera.
Vector3 cameraPosition = new Vector3 (followPosition.x, followPosition.y, transform.position.z);
// Atualiza a posição da câmera.
transform.position = cameraPosition;
}
}
GAMEMENU
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
/**
* Responde a interações nos botões do menu inicial.
* 1) Esse componente precisa ser vinculado a algum game object
* 2) Os métodos desse component devem ser vinculados aos botões através do
* editor.
*/
public class GameMenu : MonoBehaviour
{
// Clique em "Novo Jogo".
public void NewGame ()
{
GameManager.instance.NewGame ();
}
// Clique em "Sair"
public void QuitGame ()
{
GameManager.instance.QuitGame ();
}
}
By Danielle Teixeira
Unity 2d
Desenvolvedora front-end e mobile intusiasta IoT e UX/UI Design, compartilho minhas experiências profissionais