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

Encounter

Frischling

  • »Encounter« ist der Autor dieses Themas

Beiträge: 22

Wohnort: Aachen

  • Private Nachricht senden

1

30.03.2016, 19:20

SFML 2.3.2 Hitboxen nach Skalierung des Fensters verschoben

Hallo liebe Spieleprogrammierer Community,

zu vielen Themen findet man über Google tolle Lösungen zu Problemen.
Leider hab ich zu meinem aktuellen Problem nichts gefunden und da fiel mir wieder diese nette Community ein.

Zum Thema:
Wir versuchen derzeit ein Spiel oder zumindest Basics davon als Teamprojekt in Viusal Studio Community 2015 zu erstellen.
Als Engine haben wir uns für SFML 2.3.2 entschieden. Nun ist es ja aber so, dass man das Fenster frei skalieren kann, was wir auch grundsätzlich im Fenstermodus beibehalten wollen.
Um je nach Größe einen Button immer in der Mitte zu halten, werden entsprechend Fensterhöhe und -breite abgefragt. Das klappt auch, allerdings wandert die Hitbox des Buttons nicht mit. Ich denke, ich habe da einfach die Handhabung von SFML des Fensters beim skalieren nicht wirklich verstanden.

Hoffe ihr habt eine Idee dazu :)

Der C++ Code dazu:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//Eigene Klasse zur Sprite Verwaltung (Member Variablen sind sf::Sprite Sprite und sf::Texture Texture und entsprechende Funktionen und Konstruktoren um die Textur auf den Sprite zu legen)
GameSprite spEditorButton("data/graphics/EditorButton.png");

//Button mitttig platzieren
spEditorButton.Sprite.setPosition(window.getSize().x/2-spEditorButton.Sprite.getGlobalBounds().width/2, window.getSize().y / 2 - spEditorButton.Sprite.getGlobalBounds().height / 2);

//[...]

//Nachfolgend soll die Maus Position abgefragt werden und entsprechend das Feld heler darstellen wenn sie auf dem button liegt
    if (sf::Mouse::getPosition(window).x >= spEditorButton.Sprite.getGlobalBounds().left && 
        sf::Mouse::getPosition(window).x <= spEditorButton.Sprite.getGlobalBounds().left + spEditorButton.Sprite.getGlobalBounds().width && 
        sf::Mouse::getPosition(window).y >= spEditorButton.Sprite.getGlobalBounds().top &&
        sf::Mouse::getPosition(window).y <= spEditorButton.Sprite.getGlobalBounds().top + spEditorButton.Sprite.getGlobalBounds().height) {
        spEditorButton.Sprite.setColor(sf::Color(255, 255, 255, 255)); //Button heller darstellen
        if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { 
            //Editor wird geladen
        }
    }
    else spEditorButton.Sprite.setColor(sf::Color(150, 150, 150, 255)); //Button wieder dunkler dartellen
Ich war hier und hab ALLES gesehen!

cojo2015

Alter Hase

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

2

30.03.2016, 19:54

Kurze Frage: Warum willst du denn, dass man das Fenster skalieren kann?

Encounter

Frischling

  • »Encounter« ist der Autor dieses Themas

Beiträge: 22

Wohnort: Aachen

  • Private Nachricht senden

3

30.03.2016, 19:57

Hey cojo2015,

ich fände es einfach schön, wenn man wie bei sagen wir mal Minecraft selber bestimmen kann, wie viel Platz das Spiel auf dem Monitor einnimmt und welche Form es hat (Wobei das natürlich in teilweise absurde verzerrungen führt, aber das will ich mir auch noch ansehen).
Vielleicht will man nur nebenher spielen oder neben dem Editor auch noch einen Chat beobachten.
Ich war hier und hab ALLES gesehen!

4

30.03.2016, 20:12

Also auf anhieb sehe ich kein Fehler für die Hitbox, dennoch könnt man sich das if sehr vereinfachen.

C-/C++-Quelltext

1
2
if(spEditorButton.Sprite.getGlobalBounds().contains(sf::Mouse::getPosition(window)))
...


Vielleicht bringt es ja schon was.

Ansonsten mal die Daten ausgeben oder im debugger schauen was schief läuft.

Edit:
Wird eigentlich der Code nur 1 mal aufgerufen oder jedes mal wenn die Fenstergröße sich ändert bzw. in jeder Update-Methode?
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

5

30.03.2016, 20:19

Ich weiß leider nicht, wie sich SFML genau verhält: wird das Zeichnen mit einem festen Skalierungsfaktor (bspw. 1:1 oder 128:1) durchgeführt oder ist die Skalierung abhängig von der Fenstergröße? Oder anders gefragt: wenn du das Fenster skalierst, verändert sich der Dargestellte Inhalt oder behält er die gleiche Größe bei?
Sollte eine Skalierung abhängig von der Fenstergröße durchgeführt werden, musst du das natürlich auch bei der Darstellung/Abfrage berücksichtigen.

@cojo:
Ich finde die Bestrebung in dieser Richtung (skalierbares Fenster) nicht unsinnig. Warum sollten für einen Fenstermodus nur feste Auflösungen angeboten werden?
Das Problem bei Minecraft ist relativ einfach: der "Field of View" Winkel bezieht sich auf die Vertikale. Verbreitert man das Fenster, vergrößert sich der Winkel auf der Horizontalen. Bei 2D Spielen hat man ein solches Problem nicht, man muss sich aber dennoch Gedanken darüber machen, was/wie viel der Spieler sehen kann.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

6

30.03.2016, 20:41

Verstehe ich das Richtig du Skalierst den Inhalt wenn sich die Fenstergröße ändert?

Da wäre Interesannt zu wissen ob dies über den sf::View machst oder den Inhalt selber skalierst?

Übrigens unter Skalieren verstehe ich jetzt nicht den Button in der Mitte des Fensters zu halten.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Encounter

Frischling

  • »Encounter« ist der Autor dieses Themas

Beiträge: 22

Wohnort: Aachen

  • Private Nachricht senden

7

30.03.2016, 20:53

Ich weiß leider nicht, wie sich SFML genau verhält: wird das Zeichnen mit einem festen Skalierungsfaktor (bspw. 1:1 oder 128:1) durchgeführt oder ist die Skalierung abhängig von der Fenstergröße? Oder anders gefragt: wenn du das Fenster skalierst, verändert sich der Dargestellte Inhalt oder behält er die gleiche Größe bei?
Sollte eine Skalierung abhängig von der Fenstergröße durchgeführt werden, musst du das natürlich auch bei der Darstellung/Abfrage berücksichtigen.


Hey Sacaldur, beim Skalieren werden Grafiken entsprechend gestaucht oder gedehnt. Ja, genau das versuche ich gerade irgendwie :D


@Koschi Danke erstmal für den Vereinfachungsvorschlag sieht super aus. Leider ist bei meinem ersten schnellen Test damit ein Fehler aufgetreten "Keine Instanz von Überladene Funktion "sf::Rect<T>::contains [mit T=float]" stimmt mit der Argumentliste überein."

Edit:
Wird eigentlich der Code nur 1 mal aufgerufen oder jedes mal wenn die Fenstergröße sich ändert bzw. in jeder Update-Methode?


Alle gezeigten Codeabschnitte befinden sich in einer Schleife.


Verstehe ich das Richtig du Skalierst den Inhalt wenn sich die Fenstergröße ändert?

Da wäre Interesannt zu wissen ob dies über den sf::View machst oder den Inhalt selber skalierst?

Übrigens unter Skalieren verstehe ich jetzt nicht den Button in der Mitte des Fensters zu halten.


Ok du hast recht ich drücke mich unklar aus. Der Button soll an einer Position gehalten werden zusammen mit seiner Hitbox. Beim skalieren durch das Fenster (was SFML ja von haus aus kann) verschiebt sich eben genau diese Hitbox. Das Stauchen der Grafiken möchte ich in Zukunft noch angehen, dass ich da lieber den Bildausschnitt vergrößer oder verkleiner anstatt die Stauchung in Kauf zu nehmen. Damit habe ich aber noch keinerlei erfahrung und werd das mal in Ruhe erörtern müssen. Soll hier aber auch nicht thema sein, sofern nicht notwendig für die Hitbox handhabung.

Hab mal den ganzen Code der main() kopiert. Bitte nicht über die Unordnung wundern, ich habe da erstmal jede menge zeug reingepackt um einfach mal die Grundfunktionen von SFML an meinen Teampartner zu vermitteln. Aber vielleicht liegt genau in der unordnung ja auch der Fehler, nur sehe ich ihn halt nicht.


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int main()
{
    sf::RenderWindow window(sf::VideoMode(1600, 900), "TITEL");
    window.setFramerateLimit(200);

    GameSprite spBackground("data/graphics/MenüBack.png");
    spBackground.Sprite.setScale(window.getSize().x / spBackground.Sprite.getLocalBounds().width, window.getSize().y / spBackground.Sprite.getLocalBounds().height);
    GameSprite spEditorButton("data/graphics/EditorButton.png");
    spEditorButton.Sprite.setPosition(window.getSize().x/2-spEditorButton.Sprite.getGlobalBounds().width/2, window.getSize().y / 2 - spEditorButton.Sprite.getGlobalBounds().height / 2);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //kommt beschriebener fehler:  if (spEditorButton.Sprite.getGlobalBounds().contains(sf::Mouse::getPosition(window)));

        if (sf::Mouse::getPosition(window).x >= spEditorButton.Sprite.getGlobalBounds().left && 
            sf::Mouse::getPosition(window).x <= spEditorButton.Sprite.getGlobalBounds().left + spEditorButton.Sprite.getGlobalBounds().width && 
            sf::Mouse::getPosition(window).y >= spEditorButton.Sprite.getGlobalBounds().top &&
            sf::Mouse::getPosition(window).y <= spEditorButton.Sprite.getGlobalBounds().top + spEditorButton.Sprite.getGlobalBounds().height) {
            spEditorButton.Sprite.setColor(sf::Color(255, 255, 255, 255));
            if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) { 
                spBackground.Texture.loadFromFile("data/graphics/EditorGuiBack.png"); 
                spBackground.Sprite.setTexture(spBackground.Texture); 
            }
        }
        else spEditorButton.Sprite.setColor(sf::Color(150, 150, 150, 255));


        window.clear();
        window.draw(spBackground.Sprite);
        window.draw(spEditorButton.Sprite);
        window.display();

    }

    return 0;
}
Ich war hier und hab ALLES gesehen!

8

30.03.2016, 21:10

@Koschi Danke erstmal für den Vereinfachungsvorschlag sieht super aus. Leider ist bei meinem ersten schnellen Test damit ein Fehler aufgetreten "Keine Instanz von Überladene Funktion "sf::Rect<T>::contains [mit T=float]" stimmt mit der Argumentliste überein."


Mit einem Cast nach sf::Vector2f gehts da sf::Mouse::getPosition(window) sf::Vector2i zurückgibt.

Ansonsten liegt das Problem wohl daran das die Hitbox wandert aber Button an Ort und Stelle bleibt du setzt die Position nicht neu (nur einmal außerhalb der Schleife).
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Encounter

Frischling

  • »Encounter« ist der Autor dieses Themas

Beiträge: 22

Wohnort: Aachen

  • Private Nachricht senden

9

30.03.2016, 21:34


Mit einem Cast nach sf::Vector2f gehts da sf::Mouse::getPosition(window) sf::Vector2i zurückgibt.


Hätte ich auch drauf kommen können, jo klappt, danke.

Bezüglich der Hitbox habe ich jetzt mal ein bisschen rumexperementiert. Wenn dich die Position des Buttons jedesmal neu setze wenn sich das Fenster verändert, bleibt die Hitbox zwar an Ort und Stelle, aber der Button wandert :S Beim verkleinern in die negativen richtungen, beim vergrößern in die Positiven. Das set Scale scheint gar keine Wirkung zu haben.

Interessant finde ich an der Stelle auch, dass das Maximieren des Fensters nicht als Resized gilt, da muss ich auch nochmal gucken wie ich das abfrage

C-/C++-Quelltext

1
2
3
4
        if (event.type == sf::Event::Resized) {
            spEditorButton.Sprite.setScale(1, 1);
            spEditorButton.Sprite.setPosition(window.getSize().x / 2 - spEditorButton.Sprite.getGlobalBounds().width / 2, window.getSize().y / 2 - spEditorButton.Sprite.getGlobalBounds().height / 2);
        }
Ich war hier und hab ALLES gesehen!

10

30.03.2016, 21:49

Das wir die gleiche Sicht haben:

- Die Hitbox ist für mich ein Bereich der Zurückgeben kann ob die Maus drin ist oder nicht.
- Das was du am Bildschirm siehst ist für mich die Grafische Präsentation des Button.

Der Button Wandert weil du ihn in der Mitte halten möchtest (zumindestens habe ich das so Verstanden) von daher wäre das Verhalten korrekt, denn wenn du etwas vergrößerst oder verkleinerst wandert der Mittelpunkt ja mit.

Bezüglich des Scale:
1 bedeutet dabei es bleibt gleich
< 1 wird kleiner
> 1 wird gößer

Wenn ich dich Falsch Verstanden habe und du den Bildschirminhalt mitskalieren möchtest solltest du dir vielleicht mal sf::View anschauen.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Werbeanzeige