Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Des boutons avec sf::IntRect  (Lu 3782 fois)

0 Membres et 1 Invité sur ce sujet

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Des boutons avec sf::IntRect
« le: Mai 23, 2013, 05:28:54 pm »
Bonjour,

Comme dit dans le titre, je me sers de sf::IntRect et d'une vérification de la souris dans ce rectangle avec un clic pour créer un bouton.

Le "problème" est que cela force mes boutons à être rectangulaire.

N'y aurait-il pas un moyen de faire des boutons avec d'autres formes géométriques ?

Merci d'avance :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Des boutons avec sf::IntRect
« Réponse #1 le: Mai 23, 2013, 06:05:36 pm »
Si, cela ne tient qu'à toi de coder l'algo qui va bien.
Laurent Gomila - SFML developer

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #2 le: Mai 23, 2013, 06:31:41 pm »
Hum...

J'avoue que ça me tenterai bien :)

Je vais aller juste voir comment tu as fait vite fait pour les rectangles même si j'ai déjà quelques idées :)

Par contre je ne trouve pas de Rect.cpp sur le GitHub, c'est normal ou je ne suis pas doué (ce qui est fort possible)

Le Rect.inl ne serait pas le Rect.cpp ou du moins remplirait la même fonction ?
Devrais-je faire un inl aussi ? (Je me suis jamais servi des inl, je ne sais pas ce que c'est et je crois que ça se voit xD)

« Modifié: Mai 23, 2013, 06:46:45 pm par Cmdu76 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Des boutons avec sf::IntRect
« Réponse #3 le: Mai 23, 2013, 06:52:09 pm »
En fait, la classe sf::Rect étant template, elle doit être entièrement définie dans un en-tête et non dans un .cpp. Mais pour montrer que cet en-tête contient des définitions et non des déclarations, on lui donne en général une autre extension, dans mon cas c'est .inl (inline). Ca pourrait tout aussi bien être .tpl (template) ou .hpp, c'est juste une convention.
Laurent Gomila - SFML developer

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #4 le: Mai 23, 2013, 07:02:57 pm »
Okay d'accord :)

J'ai nommé la classe Ovale, j'ai repris ton fichier .hpp et changé ce qui fallait.

J'attaque le .inl là ;)

Par contre je vais devoir trouver un truc pour le contains...

Question bête (encore) comment un rectangle peut avoir des dimensions négatives ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Des boutons avec sf::IntRect
« Réponse #5 le: Mai 23, 2013, 07:06:34 pm »
Citer
Par contre je vais devoir trouver un truc pour le contains...
Ne te casse pas la tête, les tests du style contains ou intersects pour des formes géometriques simples sont très bien documentés sur le net. Tu peux même trouver assez facilement des exemples d'implémentation.

Citer
Question bête (encore) comment un rectangle peut avoir des dimensions négatives ?
Ca c'est surtout pour autoriser une feinte qui est utile dans un ou deux cas très précis, c'est pas vraiment très "propre" conceptuellement parlant. D'ailleurs il est probable que je le retire un de ces jours.
Laurent Gomila - SFML developer

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #6 le: Mai 23, 2013, 07:17:01 pm »
Ah oui pour inverser les sprites par rapport à un axe :)

Sinon je finirai demain après un peu de réflexion sur les polynômes du second degré, j'ai envie de trouver ça tout seul plutôt que d'avoir à le reprendre sans comprendre.

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #7 le: Mai 24, 2013, 05:32:19 pm »
J'ai fini la méthode contains !

Je pense continuer à travailler sur les Boutons et autres pour SFML, c'était vraiment lucratif pour moi :)

Je pense faire un bouton Rectangle avec des coins arrondis maintenant :)

MODIFICATION : Après réfléxion, ce code marche très bien pour faire de beau rond mais pas pour de beaux ovales, car les extrémités de sont pas bien arrondies dans le cas de diamètre trop différent...
Je suis désolé, je ne maitrise pas encore les équations de la forme : x=a(Y-K)^2+H, ducoup je mettrais à jour ce code plus tard, j'ai déjà l'idée de comment le traiter (en fonction du diamètre le plus long).
MAIS, le plus important est que les ronds marchent bien, car ils me serviront pour le RoundRect qui sera plus utile que des Ovales :)

Enfin bref, voilà quand même le code :)

Ovale.hpp
#ifndef SFML_OVALE_HPP
#define SFML_OVALE_HPP

#include <SFML/System/Vector2.hpp>

namespace sf
{
template <typename T>
class Ovale
{
public :
    Ovale();
    Ovale(T leftX, T topY, T diamX, T diamY);
    Ovale(const Vector2<T>& position, const Vector2<T>& size);

    bool contains(T x, T y) const;
    bool contains(const Vector2<T>& point) const;

    T left;
    T top;
    T diameterX;
    T diameterY;
};

#include <SFML/Graphics/Ovale.inl>

typedef Ovale<int> IntOvale;
typedef Ovale<float> FloatOvale;

} // namespace sf


#endif // SFML_OVALE_HPP
 

Ovale.inl
////////////////////////////////////////////////////////////
template <typename T>
Ovale<T>::Ovale() :
left(0),
top(0),
diameterX(0),
diameterY(0)
{

}

////////////////////////////////////////////////////////////
template <typename T>
Ovale<T>::Ovale(T leftX, T topY, T diamX, T diamY) :
left(leftX),
top(topY),
diameterX(diamX),
diameterY(diamY)
{

}

////////////////////////////////////////////////////////////
template <typename T>
Ovale<T>::Ovale(const Vector2<T>& position, const Vector2<T>& size) :
left(positon.x),
top(position.y),
diameterX(size.x),
diameterY(size.y)
{

}

////////////////////////////////////////////////////////////
template <typename T>
bool Ovale<T>::contains(T x, T y) const
{
    float yTest;
    float a;
    float b;
    float c;
    float Beta(top);
    float Alpha(left+diameterX/2);
    float x1(left);
    float x2(left+diameterX);

    if (y = top+diameterY/2)
    {
        if (x >= x1 && x <= x2) return true;
        else return false;
    }
    else if (y > top+diameterY/2)
    {
        Beta += diameterY;
        a = -Beta/(x1-Alpha)^2;
        b = -a*x1 -a*x2;
        c = x1*x2*a;
        yTest = a*x^2 + b*x + c;
        if (yTest >= y && x >= x1 && x <= x2) return true;
        else return false;
    }
    else if (y < top+diameterY/2)
    {
        a = -Beta/(x1-Alpha)^2;
        b = -a*x1 -a*x2;
        c = x1*x2*a;
        yTest = a*x^2 + b*x + c;
        if (yTest <= y && x >= x1 && x <= x2) return true;
        else return false;
    }
}

////////////////////////////////////////////////////////////
template <typename T>
bool Ovale<T>::contains(const Vector2<T>& point) const
{
    return contains(point.x, point.y);
}
« Modifié: Mai 24, 2013, 06:28:55 pm par Cmdu76 »

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #8 le: Mai 24, 2013, 06:08:33 pm »
Ducoup, je peux juste rajouter mes fichiers dans les sources que j'ai téléchargé et ensuite en compilant SFML avec CMake j'aurais ma classe ?
Ou il y a d'autres choses à faire avant ?

kimci86

  • Full Member
  • ***
  • Messages: 127
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #9 le: Mai 24, 2013, 06:32:49 pm »
Bonjour,

Tout d'abord, remarque bien qu'en C++, l'opérateur ^ ne calcule pas une puissance mais c'est l'opérateur ou exclusif bit à bit.

Ensuite, je voudrais pas te dégouter mais tu peux beaucoup simplifier ta fonction.
D'après l'équation cartésienne d'une ellipse (cf wikipédia), on peut procéder comme ceci:
template <typename T>
bool Ovale<T>::contains(T x, T y) const
{
    // calcul des rayons de l'ellipse
    T a = diameterX / 2;
    T b = diameterY / 2;

    // expression de x et y par rapport au centre de l'ellipse
    x -= left + a;
    y -= top + b;

    // x² / a² + y² / b² = 1 lorsque un point est situé sur l'ellipse
    // ici, l'opérateur <= permet de savoir si le point est situé dans l'ellipse
    return (x*x) / (a*a) + (y*y) / (b*b) <= 1;
}

Citer
Ducoup, je peux juste rajouter mes fichiers dans les sources que j'ai téléchargé et ensuite en compilant SFML avec CMake j'aurais ma classe ?
Ou il y a d'autres choses à faire avant ?

Comme c'est une classe template définie dans des headers, il n'y a pas besoin de compiler.
Si tu veux faire un truc propre, tu peux ajouter le nom des fichiers dans le CMakeLists du module graphique.
« Modifié: Mai 24, 2013, 06:34:35 pm par kimci86 »

Cmdu76

  • Full Member
  • ***
  • Messages: 194
    • Voir le profil
Re : Des boutons avec sf::IntRect
« Réponse #10 le: Mai 24, 2013, 07:10:17 pm »
Merci, le fait de m'aider ne me dégoute pas du tout, si je poste le but c'est justement de pouvoir être amélioré au maximum.
Je suis encore en première S donc j'ai pas encore fini de voir tout ce qui est fonction du genre Polynôme.

En attendant, voilà ma classe RoundRect ! (elle, elle marche correctement !)

RoundRect.hpp
#ifndef SFML_ROUNDRECT_HPP
#define SFML_ROUNDRECT_HPP

#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Ovale.hpp> //je mets ca même si c'est pas le vrai chemin :)

namespace sf
{
template <typename T>
class RoundRect : public Ovale, public Rect
{
public :
    RoundRect();
    RoundRect(T leftX, T topY, T diamX, T diamY, T rad = 0);
    RoundRect(const Vector2<T>& position, const Vector2<T>& size, T rad = 0);

    bool contains(T x, T y) const;
    bool contains(const Vector2<T>& point) const;

    T left;
    T top;
    T width;
    T height;
    T radius;
};

#include <SFML/Graphics/Ovale.inl>

typedef RoundRect<int> IntRoundRect;
typedef RoundRect<float> FloatRoundRect;

} // namespace sf


#endif // SFML_ROUNDRECT_HPP
 

RoundRect.inl

////////////////////////////////////////////////////////////
template <typename T>
RoundRect<T>::RoundRect() :
left(0),
top(0),
width(0),
height(0),
radius(0)
{

}

////////////////////////////////////////////////////////////
template <typename T>
RoundRect<T>::RoundRect(T leftX, T topY, T diamX, T diamY, T rad) :
left(leftX),
top(topY),
width(diamX),
height(diamY),
radius(rad)
{

}

////////////////////////////////////////////////////////////
template <typename T>
RoundRect<T>::RoundRect(const Vector2<T>& position, const Vector2<T>& size, T rad) :
left(position.x),
top(position.y),
width(size.x),
height(size.y),
radius(rad)
{

}

////////////////////////////////////////////////////////////
template <typename T>
bool RoundRect<T>::contains(T x, T y) const
{
    Ovale<T> leftTop(left,top,radius,radius);
    Ovale<T> leftBottom(left,top+height-radius*2,radius,radius);
    Ovale<T> rightTop(left+width-radius*2,top,radius,radius);
    Ovale<T> rightBottom(left+width-radius*2,top+height-radius*2,radius,radius);

    Rect<T> bloc1(left+radius,top,width-radius*2,height);
    Rect<T> bloc2(left,top+radius,width,height-radius*2);
    if(leftTop.contains(x,y)==true || leftBottom.contains(x,y)==true || rightTop.contains(x,y)==true || rightBottom.contains(x,y)==true || bloc1.contains(x,y)==true || bloc2.contains(x,y)==true)
    {
        return true;
    }
    else return false;
}

////////////////////////////////////////////////////////////
template <typename T>
bool RoundRect<T>::contains(const Vector2<T>& point) const
{
    return contains(point.x, point.y);
}
 
« Modifié: Mai 24, 2013, 08:40:38 pm par Cmdu76 »

 

anything