O documento apresenta tópicos avançados para desenvolvedores de jogos, incluindo introdução teórica sobre anatomia de jogos para Android, engeninas e frameworks para desenvolvimento, e demonstrações práticas de código usando a engine AndEngine para criação de sprites, partículas, tilemaps e outros elementos.
2. Agenda
1. Sobre mim
2. Introdução teórica
3. Tópicos nível Básico
4. Tópicos nível Intermediário
5. Tópicos nível Avançado
6. Q/A
7. Fim
3. Sobre mim
Graduado em Engenharia de Computação pela Veris Educacional - Metrocamp
Especialista em Desenvolvimento de Jogos Digitais pela PUC - Paraná
MBA em Gestão Empreendedora de negócios pela ESAMC - Campinas
Desenvolvedor de jogos desde 2004 onde atuou em empresas como Overplay,
Vostu e Daitan Games Studio(consultoria)
Fundador da empresa CooperGames
Coautor do livro "Design de Jogos: Fundamentos", publicado em 2008 pela
editora Brasport.
12. Engines e frameworks
para jogos Android
Os exemplos de código serão feitos usando por base a AndEngine, pois :
É uma engine open source
Grátis
Código fonte aberto e disponível par olhar/estudar/entender/usar/melhor
Cheia de exemplos
Bem suportada pela comunidade e criadores
Engine intuitiva e classes de fácil uso
Performática : Suporta OpenGL ES 2
Bacana ;)
14. Don't repeat yourself
A grande maioria dos jogos(ou mesmo Engines) dispõe de um conjunto de
classes básicas e comuns ao seu desenvolvimento, independente do gênero.
Tipicamente conhecidas como core game classes
A classe fundamental é o GameObject , que representa um elemento
qualquer de jogo ( Sprite, Jogador, Inimigo, texto etc.)
Cada engine/desenvolvedor organiza o GameObject da maneira mais
genérica possível adequada dentro do contexto do projeto do jogo.
15. Don't repeat yourself
Outras classes comuns também estão presentes, como por exemplo
Sprite(objetos animados em tela), GuiText( Textos dinâmicos dentro do jogo)
,Background( fundo do jogo, podendo ser animado ou estático).
Todas as classes restantes do jogo herdam de GameObject.
18. Gráficos
Recomendação quanto ao uso das APIS Gráficas :
Jogos 2D Simples : Puzzles, Plataformas simples, jogos de uma única tela : Use Canvas
19. Gráficos
Recomendação quanto ao uso das APIS Gráficas :
Jogos 2.5 D, 3D ou com muita atualização em tela : Use Opengl ES nem que seja a
versão 1.0
20. Em suma : Sempre que possível,
opte pelo OpenGL ES
21. Gráficos – Aceleração por Hardware
A partir da API 11(Android 3.0) a renderização é suportada por hardware
Todas as operações de desenho em tela são executadas usando a GPU
Mas......
Seu jogo IRÁ consumir mais memória ;(
Aceleração de hardware é habilitada por padrão a partir da API 14 mas deve ser feita explicitamente :
<application android:hardwareAccelerated="true" ...>
22. Tela cheia neles
Jogos : Usualmente em tela cheia !
Código da Activity do game :
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
24. Mão na massa : Conte o FPS
Frame rate é a frequência (taxa) em que um dispositivo de imagem produz imagens
únicas e consecutivas únicos chamadas frames
Frame rate é na maioria das vezes expressa em quadros por segundo (FPS)
Importante contar para verificar se o jogo não ficou travado em alguma rotina
AndEngine
this.mEngine.registerUpdateHandler(new FPSLogger());
E Pronto
26. Mão na massa : Desenhe alguns
GameObjects
Sprites !!
Passo 1 : Criar e carregar a textura :
this.mTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/face_box.png");
}
});
this.mTexture.load();
27. Mão na massa : Desenhe alguns
GameObjects
Passo 2 : Criar e adicionar o Sprite na cena :
Criar o Sprite :
final Sprite face = new Sprite(
centerX,
centerY,
this.mFaceTextureRegion
, this.getVertexBufferObjectManager());
Adicionar na cena :
scene.attachChild(face);
29. Mão na massa : Leia as entradas
TouchListener se estiver fazendo a própria engine (Chuck Norris mode = ON )
Ou, AndEngine !
Habilitando o Multi Touch :
engineOptions.getTouchOptions().setNeedsMultiTouch(true);
30. Mão na massa : Leia as entradas
final Sprite sprite = new Sprite(...) { // Pegando eventos de toque em um Sprite
@Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) {
switch(pSceneTouchEvent.getAction()) {
case TouchEvent.ACTION_DOWN:
// Touch em direção para baixo
break;
case TouchEvent.ACTION_MOVE:
// Toque E movimento
break;
case TouchEvent.ACTION_UP:
// Touch em direção para cima
break;
}
return true;
}
}
32. Mão na massa : Controles em tela !!!
Sempre que possível , use controles em tela pois :
Independem dos controles físicos em hardware
Fornecem melhor ergonomia de jogo em smartphones
São mais intuitivos de usar de calibrar por parte dos jogadores
34. Mão na massa : Controles em tela !!!
A AndEngine já possui uma classe própria para controles em tela :
AnalogOnScreenControl
35. Mão na massa : Controles em tela !!!
public AnalogOnScreenControl
(
final float pX,
final float pY,
final Camera pCamera,
final ITextureRegion pControlBaseTextureRegion,
final ITextureRegion pControlKnobTextureRegion,
final float pTimeBetweenUpdates,
final long pOnControlClickMaximumMilliseconds,
final VertexBufferObjectManager pVertexBufferObjectManager,
final IAnalogOnScreenControlListener pAnalogOnScreenControlListener
);
36. Mão na massa : Controles em tela !!!
new IAnalogOnScreenControlListener() {
@Override
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float
pValueX, final float pValueY) {
physicsHandler.setVelocity(pValueX * 100, pValueY * 100);
}
@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
face.registerEntityModifier(new SequenceEntityModifier(new ScaleModifier(0.25f, 1, 1.5f),
new ScaleModifier(0.25f, 1.5f, 1)));
}
});
38. Mão na massa :
Intermediário e Avançado
MOTHER OF GOD...
39. Mão na massa : Desenhe algumas
partículas !
Partículas : Menor ponto renderizável em uma cena de jogo, mas
com tempo de vida, trajetória e características próprias
Permitem reproduzir efeitos de fumaça, fogo, jatos de agua, sprays
etc.
40. Mão na massa : Desenhe algumas
partículas !
Usando a AndEngine :
this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 32, 32,
TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mParticleTextureRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mBitmapTextureAtlas, this,
"particle_point.png", 0, 0);
41. Mão na massa : Desenhe algumas partículas !
final CircleOutlineParticleEmitter particleEmitter = new
CircleOutlineParticleEmitter(ParticleSystemSimpleExample.CAMERA_WIDTH * 0.5f,
ParticleSystemSimpleExample.CAMERA_HEIGHT * 0.5f + 20, 80);
final SpriteParticleSystem particleSystem = new SpriteParticleSystem(particleEmitter,
60, 60, 360, this.mParticleTextureRegion, this.getVertexBufferObjectManager());
particleSystem.addParticleInitializer(new ColorParticleInitializer<Sprite>(1, 0, 0));
particleSystem.addParticleInitializer(new AlphaParticleInitializer<Sprite>(0));
particleSystem.addParticleInitializer(new
BlendFunctionParticleInitializer<Sprite>(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE));
particleSystem.addParticleInitializer(new VelocityParticleInitializer<Sprite>(-2, 2, -20,
-10));
particleSystem.addParticleInitializer(new RotationParticleInitializer<Sprite>(0.0f,
360.0f));
particleSystem.addParticleInitializer(new ExpireParticleInitializer<Sprite>(6));
44. Mão na massa : Use Tilemaps !!
Tilemap : Técnica de otimização de mapeamento de texturas onde é possível se ter uma
única textura, dividida em blocos(“azulejos”) e um ou vários cenários com mapeamentos
diferentes da mesma textura (sistema de matriz).
45. Mão na massa : Use Tilemaps !!
TileSet: Conjunto de áreas de textura delimitadas por uma região fixa
46. Mão na massa : Use Tilemaps !!
Tilemap : Tileset + Mapeamento usualmente feito com uma ou mais ferramentas por
exemplo,tiled.
47. Mão na massa : Use Tilemaps !!
Usando Tilemaps com a AndEngine :
TMXTiledMap mTMXTiledMap;
final TMXLoader tmxLoader = new TMXLoader(this.getAssets(), this.mEngine.getTextureManager(),
TextureOptions.BILINEAR_PREMULTIPLYALPHA, this.getVertexBufferObjectManager(),null);
this.mTMXTiledMap = tmxLoader.loadFromAsset("tmx/desert.tmx");
final TMXLayer = this.mTMXTiledMap.getTMXLayers().get(0);
scene.attachChild(tmxLayer);
49. Gráficos
Carregar texturas em arquivos .PNG é legal mas, quando se precisa carregar
muitas imagens, com memória(VRAM) limitada....
Solução ?
Usar compressão de texturas :
PVRTC e PVRTC2 : Algoritmos de compressão de textura(com perda) implementados
na maioria dos chips gráficos dos dispositivos Android(dentre outros)
Permitem o uso de texturas grandes comprimidas
51. Gráficos
Criar a PVRTexture com a AndEngine :
this.mTextureRGB565 = new PVRTexture(this.getTextureManager(), PVRTextureFormat.RGB_565, new
TextureOptions(GLES20.GL_LINEAR, GLES20.GL_LINEAR, GLES20.GL_CLAMP_TO_EDGE,
GLES20.GL_CLAMP_TO_EDGE, false)) {
@Override
protected InputStream onGetInputStream() throws IOException {
return PVRTextureExample.this.getResources().openRawResource(R.raw.house_pvr_rgb_565);
}
};
Implementar chamadas na mão via Chuck norris mode : Fica para os universitários
52. Dicas Finais
Garbage collector is our friend : Coopere com ele evitando alocações de
novos objetos dentro do game loop
Somente habilite os sensores(acelerometro) quando realmente precisar para
evitar descarregar a bateria rapidamente.
O jogo deve respeitar o ciclo de vida de uma Activity : lembre-se de
implementar os metodos de pause; resume, assim os jogadores poderão
restaurar o estado do jogo de onde foi parado.