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

18.02.2013, 17:07

[SFML2] Sprite Drag and Drop fehlerhaft

Hallo,

ich erstelle momentan ein 2D Spiel mit SFML2.
Derzeit programmiere ich das Inventar bzw. das Interface.
Nun möchte ich meine Itemsprites (alle 32x32 px) per Drag and Drop bewegen können, was ansich auch funktioniert, jedoch kann ich die Sprites nur nach oben links und unten rechts in einem bestimmten Feld bewegen (wahrscheinlich ebenfalls 32x32 px), warum weiß ich jedoch nicht.
Es hat aufjedenfall mit dem sf::FloatRect um bzw. auf meinem Iconsprite zu tun.

Hier ist mein Code:

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
    // Item verschieben
            void getMouseOver(sf::RenderWindow &Spiel, sf::View &view)
            {
                    // Maus- und Spritekoordinaten im Fenster "Spiel" ermitteln
                    // Mauskoordinaten müssen wegen der verschobenen Kamera "view" konvertiert werden
                    sf::Vector2f m = Spiel.convertCoords(sf::Mouse::getPosition(Spiel), view);
     
                    // 1x1 Pixelfeld um Mauszeiger erstellen
                    sf::FloatRect maus(m.x-1, m.y-1, 1, 1);
     
                    // 32x32 Pixelfeld um Item erstellen
                    sf::FloatRect frSprite;
                    frSprite.top = items.at(0)->getIcon()->getPosition().x;
                    frSprite.left = items.at(0)->getIcon()->getPosition().y;
                    frSprite.height = 32;
                    frSprite.width = 32;
     
                    for(int i = 0;i<items.size();i++)
                    {
                            if(frSprite.intersects(maus))
                            {
                                    // Drag and Drop
     
                                    // Drag
                                    if(sf::Mouse::isButtonPressed(sf::Mouse::Left) && dragged == false)
                                    {
                                            std::cout << "a";
                                            dragged = true;
                                            pos = items.at(i)->getIcon()->getPosition();
                                    }
                                    if(sf::Mouse::isButtonPressed(sf::Mouse::Left) && dragged == true)
                                    {
                                            std::cout << "b";
                                            nPos = Spiel.convertCoords(sf::Mouse::getPosition(Spiel), view);
                                            // Test anfang - floatRect mit verschieben - Gleicher Fehler
                                            frSprite.top = nPos.x-16;
                                            frSprite.left = nPos.y-16;
                                            // Test ende
                                            items.at(i)->getIcon()->setPosition(nPos.x-16, nPos.y-16);
                                    }
                            }
                    }
            }

(Ich mache bei der Position bewusst -16, da die Bilder alle 32x32 px groß sind und dann genau mittig vom Mauszeiger platziert sind.)

Ich erstelle derzeit nur 1 frSprite, da nur 1 Item vorhanden ist und ich den Fehler finden möchte.

Habe ich etwas übersehen/vergessen?

Ich habe das Projekt hochgeladen, vielleicht könnt ihr euch dann mehr darunter vorstellen: http://ul.to/wm9ykwkh
In der unteren Hälfte seht ihr eine Flasche, diese soll man verschieben können.

Ich danke für jede Vorschlag.

MfG

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Kaev« (18.02.2013, 17:19)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

18.02.2013, 17:51

Stichwort "break". Das zweite IF im FOR-Loop ist nämlich automatisch erfüllt, wenn das erste IF erfüllt ist.
Überhaupt wirst Du da wohl unterscheiden müssen für MouseDown und MouseUp. Alles in einem Loop abhandeln zu wollen ist jedenfalls logisch falsch.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

18.02.2013, 18:07

Hatte zu Testzwecken schon break; in der ersten If-Abfrage, macht 0 unterschied.
Drag ist schon fertig (und ist ihm selben Loop), jedoch hab ich das erstmal auskommentiert und nicht angehängt, da das bewegen komischerweise nicht richtig funktioniert.
Hatte das ganze vorher mal mit einem Sprite in der main.cpp getestet, da ging alles einwandfrei.
Nachdem ich nun den Sprite aus dem Itemvector nehme, kam es zu diesem seltsamen Fehler.

Vielleicht hab ich dich aber auch falsch verstanden.
Danke trotzdem schonmal!

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

18.02.2013, 18:34

Es ist algorithmisch absolut unmöglich, dass es 0 Unterschied macht. Aber es macht sicherlich trotzdem nicht das, was du gern hättest.
Wie ich schon sagte, das alles in einem Loop zu machen kann nicht klappen. MouseDown und MouseUp ist das, was Du willst, denn so funktioniert Drag&Drop nunmal.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

5

18.02.2013, 18:40

Na gut, zumindest habe ich keinen spürbaren Unterschied bemerkt oder einfach übersehen.
Mit MouseDown und MouseUp meinst du ja bestimmt Drag (MouseDown) und Drop (MouseUp), jedoch habe ich Drop erstmal weggelassen, da Drag nicht richtig funktioniert.
Oder meinst du die beiden If-Abfragen, die oben sichtbar sind?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

18.02.2013, 18:51

So funktioniert Drag'n'Drop:
Wenn die MausTaste gedrückt wird, wird das darunter liegende Item "aufgehoben" und wird die Maus wieder losgelassen, wird auch das Item "losgelassen". Das macht Dein Code z.B. aber absolut nicht.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

7

18.02.2013, 18:57

Das es so funktioniert, weiß ich. Jedoch kann ich das Sprite ja nicht einfach "aufheben", darum ändere ich die Position, wenn "dragged == true" und die linke Maustaste betätigt ist. Hast du evtl. einen anderen Lösungsvorschlag (Pseudocode? .. )
Nehme alle Ideen gerne an.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

8

18.02.2013, 19:05

Ich würde das so angehen und habe es auch schon so gelöst.
Wenn Maus gedrückt wird:
Speicher das "aufgehobene" Objekt und dessen aktuelle Position,
verschiebe dann in jedem Schritt das aufgehobene Objekt. Da du die letzte Position kennst und die Verschiebung der Maus sollte das kein Problem sein,
Sobald die Maustaste losgelassen wird, hörst du damit auf.

Ob du jetzt ein Boolflag benutzt um kenntlich zu machen, dass ein Objekt aufgehoben wurde, ist dir überlassen. Da gibt es viele Möglichkeiten. Aber das Prinzip sollte klar sein. Mach dir diese drei Schritte vielleicht klar, indem du alle 3 in verschiedenen Methoden implementierst.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

9

19.02.2013, 15:50

Habe es nun in 3 Methoden geschrieben, Bug besteht leider immernoch.

Maus ist über dem Sprite/Item? (MouseOver)

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
    bool getMouseOver(sf::RenderWindow &Spiel, sf::View &view)
    {
        // Maus- und Spritekoordinaten im Fenster "Spiel" ermitteln
        // Mauskoordinaten müssen wegen der verschobenen Kamera "view" konvertiert werden
        sf::Vector2f m = Spiel.convertCoords(sf::Mouse::getPosition(Spiel), view);
        // 1x1 Pixelfeld um Mauszeiger erstellen
        sf::FloatRect maus(m.x-1, m.y-1, 1, 1);

        sf::FloatRect frSprite; // 32x32 Pixelfeld um Item erstellen
        frSprite.top = sIcon.getPosition().x;
        frSprite.left = sIcon.getPosition().y;
        frSprite.height = 32;
        frSprite.width = 32;

        if(frSprite.intersects(maus))
        {
            return true;
        }
        else
        {
            return false;
        }
    }


Ist aufgehoben (Drag)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void Drag(sf::RenderWindow &Spiel, sf::View &view)
    {
        if(sf::Mouse::isButtonPressed(sf::Mouse::Left) && dragged == false)
        {
            std::cout << "a";
            dragged = true;
            pos = sIcon.getPosition();
        }
        if(sf::Mouse::isButtonPressed(sf::Mouse::Left) && dragged == true)
        {
            std::cout << "b";
            nPos = Spiel.convertCoords(sf::Mouse::getPosition(Spiel), view);
            sIcon.setPosition(nPos.x-16, nPos.y-16);
        }
    }


Ist nicht mehr aufgehoben (Drop)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    void Drop(sf::FloatRect &frSlot, sf::Sprite &sSlot, sf::RenderWindow &Spiel, sf::View &view)
    {
        if(dragged == true && sf::Mouse::isButtonPressed(sf::Mouse::Left) == false)
        {
            dragged = false;
            nPos = Spiel.convertCoords(sf::Mouse::getPosition(Spiel), view);
                        // Testweise
            /*// Position zurücksetzen
            if(frSlot.intersects(sIcon.getGlobalBounds()))
            {
                sIcon.setPosition(sSlot.getPosition());
            }
            else
            {
                sIcon.setPosition(pos);
            }*/
        }
    }


So rufe ich es in meiner Interfaceklasse auf (Dort werden die Items in einen Vector hinzugefügt, der diese "verwalten" soll)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
...
for(int i = 0;i<items.size();i++)
{
    Spiel.draw(items.at(i).getIcon());
    if(items.at(i).getMouseOver(Spiel, view) == true)
    {
        items.at(i).Drag(Spiel, view);
        for(int x = 0;x<9;x++)
        {
            items.at(i).Drop(frSlot[x], sSlot[x], Spiel, view);
        }
    }       
}
...


Ich verzweifel langsam!
Ich denke der Fehler liegt im MouseOver, weiß jedoch nicht wie ich ihn beheben soll, frSprite.top und frSprite.left verschieben behebt es nicht.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Kaev« (19.02.2013, 16:30)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

19.02.2013, 16:30

Es gibt da so ein Ding... das nennt sich Debugger. Damit kannst du die notwendigen Code-Stellen prima mit Breakpoints versehen und Schritt für Schritt durchgehen, um zu prüfen, was da wohl verkehrt ist. Generell aber erstmal besser als der alte Code, auch wenn noch immer ziemlich gruselig für meine Begriffe.
(weil Du z.B. in einer Schleife immer wieder prüfst, ob der Maus-Button gedrückt ist, obwohl das EINMAL reichen würde)
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige