20 de janeiro de 2013

C, C++, Haskell, Java?

Estou empolgado e agoniado com meu aprendizado sobre OpenGL. Ao mesmo tempo em que aprender OpenGL me deixa muito satisfeito, também me deixa inquieto: dediquei muito tempo aprendendo Haskell e fui envolvido de uma forma a gostar muito da linguagem e da comunidade. Porém, fazer algo em OpenGL se mostrou muito difícil e até mesmo solitário. Existem pouquíssimos materiais sobre isso e a maioria deles estão obsoletos.

Tive que largar Haskell por um tempo e religar os neurônios da linguagem C para aprender o fluxo das versões mais modernas do OpenGL, com shaders e buffer objects. O motivo foi simples: não consegui fazer nada funcionar em Haskell e não tive certeza se a culpa era minha ou das bibliotecas que utilizava.

Pois bem, fazer uma câmera se movimentar em um mundo 3D em C também não foi nada fácil. Mas com a abundância de material, consegui deixar funcionando de uma forma que me deixou bem satisfeito.

Decidi então voltar para Haskell e aplicar este conhecimento que acabei de conquistar.

Que trabalheira! Fazer tudo se encaixar da maneira certa e com os tipos corretos me fez suar algumas camisas. Se não fosse tão teimoso, não teria conseguido. Tive que trocar o pacote OpenGL pelo OpenGLRaw pois o pacote OpenGL não tem binding para "glUniformMatrix*"; também troquei o GLFW pelo GLFW-b porque o primeiro dependia do pacote OpenGL.

Recentemente li um artigo no InfoQ questionando se a linguagem C ainda era útil. Me fez pensar em muita coisa, inclusive em abandonar definitivamente Haskell e voltar às origens: ponteiros, gerenciamento de memória manual, strings cabulosas, ...

Talvez seja porque sou muito novo neste mundo, mas me sinto meio improdutivo programando em Haskell. A impressão que tenho é que, a menos que seja algo muito bem consolidado e utilizado por muitas pessoas da comunidade, muito tempo será gasto atrás de bibliotecas que normalmente são apenas um binding para uma escrita em C. Quando não for isto, só para ter uma breve ideia do que a API de uma biblioteca faz, acabo lendo alguns papers relembrando o que são Functors e Monads (para entender Arrows acho que vou precisar comprar um livro!).

Entender ponteiros e gerenciamento de memória em C também foi difícil. Mas naquela época eu era um jovenzinho no mundo da programação, meu conhecimento era muito limitado, se baseava muito em bater no código até que ele fizesse o que eu queria. Agora não consigo mais aceitar fazer alguma coisa sem entender o que estou fazendo.

Eu lembro que tive bons motivos para trocar C por Java. Depois de passar um tempo utilizando Java, vejo também as partes negativas da linguagem. Meu trabalho de conclusão da graduação foi dedicado a evidenciar os motivos desta troca e do futuro promissor de linguagens como Haskell.

No final das contas, acredito que esta pseudo-decepção acontece com toda linguagem em que você dedica bastante tempo para aprendê-la. A propaganda e os primeiros passos são maravilhosos. Parece que você descobriu um novo mundo onde todos são ricos e podem desfrutar de todas as coisas boas. Com o tempo você percebe que não é bem assim: cada escolha que a linguagem fez significa pontos positivos e negativos para nós usuários. Foi assim com C, Python, Java e agora com Haskell.

Java escolheu uma abordagem orientada a objetos: mesmo que seja uma função estática ou uma variável global, será necessária a roupagem de uma classe para acomodar este código. Haskell escolheu o funcional puro: mesmo operações que envolvam I/O recebem a roupagem de um monad.

Não que isto seja ruim. A utilização de monads para modelar computação sequencial foi uma grande descoberta que proporcionou a criação de inúmeras soluções. Estas escolhas trazem pontos positivos e negativos. Só devemos ter cuidado com o purismo extremo para não criar aberrações (e.g. Singleton).

Enfim, estou agoniado pois não sei o que escolher:

  • C me parece flexível mas com as complexidades que não quero ter. C11 parece solucionar algumas coisas (e.g. <threads.h>), mas o GCC ainda não suporta;
  • Sou bem produtivo em Java mas o overhead obrigatório e a necessidade de ter uma JVM me irritam profundamente;
  • C++ ainda é uma incógnita para mim, se for para ir neste nível ainda prefiro utilizar C. Java já me fez ver os motivos para dizer não à O.O. Por outro lado, boa parte de quem utilizava C está indo para C++, inclusive o GCC está utilizando C++. As bibliotecas disponíveis para C++ também pesam bastante (e.g. GLM, Boost);
  • Haskell é minha linguagem da vez mas está começando a me incomodar um pouco, sentimento de improdutividade me deixa muito tenso. Talvez precise dedicar mais tempo para que isto passe. Não sei se este esforço irá valer a pena ou poderia ser melhor aproveitado aprimorando meus conhecimentos em outra linguagem.

A diferença de desempenho entre C e Haskell não me preocupa muito, pois não vou escovar bits para ter um bom desempenho tão cedo.

No final das contas, a opinião mais correta sempre é: depende do projeto, escolha a melhor linguagem para o seu projeto. Pois bem, não tenho projeto nenhum, mas quero me aprofundar no desenvolvimento de jogos.

E agora?

9 de janeiro de 2013

DuDuHoX com som: OpenAL

Trabalhar no DuDuHoX está cada vez mais difícil. Já pensei em desistir em alguns problemas que tive, seja com código ou com bibliotecas.

Colocar animação no jogo foi muito complicado. Porque o motor do jogo não tem estados intermediários em que o personagem está indo de uma casa para outra. O estado do jogo só permite que o personagem ocupe uma casa e não metade de uma e metade de outra.

Minha solução para isto foi colocar a informação de animação no código da interface gráfica (OpenGL). Após pressionar alguma tecla que movimente o personagem, o motor do jogo já estará no estado novo completo, mas a interface não aceitará mais nenhuma entrada enquanto não terminar de exibir a animação de movimentação.

Outro grande problema que tive foi quando decidi colocar sons no jogo. Meus objetivos são: música de fundo e sons posicionais. A biblioteca que achei para isto foi a OpenAL. Ela é feita em C mas existe o pacote Haskell que faz o binding.

Mas, nem tudo é tão bonito. Instalar a biblioteca OpenAL no Windows foi um tremendo caos. Foi uma tarde inteira tentando fazer isto. Quando finalmente consegui instalar, percebi que também iria precisar da biblioteca ALUT. Esta não foi tão difícil de instalar, porém, ocorriam erros de link durante a compilação. Felizmente encontrei um bug reportado para o GHC que tratava exatamente do meu problema: Ticket 1243. Depois de aplicar o patch, tudo funcionou.

Fiz uma música no OpenMPT, desenhei o personagem no GIMP e coloquei tudo dentro do jogo.

Apesar das dificuldades, estou muito feliz com resultado que estou obtendo em fazer o DuDuHoX em Haskell. Decidi gravar um gameplay com o CamStudio e compartilhar com vocês através do YouTube: