D
DocJunioR
Ambitioniertes Mitglied
- 7
Herzlich Willkommen zurück in meinem Gedankengut- ich hoffe, es ist nich zu wirr.
Wir haben es bisher geschafft, unser Menü zu steuern, und Spieledaten zu speichern. Das alles würde in Verbindung mit ein paar ListViews, etc. schon ausreichen um beispielsweise ein Börsenspiel zu programmieren.
Aaaber man will ja mehr. Echte Grafik beispielsweise. Android bietet hier eine so genannte SurfaceView, die wir als Basis für ein Grafikpanel nutzen wollen. Dieses Panel wird zudem IGameView implementieren, es soll ja in den Rest unseres Framework integriert werden können.
Über Drawables, oder einfach Graphics-Primitive könnten wir im Android schon malen, auch das Abfangen von events ist ein sehr einfaches Unterfangen. Allerdings sieht es ein wenig unglücklich aus, wenn die Gegner sich nur bewegen, wenn man selbst irgendetwas getan hat. Dies ist der große Nachteil eventbasierter Softwaresysteme. Früher zu DOS-Zeiten gab es einen Mainloop der erst einmal geschaut hat, ob irgendetwas neues vom Spieler kam und anschließend die KI, sowie Grafiken aktualisierte.
Dies gilt es, jetzt nachzustellen. Hierbei hilft uns nach meiner Auffassung das Android-Framework nicht sonderlich. Der Java-Standard Allerdings schon. Java bietet die Möglichkeit, Funktionen über Threads parallel ablaufen zu lassen.
Wir schreiben uns also eine Klasse, die als parallel laufender Thread unser Spielefenster aktualisiert. Dies sollte nicht unbedingt permanent passieren. Unser Thread wird sich nach 25ms schlafen legen. Dies ermöglicht uns (je nach Rechenzeit der Einzelschritte) ca. 40 Frames pro Sekunde- mehr als ausreichend.
Threads sind mit Vorsicht zu genießen. Wenn man auf nicht direkt am Thread hängende Daten zugreift, kann das zu ziemlichen Zugrifssproblemen und zum Absturz des Programms führen. Wir müssen uns synchronisieren. Das Ganze kann dann so aussehen.
So, nun kann man seinen canvas je nach Wunsch alle 25ms neu bemalen und das auch noch per Reaktion auf irgendwas. Die Reaktion eines Objekts würde ich an dieses anhängen. Wie, erkläre ich dann beim nächsten Mal. Möglicherweise kann dies etwas länger dauern. Ich hab auch sowas wie Familie und die hat ab jetzt frei..
Kritik und Diskussion sind wie immer erwünscht.
Wir haben es bisher geschafft, unser Menü zu steuern, und Spieledaten zu speichern. Das alles würde in Verbindung mit ein paar ListViews, etc. schon ausreichen um beispielsweise ein Börsenspiel zu programmieren.
Aaaber man will ja mehr. Echte Grafik beispielsweise. Android bietet hier eine so genannte SurfaceView, die wir als Basis für ein Grafikpanel nutzen wollen. Dieses Panel wird zudem IGameView implementieren, es soll ja in den Rest unseres Framework integriert werden können.
Code:
public class GamePanel extends SurfaceView implements
SurfaceHolder.Callback, IGameView {
protected IViewSetter viewSetter = null;
protected GameThread thread = null;
.... <-- Das aus dem vorherigen Teil muss auch noch rein
/**
* @param context
*/
public GamePanel(Context context) {
super(context);
// Änderungen am Canvas werden hier verarbeitet
this.getHolder().addCallback(this);
// Gamethread erstellen
this.thread = new GameThread(this);
// das Panel ist fokussierbar
this.setFocusable(true);
}
/**
* @return
* @see de.docjunior.androidengine.GameThread#isRunning()
*/
public boolean isRunning() {
return thread.isRunning();
}
/**
* @param running
* @see de.docjunior.androidengine.GameThread#setRunning(boolean)
*/
public void setRunning(boolean running) {
thread.setRunning(running);
}
/**
* spielupdate
*/
public void updateGame() {
// TODO: Physikberechnungen, Objekt-KI, etc.
}
@Override
public void onDraw(Canvas canvas) {
// TODO: Darstellen der Objekte
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// tote Threads werden wieder erschaffen
if (!this.thread.isAlive()) {
this.thread = new GameThread(this);
}
// der thread wird gestartet
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean waiting = true;
thread.setRunning(false);
while (waiting) {
try {
this.thread.join();
retry = false;
} catch (InterruptedException e) {
//versuche mit thread eins zu werden..
}
}
Log.i(getClass().getSimpleName(), "Thread terminated...");
}
}
Über Drawables, oder einfach Graphics-Primitive könnten wir im Android schon malen, auch das Abfangen von events ist ein sehr einfaches Unterfangen. Allerdings sieht es ein wenig unglücklich aus, wenn die Gegner sich nur bewegen, wenn man selbst irgendetwas getan hat. Dies ist der große Nachteil eventbasierter Softwaresysteme. Früher zu DOS-Zeiten gab es einen Mainloop der erst einmal geschaut hat, ob irgendetwas neues vom Spieler kam und anschließend die KI, sowie Grafiken aktualisierte.
Dies gilt es, jetzt nachzustellen. Hierbei hilft uns nach meiner Auffassung das Android-Framework nicht sonderlich. Der Java-Standard Allerdings schon. Java bietet die Möglichkeit, Funktionen über Threads parallel ablaufen zu lassen.
Wir schreiben uns also eine Klasse, die als parallel laufender Thread unser Spielefenster aktualisiert. Dies sollte nicht unbedingt permanent passieren. Unser Thread wird sich nach 25ms schlafen legen. Dies ermöglicht uns (je nach Rechenzeit der Einzelschritte) ca. 40 Frames pro Sekunde- mehr als ausreichend.
Threads sind mit Vorsicht zu genießen. Wenn man auf nicht direkt am Thread hängende Daten zugreift, kann das zu ziemlichen Zugrifssproblemen und zum Absturz des Programms führen. Wir müssen uns synchronisieren. Das Ganze kann dann so aussehen.
Code:
public class GameThread extends Thread {
private boolean running = false;
private GamePanel gamePanel;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
public GameThread(GamePanel pGamePanel) {
this.gamePanel = pGamePanel;
}
/* (non-Javadoc)
* @see java.lang.Thread#run()
*/
@Override
public void run() {
while (isRunning()) {
Canvas canvas = null;
try {
canvas = gamePanel.getHolder().lockCanvas();
synchronized (gamePanel.getHolder()) {
// spieledaten updaten
gamePanel.updateGame();
// spiel neu zeichnen
gamePanel.onDraw(canvas);
}
sleep(25);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (canvas != null) {
gamePanel.getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
}
Kritik und Diskussion sind wie immer erwünscht.