1. Nimm jetzt an unserem 2. ADVENT-Gewinnspiel teil - Alle Informationen findest Du hier!

Spieleprogrammierung: Grafik verrutscht auf Hintergrundbild

Dieses Thema im Forum "Android Spiele Entwicklung" wurde erstellt von Duckemai, 18.02.2011.

  1. Duckemai, 18.02.2011 #1
    Duckemai

    Duckemai Threadstarter Erfahrener Benutzer

    Beiträge:
    227
    Erhaltene Danke:
    6
    Registriert seit:
    05.04.2010
    Phone:
    Nexus
    Hallo zusammen,

    ich versuche derzeit ein kleines Spiel zu programmieren und habe dabei folgendes Problem:

    Ich habe ein Hintergrundbild (Landschaft) auf dem sich eine Grafik (Haus) befindet, das in einer ArrayList gespeichert ist.

    Das Hintergrundbild ist größer als mein Bildschirm. Daher berechne ich mittels MotionEvent.ACTION_MOVE immer den neuen Koordinaten-Wert, entsprechend meiner Fingerbewegung auf dem Bildschirm. Das klappt auch. Das Hintergrundbild scrollt.

    Nun muss sich die Grafik(Haus) auf dem Hintergrundbild ja mitbewegen, damit es wie fest verankert wirkt. Also verschiebe ich die Grafik ebenfalls um den ACTION_MOVE Wert. Das klappt auch, solange ich mich in der Mitte des Hintergrundbildes befinde.

    Wenn ich nun aber an den (zB linken) Rand des Hintergrundbildes komme, dann stoppe ich die Berechnung des Hintergrundbildes, da es sonst aus dem Bildschirm wandern würde. Die Koordinaten meines Hauses werden dann ebenfalls nicht neu berechnet, sonst würde es sich ja auf dem Hintergrund bewegen. Das klingt theoretisch richtig und klappt auch, wenn ich langsam scrolle. Scrolle ich aber schnell gegen den Rand, dann rutscht das Haus doch um einige Pixel.

    Meine eher allgemeine Frage ist:
    Ist mein theoretischer Ansatz richtig, um so etwas zu programmieren?
    Oder kennt jemand ein Tutorial, das so etwas beinhaltet? Habe schon einige gefunden, aber nicht mit scrollendem Hintergrund und Grafiken darauf.

    PS: habe jetzt mal bewusst auf Quelltext verzichtet. Wenn der Ansatz von mir richtig ist, dann kann ich die entsprechenden Code-Stellen gerne noch posten.

    Vielen Dank
    Duckemai
     
    Zuletzt bearbeitet: 18.02.2011
  2. v Ralle v, 18.02.2011 #2
    v Ralle v

    v Ralle v Android-Lexikon

    Beiträge:
    913
    Erhaltene Danke:
    199
    Registriert seit:
    27.08.2010
    Duckemai bedankt sich.
  3. Duckemai, 18.02.2011 #3
    Duckemai

    Duckemai Threadstarter Erfahrener Benutzer

    Beiträge:
    227
    Erhaltene Danke:
    6
    Registriert seit:
    05.04.2010
    Phone:
    Nexus
    Danke für den Tipp. Es ist aber nicht das Richtige dabei, das mein
    Problem löst.

    Vielleicht sind hier ein paar Spieleprogrammierer, die noch einen allgemeinen Rat zu meinem Problem haben?

    Gruß
    Duckemai
     
  4. sellfisch, 22.02.2011 #4
    sellfisch

    sellfisch Neuer Benutzer

    Beiträge:
    18
    Erhaltene Danke:
    1
    Registriert seit:
    22.02.2011
    Phone:
    HTC Desire
    Verwendest du irgendein Framework? Es gibt einige richtig gute OpenSource Engines für Android.

    Schau dir zum Beispiel mal AndEngine an: AndEngine - Free Android 2D OpenGL Game Engine
    Da sind viele Standartprobleme die man bei Spielen hat von vornherein gelöst und man muss sich seinen Kopf nicht mehr zerbrechen
     
    Duckemai bedankt sich.
  5. Duckemai, 22.02.2011 #5
    Duckemai

    Duckemai Threadstarter Erfahrener Benutzer

    Beiträge:
    227
    Erhaltene Danke:
    6
    Registriert seit:
    05.04.2010
    Phone:
    Nexus
    Hi sellfisch,

    ich benutze kein spezielles Framework, weil ich dachte, es müsste doch auch so gehen. Ich wollte mich nicht in ein riesen Framework einarbeiten, das ich nur für EIN Projekt brauche. Ich hatte mir AndEngine schon mal flüchtig angeschaut. Vielleicht werfe ich jetzt doch noch mal einen detaillierten Blick darauf.

    Danke und Gruß
    Duckemai
     
  6. wilco, 23.02.2011 #6
    wilco

    wilco Android-Hilfe.de Mitglied

    Beiträge:
    106
    Erhaltene Danke:
    32
    Registriert seit:
    10.08.2010
    Das klingt so als seien da die Berechnungen und die Grafik-Routinen nicht vollständig koordiniert. Was Du brauchst ist die Abarbeitungs-Reihenfolge:

    1. Berechnung Hintergrund-Position
    2. Berechnung Haus-Position
    3. Zeichnen des Hintergrunds
    4. Zeichnen des Hauses

    Wenn Du Berechnung und Zeichnen in verschiedenen Threads machst, musst Du aufpassen dass aus der gewünschten Reihenfolge 1234 dieser Schritte nicht z.B. die Reihenfolge 1342 wird.

    Du kannst Dir da z.B. ein Flag setzen das sagt "Berechnung abgeschlossen". Sobald Du in Schritt 1 gehst setzt Du das auf false, sobald Du Schritt 2 verlässt setzt Du es auf true. Schritt 3 startest Du dann erst wenn das Flag auf True steht.

    Gleichzeitig musst Du natürlich aufpassen dass nich während Schritt 3 und 4 laufen die Schritte 1 und 2 wieder parallel anfangen...
     
  7. Duckemai, 23.02.2011 #7
    Duckemai

    Duckemai Threadstarter Erfahrener Benutzer

    Beiträge:
    227
    Erhaltene Danke:
    6
    Registriert seit:
    05.04.2010
    Phone:
    Nexus
    Danke für den Eintrag!
    Würdest Du denn sagen, dass man grundätzlich so an die Sache rangehen kann. Oder ist schon der Grundgedanke falsch? Man könnte ja auch mit einem Hintergrund arbeiten, der aus Kacheln besteht.
     
  8. wilco, 23.02.2011 #8
    wilco

    wilco Android-Hilfe.de Mitglied

    Beiträge:
    106
    Erhaltene Danke:
    32
    Registriert seit:
    10.08.2010
    Ob Kacheln oder nicht ändert am Grundproblem das Du hast nichts. Wenn Du mit Kacheln arbeitest musst Du nur zusätzlich Dein Hintergrundbild erst aus den Kacheln heraus aufbauen.

    Letztlich ist hier die Frage wie groß Dein Hintergrundbild ist. Wenn Du ein Spielfeld hast sich über mehrere Bildschirme erstreckt (z.B. 10 Bildschirmlängen und 10 Bildschirmbreiten) dann hast Du eigentlich keine andere Wahl als mit Kacheln zu arbeiten, da Du eine Hintergrundgrafik von einer solchen Größe nicht mehr im Speicher wirst halten können.
     
    Duckemai bedankt sich.
  9. funcoder, 23.02.2011 #9
    funcoder

    funcoder Erfahrener Benutzer

    Beiträge:
    218
    Erhaltene Danke:
    38
    Registriert seit:
    15.08.2009
    Ich muss wilco recht geben ich habe in meinem aktuellen Projekt auch eine Landschaft ähnlich wie bei dir. Hatte zuvor abgewägt was besser wäre, einzelne Tiles zu erstellen und diese dynamisch zusammen setzen und rendern oder eine große Hintergrundgrafik.
    Was gegen die Kachel-Methode sprach, war einfach die unflexibilität. Meine Landschaftens sollten immer möglichst "anderst" aussehen. Die Performance bei dieser Methode ist zumindest speichertechnisch besser.

    Mein Problem ist, dass ich die gesamte Hintergrundmap in den Speicher laden muss. Die Dateigröße als JPG gespeichert ist das geringste Problem, aber in den recht kleinen 16MB Heap Space der dir zur Verfügung steht, werden alle Grafiken unkomprimiert abgelegt. Meine 500KB JPG wird dadurch gut 10mal so groß!

    Sollte daher deine Hintergrund Landschaft größer als 2000x2000 Pixel haben wirst du um die Kachel-Methode nicht vorbei kommen.

    Noch ein kleiner Performance Tipp, wenn du doch jedesmal die Landschaft rendern solltest. Zeichne nicht die gesamte Bitmap. Es wird ja nur ein kleiner Teil dargestellt. Besser ist es 2 Rectangles zu erstellen. Die eine enthält die Zielfläche (0,0,Viewport-Width,Viewport-Height) und die andere die Koordinaten die du von deiner Landschaft rendern möchtest. Beide Rectangles kannst du wiederum simple über drawBitmap(Bitmap, RectangleA, RectangleB, Paint) rendern.

    Und wegen deinem eigentlichen Problem. Du solltest die Position des Hauses nicht anhand des Fingerslides abhängig machen, sondern eher anhand der Koordinate an dem sich die Map befindet.

    Du slidest beispielsweise 10px nach "links". Somit reduziert sich der X Wert von dem die Landschaft gerendert wird um 10px.
    Von diesem Wert solltest du nun die Hausposition errechnen.
    z.B. HauspositionX = HausPosition+AktuelleSlidePosition

    HausPosition, ist die tatsächliche Position auf der dein Haus angezeigt werden soll, unabhängig wie geslidet ist. AktuelleSlidePosition enthält die Position von der an die Landschaft gerendert wird (mapPosition).

    Wichtig ist auch hier die Reihenfolge:
    1. Sliden erkennen, Differenz berechnen
    2. neue Map Position festlegen
    3. Haus Position anhand neuer Map Position festlegen
    4. Rendern
     
    Duckemai bedankt sich.
  10. Duckemai, 23.02.2011 #10
    Duckemai

    Duckemai Threadstarter Erfahrener Benutzer

    Beiträge:
    227
    Erhaltene Danke:
    6
    Registriert seit:
    05.04.2010
    Phone:
    Nexus
    Das klingt super und könnte mein Problem lösen. Werde ich gleich morgen früh ausprobieren. Jetzt erscheint es mir selbst absurd, dass ich die Hausposition vom Slide abhängig gemacht habe...:huh:
     
  11. MichaelS, 23.02.2011 #11
    MichaelS

    MichaelS Fortgeschrittenes Mitglied

    Beiträge:
    370
    Erhaltene Danke:
    51
    Registriert seit:
    14.08.2009
    Bin mich grade selber in die OpenGL Sachen am einarbeiten.

    Ich benötige selbst eine Tilemap. Wobei diese sehr groß sein kann, manchmal > 2048pixel breit / hoch. Ich habe mir viele verschiedenen Möglichkeiten angeschaut. Auch die AndEngine getestet, da diese TMX Support hatte.

    jedoch musste ich feststellen, dass bei großen karten + großen tilesets (1500x1500) die AndEngine sehr schlecht alles abarbeitet...

    Ich habe dann versucht die AndEngine zu verbessern... jedoch merkte ich schnell, dass deren ihrer Ansatz nicht optimal ist für so große karten...

    Meine Lösung die ich nun grade ausarbeite ist, ein eigenen TMX Support geschrieben und die AngleEngine genommen als Schablone und diese arg angepasst.

    Für so ein Vorhaben sollte man den Framebuffer verwenden. Wozu das ganze? Beim Level laden, erstelle ich mir 512er Texturen soviele wie ich für die map benötigen würde. auf diese Texturen rendere ich über den framebuffer die map in kacheln. somit erhalte ich für eine map von 1536x1536pixel 9 Kacheln a 512x512 pixel :) 512er Texturen kann eigentlich jedes device anlegen :)

    Mit der AndEngine hat alles geruckelt und unter 15fps....
    Mit der AngleEngine hat alles geklappt jedoch auch nur 23fps...

    Mit sehr stark angepasster AngleEngine + Framebuffer = > 60fps :)

    Mein Ziel war erreicht :) Wie hoch die Performance wirklich ist, kann ich wegen vsync nicht sagen ;) jedoch ist klar, dass es deutlich schneller geht statt 2300 (32x32) kacheln zu redern als 9 (512x512) Kacheln ;)

    Gruß
    Michael S
     
  12. Duckemai, 24.02.2011 #12
    Duckemai

    Duckemai Threadstarter Erfahrener Benutzer

    Beiträge:
    227
    Erhaltene Danke:
    6
    Registriert seit:
    05.04.2010
    Phone:
    Nexus
    @funcoder

    SUPER. Genau das war es!!!

    Vielen Dank
    Duckemai
     

Diese Seite empfehlen