A Equipe de Desenvolvimento – Parte III: Programador

Fala galera,

Após algum tempo de ócio pós-final-de-ano, fui “convidado” a dar continuidade à série. Entre os projetos de uma aventura-solo, um jogo da cobrinha (também quero) e outros projetos de jogos casuais (tive tempo até pra ser assaltado), aqui estamos.

Programador

Programador é o profissional responsável pelas implementações técnicas dos jogos. Em algumas empresas, o título de Programador é subdividido em vários cargos, como os exemplos a seguir:

• Tools Programmer: desenvolve ferramentas como editores de mapas, editores de chars, automação de tarefas, organização de projeto, pesquisa, editor de fluxogramas, comunicação da equipe, randomizadores, thesaurus, painéis eletrônicos, plugins e addons, dentre outras variadas possibilidades que se façam necessárias;
• Engine Programmer: produz as estruturas de software que rodam por trás do jogo em si, utilizando linguagens poderosas e interação direta entre softwares, drives e hardwares de entrada, processamento e saída de dados. Comumente, engines utilizam tecnologias externas ou específicas para o tipo e plataforma do jogo a ser produzido.
• Graphics Programmer: tendo uma certa relação com a parte de programação de engine, para o caso da engine gráfica, a função deste programador não se limta apenas aos recursos básicos de renderização, mas à programação de diversos elementos necessários aos projeto, como programação de efeitos de tela, shadders, materiais, smooths, shakes, câmeras e outros recursos e elementos vinculados;
• Database Programmer: esta é uma função mais específica, onde as principais tarefas são organizações de tabelas e gráficos relacionados aos sistemas internos do jogo, geralmente envolvendo recursos de customização e configuração de contas de usuários e suporte para jogos on-line.
• Gameplay Programmer: esta função é a programação do jogo propriamente dita, em seu formato final. Este programador é responsável pela implementação técnica dos sistemas de jogabilidade, coordenação de animações, interação entre levels, elementos de cenário, movimentação, física e matemática dos jogos.

As tarefas mais comuns exercidas pelos Programadores são:

Prototipação de Software de Jogo;
Desenvolvimento de Softwares, Tools, Plugins;
Desenvolvimento de Engines e Core;
Estruturação de Dados;
Correção de Bugs, Otimização de Códigos;

O caminho mais comum para se tornar um Programador é obtendo uma graduação em Ciência da Computação, Engenharia ou Tecnologia da Informação, mas é possível adquirir também conhecimentos e experiência por conta própria. Conhecimentos de lógica de programação, contrução de algorítmos e matemática são fundamentais.

3 Comentarios

Burning Down: Fire Effect

Olá galera. Acho que já falei bastante sobre esse efeito aqui. Mesmo assim, vale a pena olhar novamente!!

O efeito de Fogo!!!!

O efeito de fogo é um efeito bem simples de ser implementado, e que tem um resultado bem atraente. Basicamente o que fazemos com ele é pegar um array colocar nele valores aleatórios e ficarmos fazendo cálculos com esses valores.

Como queimar Roma:

Para calcular a cor de um pixel, o que prescisamos fazer é pegar os valores dos 4 pixels vizinhos ( (x+1,y), (x-1,y), (x,y+1) e (x,y-1) ) , somá-los, tirar a média e subtrairmos algum valor para diminuir a vida do pixel.

A idéia é usar um array de bytes (Mapa: array of array of Byte), e trabalharmos com os seus valores de 0..255. Qdo um valor for igual a 0 esse pixel não seria desenhado, e do contrário ele seria plotado na tela.

E se o valor da divisão dos pixels for 0?? Bom, nós teremos então um valor de pixel negativo. Por estranho que pareca, o delphi faz com que os valores retornem para o final do índice, assim, um valor de pixel - 15 será convertido para o valor 240, assim, acabamos tendo a impressão que se forma um rio de mapa na tela. Então, devemos tratar isso manualmente para que valores menores que zero, continuem zero ;)

E a animação? Como o fogo sobe? Bom, isso eh simples, na hora que formos calcular o valor do pixel, vamos devolvê-lo uma linha para cima no array.

Dois arrays ou um só?

A recomendação desse código é usar dois arrays para calcular o fogo, alternando entre eles enquanto se plota os pixels, (faz-se um cálculo em um array, e plota os valores em outro array que será desenhado, depois inverte), isso é desnecessário, pois pode ser feito apenas com um array, dizem, que fazendo assim o fogo fica estranho, mas eu gostei do resultado, e vc vai poder curtir ele com os meus exemplos que vc vai baixar no final desse post ^^.

Calculando as Cores:

Para calcularmos as cores usamos uma paleta indexada de 0..255 (mesmo comprimento do tipo byte :) ), sendo que nela configuraremos os valores da seguinte maneira:

0: Valor frio ou preto

1: Valor quase totalmente preto

255: Valor máximo de calor

Sendo assim, qdo mais alto o valor, mas quente será o nosso fogo, e mais ele demorará para morrer tb. :)

Não vou esplicar aki como calcular a diferença de cores, pois vc pode achar isso na net, e com o exemplo vem duas boa paletas tb.

A estrutuda das peletas é bem simples:

Type TPalete = Array[0..255] of TColor;

Bom, vc já deve estar imaginando que os valores de cor são em RGB. logo não será mto difícil trabalhar com essas paletas.

Plotando a cor no Array:

Nada difícil de se fazer, simplesmente use:

NovaCor:= ( Mapa[x+1,y] + Mapa[x-1,y] + Mapa[x,y+1] + Mapa[x,y-1] ) / div 4 - Cooling;

if NovaCor < 0 then NovaCor := 0;

Mapa[x,y + 1]:=NovaCor;

O Mapa[x,y + 1]:=NovaCor, é o que fará a animação do nosso fogo subindo.

O Cooling é um valor inteiro que decrementa o valor do pixel, fazendo assim com que a vida do pixel diminua.

Plotando o Pixel na Tela:

Plotar o pixel na tela vai depender da biblioteca que vc está usando. No meu caso eu estou usando o DelphiX, que tem métodos de desenho mto semelhantes ao Canvas padrão do Delphi, então eu faço assim:

DXDraw.Surface.Canvas.Pixels[x,y] := Paleta[Mapa[x,y]];

Recomendo que faça o desenho dos pixels em uma procedure separada da proedure em que se calcula os valores, isso por questão de organização do código ok? ;) Bom, creio que não precisa dizer que Paleta é um objeto do tipo TPalete né?

Carregando a Paleta:

Já que tocamos no assunto, devemos criar tb. um tipo:

Type TPaleteFile = File of TPalete;

Com ele podemos tanto salvar e carregar uma paleta com poucas linhas de código:

var MeuArquivo: TPaleteFile; MinhaPaleta:Tpalete;

If FileExists(Nome_do_arquivo) then begin

AssignFile(MeuArquivo, Nome_do_arquivo);

Reset(MeuArquivo); // Para ler;

Read(MeuArquivo, MinhaPaleta);

CloseFile(MeuArquivo);

end;

Já para salvarmos um arquivo usamos:

var MeuArquivo: TPaleteFile; MinhaPaleta:Tpalete;

AssignFile(MeuArquivo, Nome_do_arquivo);

Rewrite(MeuArquivo); // Escrita;

Write(MeuArquivo, MinhaPaleta);

CloseFile(MeuArquivo);

Reabastecendo o Fogo:

Logicamente, temos que dar algo para o nosso fogo queimar, então podemos chamar uma procedure, que plota pixels aleatórios em nosso mapa. (De preferência na Ultima linha) , periodicamente, para que assim tenhamso algo pra queimar. E o nosso fogo se tornar contínuo.

Bom, vamos ficar por aki hj, claro que efeitos de fogo não se fazem apenas com isso, podemso usar cooling Map para “modelarmos” o nosso fogo ^^. No exemplo da tocha (que na verdade é uma pira olimpica), eu uso um mapa assim.

Bom, acredito que vc pensou: Com todos estes cálculos, pixels plotanto, isso deve ser lento…

E eh ^^!

Mas, isso pode ser resolvido renderizando as imagens primáriamente antes de mostrar na tela, assim temos frames prontos que não vão mas nos encher com cálculos enormes. Assim como tb. podemos salvar as imagens no disco e carregá-las em nosso jogo para economizarmos tempo de loading, qdo as imagens serão criadas. Isso tb. é ilustrado em meus exemplos, note a diferança da FPS de ambos os desenhos. Note tb. que, usando imagens pré renderizadas, temos um problema, que é acertamos o fluxo dos frames enquanto damos um loop na animação. Esse problema eh ilustrado no exemplo, e vc vai notar o pulo de animação.

Bom eu falei dos exemplos e vc deve estar curioso para vê-los bom aki estão eles:

DOWNLOAD DOS EXEMPLOS

Bom, lamento por deixar uma explicação tão vaga e confusa, mas o meu tempo é curto, mas, não se preocupem, logo vcs verão mais desse efeito.

VLW!

Leitura Recomendada:

special effects game programming With DirectX

Quem quizer um artigo mais detalhado sobre o efeito de fogo pode ler o meu artigo (Fire and Smoke) na PDJ Zine 2:

Bye o/

Um Comentario

Pixel art isométrico - Parte 2

Voltamos com a segunda parte de Pixel art isométricos.

Nessa segunda(e última) parte serão abordados: iluminação, outras formas geométricas e criação de tiles. Eu acabei atrasando bastante o texto, desculpa aê pessoal! (mas é que essas imagens são complicadinhas de fazer ¬¬). Para entender esse texto você tem que ter lido o primeiro texto da série. Espero que gostem ;)

Iluminação

Iluminaçáo é muito importante em representações visuais de um objeto 3d em alguma mídia 2d por vários motivos e um deles é que a iluminação dá a sensação de profundidade. Nos nossos pixels isométricos isso é mais do que válido, já que se não diferenciarmos pelo tom da cor aonde que uma fonte de luz vem, nós nunca saberemos o quão 3d aquilo é(sem contar que não parece real mesmo). Com um exemplo fica mais fácil de acompanhar:

Ou seja, a imagem fica sem uma profundidade aparente, e nós só achamos que ela pode ser 3d por causa da perspectiva usada com isometria. Mas se nós fossemos rotacionar o “cubo” para a direita ficaria algo assim:

Um plano! Tudo bem que eu forcei um pouco, mas a idéia é que se nós não sabemos se isso é 3d ou não, é como ver algo sem luz nenhuma! Nós só veriamos a silhueta em 2d já que a luz é que diferencia a pronfudidade algum objeto. Mas agora vamos ver como nós fazemos para que nosso cubo fique 3d.

Tudo depende de onde a luz está vindo. Geralmente em imagens isométricas que eu vejo pela internet as fontes de luz são muito simples e as pessoas geralmente variam com 3 tons de cor. Mas a ideia é mais ou menos a seguinte: Se a luz está vindo da direita, a direita será mais clara, se a luz está vindo da esquerda, a esquerda será mais clara.. e por aí vai.

Veja que a luz está vindo do canto superior esquerdo, então a parte de cima é mais clara e a parte da esquerda é um pouco mais escura(mas nem tanto) e a direita é a mais escura de todas já que a luz não atinge lá tanto quanto os outros 2 lados.
Você pode usar outras fontes de luz também e fontes de luz com outras cores, isso é um assunto meio avançado mas se você quiser saber mais sobre o assunto eu recomendo procurar na internet ou em livros já que isso é o que diferencia uma imagem bem composta e complexa do que uma mais simples(geralmente as dos jogos são mais complexas).

Outras formas geométricas

Bom, essa parte é importante já que eu creio que você não queira ficar fazendo imagens que pareçam cubos pintados, certo?
A idéia aqui é aprender a criar outras formas que não sejam o cubo e depois aprender a juntá-las.

Primeiro vamos ver rampas. Para se criar uma rampa primeiro faça um cubo, depois ligue a extremidade superior do cubo com a inferior, dependendo da distância que você deseja, exemplo:

Muito fácil né? Agora vamos as pirâmides! Elas são bem fáceis também, a idéia é que você tem um quadrado e tem que ligar as extremidades do quadrado no centro, assim:

Tenho uma observação quanto as pirâmides, observe bem que o quadrado que eu usei tem a base de 3 pixels. Se eu não fizesse assim ficaria difícil achar o meio e a pirâmide iria sair irregular.

Agora vamos aos triângulos. Os triângulos são importantes já que qualquer telhado é basicamente um triangulo meio oco(entenderam? :P), então se você quiser aprender a fazer casas siga o exemplo:

Essa imagem serve para mostrar que para se fazer um triângulo numa perspectiva isometrica é o mesmo processo de uma perspectiva normal, ou seja, faz uma linha na horizontal e a partir do meio puxa as 2 linhas da extremidade pra cima.

Agora as coisas complicam um pouco, mas é só prestar atenção. O que eu fiz aqui foi um triângulo comum e eu repliquei ele ao longo de um retângulo, com isso eu liguei a parte de cima e fiz algo meio parecido com um telhado.
Percebam que existem 2 casos, isso nada mais é do que o tamanho da base do retângulo, ou seja, quando a base for muito grande(o caso 2) você terá que desenhar o lado direito do “telhado” que fica escondido no caso 1.

E por fim, os cilindros. Para se fazer cilindros se segue a mesma idéia dos triângulos, é como se fosse desenhando em uma perspectiva normal para depois passar pra uma perspectiva isométrica:


Tem também as esferas, mas como as esferas são uma figura que independente do ângulo são desenhadas da mesma maneira(um circulo!) eu não desenhei aqui, a única coisa a se prestar atenção na construção de uma esfera é aonde a fonte de luz está atingindo para colorir direito parecendo realmente uma esfera.

Como juntar as figuras geometricas é algo bastante simples e intuitivo. Basicamente é como se fosse brincar de lego ou aqueles brinquedos de criança que tem várias formas e simplesmente juntar! Aqui vão exemplos tirados de jogos onde eu tirei uma screenshot e depois fiz uma imagem equivalente só com os traços:



Eu num fiz todos os contornos(deu preguiça :P), mas dá pra ver que se a textura for tirada da imagem, o que sobra são as formas geométricas, tente observar quais são as formas geométricas dessa imagem aqui:

http://pixeljoint.com/pixelart/13806.htm

Uma coisa interessante a se observar é que nos jogos nem sempre os traços são simétricos(o do Megaman por exemplo), isso acontece porque em alguns jogos devido o engine isométrico utilizado, nem sempre alguns objetos são colocados de acordo com as posições do tamanho do tile. Por exemplo, se o programador criou um engine que coloca os tiles a cada 14 pixels, então é esperado que os objetos(o armário, o tapete, a cama, etc) também sejam colocados a cada 14 pixels, ou seja, eles também seriam tiles. Mas em alguns engines de tiles existe uma diferença aonde o tile é colocado(no caso seria fixo, de 14 em 14) e aonde os objetos são colocados. Nesse caso os objetos podem ser botados na posição onde o artista quiser, isso acontece pra dar uma maior mobilidade ao artista fazendo com que a imagem fique mais dinâmica e não pareça um monte de tiles juntos.

Tiles isométricos

Bom, a criação de tiles isométricos é razoavelmente diferente da criação de tiles para jogos com perspectiva top-down(que nem aqueles RPGs de Snes). Isso acontece devido ao fato de que em isometria a profundidade de onde os tiles estão importa, e nós queremos que pareça um ambiente em 3 dimensões, então temos que levar algumas coisas em consideração.

Primeiro vamos fazer um tile comum na perspectiva top-down:

Agora, como nós fizemos acima na criação de formas geométricas, vamos mudar a perspectiva do quadrado e assim temos um tile isométrico:

Certo, agora você tem um tile que representa uma grama, você poderia usar a mesma técnica para criar coisas simples sem dimensão no eixo Y, os chamados tiles de terreno, por exemplo: água, areia, tapete, ladrilhos, etc. Mas para nós criarmos algo como por exemplo uma casa é mais complicado em tiles isométricos do que na perspectiva top-down, pois nela para fazer isso nós simplesmente separamos os vários tiles para que quando nós formos juntar eles, eles se tornem uma casa:

Mas em isometria isso não acontece, devido ao fato da pronfudidade. Isso significa que quanto mais o tile está embaixo, mais profundo ele é, mais perto da visão do jogador ele está, então não teria como o programador fazer coisas como esconder o jogador atrás de uma parede, veja bem:

É até possivel criar tiles para se desenhar uma ilustração isométrica dessa maneira(em algum engine tipo Rpg Maker), mas para jogos isso não seria útil por causa dessa colisão. Para se criar paredes ou “coisas altas” precisa que o programador ajuste o engine para que ele aceite “tiles de objeto”. A diferença de um “tile de objeto” isométrico é que nós construimos o tile do tamanho da base que todo tile isométrico tem, mas a diferença é que verticalmente o tile pode ultrapassar o limite permitido em um engine de tiles convencional:

Ou seja, para fazer uma casa, nós simplesmente juntariamos os tiles como se fosse na perspectiva top-down, mas devido a profundidade da visão isometrica e de que os tiles são desenhados no mapa de cima para baixo, cria-se a impressão de que é 3D:

Ou seja, o importante na criação de tiles isométricos é não ultrapassar os limites da base horizontal, mas quando for desenhar na vertical não há problema.

Considerações Finais

Bom, esse é o final da pequena série(que era pra ter sido em um só artigo). Meus próximos artigos vão ser sobre programação e game design, mas como a demanda para artigos de arte/visual é grande nós vamos providenciar algo para vocês ;).

7 Comentarios

O Caminho das Pedras - problemas e suas (possíveis) soluções no mercado nacional de jogos

Há algum tempo, quando eu estava buscando novos conteúdos para a nossa zine “multi-comunitária” (rs), me deparei com um blog anualmente atualizado mas com um bom material. Estou falando do “Aventuras e Desventuras de um Designer de Jogos Brasileiro“, blog de Rafael “Wind Blow” iniciado no final de 2005 e que possui o interesse em ser um “canto para reflexões, discussões, idéias e artigos sobre o cenário de Game Development brasileiro e mundial.”

Um artigo que se encontra lá e que eu quero compartilhar com vocês é o “O Caminho das Pedras - problemas e suas (possíveis) soluções no mercado nacional de jogos” que, apesar de ter sido publicado há um ano, considero um material bem atual.

Prepare-se, pois como eu coloquei as duas partes aqui, ficou um texto bem extenso! =D

(Parte 1)

Todo mundo que se interessa por jogos eletrônicos além da trivial questão “o que comprar no camelô semana que vem” ou “o que dar pro meu filho no Natal” sabe que o mercado brasileiro está simplesmente errado. Dominado pela pirataria, recebendo efusivos incentivos verbais e iniciativas limitadas por parte do governo, ignorado por quase todas as forças econômicas brasileiras, a coisa realmente não parece em condições ótimas para os desenvolvedores de jogos nacionais – muito embora o surgimento de vários cursos nessa área de uns anos para cá tenha feito parecer que o nosso mercado de games está prestes a explodir em glória, ao menos para os alunos dos mesmos.

Eu mesmo sou um desses estudantes de game design, que entrou num curso crente que iria sair de lá direto para o estrelato como o designer-revelação do Independent Games Festival do ano seguinte. Obviamente, é natural que a realidade ajude a diminuir bastante as expectativas de um jovem sonhador, mas ainda assim, será que o Brasil não merecia um mercado mais inteligente e coeso do que o que se apresenta hoje em dia? Será que um mercado de jogos eletrônicos no Brasil é um sonho impossível?

Eu espero não estar sendo muito ousado ao dizer: não, definitivamente não! E pretendo compartilhar algumas das opiniões que me levam a crer que realmente há um mercado milionário esperando para ser descoberto em terras brazucas, mas ele – surpresa, surpresa – não está aonde todos o estão procurando.

Antes de analisar o mercado brasileiro, é necessário analisar o mercado de jogos como um todo. Recentemente, a indústria norte-americana de jogos alardeou aos quatro ventos que tinha ultrapassado a indústria cinematográfica em geração de lucros. Certamente todo mundo (ao menos, todo mundo que se dá ao trabalho de ler um blog sobre o assunto, como este) já ouviu isso em algum lugar e se sentiu muito orgulhoso. Porém, isso não é nem de longe verdade. Primeiro de tudo, a comparação é entre lucro de venda de jogos versus lucro de box office, ou seja, bilheteria. Se levarmos em conta o mercado de home video/DVDs, que hoje em dia é responsável por metade do lucro das produtoras de cinema, a indústria de jogos perde de muito. E isso sem nem entrar no mérito do merchandising.

Além disso, o excelente blog Lost Garden, mantido por um insider da indústria com currículo extenso e idéias bastante inovadoras (leitura obrigatória para quem sabe inglês, aliás), publicou recentemente um artigo fantástico chamado “Um Programa de Cinco Passos para Evoluir Além dos Jogos”[1], que diz que, segundo estatísticas, enquanto o mercado norte-americano está de fato crescendo, a taxa de crescimento é de 7,3% ao ano, muito longe de ser um mercado em franca expansão. Como objeto de comparação, ele mostra que o mercado de aparelhos celulares cresce à taxa de 19,1% ao ano. Além disso, a base instalada de consoles nos EUA é de 35 milhões de aparelhos, enquanto a de TV a Cabo, por exemplo, é de 200 milhões, e a de PCs de 500 milhões. Logo, o mercado americano nem é grande, nem está crescendo rapidamente como a “ultrapassagem” sobre o cinema faria deduzir. Além disso, a ilusão de crescimento incha a indústria, mas não a massa consumidora. Isso gera uma competição feroz por uma fatia fixa do público enquanto uma quantidade muito maior de consumidores em potencial permanece ao largo do mercado. O autor resume sua opinião no seguinte trecho:

Então, nossa grande população de jogadores é realmente uma coisa insignificante se você olha de fora da nossa pequena comunidade insluar. Enganamos a nós mesmo dizendo que a indústria ‘venceu’ porque os poucos jogadores que angariamos gastam uma imensa quantidade de dinheiro. Nós temos até eventos badalados na MTV. Desculpem.

Mas o que os problemas do mercado norte-amerciano têm a ver com o nosso inexistente mercado brasileiro? Para ser bem direto: tudo. O mercado brasileiro se espelha no americano até o último fio de cabelo, e quanto mais nós somos ignorados pelas softhouses e empresas americanas, mais tentamos ser iguais a eles. Então, se o sistema deles tem sérias falhas, é essencial ao nosso mercado entender e evitar a repetição inútil de erros já cometidos historicamente em outro lugar, mesmo que esse outro lugar seja nosso sonho de consumo (ou principalmente).

O maior e mais grave erro do mercado brasileiro é tentar competir com o norte-americano. É uma corrida impossível de vencer, visto que eles têm 20 anos de vantagem em relação a nós, E o produto deles já estabeleceu seu mercado consumidor aqui. Gamers que jogam os jogos americanos e japoneses dificilmente vão abandoná-los para ficar com os nacionais. E não é por preconceito e nem por diferença de qualidade, mas sim porque os jogos brasileiros são, em 90% dos casos, “derivados” (para não dizer copiados) de jogos estrangeiros já existentes – e que, muitas vezes, também são clones de outros jogos que vieram antes! A crise de conteúdo no mundo dos jogos é um assunto tão debatido ultimamente que até mesmo gente de fora da indústria já sabe o que está acontecendo. Diversos artigos são escritos sobre isso semanalmente, os estúdios independentes são enaltecidos como o último bote de salvação, etc etc. Então qual o sentido de nós, developers brasileiros, querermos fazer jogos de tiro em primeira pessoa, ou jogos de estratégia em tempo real, se mesmo os jogos feitos pelas empresas que inventaram esses estilos, com anos de experiência e excelência técnica, já estão sendo descartados e taxados de repetitivos e monótonos?

Então, o primeiro passo já é tentar fugir dos estereótipos e criar jogos criativos e com estilo próprio. Alguém pode querer argumentar que, se lá fora, onde o mercado é grande e lucrativo, já é muito difícil alguém lançar um jogo inovador, aqui então seria impensável. Pelo contrário! O mercado brasileiro, por estar ainda incipiente em sua organização, não sofre dos vícios das grandes publishers estrangeiras. Nós instintivamente os imitamos, sim, mas não porque temos uma história pessoal de sucesso com o estilo X ou Y e preferimos nos mantermos na estratégia vencedora, e sim porque esperamos que o sucesso da Eletronic Arts ou da Blizzard vá se repetir por aqui se fizermos e publicarmos apenas os exatos mesmos jogos para o exato mesmo público. O que, francamente, é a maior besteira! Com um mínimo de conscientização, tanto os publishers quanto os developers brasileiros poderão desviar do pré-estabelecido e ousar seguir em novas direções, com o vigor de quem acabou de entrar na jogada e tem energia e disposição para arriscar.

(Parte 2)

Na primeira parte do artigo, concluímos que o primeiro passo para desenvolver uma indústria de jogos nacional forte e soberana era aprender com os erros da indústria americana (cujo público é o mais parecido com o nosso, logo há uma tendência entre nós de seguirmos os passos dela) e evitar os estilos consagrados e dominados por grandes desenvolvedores com muito mais experiência e orçamento do que os nossos.

Porém, se por um lado inventar todo um novo estilo de entretenimento eletrônico é uma coisa infinitamente complicada, por outro também não é apenas isso salvará a indústria brasileira de jogos de virar um irmão menor maltratado e ignorado das grandes companhias internacionais. Isso é só metade da história. A outra metade, e que é o grande pulo do gato, na minha opinião, é cativar no público que NÃO joga atualmente. É isso mesmo. Ignorar os gamers de hoje em dia, e fazer jogos para quem não encosta num videogame ha muito tempo, se é que já encostou na vida! Embora muitos gamers possam estar se sentindo magoados agora, essa é a dura realidade: enquanto mercado consumidor, os jogadores atuais são um nicho minúsculo. E justamente porque eles são… gamers!

Permitam-me esclarecer. Todo mundo acha que o mercado brasileiro é ruim por causa da pirataria. Ou por causa dos impostos altos. Ou por ambos. Eu digo que isso é bobagem! O mercado brasileiro está ruim porque há anos ele deixou de ser incentivado. A maior prova disso é que qualquer campanha relativamente bem-feita de marketing de um jogo ou sistema, no Brasil, dá resultados. O problema é justamente esse: o marketing.

Um pouco de história pode ajudar a entender a situação atual do mercado. Na década de 90, as grandes empresas produtoras de consoles eram oficialmente representadas no Brasil, e o mercado era bastante próspero. Eis que, lá fora, a Sony lança o PlayStation. É a chegada da era 3D. Infelizmente, por uma confusão de direitos relativos ao nome do PlayStation, a Sony decide não lançar oficialmente o console no Brasil. Pouco tempo depois, a pirataria de CDs explode, e com ela, naturalmente, vem a pirataria de jogos do PlayStation. As pessoas começam a comprar o console da Sony porque os jogos são bem mais baratos do que os da Nintendo, paralelamente a Sega mete os pés pelas mãos e o Saturn fracassa, dando assim um golpe mortal na Tec Toy. Enquanto isso, perdendo território e jogadores para o console da Sony, a Nintendo finalmente se manda do Brasil. Certo?

Errado. Não foi exatamente a pirataria que afastou os consumidores da Nintendo, mas sim a mudança radical que os jogos sofreram devido à migração do 2D para o 3D. As pessoas que pararam de comprar videogames nessa época são as mesmas que pararam de comprá-los nos EUA e no resto do mundo na mesma época. Uma grande parcela dos jogadores das décadas de 80/90 simplesmente não se adaptaram ao 3D.

Então, por que o mercado nos EUA não morreu como o brasileiro? Porque ele se renovou. A Sony soube encontrar um novo nicho para seu PlayStation, e ela fez isso com marketing. Mirou no público que achava que videogame era coisa de criança (a Nintendo tinha uma política muito restrita quanto a violência e conteúdo adulto em jogos para seus consoles), e acertou em cheio. A quantidade de jogadores que entraram no mercado foi maior do que a quantidade de ex-jogadores que abandonaram os games. No papel e nas estatísticas, o mercado cresceu. E o que aconteceu de fato foi uma mudança drástica no perfil do gamer americano.

Só que no Brasil, não houve campanha nenhuma. Quem abandonou os jogos, abandonou de vez. Da grande massa de público que tinha (e tem) imenso potencial para gostar de jogos, só uma minúscula porcentagem foi angariada, por divulgação boca-a-boca ou por puro acaso ao se perguntar o que diabos o camelô estava vendendo que era tão colorido. Paralelamente, o público que já consumia produtos piratas absorveu rapidamente a novidade. E um bando de jogadores hardcore dedicados, que não queriam ficar órfãos dos consoles da noite pro dia, acabou sendo atraído para o produto pirata.

Hoje, enquanto publishers e o governo batem boca sobre quem nasceu primeiro, o ovo (imposto) ou a galinha (pirataria), a verdade é que a pirataria que existe hoje já é cultural – já era antes do PlayStation aparecer – e nada do que se faça vai mudar os hábitos de consumo de quem compra jogos piratas. Mas o que ninguém percebe, é que esses consumidores da pirataria são uma parcela ínfima perto da parcela economicamente ativa e disposta a comprar jogos, caso algum jamais os pareça interessante.

O problema é que não parecem. Não há campanha nenhuma direcionada para esse público. Na verdade, não há campanha alguma a favor de jogos que não seja direcionada ao público hardcore, e esse já consome pirataria ha tempo demais para repentinamente agora querer pagar 10 a 25 vezes mais pelo mesmo produto – produto esse que muitas vezes é uma releitura ou continuação de um outro produto, feita única e exclusivamente para apelar ao público que comprou as versões anteriores. De todos os lados, só o que se vê são vícios – vícios de produção, de mercado, de consumo – e nenhuma atitude, por menor que seja, para reverter a situação e trazer um pensamento novo a um mercado que ainda está engatinhando, e até por isso deveria ser inovador e livre de cacoetes.

Se duvidam da minha palavra, pensem em quantos jogadores de Ragnarok vocês conhecem que nunca jogaram nada no computador antes. E isso porque a campanha da LevelUp nem foi muito longe além das bordas do microverso gamer. Os MMORPG são um estilo muito diferente dos jogos de console e dos single player comuns, e bastou uma pequena campanha oficial para que se espalhassem como vento. Jogos de celular, apesar de ignorados pelos gamers “hardcore”, estão em rápida expansão e vão atingir um mercado muito maior do que os jogos de console ou PC bem antes do fim da década. O segredo deles? O marketing que as próprias operadoras fazem, direcionado a um público que, em sua maioria, nunca tinha sido atraído por jogos eletrônicos antes. Até mesmo alguns consoles antigos, de mais de 10 anos de idade, volta e meia são vendidos nos balcões de lojas de departamento pelo Brasil afora, simplesmente porque, para um leigo, aquilo é tão “videogame” quanto um PlayStation2 ou um GameCube.

Há um medo muito grande por parte dos produtores em se arriscarem dessa maneira a buscar um público que não é gamer. Os gamers, como qualquer outra cultura “underground“, são sectários e desprezam quem é “de fora” (e que fique bem claro, só no Brasil somos underground. Nos EUA, a televisão exibe uma propaganda de videogame por intervalo durante transmissões de campeonatos de futebol ou beisebol, por exemplo, e as campanhas de divulgações de consoles e jogos são massivas. No Japão nem se fala. Na Coréia, onde a pirataria é tão ruim ou pior do que aqui, os cyberatletas são celebridades nacionais e os campeonatos de games são amplamente divulgados). Produzir jogos para os “menos dignos” é ter a certeza de ser desprezado pelo público hardcore. Mas, financeiramente falando, dadas as proporções entre os hardcore e os potenciais, e dado o fato de que 90% do mercado movimentado pelos gamers atuais é pirata e não dá lucro pra ninguém além do tráfico de drogas, isso não deveria ser a preocupação de nenhuma empresa, publisher ou estúdio brasileiro nesse momento.

Então, é isso. Dois passos decisivos para o Brasil criar um mercado infinitamente lucrativo (porque entretenimento eletrônico, quando vencido o preconceito criado pela má divulgação da mídia ao longo de sua história, é o produto mais vendável do mundo): Criar jogos de estilos diferentes e para um público diferente. Não adianta bater de frente com os gigantes. Vamos mirar em todo o público que eles estão ignorando – e rápido, porque mais cedo ou mais tarde eles acordam. A Nintendo já deu sinais de que percebeu isso, com sua estratégia de marketing do Revolution claramente direcionada para a família e os jogadores chamados “casuais.”

Na verdade, se agirmos rápido, podemos até estabelecer um mercado forte o suficiente para começarmos nós mesmos a exportar para fora. Não é impossível – mais uma vez, vejam o exemplo da Coréia. É uma questão de visão, pensamento “fora-da-caixa” e rapidez. E eu tenho certeza que esses são requisitos muito fáceis de se achar em quem é apaixonado por jogos eletrônicos!

Claro que existem vários obstáculos cabeludos a serem vencidos, especialmetne o pré-conceito da maioria das pessoas não-jogadoras ao ouvirem a palavra “game“, mas isso eu deixo para um próximo artigo.

8 Comentarios

Colisão sem bater cabeça

Hoje veremos algumas técnicas básicas, e comumente utilizadas, para detecção de colisão no Flash.

Este artigo é voltado para os iniciantes em programação AS que estão desenvolvendo seus primeiros jogos, e muitos se deparam com o mesmos problema que deparei há não muito tempo atrás, como alguém que também iniciou estudos nessa área recentemente. Espero que esse material seja de utilidade para os interessados.

Estão disponibilizados os arquivos de exemplo no link abaixo, para que possam acompanhar o artigo.

http://rapidshare.de/files/38219238/colisao.zip.html

1- Bounding Boxes - bbox.fla
O meio mais simples de testar uma colisão, é através do método hitTest, também conhecido como colisão entre boxes (caixas).

Esse método checa as extremidades(bounds) de cada um dos objetos, traçando um quadrado que o envolva como um todo (box), e então através de geometria verifica se estes quadrados se sobrepõem.

A utilização de bounding boxes é de certa forma restrita a quadriláteros ou objetos menores onde imperfeiçoes de colisão não seriam notadas.
2- Raio - raio.fla
Técnica similar a dos BoundingBoxes, porém ao invés de quadrados, é testada a sobreposição entre 2 círculos para identificar a colisão

O Flash não possui um método próprio para colisão entre 2 objetos através de raio, porém o processo é bem simples:

distancia = Math.sqrt ( (obj2.x - obj1.x)*(obj2.x - obj1x) + (obj2.y - obj1.y)*(obj2.y - obj1.y) )

if(distancia < obj1.raio + obj2.raio){
//colisão confirmada
}else{
//não há colisão
}

3- Ponto e bound - bound.fla
Nesse tipo de colisão se determina uma extremidade em um eixo, e testa se a posição de um ponto perante a linha imaginária traçada em perpendicular ao eixo que foi determinada essa extremidade.

Esse tipo de colisão pode ser utilizada em vários casos, num game estilo Space Invaders por exemplo, pode ser utilizada para limitar o deslocamento horizontal da nave, já num game sidescroller, essa técnica pode ser utilizada para definir um chão para os objetos.

No arquivo de exemplo apliquei esta técnica 2 vezes, sendo a primeira para determinar a penetração da faca na “parede”, e a segunda para limitar a movimentação da mesma ao comprimento da lâmina.

Note que a “parede” é apenas uma linha, sem nenhum tipo de ligação com o código, mover essa linha no palco exigirá que se reestabeleça o valor “paredeX” para que se mantenha o efeito correto.
4- Ponto e objeto - pontoObj.fla
O método ponto-objeto toma como referência o bounding box do objeto que chama o método, mais o ponto formato pelas coordenadas X e Y passadas como parâmetro, e identifica se este ponto está dentro ou fora do quadrado formado pela box do objeto.

O grande diferencial desse método, é um terceiro parâmetro booleano que permite que utilizemos-nos de ShapeFlag, permitindo um teste de colisão ponto-objeto preciso para objetos complexos.
A primeira vista, um método de colisão preciso, mas que se utiliza apenas de um ponto pode parecer algo meio inútil, mas se avaliarmos as possibilidades possíveis ao utilizar se de vários pontos para o teste de colisão entre 2 objetos, essa técnica pode resolver diversos problemas de colisão.
5- Setor Angular - setorAngular.fla
Aqui utilizamos da mesma técnica do exemplo de Raio, porém, adicionar uma outra condicional, testando o angulo do objeto “flutuante” em relação ao a centro do objeto que gera o setor do angular.

A novidade aqui é o método Math.atan2(), que ao receber as coordenadas de um ponto, retorna seu angulo, no caso nós subtraimos o (x,y) do mouse pelo (x,y) da lanterna, para que essa seja utilizada como centro e referencia para calculo de angulo.
O miolo do código de colisão é esse:

if(dist < raioSetorAngular){
if(Math.abs(anguloObjeto) < anguloSetorAngular/2){
//colisao detectada
}else{
//não há colisão
}
}

Por hoje é só, citei aqui alguns dos métodos mais comuns e efetivos de se testar colisão, e é claro, ainda existem as diversas formas de se resolvê-las, mas isso daria assunto para muitos outros artigos.

[]’s e até a próxima.

4 Comentarios

Novo livro na área: Videogame Arte

Há um bom tempo eu não via novas publicações de livros, em português, voltados para nossa área (se eu estiver errado, por favor gritem nos comentários!). O primeiro material que tive contato foi o SimulacrON, do Luciano Augusto, publicado em 2004 e dizendo ser “o primeiro do Brasil na área de Game e Level Design”. Em 2005, surgiu o “Programação de Jogos com C++ e DirectX” do André Santee, publicado pela Editora Novatec e mais robusto do que o livro do Luciano, este conta com cerca de 400 páginas e foca mais especificamente a programação de jogos. Também pela Novatec e no mesmo ano, Alexandre Perucia, Antônio de Berthêm, Guilherme Bertschinger e Roberto Castro lançaram o livro “Desenvolvimento de Jogos Eletrônicos - Teoria e Prática” que ano passado teve sua 2ª edição publicada.

Por falar em 2007 (que coisa velha! Notícia do ano passado…), estava acessando o site CGMax e vi a notícia de que seria lançado em dezembro o livro “Videogame Arte”, de Arthur Bobany. Explico: o professor Paulo Andrade, que coordenada os cursos do CGMax, está com um artigo falando sobre as carreiras no mercado de games. Fui pertubar o Paulo e ele me disse que tinha um anúncio na 3D4All. Lá finalmente encontrei um link para o site do livro (me senti em um atendimento de companhia telefônica, só faltou a trilha sonora “Für Elise”) e pude conferir um pouco mais sobre o trabalho.

De acordo com o site, o livro “fala sobre o desenvolvimento de games, discute as características que constituem os jogos como formas de arte, aborda temas como o futuro dos games e sua relação com a cultura, além de falar sobre as etapas para o desenvolvimento de um jogo.” Logo no início é possível conferir a capa e o layout de algumas páginas, além de poder baixar o “pacote de expansão”, um pdf de quase 2MB abordando um pouco sobre a arte nos games.

Videogame Arte: www.novasideias.com.br/games


(Nota: no blog Tupinihon, mais especificamente neste post, você pode conferir mais informações sobre livros em português da área de gamedev)

3 Comentarios

A Equipe de Desenvolvimento – Parte II: Produtor

E aí comunidade PDJ,

Consegui escrever mais este artigo a tempo para o final do ano. Como na parte 1 analisamos as funções do Game Designer, vamos falar aqui do Produtor. Então direto ao assunto…

Produtor

Segundo o Game Design Workshop – Fullerton, Swain e Hoffman – a definição mais simples para o Produtor dentro de uma equipe de desenvolvedores é “Lider do Projeto”. O Produtor é responsável pela entrega do jogo pronto (claro que é uma responsabilidade de toda a equipe também…) no prazo e custo predeterminados. O Produtor deve ter um controle to que está sendo desenvolvido, utilizando calendários, organogramas, listas de checagem, balanços entre outros.

Embora estejamos focados aqui na equipe de desenvolvimento, devo incluir que muitas vezes os Produtores trabalham em publishers (distribuidoras de jogos) também, servindo de eixo de contato para as decisões importantes. Em casos de projetos envolvendo equipes muito grandes, ou em parcerias entre desenvolvedoras, costumam-se ter um Produtor em cada equipe, para manter a organização do projeto equilibrada e focada nas mesmas metas entre todas as equipes de desenvolvimento, propaganda e distribuição.

Aqui vai uma lista das principais responsabilidades do Produtor:

• Lider (team leader) da equipe de desenvolvimento.
• Eixo de comunicação entre as equipes de desenvolvimento e distribuição/propaganda.
• Responsável pelo plano de produção, organogramas e calendários.
• Responsável pela preparação de recursos, planejamento de transportes e armazenagem.
• Contratação de serviços terceirizados e aluguel/compra de equipamentos.
• Gerenciamento da equipe de desenvolvimento para a conclusão do projeto nos prazos estipulados.
• Motivar e integrar a equipe, e solucionar problemas gerais relacionados.

Muitas vezes cabe ao Produtor executar diversos “cortes” em implementações planejadas para o projeto, devido a limitações de tempo, pessoal e recursos, trabalhando em conjunto com o Game Designer para buscar soluções alternativas (muitas vezes um corte total não é necesário, sempre há outra solução).

O Produtor recebe, também, o papel de “representante” da equipe, como se fosse um tipo de “acessor de imprensa”, negociando diretamente com os clientes e parceiros externos. Uma equipe complexa pode ter mais de um Produtor, sendo cada um responsável por um grupo de produção, estes são os Produtores Assistentes e Produtores Associados, havendo também possíveis Produtores Sênior e um Produtor Executivo, responsável pelo projeto como um todo.

É isso aí…

3 Comentarios

Desenvolvendo Jogos em Delphi

Um grande “olá” a todos!

 

Demoramos, mas não falhamos em publicar aqui mais um tópico e hoje é a vez de apresentar um pouco do mundo da programação de jogos em Delphi.

 

Não, não será este um curso completo de programação em Delphi + criação de jogos em Delphi. Acho que está mais para um bate-papo sobre o que pode ser feito com a ferramenta e onde procurar informações que o nortearão neste processo de aprendizagem, ok?

 

Aos que não conhecem, uma apresentação sobre a ferramenta: Delphi não é uma ferramenta desenvolvida ESPECIFICAMENTE para a criação de jogos. Delphi trata-se de uma IDE (Integrated Development Environment) para a linguagem Object Pascal (os mais xiitas dizem ser uma variação da Object Pascal a linguagem com que Delphi trabalha). É uma ferramenta RAD, ou seja, para o desenvolvimento rápido de sistemas, e talvez isso explique por que esta ferramenta popularizou-se tanto dentre o pessoal de programação.

Por ser uma ferramenta RAD, o desenvolvimento de sistemas tradicionais é feito muito rápido nessa ferramenta, já com jogos, nem tanto, mas também não é nenhum bicho de sete cabeças!

Na verdade, considero o desenvolvimento de jogos em Delphi mais fácil do que em outras linguagens, mas não vou me prolongar mais a fim de evitar atritos desnecessários, como a “guerra das linguagens”.

O Borland Delphi é uma ferramenta paga, mas a Borland lançou o Delphi Explorer, uma versão free de seu software e que pode ser usado livremente.

 

Você deve estar se perguntando: e o que será que serei capaz de criar em Delphi? Será que há bons jogos desenvolvidos nisso?

Até há!

Um exemplo que já foi muito citado anos atrás são os jogos da série Age of Wonders. Quem quiser conhecer um pouco, pode ver o jogo Age of Wonders 2. Nos sites abaixo (o primeiro é o da empresa desenvolvedora) você poderá encontrar várias informações e telas dele:

http://www.triumphstudios.com/ageofwonders/

http://aow2.heavengames.com/

Um lugar cheio de informações e jogos desenvolvidos em Delphi pode ser encontrado no seguinte site:

http://www.delphigamer.com/main.php

 

Bem, se você quer criar jogos em Delphi, pode ser uma boa idéia primeiro conhecer a ferramenta, não? Algumas pessoas me perguntam se não há um curso pronto, onde ensine Delphi e desenvolvimento de jogos nesse ambiente. Olha, pode até ter! Se quer em português, o único lugar onde você deve encontrar é a Tilt.net .

Na PDJ nós temos alguns tutoriais, mas nada ensinando o básico de programação em Delphi, então o jeito é ou procurar na Internet (salve Google!) ou correr atrás de alguma empresa/escola que ofereça isso.

 

Uma vez que você já conhece um pouco a feramenta (aprendeu sobre como ela funciona e fez alguns programas para testar esse aprendizado) você estará apto a começar a pesquisar e estudar sobre a criação de jogos nele.

Uma boa idéia é começar vendo um pouco sobre como desenvolver jogos sem uso de APIs, bibliotecas, etc. voltados ao desenvolvimento de jogos. Por quê? Assim você não se prende aos “vícios” que nos acostumamos quando aprendemos a criar somente com um determinado conjunto de bibliotecas.

 

A revista ClubeDelphi apresenta esporadicamente artigos e tutoriais sobre criação de jogos, então você pode procurar por edições que sejam do seu interesse. Como já foi citado, a Tilt.net também pode lhe ser de bastante ajuda. Além disso, não se esqueça de nosa querida PDJ.

Você pode encontrar alguns tutoriais sobre jogos em Delphi no seguinte link:

http://www.programadoresdejogos.com/forum/viewtopic.php?t=5758

 

Se você vai começar estudando desenvolvimento de jogos em Delphi do zero ( o que acho excelente!), você provavelmente vai começar desenhando tudo diretamente no Canvas.

Canvas é uma superfície de um objeto na qual podemos desenhar, por exemplo, quando você coloca uma bitmap para aparecer num TImage, é no canvas do mesmo que ele desenha! Dá para se desenhar no canvas de diversos componentes: TForms, TImages, TPaintbox, etc.
Se você for trabalhar puramente com o Delphi, sem nenhuma biblioteca em especial, experimente brincar de desenhar no canvas do TPaintBox.

O Canvas possui um atributo Pixels, que é um array bidimensional, onde cada ponto representa a cor de um determinado pixel naquele objeto. Pronto! Você precisará mexer com esses pixels para desenhar no canvas.

Desenhe sempre o que vai ficar “por baixo” antes do que vai ficar “por cima”, porque o que você desenha sempre vai cobrir o que já estava lá antes!

Como desenhar um personagem com fundo transparente? Simples! Vamos supor que o preto é a nossa cor transparente… Então para cada ponto que você for desenhar você verifica se aquele pixel é da cor preta, se for, desconsidere-o, caso contrário, pinte no Canvas (plotar um pixel, eis o termo mais usado).

Legal, mas você está querendo criar uma esfera semi-transparente que irá ficar em volta do personagem, dando a impressão de ser um escudo, né? Bem, depois de plotar o seu personagem, você vai, para cada ponto da sua esfera (lembrando de só plotar os que não são parte do fundo!) fazer a média entre a cor que pertence à esfera e a cor que já está na posição em que você vai plotar. Desta forma, você consegue plotar algo com 50% de transparência. Bem, mas você talvez não tenha entendido direito esse cálculo, ou queira que seja plotada a imagem com outro percentual de transparência, então… Vamos a uma rápida fórmula para fazer esse cálculo, ok?
R1,G1,B1 -> são os valores RGB da cor de um dado pixel da esfera
R2,G2,B2 -> são os valores RGB da cor de um dado pixel no canvas
P -> percentual de transparência (0 a esfera não aparece, 100 a esfera aparece sem transparência)
RF,GF,BF -> são os valores RGB da cor que nós plotaremos no pixel
RF = (R1*P + R2*(100-P))/100
GF = (G1*P + G2*(100-P))/100
BF = (B1*P + B2*(100-P))/100
Pronto, ae é só pegar os valores RGB, converter para a cor e jogar nesse pixel!

Agora, você deve perceber que quando for aparecer na tela, ela às vezes ficará piscando. Por que isso? É que enquanto ainda está sendo desenhado no seu PaintBox, o formulário já está sendo desenhado na tela, ae fica mostrando a imagem se formando ainda (flickering ou cintilação, esse é o nome do efeito).
Para resolver isso é só ativar a dupla bufferização nos componentes sendo utilizados. Dependendo de qual o componente usado para desenhar, ativa-se no formulário ou no próprio componente. É só dizer: nome_componente.doublebuffered := true;

Dupla bufferização (ou double buffering) é uma técnica que usa uma superfície auxiliar para desenhar, enquanto que exibe somente a principal. Após concluir o desenho, essas superfícies são trocadas. Assim, o que sempre é visto na tela é uma superfície já totalmente desenhada.


Bem, mas você precisa que tudo isso seja executado infinitamente, num laço. O Delphi te oferece, para isso, um componente Timer. Ajuste o intervalo para que fique razoável a velocidade. Nele você deverá:
1. Verificar quais teclas foram pressionadas;
2. Apagar a tela;
3. Cálculos de colisões, física, etc;
4. Movimentar objetos;
5. Redesenhar a Tela;
6. Validações de vitória, derrota, etc;

Pronto! É algo mais ou menos assim!

Treine bastante a parte de manipulação gráfica e cálculos para detecção de colisão. Após “maestrar” a parte gráfica, cuide da parte sonora.

Como seu objetivo nos primeiros projetos será fazer tudo sem bibliotecas extras, você pode usar o componente MediaPlayer que devem estar em seu Delphi.

Depois de um ou dois projetos completos assim, você deverá ter compreendido as dificuldades que há no desenvolvimento de jogos sem as facilidades das APIs e bibliotecas auxiliares.

Há várias opções para quem está interessado em criar seus jogos em Delphi, algumas delas são:

- DelphiX

- Jedi-SDL

- Jedi-DirectX

- GLScene

Eu já usei bastante a DelphiX. Thiago Martinez (W_Snipes) já estudou a GLScene. Enfim, todo mundo que já estudou Delphi para jogos já se envolveu com alguma delas e conhece um pouco de suas vantagens e desvantagens, então querendo conversar sobre, é só falar, ok?

Quando você começar a criar seus jogos, vai perceber que irá precisar de um editor de mapas para criar mais cenários facilmente. Se precisar, pode usar o editor de mapas que eu criei para os meus projetos de jogos 2D tiled. Se bem me lembro, já está com o código-fonte, então você poderá estudá-lo e desenvolver o seu próprio, se preferir.

Bem, como disse, este não é um tutorial. Acho que está mais para um guia falando sobre o que você irá precisar e onde pode encontrar algo sobre. Quem souber tirar proveito pode conseguir com isso um excelente pontapé em seus estudos.

É isso. Até breve!

11 Comentarios

LuaJava – uma ferramenta de scripting para Java

Hoje vamos falar sobre como estender a linguagem Java usando a linguagem Lua. Mostraremos o Lua Java e como usá-lo para as principais operações.

Lua

Hoje não estamos aqui para falar do satélite natural da Terra, mas sim da linguagem de scripting Lua. Desenvolvida totalmente em território tupiniquim pelo time da TecGraf (Pontifícia Universidade Católica do Rio de Janeiro – Puc-rio). Lua é leve, veloz, é basicamente procedural, tipada dinamicamente, tem suporte a threads e possúi suporte a Orientação a Objetos usando metamecanismos (LuaTables!!).

Lua já foi empregada com sucesso em vários jogos comerciais, entre eles MDK2, World of Warcraft e Grim Fandango.

Você pode obter mais informações sobre Lua em www.lua.org.
LuaJava

Não, a Nasa não descobriu uma ilha chamada Java na Lua, nem tão pouco os cientistas da ilha de Java estão indo para a Lua. LuaJava é uma biblioteca que permite estender a linguagem Java usando Lua como ferramenta de scripting.

A grande jogada da biblioteca LuaJava é permitir interoperabilidade total entre o ambiente Java e o ambiente Lua. Você pode, por exemplo, criar classes em Lua e usar uma interface para instanceá-las em Java, ou então “importar” uma biblioteca escrita em Java (seja ela criada por você ou do pacote padrão) e usar em seus scripts Lua.
Indo para Lua com Java

A primeira coisa que precisamos para dar início a nossa viagem é do LuaJava, que pode ser adquirido em: http://www.keplerproject.org/luajava/.

Existem dois arquivos necessários para o funcionamento de LuaJava: luajava-x.x.jar e luajava-x.x.dll (libluajava-x.x.so para usuários do Linux)

Para instalar a biblioteca basta copiar o arquivo luajava-x.x.dll para a pasta bin no diretório do seu Java runtime (ou no diretório bin do seu Jdk), o arquivo luajava-x.x.jar deve ficar em algum caminho do CLASSPATH.

Feito isso você estará com o LuaJava instalado e funcionando.

Iniciando o LuaJava

A primeira coisa que você que já programou com Lua em C ou C++ antes deve saber é que as funções da API Lua estão totalmente disponíveis aqui através da classe org.keplerproject.luajava.LuaState. Entretanto, quem não tem intimidade com a API Lua, não fique desesperado. A LuaJava oferece várias funções que facilitam a integração de Lua com Java.

A Classe LuaState

O principal objeto da LuaJava é o LuaState. O LuaState guarda uma referencia para a máquina virtual Lua, e é a partir dele que você vai carregar arquivos de script, registrar classes, chamar funções, etc.

Para iniciar o LuaJava, você deve criar uma nova instância do objeto LuaState. Você pode também opcionalmente abrir as bibliotecas padrão do Lua. O seguinte trecho de código mostra um programa completo que abre uma nova instância da LuaJava e imprime Hello World na tela usando a função print do Lua.

package testeluajava;

import org.keplerproject.luajava.*;

public class Main {

public static void main(String[] args) {

LuaState l = LuaStateFactory.newLuaState();

l.openLibs();

l.LdoString(”print \”Hello World\” “);

l.close();

}

}

Claro, não precisamos nos fixar a executar comandos com o LdoString. Podemos usar o LdoFile para executar nossos arquivos de Script:

package testeluajava;

import org.keplerproject.luajava.*;

public class Main {

public static void main(String[] args) {

LuaState l = LuaStateFactory.newLuaState();

l.openLibs();

l.LdoFile(”teste.lua”);

l.close();

}

}

//teste.lua

print “Entre com seu nome:”;

local nome = io.read();

local texto = “Hello ” .. nome;

print (texto);

O forte do LuaJava como dissemos anteriormente é permitir a interoperabilidade entre o ambiente Lua e o ambiente Java.

Usando classes Java em Lua.

Para usar classes escritas em Java no ambiente Lua, o LuaJava nos fornece duas funções: luajava.bindClass e luajava.new.

A função luajava.bindClass permite importar uma referencia para uma classe escrita dentro do ambiente Java, isso é feito da seguinte maneira:

//teste.lua

JFrame = luajava.bindClass(”javax.swing.JFrame”);

O único parâmetro que a função bindClass recebe é o nome completo (incluindo os pacotes) para uma classe Java. No exemplo acima JFrame agora é uma referencia para a nossa classe javax.swing.JFrame. Para podermos usar esta referencia para instancear um novo objeto, basta usar a função luajava.new da seguinte maneira:

//teste.lua

c = luajava.new(JFrame);

Após isso, podemos trabalhar com o objeto normalmente como se fosse uma classe nativa do Lua. O código abaixo cria uma janela com o título “Hello PDJ” com 300 x 300 pixels e que encerra a aplicação quando fechada.

//teste.lua

JFrame = luajava.bindClass(”javax.swing.JFrame”);

f = luajava.new(JFrame);

f:setTitle(”Hello PDJ”);

f:setSize(300,300);

f:setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f:setVisible(true);

Também podemos importar classes criadas por nós mesmos. Vamos considerar como exemplo a seguinte classe:

//PdjBlog.java

package testeluajava;

import java.util.ArrayList;

public class PdjBlog {

private ArrayList<String> posts = null;

public PdjBlog() {

this.posts= new ArrayList();

}

public void newPost(String post) {

this.posts.add(post);

}

public void printPosts()

{

for (int i = 0; i < this.posts.size(); i++) {

System.out.println(this.posts.get(i));

}

}

}

Em lua podemos usá-la da seguinte maneira:

//teste.lua

PdjBlog = luajava.bindClass(”testeluajava.PdjBlog”);

blog = luajava.new(PdjBlog);

blog:newPost(”Teste Lua Java!!”);

blog:newPost(”Usando Lua com Java!!”);

blog:newPost(”Outro Teste Lua Java!!”);

blog:printPosts();

Usando classes Lua em Java

Assim como é possível criar classes em Java e usá-las em Lua, também é possível fazer o contrário, definindo classes em Lua e usando-as em Java.

O processo para usar classes Lua em Java já é um pouco mais complicado. Para usar as classes você deve definir ma interface em Java que descreva a classe Lua que você deseja utilizar.

Podemos pegar como exemplo a seguinte interface:

//INpc.java

package testeluajava;

public interface INpc {

void setNome(String nome);

void falar();

}

Em Lua esta interface poderia ser definida como a seguinte classe:

//npc.lua

Npc = {

Nome = “”;

setNome = function(nome)

Nome = nome;

end;

falar= function()

local texto = “Olá eu sou um npc, meu nome é ” .. Nome;

print (texto);

end;

}

Para usar esta classe precisamos pegar sua referencia através do método getLuaObject da classe LuaState, como no código a seguir:

LuaObject obj = l.getLuaObject(”Npc”);

A função getLuaObject recebe um parâmetro que é o Nome do objeto no ambiente Lua, ele retornar uma referencia para esse objeto com o qual podemos trabalhar. Porém ainda não estamos aptos a usar a nossa classe Lua. O LuaObject pode ser qualquer coisa adquirida do ambiente Lua. Podemos por exemplo criar uma função no ambiente Lua e chamá-la do nosso código Java da seguinte maneira:

//teste.lua

function HelloWorld()

print “Hello world from Lua function”;

end;

//Código java

package testeluajava;

import org.keplerproject.luajava.*;

public class Main {

public static void main(String[] args) {

LuaState l = LuaStateFactory.newLuaState();

l.openLibs();

l.LdoFile(”teste.lua”);

try

{

LuaObject func = l.getLuaObject(”HelloWorld”);

func.call(null);

}catch(Exception e)

{

System.out.println(e.getMessage());

}

l.close();

}

}

Voltando a nossa classe npc, para podermos usá-la precisamos criar uma “proxy” para ela, ou seja, precisamos dizer ao LuaJava que a nossa Interface INpc é compatível com nossa classe npc e que podemos usá-la para manipular nosso objeto. Fazemos isso através da função createProxy, como mostrado a seguir:

INpc npc = (INpc) obj.createProxy(”testeluajava.INpc”);

A função createProxy recebe como parâmetro o nome da Interface que desejamos fazer a Proxy (note que novamente precisamos passar o nome do pacote junto). A função retorna um objeto o qual fazemos casting para INpc. Uma vez feito isso podemos chamar as funções da classe normalmente. Aqui vai a listagem completa do código Java.

package testeluajava;

import org.keplerproject.luajava.*;

public class Main {

public static void main(String[] args) {

LuaState l = LuaStateFactory.newLuaState();

l.openLibs();

l.LdoFile(”npc.lua”);

try

{

LuaObject obj = l.getLuaObject(”Npc”);

INpc npc = (INpc) obj.createProxy(”testeluajava.INpc”);

npc.setNome(”Supersayajin”);

npc.falar();

}catch(Exception e)

{

System.out.println(e.getMessage());

}

l.close();

}

}

Note que, como estamos lidando com código externo a nossa aplicação é sempre bom tratar possíveis exceções. A função createProxy ainda nos obriga a tratar possíveis LuaException e ClassNotFoundExceptions.

Passando objetos por parâmetro

Quando trabalhamos com proxys chamando classes Lua no ambiente Java não precisamos chamar a função luajava.bindClass para usarmos em Lua uma classe Java que estejamos passando por parâmetro para algum método, a tipagem dinâmica do Lua cuida disso para nós, altere a INpc adicionando um novo método void postarNoBlog(PdjBlog blog); e implemente essa rotina na sua classe em lua:

postarNoBlog = function(blog)

blog:newPost(”Post do Npc “.. Nome);

end;

Quando chamarmos a função postarNoBlog podemos passar para ela um objeto do tipo PdjBlog, sem precisarmos usar a função luajava.bindClass. A seguir segue todo o código fonte para esse exemplo:

//PdjBlog.Java

package testeluajava;

import java.util.ArrayList;

public class PdjBlog {

private ArrayList<String> posts = null;

public PdjBlog() {

this.posts= new ArrayList();

}

public void newPost(String post)

{

this.posts.add(post);

}

public void printPosts()

{

for (int i = 0; i < this.posts.size(); i++) {

System.out.println(this.posts.get(i));

}

}

}

//INpc.java

package testeluajava;

public interface INpc {

void setNome(String nome);

void falar();

void postarNoBlog(PdjBlog blog);

}

//Main.java

package testeluajava;

import org.keplerproject.luajava.*;

public class Main {

public static void main(String[] args) {

LuaState l = LuaStateFactory.newLuaState();

l.openLibs();

l.LdoFile(”npc.lua”);

try

{

PdjBlog blog = new PdjBlog();

LuaObject obj = l.getLuaObject(”Npc”);

INpc npc = (INpc) obj.createProxy(”testeluajava.INpc”);

npc.setNome(”Supersayajin”);

npc.postarNoBlog(blog);

blog.printPosts();

}catch(Exception e)

{

System.out.println(e.getMessage());

}

l.close();

}

}

//npc.lua

Npc = {

Nome = “”;

setNome = function(nome)

Nome = nome;

end;

falar = function()

local texto = “Olá eu sou um npc, meu nome é ” .. Nome;

print (texto);

end;

postarNoBlog = function(blog)

blog:newPost(”Post do Npc “.. Nome);

end;

}

Bom pessoal, esta foi uma pequena introdução ao que é possível fazer com LuaJava. Mais detalhes e tutoriais sobre o LuaJava podem ser conseguidos no site oficial do projeto www.keplerproject.org/luajava/

Espero que tenham gostado.

Abraços e até a próxima. ;)

At. Edmar.

5 Comentarios

Dando um Zoom em Imagens

Boa noite!
Bem, desta vez, vamos ver como fazer um efeito de zoom para as imagens.

Em primeiro lugar, definamos três coisas:

Zoom -> Efeito de escalonamento proporcional da imagem;
Zoom In -> Efeito de aumento do tamanho da imagem;
Zoom Out -> Efeito de redução do tamanho da imagem.

Seria ridículo se vocês saíssem daqui sem saber isso, né? =)

Bem, agora sim.
Estou falando tudo isso, porque algum tempo atrás estudei os efeitos de Zoom e consegui fazer isso de um jeito bem simples.
O caso é que, dada uma imagem de tamanho largura x altura, nós queremos exibir ela alterada por um determinado fator de zoom centralizada numa outra superficie de tamanho largura x altura.

O que vamos precisar é simplesmente varrer toda a imagem destino (ImgDest) e sair verificando qual a cor do pixel correspondente na imagem origem (ImgOrg).

Agora, a dúvida é: como saber qual o pixel de onde pegar a cor da ImgOrg?

Bem, como a gente falou, a imagem deve ficar centralizada.
Logo o pixel (largura/2, altura/2) de ImgDest deve ser igual ao pixel (largura/2, altura/2) de ImgOrg.

Agora, pensemos juntos. Se eu tenho um pixel de Img que está a uma distância X do centro, ao dobrar a imagem (zoom = 2), a que distância ela estará do centro? 2X.
Do mesmo jeito, se eu reduzir à metade o tamanho da imagem (zoom = 0.5), a que distância ficará? 0.5X.

Viu só? Da ImgOrg para a ImgDest, a distância para o centro fica multiplicada pelo fator zoom.
Mas nós falamos que vamos varrer a ImgDest, ou seja, nós vamos sair de ImgDest para achar valor em ImgOrg, então a gente aplica a operação inversa: divide a distância ao centro por zoom.

Então o que nós vamos ter que fazer é achar a posição relativa de cada pixel ao centro da ImgDest, dividir pelo fator de zoom, somar então novamente o valor do ponto central e então nós teremos achado o pixel correspondente na ImgOrg!

Ae vocês me perguntam… Desse jeito, eu posso pegar um pixel fora da ImgOrg! O que fazer nesse caso?
Simples: o Delphi automaticamente estabelece cor Preta caso o pixel não exista, mas daí vocês podem tratar dentro do código, primeiro verificando se aquele pixel realmente está nos limites, se não estiver, usam uma cor qualquer para plotar na ImgDest.

Ah! E já que vamos trabalhar com divisões, zoom tem que ser diferente de zero!

Bem, o algoritmo no Delphi fica da seguinte forma…


  If zoom 0.0 Then

    exit;

  for x := 0 to largura-1 do

    for y := 0 to altura-1 do

      ImgDest.Canvas.Pixels[x,y] := ImgOrg.Canvas.Pixels[

                                           trunc((x - largura/2)/zoom + largura/2),

                                           trunc((y - altura/2)/zoom + altura/2)];

Viu só como é simples?
Caramba, e eu sempre achando que era bem mais complicado!

Bem, pra concluir, vejam aqui duas imagens exibindo o resultado final…

Essa é a imagem original, vamos agora aplicar a ela um fator de zoom 3 (vamos ter uma imagem resultado correspondente a esse retângulo marcado aí no meio…)

Pronto, aqui está a imagem resultado, lembrando-se que aplicamos um fator de zoom 3.

Então já fica perceptível que para valores absolutos de zoom entre 0 e 1, teremos efeito zoom out (a imagem fica reduzida) e para valores absolutos de zoom maiores que 1, zoom in.

Mas, porque eu falei em valores absolutos?

Simples, porque quando zoom é positivo, a imagem vai ficar normal, mas… quando zoom é negativo, ocorre zoom in/out, mas a imagem final fica invertida (rotacionada 180 graus). Por quê? É só lembrar que nós dividimos por zoom para encontrar o pixel correspondente, nossa origem ( 0, 0 ) é o centro da imagem e, quando for negativo o zoom, irei portanto pegar o pixel do lado oposto da imagem (tanto na horizontal quanto na vertical) .

Bem, é só isso por enquanto, espero que tenham gostado.

Um abraço e até breve!

Um Comentario