Um elemento primordial no desenvolvimento de games são os elementos gráficos e seu posicionamento na tela. A manipulação gráfica no Gideros é bastante simples e consiste na instanciação de uma imagem e sua inclusão na área gráfica. O código a seguir instancia, na primeira linha, uma das imagens disponíveis no projeto (chamada field.png) que será utilizada como fundo de tela (background). A segunda linha é utilizada para adicionar a instancia na área de jogo (chamada de stage).
A imagem relacionada no código precisa estar incorporada no projeto. Isso é feito clicando na pasta do projeto com o botão direito do mouse e escolhendo a opção “Add Existing Files” e posteriormente selecionando os arquivos de imagem. A Figura 3 ilustra o acesso a adição de arquivos no projeto e também é possível visualizar a opção “Add New File” que permite criar um novo script de programação em LUA.
Figura 3. Adição de novos elementos ao projeto
Os elementos gráficos devem ser elaborados para uma determinada resolução de tela. No caso da imagem de fundo, essa precisa ter largura e altura iguais a resolução de tela. Em um jogo onde existe uma “passagem” do fundo (como nos jogos side-scrolling), essa deverá ter uma largura ou altura maior e ser feito o deslocamento do gráfico conforme necessário. As duas imagens que estão sendo utilizadas nesse tutorial estão disponíveis na pasta “\Examples\Graphics\Jumping Ball” a partir do diretório de instalação da Gideros.
Destaca-se que a Gideros permite tratar automaticamente a escala do jogo para outras resoluções de tela. Esse recurso é configurado na opção “Properties” acessada como visto na Figura 3. A tela de configuração do jogo é mostrada na figura 4 onde é possível visualizar a opção “scale mode” que permite solicitar esse ajuste automático a várias resoluções.
Figura 4. Janela de configuração das propriedades do jogo
A figura 5 representa um pedaço de 3 execuções no jogo em escalas diferentes. A primeira tela representa a opção sem ajuste de escala (No Scale – Top Left) onde é mostrada as imagens sem qualquer alteração nos tamanhos, fazendo com que os elementos gráficos devam ser exportados para várias resoluções de tela distintas.
A segunda tela mostra o jogo com a opção de escala “crop” e a execução em uma tela maior do que para a qual os gráficos foram elaborados. Observe que nessa segunda tela a imagem da bola aparece cortada na parte superior, isso porque o ajuste da resolução acabou exigindo o corte de alguns pixels na altura do jogo. Observe também que para se adequar a uma resolução maior a imagem perdeu qualidade gráfica. Destaca-se que com essa configuração de escala o gráfico não sofre distorção na proporção das imagens e isso é um recurso importante em vários jogos como o apresentado, pois de outro modo a bola ficaria ovulada se as proporções não fossem mantidas. As opções de escala “stretch”, “fit width” e “fit height” são opções que ajustam a escala causando distorção na proporção das imagens.
Por fim, a terceira imagem da Figura 5 mostra o jogo em escala “Pixel Perfect” que consegue manter o ajuste automático sem cortar parte da cena e sem distorcer as imagens, mas para isso acaba gerando bordas ao redor da cena. Essa escala também acaba diminuindo a qualidade gráfica.
Figura 5. Pedaços da cena do jogo em algumas opções de escala
Na figura 4 ainda é possível verificar outros elementos de configuração, como a configuração das dimensões da tela (logical dimensions), onde é possível definir a largura e altura para a qual o jogo é objetivado; a orientação da tela, podendo o jogo ser projetado para visualização em orientação retrato (portrait) e paisagem (landscape). A orientação também permite algo que seria o uso em orientação retrato de “cabeça para baixo”, bem como paisagem de “cabeça para baixo”; por fim também é pode-se observar a opção FPS (frames per second) que é uma configuração de quantos frames o jogo mostrará a cada segundo. Quanto maior a quantidade de frames maior o custo computacional, mas melhor será a visualização e a resposta aos comandos.
Com relação a taxa de FPS, a Gideros somente permite a opção de 30 e 60 frames por segundo. 30 FPS é o que uma pessoa consegue realmente visualizar e pode ser utilizada em diversos jogos em que a resposta aos comandos não é essencial, como jogos de raciocínio. Para jogos que envolvem reflexo, como jogos de ação, é recomendável utilizar 60 FPS pois o jogo responderá mais rapidamente aos comandos do jogador.
Plano cartesiano
Antes de dar continuidade codificação do jogo é preciso ter conhecimento de um conceito primordial. Para o desenvolvimento de jogos é importante entender como é realizado o posicionamento dos elementos gráficos e para isso é preciso entender o plano cartesiano (Relembre os conceitos a partir de: http://www.youtube.com/watch?v=y2r8UfK0LTg). No caso de jogos 2D é utilizado o plano cartesiano bidimensional, enquanto jogos 3D precisam da manipulação do plano cartesiano tridimensional (que não será abordado nessa obra).
O plano cartesiano bidimensional como é apresentado na escola é como o mostrado na Figura 6, onde existe um eixo horizontal (denominado eixo X) e um eixo vertical (denominado eixo Y). Onde esses eixos se cruzam é estabelecido como ponto de origem do plano e referenciado como 0,0 onde o primeiro valor (antes da vírgula) representa o valor no eixo X e o segundo valor (depois da vírgula) representa o valor no eixo Y. Aumentando o valor de X se tem pontos mais para a direita e aumentando os valores de Y tempos pontos mais para cima. O plano cartesiano é representado normalmente tendo o ponto de origem no centro do plano.
Figura 6. Representação tradicional do plano cartesiano
A ideia do plano cartesiano é mantida no computador, mas com uma alteração. Repare na Figura 7 que existe uma diferença no eixo Y (no eixo X não existe mudança). Veja que quando os valores de Y aumentam, o ponto acaba sendo mais para baixo (ao contrário do visto antes).
Figura 7. Plano cartesiano do computador.
Outra diferença existente na representação no computador é que o ponto de origem não é no centro do plano, sendo considerando no canto superior esquerdo. Isso faz com que os valores negativos de X e Y formem posições fora da tela do computador. A Figura 8 mostra onde está o ponto de origem da cena que é exibida e também de um elemento gráfico inserido na cena (a bola). A origem considera sempre a orientação retrato (portrait), mesmo que o jogo seja executado em uma orientação diferente.
Figura 8. Ponto de origem da cena e do elemento gráfico
A posição 0,0 destaca na bola é o ponto de origem do elemento gráfico da bola. Mesmo sendo um círculo, os elementos gráficos são sempre considerados em forma retangular. Essa bola tem sua origem posicionada dentro da cena em posição 120,20, manipulação que será vista a seguir.
Adicionando outro elemento gráfico ao jogo
Tendo entendido como posicionar elementos gráficos no plano, vamos adicionar e posicionar um novo elemento gráfico (a bola) ao jogo e posiciona-lo na cena. O código abaixo realiza essa tarefa.
A primeira e a última foram explicadas anteriormente. Destaca-se aqui a segunda e terceira linhas que realizam o posicionamento da boa. Isso é feito através das instruções setX e setY alterando, respectivamente, as coordenadas X e Y do gráfico. Se não definida a posições X e Y, por padrão é atribuído zero para cada coordenada, o que faria a bola ser posicionada no canto superior esquerdo da cena. O posicionamento na coordenada 120,20 gera um resultado como mostrado anteriormente na Figura 8.
Digamos que agora precisamos posicionar a bola no centro com relação a largura da cena. Em um primeiro momento poderíamos pensar na seguinte forma: pegamos a largura da cena (no nosso caso 320) e dividimos por 2, pegando o meio da cena. O código abaixo ilustra essa definição. Em vez de solicitar a operação aritmética, também poderia ser fornecido o diretamente o resultado da operação, no caso 160, dispensando esse processamento.
A figura 9 mostra como fica posicionada a bola com a aplicação dessa coordenada X e vemos que o gráfico não ficou posicionado exatamente no meio. A figura 10 ajuda a entender o motivo desse posicionamento não ter funcionado. A linha em azul corta a cena ao meio, no coordenada 160 em X. As setas em vermelho possuem intersecção na origem do objeto, sendo que é essa origem do objeto que posicionamos no através das instruções setX e setY. Da maneira como solicitamos o posicionamento do elemento gráfico fez com que ele começasse a partir do centro da cena.
Figura 9. Resultado da tentativa de posicionar a bola no centro da cena
Figura 10. Destaques na imagem para explicar o posicionamento no centro da cena
Para o correto posicionamento da bola no centro da largura da cena precisamos colocar o centro da largura da bola no centro da largura da cena. Para isso precisamos posicionar a bola mais a esquerda, diminuindo sua coordenada X. O elemento gráfico da bola possui largura de 80 pixels, então poderíamos em um segundo momento fazer o seguinte cálculo para a posição: 160 da posição X central da cena subtraídos os 80 pixels da largura da bola, resultando na posição 80. O resultado dessa nova posição é mostrado na figura 11 onde vemos que nossa tentativa foi novamente frustrada já que a bola ficou posicionada muito para a esquerda. Isso aconteceu pois consideramos toda a largura da bola, enquanto o que precisávamos era descontar apenas até o centro dela, ou seja 40 pixels. Se colocarmos a posição X com valor 120 (160 – 40), o resultado será o esperado (mostrado na figura 12).
Figura 11. Resultado da nova tentativa de posicionar a bola no centro da cena
Figura 12. Resultado da nova tentativa de posicionar a bola no centro da cena
Existe uma maneira melhor para especificar o posicionamento que queremos e esse modo é mostrado no código a seguir, onde é utilizada uma instrução que retornam o tamanho da largura da tela (stage:getWidth) e outra instrução que retorna a largura da bola (ball:getWidth , onde ball é o nome definido anteriormente no código para o elemento gráfico da bola). A utilização dessas instruções é interessante para permitir que o script possa ser reutilizado mesmo com elementos gráficos de tamanho diferentes, caso se pretenda fazer versões do jogo para resoluções de tela diferentes.
Próximo passo: adicionar movimento ao jogo