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

28.05.2014, 14:14

[VC++] Bizarres Problem mit dem Maus-Input in SFML

Hi,

ich bin gerade dabei mein erstes kleines Programm mit der SFML zu erstellen (TicTacToe). Nachdem ich die Grafiken fertig gestellt habe, muss ich den Maus-Input managen: Man soll, ganz einfach auf eines der 9 TicTacToe-Felder klicken und dann wird je nachdem ein 'X' oder 'O' gezeichnet. Da ich nicht wusste wie das geht, hab ich mehrere Stunden nach einer Möglichkeit gesucht, mit Erfolg: #Click on a sprite - SFML Forum# Dort sieht man direkt, sogar vom SFML-Entwickler selbst einen für jeden Idioten, verständlichen und logischen Code wie man das löst. Wenn man runterscrollt sieht man zwar eine weitere Möglichkeit, doch die gilt nur für das veraltete SFML 1.6, ich habe dagegen SFML 2.0/2.1. Im folgendem Projekt müsste ich das doch eigentlich richtig zur Schau gestellt haben:

Sprite.hpp:

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
#ifndef SPRITE_HPP
#define SPRITE_HPP

#include <SFML\Graphics.hpp>
#include <SFML\System.hpp>

extern sf::Texture TicTacToe_Texture;
int LoadTexture();

//Slot class
class CSlot : public sf::Drawable, public sf::Transformable
{
    friend class CCollision;
    
    private:    
    sf::Sprite m_Slot;
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        states.transform *= getTransform();

        states.texture = &TicTacToe_Texture;

        target.draw(m_Slot, states);
    }
    public:
    CSlot ();
};

//X and O class
class CXO : public sf::Drawable, public sf::Transformable
{
    friend class CCollision;

    private:
    sf::Sprite X;
    sf::Sprite O;

    public:
    CXO();
};

#endif


Sprite.cpp:

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
#include "Sprites.hpp"

using namespace std;

sf::Texture TicTacToe_Texture;

int LoadTexture()
{
    if(!TicTacToe_Texture.loadFromFile("TicTacToe_Texture.png"))
    {
        return -1;
    }
}

CSlot::CSlot ()
    {
        LoadTexture();

        m_Slot.setTexture(TicTacToe_Texture);
        m_Slot.setTextureRect(sf::IntRect(0, 0, 199, 199));
        m_Slot.setPosition(0, 0);
    }
    
    CXO::CXO()
    {
        LoadTexture();

        //Player 1 Sprite
        X.setTexture(TicTacToe_Texture);
        X.setTextureRect(sf::IntRect(200, 0, 199, 199));
        
        //Player 2 Sprite
        O.setTexture(TicTacToe_Texture);
        O.setTextureRect(sf::IntRect(400, 0, 199, 199));
    }


IO.hpp:

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
#ifndef IO_HPP
#define IO_HPP

#include "Sprites.hpp"

extern sf::RenderWindow MainWindow;

//Collision class
class CCollision
{
    private:
    short Player;
    sf::Vector2f Mouse;
    sf::FloatRect Slot1Box;
    sf::FloatRect Slot2Box;
    sf::FloatRect Slot3Box;
    sf::FloatRect Slot4Box;
    sf::FloatRect Slot5Box;
    sf::FloatRect Slot6Box;
    sf::FloatRect Slot7Box;
    sf::FloatRect Slot8Box;
    sf::FloatRect Slot9Box;
    bool Slot1Taken;
    bool Slot2Taken;
    bool Slot3Taken;
    bool Slot4Taken;
    bool Slot5Taken;
    bool Slot6Taken;
    bool Slot7Taken;
    bool Slot8Taken;
    bool Slot9Taken;

    public:
    CCollision();
    void CheckCollision();
};

#endif


IO.cpp:

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
44
45
46
47
48
49
#include "IO.hpp"

sf::RenderWindow MainWindow (sf::VideoMode(597, 597), "TicTacToe", sf::Style::Default);

    //Create Entities
    CSlot Slot1;
    CSlot Slot2;
    CSlot Slot3;
    CSlot Slot4;
    CSlot Slot5;
    CSlot Slot6;
    CSlot Slot7;
    CSlot Slot8;
    CSlot Slot9;

    CCollision::CCollision()
    {
        //Player: 15 for 'O', 24 for 'X'
        Player = 24;
        
        Mouse = MainWindow.mapPixelToCoords(sf::Mouse::getPosition(MainWindow));
        Slot1Box = Slot1.m_Slot.getGlobalBounds();
        Slot2Box = Slot2.m_Slot.getGlobalBounds();
        Slot3Box = Slot3.m_Slot.getGlobalBounds();
        Slot4Box = Slot4.m_Slot.getGlobalBounds();
        Slot5Box = Slot5.m_Slot.getGlobalBounds();
        Slot6Box = Slot6.m_Slot.getGlobalBounds();
        Slot7Box = Slot7.m_Slot.getGlobalBounds();
        Slot8Box = Slot8.m_Slot.getGlobalBounds();
        Slot9Box = Slot9.m_Slot.getGlobalBounds();
        Slot1Taken = false;
        Slot2Taken = false;
        Slot3Taken = false;
        Slot4Taken = false;
        Slot5Taken = false;
        Slot6Taken = false;
        Slot7Taken = false;
        Slot8Taken = false;
        Slot9Taken = false;
    }

    void CCollision::CheckCollision()
    {       
        // hit test
        if(Slot1Box.contains(Mouse))
        {
            printf("You pressed Slot1!");
        }
    }


main.cpp:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "IO.hpp"

using namespace std;

//First project: TicTacToe Project

//Create Window
int main()
{   
    //Create Entities
    CCollision Collision;
    
    CSlot Slot1;
    CSlot Slot2;
    CSlot Slot3;
    CSlot Slot4;
    CSlot Slot5;
    CSlot Slot6;
    CSlot Slot7;
    CSlot Slot8;
    CSlot Slot9;

    //Manage Entities
    Slot1.setPosition(0, 0);
    Slot2.setPosition(199, 0);
    Slot3.setPosition(398, 0);
    Slot4.setPosition(0, 199);
    Slot5.setPosition(199, 199);
    Slot6.setPosition(398, 199);
    Slot7.setPosition(0, 398);
    Slot8.setPosition(199, 398);
    Slot9.setPosition(398, 398);

    while (MainWindow.isOpen())
    {
        sf::Event event;
            while (MainWindow.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                {
                    printf("You clicked the 'Close' Button.\n");
                    MainWindow.close();
                }
                if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
                {
                    Collision.CheckCollision();
                }
            }
        MainWindow.clear(sf::Color(128,128,128));
        
        MainWindow.draw(Slot1);
        MainWindow.draw(Slot2);
        MainWindow.draw(Slot3);
        MainWindow.draw(Slot4);
        MainWindow.draw(Slot5);
        MainWindow.draw(Slot6);
        MainWindow.draw(Slot7);
        MainWindow.draw(Slot8);
        MainWindow.draw(Slot9);

        MainWindow.display();
    }
    return 0;
}


Noch nicht alles ganz fertig, aber mich interessiert im Moment nur der Maus-Input der nicht funktioniert. Könnte man zwar selbst fixen der Fehler aber es ist nun mal so: Der selbe Code hat verschiedene Ergebnisse: 1. Wenn man klickt, wird in der Konsole angezeigt: You pressed Slot1. Das soll ein Platzhalter darstellen. Das Problem ist, dass es nicht wie gedacht nur dann reagiert, wenn man wirklich NUR auf Slot1 klickt, sondern ganz egal wo im Fenster man klickt. 2. Es reagiert überhaupt nicht.
Meinen Fehler kann ich nicht erkennen, obwohl es höchstwahrscheinlich meiner ist. Was stimmt jetzt mit dem Maus-Input nicht?

MfG Pwalb

2

28.05.2014, 14:56

Wann prüft deine Collision-Klasse denn die Mausposition?

Tu dir selbst einen gefallen, und benutze Arrays.
"Theory is when you know something, but it doesn’t work. Practice is when something works, but you don’t know why. Programmers combine theory and practice: Nothing works and they don’t know why." - Anon

eXpl0it3r

Treue Seele

Beiträge: 386

Wohnort: Schweiz

Beruf: Professional Software Engineer

  • Private Nachricht senden

3

28.05.2014, 15:05

Du solltest mal hier und hier nachschauen, was denn nun der Unterschied zwischen Events und den Mouse/Keyboard Klassen sind, das soll heissen, dass du sf::Mouse::isButtonPressed nicht in der Event-Loop verwenden solltest.

Dein Problem dass es immer an der gleichen Position ist liegt daran, dass du die Mouse Position einmalig im Konstruktor von CCollision setzt. Da das Objekt dann die ganze Zeit lebt, bleibt die gespeicherte Mausposition immer am gleichen Ort.

Des weiteren solltest du dich mal schlau machen über Containers wie z.B. std::vector, auch ist das C Prefix für Klassen eine alte & schlechte Angewohnheit, da es eigentlich niemand interessiert ob der Type eine class (C) oder sonst ein Type ist.
Im gesamten gesehen, scheint es mir, als ob dir noch einiges an grundlegendem C++ Wissen fehlt und SFML inklusive Spielentwicklung setzt halt einfach eine gute Grundlage voraus. Falls du noch auf der Suche nach Literatur bist, kannst du diese Liste auf StackOverflow anschauen.
Blog: https://dev.my-gate.net/
—————————————————————————
SFML: https://www.sfml-dev.org/
Thor: http://www.bromeon.ch/libraries/thor/
SFGUI: https://github.com/TankOs/SFGUI/

Werbeanzeige