sexta-feira, 10 de maio de 2013

Unity 3D - Jogo em Split Screen

Neste artigo vou criar um pequeno jogo para dois jogadores humanos em ecrã dividido utilizando o Unity 3D.

Para começar vou mostrar o resultado final.


Na parte de cima da imagem anterior temos a composição da cena e na parte de baixo a imagem que os jogadores vão ver quando jogarem.

Primeiro vamos preparar a cena e depois vamos ao código, assim adicione um plano para servir de chão e depois defina uma textura a aplicar.

Altere o tamanho do plano, nomeadamente a largura nos eixos x e z para acomodar os dois jogadores.

Agora que temos o campo de jogo vamos tratar dos jogadores, para isso adicione uma capsule.

Agora vamos posicionar esta capsula no lado esquerdo do ecrã.

De seguida vamos posicionar a camera que temos na cena atrás da capsula, assim:


Continuamos a preparar o jogador do lado esquerdo alterando a sua cor e definindo um ponto de disparo à sua frente, para isso vamos utilizar um ponto vazio.


O próximo passo é muito importante porque vai permitir organizar o nosso trabalho por isso muita atenção.

Primeiro alteramos o nome dos objetos para os podermos identificar mais facilmente, assim, Capsule passa a graficos, GameObject passa ponto_disparo e Main Camera a Camera_esquerda.

De seguida vamos criar um novo ponto vazio e arrastar para dentro desse ponto a capsula e o ponto de disparo. Agora mudamos o nome do novo ponto vazio para jogador. No final temos algo assim:

Agora a camera, vamos às propriedades e alteramos a largura para 0.5, o campo a alterar é o w (width). Assim ficamos com metade do ecrã preenchido com a imagem desta camera a outra metade vai ser preenchida com a outra.

Então para preencher a outra metade duplicamos a camera e alteramos o nome para camera_direita, de seguida arrastamos para a direita e rodamos a camera para mostrar o jogador a partir do outro lado do plano.
Agora basta alterar a posição da imagem para 0.5, a propriedade é X.


Agora já temos duas cameras vamos criar o código para os jogadores.

Crie um javascript com o nome jogador.js

Primeiro as variáveis, como vamos utilizar o mesmo código para os dois jogadores vamos criar variáveis para configurar as teclas que controlam os jogadores a partir do inspector.

public var tecla_esquerda : String = "z";
public var tecla_direita : String = "x";
public var tecla_dispara : String = "c";

As variáveis para associar ao jogador e a velocidade de movimento:
public var jogador : CharacterController;
public var velocidade : float = 0.5;

E algumas variáveis para o modelo da bola que vamos atirar:

public var modelo_bala : GameObject;

O ponto de disparo:
public var ponto_disparo : GameObject;

A força:
public var forca : float=200.0;
public var forcaTotal : float =0;
public var forcaMax : float= 1000;
public var barraForca : Texture;
public var posBarra : int=0;
private var temp : float;
public var boladas : float = 0;
public var posTexto : int=0;

A cor do nosso jogador, que também vamos atribuir à bola:
public var cor : Color = Color.red;

De seguida apresento a função que atualiza a interface, nós vamos mostrar duas informações ao utilizador: a força com que ele vai atirar a bola (esta força é controlada pelo tempo que fica a carregar na tecla de disparo) e quantas vezes já levou com a bola.

function OnGUI(){
    if(forcaTotal<0) temp = forcaTotal * (-1);
    else temp=forcaTotal;
   
    if(temp>0){
        GUI.DrawTexture(Rect(posBarra,10,temp/forcaMax*100,10),barraForca);
    }

    GUI.TextArea(Rect(posTexto,20,30,20),boladas.ToString());
}

 A função mais importante:
function Update () {

    if (Input.GetKey(tecla_esquerda)) jogador.transform.position.z +=(velocidade*Time.deltaTime);
    if (Input.GetKey(tecla_direita)) jogador.transform.position.z -=(velocidade*Time.deltaTime);
    if (Input.GetKey(tecla_dispara)){
        forcaTotal += (forca*Time.deltaTime);
    }
    if(Input.GetKeyUp(tecla_dispara)){
        var bala : GameObject;
        bala=Instantiate(modelo_bala,ponto_disparo.transform.position,this.transform.rotation);
        bala.gameObject.renderer.material.color = cor;
       
        bala.rigidbody.AddForce(Vector3(forcaTotal,0,0));
        forcaTotal=0;
    }
   
}

Nesta função controlamos a posição do jogador bem como a força a atribuir à bola quando a lançamos.

Agora vamos criar uma função que vai ser chamada sempre que a bola acertar no jogador:

function bolada(x : float){

    boladas += x;
   
}

Passamos à bola, para isso adicionamos uma esfera e associamos-lhe um rigidbody.

Agora criamos outro ficheiro javascript com o nome bola.js, neste colocamos o seguinte código:

var tempo : float =4.0;

function Start () {

    Destroy(this.gameObject,tempo);
}

function OnCollisionEnter(col:Collision){
    if(col.gameObject.tag=="Player"){
        col.gameObject.SendMessage("bolada",1.0,SendMessageOptions.DontRequireReceiver);
        Destroy(this.gameObject);
    }
}

A função start é utilizada para controlar o tempo que a bola vai viver, depois temos a função que deteta as colisões e chama a função para contar mais um tiro certeiro.

Agora associamos este código à esfera e criamos um prefab com a esfera, para isso basta arrastar da hierarchy para a pasta project. Depois apagamos da hierarchy a cópia uma vez que vamos criar cópias por código.

Também pode criar um material para definir as propriedades da bola.

Agora duplicamos o jogador e arrastamos para o outro lado do ecrã, isto já com o script jogador.js associado. De seguida configuramos o script através do inspector para podermos definir teclas diferentes para os dois jogadores.

O jogador da direita tem de ser rodado para ficar de frente para o outro jogador, para isso devemos rodar o ponto vazio criado.

Outro ponto importante é o código que deve ser associado ao elemento gráfico do jogador e não ao ponto vazio.

Para terminar de preparar os jogadores devemos definir a tag Player nos dois jogadores.

A velocidade e a força fica ao critério de cada um basta testar e afinar até atingir os valores desejados.

Os meus valores ficaram assim:



Antes de terminar podemos adicionar algumas luzes e definir alguns pormenores visuais como um rasto para as bolas ou sons.

O projeto pode ser retirado aqui.