Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Need some help with finding out if the mouse presses or hovers over sf::Text  (Read 15099 times)

0 Members and 1 Guest are viewing this topic.

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Hi there, I'm relatively new to SFML and I have successfully made a pong clone, and I'm working on my own 2d game engine. So far, I have implemented a texture manager, a state machine for the actual engine, and a bounding box collision system. Everything works, I have tested it all already. The one thing I'm having trouble with though, is how the main menu buttons are going to work. I need some help figuring out a class for the main menu, and it's methods that will check if the mouse is clicking or hovering over some text. For example, I want 2 buttons, which are play and exit, that when you hover over the text, it will change colors and when you click it, it will either start the actual game, or exit the program.

Any help is hugely appreciated, and thank you for your time.
Current Projects:
Technoport

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11037
    • View Profile
    • development blog
    • Email
There are quite many possibilites you can use.
The easy but bit messy solution is to have all the checking and action code in your menu state. For example you just need to check if the mouse position is within in the wanted rectangle where your text is located.
A nicer solution is to write your own button class that can perform some action like text highlighting or reacte to clicks. Then you add the code for managing the buttons and passing on the events to your menu state or if wanted to another class.
The third solution is to use a GUI library like SFGUI, TGUI, libRocket or GWEN (use google to find them).
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

mutonizer

  • Newbie
  • *
  • Posts: 8
    • View Profile
+1 on Xploit post.

If you meant purely code wise, the way I usually do it is to use getGlobalbounds().contains like this  for example.

if you go the simple dirty way, just do one of these boundaries checks on mouse move (for highlight) and on mouse button press (for the actual action) and if they're true, do whatever you need to.

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Thanks for such great replies guys! I develop on my Mac, and I'm looking into using SFGUI because it looks the most promising. Do you guys know if it is available on Mac?
Current Projects:
Technoport

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
I was having some trouble writing a isSpriteClicked class, and I need some help. Here is what I have so far.

bool Button::isSpriteClicked(Sprite* spr, RenderWindow* rw) {
   
}

Could anybody help me write something that would check if the mouse was in the area, or clicking on a sprite? Thanks.
Current Projects:
Technoport

mateandmetal

  • Full Member
  • ***
  • Posts: 171
  • The bird is the word
    • View Profile
    • my blog
Could anybody help me write something that would check if the mouse was in the area, or clicking on a sprite?

People will not write code for you. Please read the documentation http://www.sfml-dev.org/documentation/2.0/annotated.php

It´s very simple. Get the mouse position relative to the window. If the left button is pressed and the mouse pos is inside the sprite dimension, do something.
- Mate (beverage) addict
- Heavy metal addict _lml
- SFML 2 addict
- My first (and free) game: BichingISH!

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Oh no, I wasn't asking for anybody to write code for me. I just needed help visualizing how it would work. What you have told me is sufficient, thank you.
Current Projects:
Technoport

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Ok, I will "explain" it a bit for you. First I would not check every frame for "IsButtonClicked". Simply handle the mouse event and then check if the mouse is inside the bounding area of your button. The 4 things to check are MouseX >= ButtonLeft, MouseY >= ButtonTop, MouseX <= (ButtonWidth - ButtonLeft), MouseY <= (ButtonHeight - ButtonTop).

Now try writing some code on top of this. If you still do not understand I can post some C# code to give you a better idea.
« Last Edit: July 22, 2012, 12:23:05 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11037
    • View Profile
    • development blog
    • Email
I wouldn't rely on the mouse moved event, since I think it's better to check every frame. So you should use sf::Mouse and getPosition(), additionally it's not needed to check all the positions, instead  you create a sf::Rect of the position and size of the button and then you can easily use the function contains() of the sf::Rect to check if the mouse pointer is within the rect/button. ;)
« Last Edit: July 22, 2012, 05:39:51 pm by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
bool Button::isSpriteClicked(Sprite *spr, IntRect *rect, Vector2i *rectPosition, RenderWindow *rw) {
    Mouse mouse;
    Vector2i mousePosition = mouse.getPosition();
   
    //If mouse position is in the rectangle do whatever
    if (rect->contains(mousePosition)) {
       
        return true;
    }
   
    //Otherwise, don't do anything
    else {
       
        return false;
    }
}

Does this look correct to you guys?
Current Projects:
Technoport

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Well I wrote the methods, but I'm kind of confused on how to put the rect around the sprite. I read the documentation on rect, but I'm still kind of confused.
Current Projects:
Technoport

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11037
    • View Profile
    • development blog
    • Email
A sf::Rect is just a normal rectangle defined through a point and it's size. Thus you'll just do something like:

Does this look correct to you guys?
Not quite and you shouldn't use pointers...

bool Button::isSpriteClicked(sf::Sprite &sprite) {
   
    sf::IntRect rect(sprite.getPosition().x, sprite.getPosition().y, sprite.getGlobalBounds().width, sprite.getGlobalBounds().height);
   
    //If mouse position is in the rectangle do whatever
    if (rect.contains(sf::Mouse::getPosition())) {
       
        return true;
    }
   
    //Otherwise, don't do anything
    return false;
}

The use of the else isn't needed since the function will either exit through the return true; or it will keep going and exit with false.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Your code works... somewhat.. Only about a quarter of the button sprite I'm loading actually responds. Heres my modified code:

bool Button::isSpriteClicked(Sprite& sprite, RenderWindow* window) {
    sf::IntRect rect(sprite.getPosition().x, sprite.getPosition().y, sprite.getGlobalBounds().width, sprite.getGlobalBounds().height);

    if (rect.contains(Mouse::getPosition()) && (Mouse::isButtonPressed(Mouse::Left))) {
        TextureManager tm;
        Sprite sprite1;
       
        sprite1.setTexture(tm.getTexture("cute_image.jpg"));
        tm.drawSprite(sprite1, *window);
       
        return true;
    }
   
    return false;
}

Pretty much, what I want is if the mouse is in the area AND clicking then using my texture manager I coded draw another image as long as the user is holding down the left mouse button. Like I said before, only about half of it works because when I click in the left quarter of the button sprite, it will respond perfectly. But anywhere else on the sprite? It won't do a thing. I don't know why it's doing this....
Current Projects:
Technoport

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11037
    • View Profile
    • development blog
    • Email
Because I've forgot again what I always forget when writing code like that, you need to use:
sf::Mouse::getPosition(window)
So you'll get the mouse position relative to the window instead of relative to the screen. ;)

Also you really need to read a good book about C++! I've already pointed it out before, you should use references and not pointers! It also makes you're life way easier since you don't have to dereference the pointer everytime you need to pass it as reference to a SFML function.
Additionally you shouldn't use: using namespace sf; neither should you use: using namespace std; It's bad practice to do so, not (only) because there could be some name conflicts but because it's hard to tell which class is now yours and which is now from SFML and which from the STL. And if makes easier to differenctiate what is now a class and what's an object. (e.g. sf::Sprite& sprite vs Sprite& sprite).
An another remark about your use of those temporary variables for the textures and sprite. You know that those will only get drawn once and every iteration when you call window.clear() (at least that's what you should do) everything will be gone again...
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Thank you so much for your help! You're right I need to get better with pointers  :P.
Current Projects:
Technoport