Na minha opinão o hello world para desenvolver jogos eh mover um desenho primitivo na tela junto com a informação de FPS (frames por segundo) até porque logo logo perguntamos : tah rodando a quantos FPS ?
assim sendo já posso dizer que fiz o meu hello world para o android.
Alguns links que ajudaram bastante foram estes :
Uma apresentação da google sobre o desenvolvimento para de jogos para o Android
Writing-Real-Time-Games-for-Android
Os exemplos de cógigo citados na apresentação
C2B 2 GameView
Com certeza este exemplo que escrevi eh extremamente simples, mas exemplifica alguns elementos básicos :
- main loop
- chamada de update
- atualização da area de vizualização
- input do usuário
O ambiente que tenho eh o Eclipse com o plugin para desenvolvimento do android instalado, para os testes eu prefiro usar o telefone porque o emulador demora muito para inicializar
e este exemplo tem basicamento 3 classes :
GameActivity – que eh a entrada da aplicação, nela eu solicito o uso fullscreen para o jogo, e determino que a visualização será realizada por uma instancia da classe GameView.
package com.athanazio.android.moveball2;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
public class GameActivity extends Activity {
private GameView view;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
view = new GameView(this);
setContentView(view);
}
protected void onPause() {
super.onPause();
view.pause();
}
}
GameView – nesta classe reside o loop principal do jogo que é iniciado no final do construtor, note que na verdade eh criado um Thread com baixa prioridade, que passará a realizar as atividades de atualização e principalmente executar o método postupdate() notficando a interface que pode ser exibida.
além do loop principal o input direcional é tratado pelo método onKeyDown() e o tocar na tela pelo método onTouchEvent()
package com.athanazio.android.moveball2;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
public class GameView extends View implements Runnable {
private static final String TAG = "GAMEVIEW";
private static final int INTERVAL = 10;
private Paint cPaint;
private float x = 50;
private float y = 50;
private boolean running = true;
FPSCounter fps;
public GameView(Context context) {
super(context);
cPaint = new Paint();
setFocusable(true);
setClickable(true);
setLongClickable(true);
fps = new FPSCounter();
// Set the background
this.setBackgroundColor(Color.WHITE);
Log.i(TAG, "game view created");
Thread monitorThread = new Thread(this);
monitorThread.setPriority(Thread.MIN_PRIORITY);
monitorThread.start();
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
return super.onKeyUp(keyCode, event);
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean handled = false;
Log.i(TAG, "key down");
if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {
y = y - 5;
handled = true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
y = y + 5;
handled = true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
x = x - 5;
handled = true;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
x = x + 5;
handled = true;
}
return handled;
}
public boolean onTouchEvent(MotionEvent event) {
x = event.getRawX();
y = event.getRawY();
Log.i(TAG, "on touch");
return super.onTouchEvent(event);
}
public void draw(Canvas canvas) {
super.draw(canvas);
cPaint.setColor(Color.BLUE);
canvas.drawCircle(x, y, 15, cPaint);
cPaint.setColor(Color.BLACK);
canvas.drawText(fps.getFPS(), 20, 20, cPaint);
}
public void run() {
while (running) {
try {
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
Log.e(TAG, "main loop finished");
}
update();
postInvalidate();
}
}
private void update() {
fps.update();
}
public void pause() {
running = false;
}
}
FPSCounter – nesta classe é feita uma contagem de frames que o jogo consegue exibir por segundo, vi algumas implementações interessantes disto, mas acabei fazendo o mais simples e mais econômico, contar frames e ver se jah passou o tempo
note que algumas variáveis eu criei fora dos métodos para evitar que o Garbage collector tivesse que trabalhar, querendo ou não isto economiza alguns milisegundos
package com.athanazio.android.moveball2;
import java.text.DecimalFormat;
import android.os.SystemClock;
public class FPSCounter {
public static final DecimalFormat format = new DecimalFormat("###0.00");
private float frames;
private String fps;
private long start;
private long current;
public FPSCounter() {
start = SystemClock.uptimeMillis();
frames = 0;
fps = "???";
}
public void update() {
frames ++;
current = SystemClock.uptimeMillis();
if( current - start > 1000 ){
fps = format.format(frames);
frames = 0;
start = current;
}
}
public String getFPS() {
return fps;
}
}
a propósito o fps esta em torno de 90 e poucos, vamos ver o que acontece quando tiver de desenhar uma imagem no fundo e varias outras na tela hehehehe.
