Spieleprogrammierung: Grafik verrutscht auf Hintergrundbild

D

Duckemai

Fortgeschrittenes Mitglied
6
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:
  • Danke
Reaktionen: Duckemai
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
 
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
 
  • Danke
Reaktionen: Duckemai
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
 
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...
 
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.
 
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.
 
  • Danke
Reaktionen: Duckemai
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
 
  • Danke
Reaktionen: Duckemai
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:
 
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
 
@funcoder

SUPER. Genau das war es!!!

Vielen Dank
Duckemai
 

Ähnliche Themen

D
Antworten
3
Aufrufe
457
jogimuc
J
CrazyC
Antworten
0
Aufrufe
731
CrazyC
CrazyC
T
  • Gesperrt
  • Tholkin
Antworten
3
Aufrufe
1.848
swa00
swa00
Zurück
Oben Unten