Iniciando no Xamarin CocosSharp – Parte 01

Hoje estou dando inicio a uma série de 16 artigos (Pode ser que seja um pouquinho mais…) minha meta é criar vários tutorais e de forma gradativa mostrar os principais recursos e potencial do Xamarin CocosSharp. Estou considerando que você já é um desenvolvedor C# e  que deseja começar a criar games 2D.  Se essa é sua situação, você está no lugar certo!  Caso não seja um desenvolvedor C#, recomendo que aprenda C# e depois retorne aqui =)

Minha meta é postar 1 ou 2 artigos por semana e assim fechar essa série + ou – 3 Meses.

Vamos ver de forma  detalhada como criar alguns games usando como base os exemplos da documentação do CocosSharp. Assim conheceremos vários estilos de jogos 2D. No final teremos nosso “TCC”, =) e vamos criar um game mais completo com fases e tudo mais. Esse game irá ser baseado em mapas (Ainda estou bolando a temática). Enfim, chega de bla bla bla e vamos ao primeiro post onde iremos criar o PalitoBall.

Mas antes, veja o artigo: Instalando o CocosSharp no Visual Studio 2015 Community

Iremos criar um game básico e no final teremos algo assim:

Criando o projeto

Abra seu visual studio (VS) e crie um projeto “CocosSharp Game (Xamarin.forms Portable).

Após seu projeto ser criado, ele ficará assim:

Note que a estrutura é similar ao um projeto Xamarin Forms padrão. Não vou aqui entrar em detalhes sobre a abordagem Xamarin e Xamarin forms, mas você pode ter mais informações sobre ele nesse post do amigo Willian.

Xamarin ou Xamarin.Forms? Qual a melhor abordagem Xamarin para desenvolvimento do meu aplicativo móvel?

Vamos entender o que o VS criou.  São basicamente foram 4 projetos.

  • PalitoBall (Portable): Que terá todo o código do jogo e será compartilhado nas várias plataformas de nosso game;
  • PalitoBall.Droid: Nossa versão Android do game;
  • PalitoBall.iOS: Nossa versão para Iphone;
  • PalitoBall.WP81: Nossa versão Windows

Olhando nosso projeto PalitoBall.Droid temos uma pasta chamada Assets/Content . Nessa pasta irão ficar todos os arquivos não gerados pelo programador como: Imagens, musicas, arquivos de controle, IA, etc..

O PalitoBall terá básicamente dois arquivos. As imagens ball.png e paddle.png

No final do post terá um link para o GitHub do PalitoBall (PB) ou baixe o Content.zip clicando aqui .

Devemos colocar essas duas imagens dentro da pasta Content de cada plataforma que estamos implementando. Então teremos que colocar no projeto Droid, iOS e WP81.

Se você colocar as imagens diretamente nas pastas do projeto o VS não irá reconhecer elas.

Nesse caso clique com o botão direito do mouse sobre a imagem e selecione a opção “Include in Project”. Pronto sua imagem está no projeto VS, faça isso para demais projetos.

Você deve estar se perguntando: Qual o motivo que leva eu ter que colocar as mesmas imagens em todos os projetos? Esse projeto não é Cross-platform ?

Calma!   =)   Sim o projeto é Cross-platform!!!!

Cada plataforma pode precisar de formato de arquivos específicos. Além de que cada plataforma tem um “Build action” próprio. Por exemplo, no Android usamos o AndroidAsset para realizar o “Build action”, já no iOS utilizamos o BundleResource. Para evitar problemas, deixamos nosso content original em cada plataforma, assim no processo de build cada plataforma irá tratar os arquivos a sua maneira. Mais adiante na serie falaremos mais sobre essa característica.

O CocosSharp fornece uma série de classes para trabalharmos os recursos visuais ou de lógica. No PalitoBall iremos usar as seguintes Classes:

  • CCNode: Classe base para toda a parte visual do CocosSharp.  A CCNode tem um AddChild que permite construir hierarquias pai/filho. Todas as classes abaixo herdam de CCNode.
  • CCScene: É a base para tudo que será visual no jogo. nada será visível no jogo se não fizer parte da CCScene.
  • CCLayer:  Um contêiner para elementos visuais. Que trabalha em camadas.
  • CCSprite: Permite exibir uma imagem ou uma parte da imagem. Além de fornecer uma série de efeitos visuais.
  • CCLabel: Exibi um texto na tela.

Para entender como os diferentes tipos são usados vamos considerar um único CCSprite no PalitoBall. Os elementos visuais serão adicionados a um CCLayer, e a árvore visual deve ter um CCScene em sua raiz. Portanto, a relação pai / filho para um único CCSprite seria CCScene> CCLayer> CCSprite.

Para mais informações sobre essa parte teórica do CocosSharo recomendo ver minha palestra do InteropMix 2016. Clique aqui para acessar.

Vamos ao código…. (Agora vai ficar bonito!!!!)

Inicialmente vamos definir uma cor de fundo para o PB, que será preto. Adicionaremos uma única CCSprite na tela. Vamos alterar o nosso GameLayer.cs que está em nosso projeto Portable.  Nosso código deve ficar assim:

using System;
using System.Collections.Generic;
using CocosSharp;

namespace PalitoBall
{
  public class GameLayer : CCLayerColor
{
  CCSprite paddleSprite;

public GameLayer() : base(CCColor4B.Black)
{

  paddleSprite = new CCSprite("paddle");//Nossa Imagem
  paddleSprite.PositionX = 100;
  paddleSprite.PositionY = 100;
  AddChild(paddleSprite);

}

protected override void AddedToScene()
{
  base.AddedToScene();
  // Mapear os limites de nossa imagem
  CCRect bounds = VisibleBoundsWorldspace;
  // registrar o touch evento
  var touchListener = new CCEventListenerTouchAllAtOnce();
  touchListener.OnTouchesEnded = OnTouchesEnded;
  AddEventListener(touchListener, this);
}

void OnTouchesEnded(List<CCTouch> touches, CCEvent touchEvent)
{
  if (touches.Count > 0)
  {
  // Perform touch handling here
  }
}
}
}

O código acima cria um único CCSprite e adiciona como um filho do GameLayer. O CCSprite construtor permite definir o arquivo de imagem para usar como uma string. Nosso código diz ao CocosSharp para procurar um arquivo chamado “paddle” (Não informamos a extensão do arquivo). CocosSharp irá procurar todos os nomes de arquivos paddle na pasta de conteúdo raiz (Content). Sempre usar letra minusculas e sem acentuação.

Antes de fazer o build sete o projeto PalitoBall.Droid como StartUp da Solution

Agora vamos dar Build e ver como está ficando

.

Que legal, compilou…rsrs

Agora vamos definir que PB apenas funcionem em retrato. Essa definição é feita e cada projeto.

No projeto iOS, abre o arquivo “info.plist”, irá abrir uma janela de edição. Deixe marcada a opção “Portrait”.

No projeto .Droid edite o arquivo MainActivity.cs e na Activity adicione ” ScreenOrientation = ScreenOrientation.Portrait”. Deve ficar assim:

O PB se baseado em coordenadas X e Y (Lembra do plano cartesiano das aulas de matemática… enfim elas não foram a “toá”). Nosso código instância um CCSprite define a posição X e posição Y com o valor 100. Por padrão, isso significa que o CCSprite será posicionado a 100 pixels para cima e para a direita, a partir do canto esquerdo da tela.

Essa definição de “pixel” não irá gerar distorção quando rodarmos nosso PB seja em um Iphone ou em um Ipad, pois ele sempre será 100 pixel proporcional a tela do dispositivo. Nós iremos definir um resolução base para o PB que será de 1024 pixels de altura e 768 pixels de largura.

Vamos agora acerta os detalhes de resolução.

No projeto .Droid clique com o direito na pasta Resources /add / New folder e nomei como “layout”.  Em seguida crie um arquivo Main.xaml vazio;

No Main.xaml vamos criar um LinearLayout que irá definir algumas resoluções e o nosso GameView propriamente dito.

Agora vamos editar a MainActivity.cs .  E vamos alterar o método OnCreate.

Agora vamos criar o método LoadGame. Comentário nos fontes, ver abaixo.

Faça um rebuild da sua solution para verificar se não digitou nada errado ou esqueceu de algo. Se gerar algum erro tente refazer os passos acima ou deixe nos comentários seu problema para que possamos te ajudar.

Agora vamos voltar para o GameLayer.cs do projeto Portable e vamos colocar a lógica do PalitoBall  =)

Primeiro vamos incluir a imagem do Palito e nosso Score (Pontuação).

Até aqui o PB apresenta uma cena parada ou estática. Precisamos agora implementar os movimento e a posição de nossos elementos no jogo. Para isso vamos utilizar método Schedule que a Classe CCNode nos fornece.  Com isso nosso código será executado 60 vezes por segundo ou 60 quadros por segundo. (caso o Hardware não suporte, esse ciclo será menor.)

Vamos colocar toda essa lógica em um único local, o metodo  RunGameLogic

O método RunGameLogic vai usar algumas variáveis, vamos criar elas junto com nossos Sprites e labels.

O CocosSharp conta com a biblioteca Box2D que simula os comportamentos físicos de forma completa. Como nosso jogo tem um comportamento de gravidade básico, vamos fazer manualmente essa implementação, assim você terá uma ideia inicial de como os comportamentos físicos acontecem no CocosSharp.

Para implementar a gravidade, precisamos armazenar a atual velocidade X e Y de nossa bola e já aproveitamos para criar um variável para nosso score de pontos. Veja o código abaixo.

Agora que a bola está caindo, vamos adicionar movimento horizontal ao nosso palito, criando um objeto CCEventListenerTouchAllAtOnce. Este objeto fornece uma série de eventos relacionados a nossa Layer. No nosso caso, queremos ser notificados se ocorrer qualquer toque na tela e assim podemos posicionar nosso palito no local correto. O GameLayer já instância um CCEventListenerTouchAllAtOnce, por isso precisamos simplesmente atribuir o OnTouchesMoved. Para fazer isso, modifique o método AddedToScene da seguinte maneira:

A seguir, vamos implementar HandleTouchesMoved:

Agora vamos voltar ao nosso método RunGameLogic e implementar as colisões. Quando falamos em colisão estamos nos referindo a lógica de reagir a sobreposição de objetos do jogo. Em nosso caso o palito e bola.

Como nossos objetos (Bola e palito) estão em constante movimento (Quadros), nossa verificação de colisão será quadro a quadro. Para dar uma emoção maior ao PalitoBall, a cada colisão a bola ganhará velocidade no eixo X. Abaixo o código comentando.

Calcular o Score. No momento que ocorre a colisão da bola com o palito nós incrementamos o nosso score.

Ufa…………Acho que terminamos.

Vamos fazer rebuild e testar se o PalitoBall está funcionando como queremos?

Aperta o F11     DJ,  opss… Programador =)

Esse post foi um pouco longo, pois abordamos varias frentes do mundo de desenvolvimento de games como recursos do CocosSharp, conceitos de Games 2D, física de objetos, Xamarin Forms e etc…  Mas atingimos o objetivo que era gerar um primeiro game 2D multiplataforma. Já pode fica feliz amiguinho, você acaba de gerar um Game 2D Básico. =)

Nós próximos post dessa serie iremos conhecer mais bibliotecas e recurso do CocosSharp e poderemos criar games mais elaborados.

Até a próxima semana. Tchau  o/

Ops…. Não deixei de colocar suas dúvidas e sugestões nos comentários.

Se precisar falar comigo:  mhbsti arroba  gmail ponto com

Me siga no twitter:  https://twitter.com/mhbsantos

Meu blog pessoal (Lá tem outros temas além de CocosSharp):  mhbs.com.br

GitHub: https://github.com/mhbsti/palitos-ball

Marcos Hitanael Barchiki dos Santos

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *