Meine Gedanken zur Spieleprogrammierung - Teil 3 - Die Leinwand

D

DocJunioR

Ambitioniertes Mitglied
Threadstarter
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.
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);
                }
            }
        }
    }

    
}
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.
 
D

DocJunioR

Ambitioniertes Mitglied
Threadstarter
Bevor noch jemand mosert: Der Code aus diesem Teil ist streckenweise einigen Quellen aus dem Internet entlehnt. Prinzipiell aber nicht einfach abgeschrieben, sondern entsprechend an mein Gedankengut angepasst.
 
S

swordi

Gewerbliches Mitglied
threads ist eine allgemeine lösung

es gibt in android noch handler. ich hab schonmal darüber etwas updaten lassen. arbeiten im prinzip wie threads, nur halt ein wenig anders aufgebaut.

kann aber keine vergleiche ziehen, was besser ist
 
D

DocJunioR

Ambitioniertes Mitglied
Threadstarter
hatte sie mir im Vorfeld zu diesem Teil nochmal angesehen. Thematisch sind sie zum Verarbeiten von Nachrichten, ansonsten könnte man sie möglicherweise auch nutzen. :) kannst sie ja mal probieren und das Ergebnis posten. Interessiert mich auch
 
Zuletzt bearbeitet:
S

swordi

Gewerbliches Mitglied
ich habe sie schon als "art" thread benutzt. wenn ich zeit hab, kann ich das ungefähr mal hier rein posten. muss aber im moment meinen umzug organisieren
 
D

DocJunioR

Ambitioniertes Mitglied
Threadstarter
hat zeit. ich werd eh so weiter machen- bin unverbesserlich.

btw. hat schonmal wer es-opengl genauer angeschaut?
 
L

Lemonbaby

Neues Mitglied
swordi schrieb:
threads ist eine allgemeine lösung

es gibt in android noch handler. ich hab schonmal darüber etwas updaten lassen. arbeiten im prinzip wie threads, nur halt ein wenig anders aufgebaut.

kann aber keine vergleiche ziehen, was besser ist
Handler dienen der Implementierung eines Messaging-Systems
und haben mit Threads nicht mehr zu tun, als das letztere sie
zur Kommunikation nutzen können.

Bitte keine Äpfel und Birnen durcheinanderwerfen...
 
S

swordi

Gewerbliches Mitglied
ja sicher sind sie für ein messaging system gedacht, aber man kann sie so verwenden wie auch threads.

ob das jetzt resourcen technischen besser ist, sei mal dahingestellt.
 
L

Lemonbaby

Neues Mitglied
swordi schrieb:
ja sicher sind sie für ein messaging system gedacht, aber man kann sie so verwenden wie auch threads.
android.os.Handler != android.os.HandlerThread

In einem anderen Thread beschwerte sich völlig zurecht ein
User darüber, dass hier Entwicklungsthemen sehr verwirrend
bis unverwertbar angehandelt werden. Eine gewisse sprach-
liche Präzision würde hier die Dinge deutlich verbessern. Du
selber magst wissen, wovon Du redest. Sinn dieses Forums
ist aber meiner Meinung nach, auch Usern, die ihre ersten
Schritte in Java machen, eine Hilfe zu sein und tiefere Ein-
blicke in fortgeschrittene Themen der Entwicklung zu geben.
Dazu muss auch mal bereit sein, etwas weiter auszuholen,
um nicht nur in reines Fachgesimpel zwischen erfahrenen
Entwicklern zu verfallen. Je mehr Details man verständlich
beschreibt, desto größer ist die Zielgruppe...
 
D

DocJunioR

Ambitioniertes Mitglied
Threadstarter
uuuh baby, baby its a wild world... ;)
mädels, zerkloppt euch nicht gegenseitig deswegen. er mensch ist nunmal unpräzise. Verallgemeinerung ist immerhin die Stärke deuronaler Verdrahtungen...
 
D

DocJunioR

Ambitioniertes Mitglied
Threadstarter
... und meine schwäche ist eindeutig das einhändig tippen und gleichzeitige anziehen von schuhen an kleinstkindern..
 
Oben Unten