Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

21.11.2013, 18:52

Scrollende Textur in SFML

Hallo zusammen,

für mein kleines Spiel – mit dem es leidlich vorangeht – möchte ich scrollende Texturen verwenden, um beispielsweise Wasserfälle, Nebelschwaden oder ziehende Wolken darzustellen. Zwar habe ich auch schon einen Weg gefunden, dies umzusetzen, aber meine Lösung funktioniert noch nicht so ganz, wie ich mir das vorstelle.

Ich habe mir einfach ein sf::Sprite geschnappt und dessen TextureRect auf die gewünschte Größe gesetzt. Für die zugewiesene Textur ist "repeated" eingestellt. Dadurch wird sie automatisch innerhalb des TextureRects wiederholt dargestellt. Das TextureRect wird dann in einer Update-Methode um einen festgelegten Geschwindigkeitsvektor verschoben. Also alles ganz einfach gelöst.

Nun zu meinem Problem: Die Koordinaten des TextureRects sind Integer. Dadurch scrollt die Textur natürlich ziemlich "hakelig", insbesondere wenn das Sprite hochskaliert wird. Ich suche deswegen nach einem Weg, die Textur weicher zu scrollen.

Die Textur soll sich auf einen festgelegten rechteckigen Bereich beschränken. Außerhalb dieses Bereichs soll die Textur nicht zu sehen sein. Deswegen ist es auch nicht so ohne Weiteres möglich, einfach das Sprite selbst zu verschieben und mehrmals neben- bzw. untereinander zu zeichnen.

Was gäbe es denn hier für Alternativen? Shader? Würde das Verschieben der Textur über einen Shader schon einen Unterschied machen?

patrick246

Treue Seele

Beiträge: 328

Wohnort: nahe Heilbronn/BW

Beruf: TG Profil Informatik-Schüler

  • Private Nachricht senden

2

21.11.2013, 19:26

Die Alternative wäre, das TextureRect nicht um den Geschwindigkeitsvektor zu verschieben, sondern um die Größe des Sprites, immer auf ein anderes Frame. Wenn genügend Frames vorhanden sind, die oft genug gewechselt werden, sollte es nicht ruckelig aussehen.

3

21.11.2013, 19:50

Ich würde es so machen wie patrick246 es schon sagt.

z.B. der Wasserfall desto mehr verschiedene Einzelbilder die nacheinander angezeigt werden um so flüssiger sieht die Animation aus und das verschieben der Sprites ist dann auch ohne weiteres möglich.

Gruß Koschi
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

KeksX

Community-Fossil

Beiträge: 2 107

Beruf: Game Designer

  • Private Nachricht senden

4

22.11.2013, 11:50

Eine andere Möglichkeit wäre, ein entsprechend großes Sprite zu nehmen und das zu bewegen. Kommt natürlich ganz darauf an, wie dein restliches Level aussieht, aber das ist unter Umständen nicht nur einfacher, sondern sieht auch noch besser aus. Zumindest für die Wolken hätte ich es so gemacht. Oder reden wir hier von Sprites, die den kompletten Bildschirm überlappen sollen?
WIP Website: kevinheese.de

5

24.11.2013, 01:00

@patrick246, @Koschi

Dieser Ansatz ist für meine Zwecke leider nicht so gut geeignet. Zum einen sind die scrollenden Texturen relativ groß und zum anderen werden sie auch nur sehr langsam gescrollt (pixelweise). Damit eine Frameanimation unter diesen Bedingungen flüssig abliefe, bräuchte ich also ausgesprochen viele Frames und dementsprechend auch eine riesige Textur.

@KeksX

Die Sprites für die Hintergrundgrafiken (wie z.B. Wolken) füllen in ihrer Breite das gesamte Level aus (die Texturen werden horizontal über das TextureRect gekachelt). Sie überlappen also den gesamten Bildschirm, falls du das damit gemeint hast. In der Tat hätte ich die Sprites einfach nur doppelt so breit wie das Level machen müssen und hätte sie dann ganz bequem anstatt der TextureRects verschieben können. Leider ist mir dieser Einfall nicht gekommen.

---

Jetzt habe ich es mit einem Shader gelöst und damit läuft es auch prima. So schaut der Fragment-Shader aus:

Quellcode

1
2
3
4
5
6
7
8
uniform sampler2D texture;
uniform vec2 scrollOffset;

void main()
{
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy + scrollOffset);
    gl_FragColor = gl_Color * pixel;
}


Und so wende ich ihn an:

C-/C++-Quelltext

1
2
3
4
5
6
void Background::drawCurrent(sf::RenderTarget& target, sf::RenderStates states) const
{
    m_scrollShader->setParameter("scrollOffset", m_scrollOffset);
    states.shader = m_scrollShader;
    target.draw(m_sprite, states);
}


Mich wundert nur, dass ich hier den texture-Parameter nicht explizit setzen musste, obwohl im Handbuch steht, dass das notwendig sei.
Vielleicht kann mir jemand sagen, warum das so ist?

Werbeanzeige