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

03.04.2014, 19:10

(SFML) Maus-Input auf Grafik übertragen?

Hi Forum,

ich habe mit meinem ersten Projekt angefangen: "Tic Tac Toe". Ich benutze SFML für die Grafiken und die Grafiken sind fertiggestellt. Doch nun muss ich das Spielprinzip erstellen wofür ich mir folgendes überlegt habe: Man klickt auf ein Feld und "X" bzw. "O" wird dort eingetragen. Ist nicht so einfach wie es klingt: Aus dem offiziellen Tutorial bekomme ich sowas nicht raus; ich habe alles nötige gelesen und das Tutorial ist... naja... schlecht. Andere Tutorials sind schwer zu finden und wenn man glaubt das man eins gefunden hat, dann ist es was völlig anderes. Hier der Code des Projekts (ich denke nicht dass ihr unbedingt alles lesen werdet...):

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

using namespace std;

//First project: TicTacToe Project

//Create Window
int main()
{
    CTicTacToeSprites Game;

    sf::RenderWindow SquareMainWindow(sf::VideoMode(650, 650), "TicTacToe", sf::Style::Default);

    while (SquareMainWindow.isOpen())
    {
        sf::Event event;
            while (SquareMainWindow.pollEvent(event))
            {
                if (event.type == sf::Event::Closed)
                {
                    printf("You clicked the 'Close' Button.\n");
                    SquareMainWindow.close();
                }
            }
        SquareMainWindow.clear(sf::Color(255,255,255));

        //Draw
        SquareMainWindow.draw(Game);

        SquareMainWindow.display();
    }
    return 0;
}




Sprites.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
43
44
45
46
47
#ifndef SPRITE_HPP
#define SPRITE_HPP

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

//Sprite class
class CTicTacToeSprites : public sf::Drawable, public sf::Transformable
{
    private:
    sf::Texture TicTacToeGrid;
    sf::Sprite m_Slot1;
    sf::Sprite m_Slot2;
    sf::Sprite m_Slot3;
    sf::Sprite m_Slot4;
    sf::Sprite m_Slot5;
    sf::Sprite m_Slot6;
    sf::Sprite m_Slot7;
    sf::Sprite m_Slot8;
    sf::Sprite m_Slot9;
    sf::Sprite X;
    sf::Sprite O;
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        states.transform *= getTransform();

        states.texture = &TicTacToeGrid;

        target.draw(m_Slot1, states);
        target.draw(m_Slot2, states);
        target.draw(m_Slot3, states);
        target.draw(m_Slot4, states);
        target.draw(m_Slot5, states);
        target.draw(m_Slot6, states);
        target.draw(m_Slot7, states);
        target.draw(m_Slot8, states);
        target.draw(m_Slot9, states);
    }

    public:
    int LoadingConstructor ();
    CTicTacToeSprites ();
    
};
#endif



Sprites.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
65
66
67
68
69
70
71
#include "Sprites.hpp"

using namespace std;

    int CTicTacToeSprites::LoadingConstructor ()
    {
        //Grid-Texture
        if(!TicTacToeGrid.loadFromFile("TicTacToeGrid.png"))
        {
            printf("Could not load 'TicTacToeGrid.png");
            return -1;
        }
    }

    CTicTacToeSprites::CTicTacToeSprites ()
    {
        CTicTacToeSprites::LoadingConstructor ();

        //upper-left Slot (Slot1)
        m_Slot1.setTexture(TicTacToeGrid);
        m_Slot1.setTextureRect(sf::IntRect(0, 0, 200, 200));
        m_Slot1.setPosition(0, 0);

        //upper Slot (Slot2)
        m_Slot2.setTexture(TicTacToeGrid);
        m_Slot2.setTextureRect(sf::IntRect(200, 0, 200, 200));
        m_Slot2.setPosition(200, 0);

        //upper-right Slot (Slot3)
        m_Slot3.setTexture(TicTacToeGrid);
        m_Slot3.setTextureRect(sf::IntRect(400, 0, 200, 200));
        m_Slot3.setPosition(400, 0);

        //middle-left Slot (Slot4)
        m_Slot4.setTexture(TicTacToeGrid);
        m_Slot4.setTextureRect(sf::IntRect(0, 200, 200, 200));
        m_Slot4.setPosition(0, 200);

        //middle Slot (Slot5)
        m_Slot5.setTexture(TicTacToeGrid);
        m_Slot5.setTextureRect(sf::IntRect(200, 200, 200, 200));
        m_Slot5.setPosition(200, 200);
        
        //middle-right Slot (Slot6)
        m_Slot6.setTexture(TicTacToeGrid);
        m_Slot6.setTextureRect(sf::IntRect(400, 200, 200, 200));
        m_Slot6.setPosition(400, 200);

        //bottom-left Slot (Slot7)
        m_Slot7.setTexture(TicTacToeGrid);
        m_Slot7.setTextureRect(sf::IntRect(0, 400, 200, 200));
        m_Slot7.setPosition(0, 400);

        //bottom Slot (Slot8)
        m_Slot8.setTexture(TicTacToeGrid);
        m_Slot8.setTextureRect(sf::IntRect(200, 400, 200, 200));
        m_Slot8.setPosition(200, 400);

        //bottom-right Slot (Slot9)
        m_Slot9.setTexture(TicTacToeGrid);
        m_Slot9.setTextureRect(sf::IntRect(400, 400, 200, 200));
        m_Slot9.setPosition(400, 400);

        //Player 1 Sprite
        X.setTexture(TicTacToeGrid);
        X.setTextureRect(sf::IntRect(600, 200, 200, 200));
        
        //Player 2 Sprite
        O.setTexture(TicTacToeGrid);
        O.setTextureRect(sf::IntRect(200, 600, 200, 200));
    }


Gratulation wer das alles gelesen hat, ich hätte wohl irgendwann einfach "tl;dr" geschrieben... Also, genauer gesagt möchte ich, dass das Programm erkennt, dass die Maus auf eine der Slots klickt und dann jeweils "X" oder "O" eingerendert wird. Doch ich weiß nicht wie. Meine Frage lautet: Wie kriege ich das mit SFML hin und ist es überhaupt möglich (wenn nicht dann ist das Projekt ja fast umsonst gemacht worden)?

btw; Ich hab kein Problem mit Korrekturen und Verbesserungen.

MfG PwalbXYZ

2

03.04.2014, 20:37

Hier steht wie du Maus Position und Maus Button abfragst :
http://www.sfml-dev.org/documentation/2.…sf_1_1Mouse.php

das könntest du sinnvoller weise bei einem Mausklick machen, wie du auf Mausklicks reagierst zeig ich dir :
unter
if (event.type == sf::Event::Closed)
{
printf("You clicked the 'Close' Button.\n");
SquareMainWindow.close();
}
einfach


if (event.type == sf::Event::MouseButtonPressed)
{
//der code hier wird bei einem Mausklck ausgeführt

if(event.MouseButton.Button==sf::Mouse::Left)
{
//Der Code bei einem Linksklick
}
}

Ich habe keine Ahnung von SFML, doch sollte so gehen wenn mich mein flüchtiger Blick nicht getäuscht hat ;)

Wenn nicht steht hier noch die Offizielle Anleitung zum Event handling der Maus :
http://www.sfml-dev.org/documentation/2.…ent.php#details

Hier noch ein Bsp. wie du an die Mausposition kommst :
Maus-Event

also du brauchst :
const sf::Input& input = Window.GetInput();

input.GetMouseX ();//gibt dir Die Mausposition auf der X-Achse (Breite) als int zurück
input.GetMouseY();//und das natürlich auf der Y-Achse (Höhe)

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »OOTD« (03.04.2014, 20:52)


Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

3

03.04.2014, 20:54

Hier noch ein kleiner Hinweis, weil das in der Doku versteckt ist und nirgendwo direkt erwähnt wird (Habe selbst eine Stunde gebraucht, um es zu finden, als es noch nicht tausende Threads mit der Frage gab :)):

sf::Mouse::getPosition() gibt die Mausposition die die SFML von Windows bekommt zurück, um die Position in deinem Fenster zu erhalten, musst du dieses als Parameter übergeben.

Den Rest solltest du selbst hinbekommen.
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

4

03.04.2014, 21:05

Hier noch ein kleiner Hinweis, weil das in der Doku versteckt ist und nirgendwo direkt erwähnt wird (Habe selbst eine Stunde gebraucht, um es zu finden, als es noch nicht tausende Threads mit der Frage gab :))



(Link)


Voll versteckt und so
http://sfml-dev.org/documentation/2.1/classsf_1_1Mouse.php

Zitat

static Vector2i getPosition (const Window &relativeTo)
Get the current position of the mouse in window coordinates.


Zum Thread:

C-/C++-Quelltext

1
2
3
4
if(m_Slot1.getGlobalBounds().contains(static_cast<sf::Vector2f>(sf::Mouse::getPosition(/*windowreference*/)))
{
    //enable/disable rendering
}

Das aktivieren/deaktivieren kannst du einfach per boolean machen, es bietet sich hier an für einen Slot eine eigene Klasse zu schreiben.
Im Stil der SFML erbt sie dann noch von sf::Drawable, hier mal kurz skizziert:

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
#pragma once
#include <SFML/Graphics/Sprite.hpp> //inkludiert sf::Drawable und sf::Transformable
#include <SFML/Graphics/RenderTarget.hpp> //Du kannst diesen Header auch erst in der *.cpp inkludieren ;)
class Field : public sf::Drawable, public sf::Transformable
{
public:
    Field(sf::Texture& tex, const sf::Vector2f& pos) : sprite(tex), bdraw(false), checkForClick(true) {sprite.setPosition(pos);}
    
    void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        if(draw){states.transform *= getTransform(); target.draw(sprite, states);}
    }

    void update(const sf::Vector2f& mousePos, const sf::IntRect& subRect)
    {
        if(checkForClick && sprite.getGlobalBounds().contains(mousePos))
        {
            checkForClick = false;
            bdraw = true;
            sprite.setTextureRect(subRect); //Die Idee hierhinter ist, dass die Textur einmal das Zeichen für Spieler 1 und Spieler 2 beinhält,
                                                                //und je nach dem wer dran ist eben entsprechende Begrenzung übergeben wird.
        }
    }
private:
    sf::Sprite sprite;
    bool bdraw;
    bool checkForClick;
};


Ein in einem Container Speichern erweist sich hier als wertvoll. std::vector bietet sich da ja ganz gut an. :)
Die Positionen kannst du dann zum Beispiel so setzen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//std::vector<Field> fields
//Konstruktor von std::vector empfängt hier im Parameter 1, die 9, wie viele Objekte er haben soll
//                                                                       Parameter 2, ein Field-Objekt, wie die Objekte "aussehen" sollen
//Hinweis: Ich habe mir diese Methode Zwecks RAII angewöhnt, solltest du hier nicht wissen was du tust, dann
//lager es auf jeden Fall in Funktionen aus und machs eben nicht im Konstruktor, gerade der "Texture-Manager"
//kann in diesem Fall bei falscher Handhabung gefährlich werden
Foo::Foo() : bla(), bar(), bal(), texManager(), fields(9, Field(texManager.getTexture(0U)))
{
    for(int y=0; y<3; ++y)
    {
        for(int x=0; x<3; ++x)
        {
            fields[y*3+x].setPosition(x*200, y*200);
        }
    }
}

Beim Rendern dann einfach schön durchiterieren.
Dein Grid würde ich persönlich übrigens selbst zusammen schnitzen aus einem std::vector voll mit sf::RectangleShapes.

MfG
Check

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »Checkmateing« (03.04.2014, 21:39)


5

03.04.2014, 22:29

Danke, Check
Das sieht hilfreich auf ich werde es mir morgen etwas genauer ansehen.

Nimelrian

Alter Hase

Beiträge: 1 216

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

6

04.04.2014, 08:28

Voll versteckt und so
http://sfml-dev.org/documentation/2.1/classsf_1_1Mouse.php

Zitat

static Vector2i getPosition (const Window &relativeTo)
Get the current position of the mouse in window coordinates.


Eben das stand früher (wieso auch immer) nicht in der Doku drin. Inzwischen schon (vllt. hat Laurent es vergessen? kA).
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

7

04.04.2014, 14:48

Naja ganz früher, SFML 1.6, war sf::Mouse ja nur ne enum, aber früher interessiert doch nicht. Acta est fabula.

MfG
Check

Werbeanzeige