Witam.
Piszę kod, który po kliknięciu i przytrzymaniu elementu (karty) myszką przesuwa go w wybrane miejsce.
Może od razu przejdę do kodu:
// Clickable.h
#pragma once
#include <SFML\System.hpp>
using namespace sf;
class Clickable
{
public:
Clickable();
~Clickable() = default;
bool isClickableNow();
void enableClicking();
void disableClicking();
void toggleClicking();
virtual bool wasClicked() = 0;
// Sprawdza czy na danym obiekcie trzymany jest obecnie lewy przycisk myszy
virtual bool isClickedNow() = 0;
protected:
Vector2i savedMousePosition;
// Jest równa 'true' jeśli nad danym obiektem kliknięty jest LPM
bool clicked;
// Ta zmienna jest równa 'true' jeśli jakiś inny obiekt
// jest aktualnie klikany (kliknięty LPM);
// Blokuje ona możliwość kliknięcia innych obietków, ponieważ
// takowy może być tylko jeden na raz
static bool blockedClickingAnotherObjects;
private:
virtual bool isHover() = 0;
bool clickableNow;
};
// Clickable.cpp
#include "Clickable.h"
Clickable::Clickable()
{
clickableNow = true;
}
bool Clickable::isClickableNow()
{
return clickableNow;
}
void Clickable::enableClicking()
{
clickableNow = true;
}
void Clickable::disableClicking()
{
clickableNow = false;
}
void Clickable::toggleClicking()
{
// Skrócony zapis if'a
clickableNow ? disableClicking() : enableClicking();
}
// Dragable.h
#pragma once
#include <SFML\Graphics.hpp>
#include "Clickable.h"
using namespace sf;
class Dragable : public Clickable
{
public:
Dragable() = default;
~Dragable() = default;
virtual void drag() = 0;
protected:
// Dystans pomiędzy punktem początkowym obiektu a myszą w poziomie
float distanceX;
// Dystans pomiędzy punktem początkowym obiektu a myszą w pionie
float distanceY;
};
I teraz najważniejsza klasa - Card, tworzy ona obiekty, które mam zamiar przesuwać:
// Card.h
#pragma once
#include <SFML/Graphics.hpp>
#include "GraphicsController.h"
#include "Caption.h"
#include "Dragable.h"
using namespace sf;
class Card : public Sprite, public Dragable
{
public:
Card();
Card(string textureAndCardName);
~Card();
string getCardName();
void setCard(string textureAndCardName);
virtual bool wasClicked();
virtual bool isClickedNow();
virtual void drag();
vector<string> neighboringCards;
private:
virtual bool isHover();
string textureAndCardName; // Nazwa karty i tekstury karty, który są takie same
bool addedToDeck;
};
// Card.cpp
#include "Card.h"
#include "Deck.h"
#include "Controller.h"
bool Dragable::blockedClickingAnotherObjects;
Card::Card()
{
addedToDeck = false;
}
Card::Card(string textureAndCardName)
{
setCard(textureAndCardName);
}
Card::~Card()
{
if(addedToDeck == true)
Deck::removeCard(textureAndCardName);
}
string Card::getCardName()
{
return textureAndCardName;
}
void Card::setCard(string textureAndCardNameToSet)
{
// Przeszukiwanie talii w celu sprawdzenia możliwości dodania karty o podanej nazwie
auto iterator = Deck::getDeck()->find(textureAndCardName);
// Jeśli nie znalazł istniejącej karty o podanej nazwie, to można ją dodać
if (iterator == Deck::getDeck()->end())
{
setImageToSprite(*this, textureAndCardNameToSet);
this->textureAndCardName = textureAndCardNameToSet;
Deck::addCard(*this, textureAndCardNameToSet);
addedToDeck = true;
}
else
{
cout << convertToPolishChars("Karta o nazwie '" + textureAndCardNameToSet + "' już istnieje! Nie można jej utworzyć ponownie!") << endl;
}
}
bool Card::wasClicked()
{
clicked = false;
bool mouseButtonClicked = Mouse::isButtonPressed(Mouse::Button::Left);
// Jeśli nie jest kliknięty LPM, odblokuj możliwość klikania
if (!mouseButtonClicked)
{
blockedClickingAnotherObjects = false;
return false;
}
if (blockedClickingAnotherObjects) return false;
// Jeśli kliknięto LPM
if (mouseButtonClicked && !blockedClickingAnotherObjects)
{
blockedClickingAnotherObjects = true;
// Jeśli mysz znajduje się nad danym obiektem
if (isHover())
{
// Pobranie wskaźnika do okna gry w celu uzyskania poprawnego położenia myszy
RenderWindow *window = Controller::getReference().getRenderWindow();
savedMousePosition = Mouse::getPosition(*window);
clicked = true;
distanceX = this->getPosition().x - savedMousePosition.x;
distanceY = this->getPosition().y - savedMousePosition.y;
return true;
}
else
return false;
}
return false;
}
bool Card::isClickedNow()
{
// Jest jeszcze obiekt nie jest kliknięty to sprawdź
// czy przypadkiem to się przed chwilą nie stało
if (!clicked) wasClicked();
// Jeśli jeszcze przed chwilą obiekt był kliknięty
if (clicked)
{
// Jeśli obiekt został już puszczony (Puszczono LPM)
if (!Mouse::isButtonPressed(Mouse::Button::Left))
{
clicked = false;
return false;
}
// Jeśli dalej nad obiektem jest kliknięty LPM
else return true;
}
else
return false;
}
void Card::drag()
{
if (isClickedNow())
{
Vector2f objectPosition(this->getPosition());
// Pobranie wskaźnika do okna gry w celu uzyskania poprawnego położenia myszy
RenderWindow *window = Controller::getReference().getRenderWindow();
Vector2f currentMousePosition(Mouse::getPosition(*window));
this->setPosition(currentMousePosition.x + distanceX, currentMousePosition.y + distanceY);
}
}
bool Card::isHover()
{
// Pobranie wskaźnika do okna gry w celu uzyskania poprawnego położenia myszy
RenderWindow *window = Controller::getReference().getRenderWindow();
// Pobieranie położenia myszy z uwzględnieniem okna gry
Vector2i currentMousePosition = Mouse::getPosition(*window);
IntRect objectRect(this->getGlobalBounds());
//cout << textureAndCardName << endl;
//cout << "x:" << objectRect.left << "y:" << objectRect.top << "w:" << objectRect.width << "h:" << objectRect.height << endl;
//cout << "x:" << currentMousePosition.x << "y:" << currentMousePosition.y << endl << endl;
// Sprawdzenie czy mysz znajduje się obecnie nad obiektem
if (objectRect.contains(currentMousePosition)) return true;
else return false;
}
Cały problem siedzi moim zdaniem w metodzie bool Card::wasClicked();
W momencie kiedy kod wygląda tak:
bool Card::wasClicked()
{
clicked = false;
bool mouseButtonClicked = Mouse::isButtonPressed(Mouse::Button::Left);
// Jeśli nie jest kliknięty LPM, odblokuj możliwość klikania
if (!mouseButtonClicked)
{
blockedClickingAnotherObjects = false;
return false;
}
// DO TEGO MOMENTU KAŻDY OBIEKT DOCHODZI
if (blockedClickingAnotherObjects) return false;
// POWYŻSZY TEST PRZECHODZI TYLKO JEDEN OBIEKT,
// KTÓRY JEST PIERWSZYM W TALII (INNA KLASA)
// Jeśli kliknięto LPM
if (mouseButtonClicked && !blockedClickingAnotherObjects)
{
// ISTOTNA JEST TA LINIJKA
blockedClickingAnotherObjects = true;
// Jeśli mysz znajduje się nad danym obiektem
if (isHover())
{
// Pobranie wskaźnika do okna gry w celu uzyskania poprawnego położenia myszy
RenderWindow *window = Controller::getReference().getRenderWindow();
savedMousePosition = Mouse::getPosition(*window);
clicked = true;
distanceX = this->getPosition().x - savedMousePosition.x;
distanceY = this->getPosition().y - savedMousePosition.y;
return true;
}
else
return false;
}
return false;
}
To przesuwalny jest tylko pierwszy obiekt w talii,
jeśli jednak kod wygląda tak:
bool Card::wasClicked()
{
clicked = false;
bool mouseButtonClicked = Mouse::isButtonPressed(Mouse::Button::Left);
// Jeśli nie jest kliknięty LPM, odblokuj możliwość klikania
if (!mouseButtonClicked)
{
blockedClickingAnotherObjects = false;
return false;
}
if (blockedClickingAnotherObjects) return false;
// WYDAJE SIĘ, ŻE JEST OK, KAŻDY OBIEKT SIĘ PRZESUWA PRAWIDŁOWO,
// ALE KLIKAJĄC W TŁO (TRZYMAJĄC LPM)
// I NAJEŻDŻAJĄC NA KARTĘ, TO ONA SIĘ PRZYKLEJA (A NIE POWINNA)
// Jeśli kliknięto LPM
if (mouseButtonClicked && !blockedClickingAnotherObjects)
{
// Jeśli mysz znajduje się nad danym obiektem
if (isHover())
{
// TA LINIJKA ZMIENIŁA MIEJSCE
blockedClickingAnotherObjects = true;
// Pobranie wskaźnika do okna gry w celu uzyskania poprawnego położenia myszy
RenderWindow *window = Controller::getReference().getRenderWindow();
savedMousePosition = Mouse::getPosition(*window);
clicked = true;
distanceX = this->getPosition().x - savedMousePosition.x;
distanceY = this->getPosition().y - savedMousePosition.y;
return true;
}
else
return false;
}
return false;
}
Wtedy wszystkie karty przesuwają się prawidłowo, jednak klikając w tło i dojeżdżając myszką nad kartę, to wtedy ona się przykleja. Oczywiste jest, że taki efekt jest niepożądany i powinno to działać jak przesuwanie ikonek na pulpicie.
Jakby ktoś chciał zobaczyć jak działa Talia i kiedy wywołuję metodę drag() to proszę pisać.
Z góry dziękuję za pomoc!