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

Author Topic: Clicking on a Sprite to highlight it  (Read 8104 times)

0 Members and 3 Guests are viewing this topic.

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Clicking on a Sprite to highlight it
« on: July 13, 2016, 10:38:30 pm »
Dear reading forum user,
i used this script to check if a sprite was clicked:
bool isTileClicked(sf::Sprite sprite)
{
        if(sf::Mouse::getPosition().x > sprite.getPosition().x
                && sf::Mouse::getPosition().x < sprite.getPosition().x + (sprite.getScale().x * 275)
                && sf::Mouse::getPosition().y > sprite.getPosition().y
                && sf::Mouse::getPosition().y < sprite.getPosition().y + (sprite.getScale().y * 275)
                && sf::Mouse::isButtonPressed(sf::Mouse::Left)
                )
        {
                return true;
        }
        else
        {
                return false;
        }
}

In the loop/grid loop i wrote:
if(isTileClicked(unselectedGrid) == true)
                                {
                                        unselectedGrid.setTexture(selected);
                                }

But only the sprite 2 below and 1 to the right was highlighted.

How can i fix that?

Just ask if you need more snippets.

EDIT:
I used the relative mouse position and getglobalbounds to create a new function but now the tile below is highlighted
« Last Edit: July 14, 2016, 11:14:12 am by epilepticPi »

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: Clicking on a Sprite to highlight it
« Reply #1 on: July 14, 2016, 12:15:26 am »
hard to tell what may cause the problem, but here few hints:

the sf::Mouse::getPosition() will gives the global position and i think you may need the position of mouse relative to window.
and for detecting whether or not the mouse position contains with sprite rectangle bounds is simple by call the sf::Sprite::getGlobalBounds() which will take care of sprite's transformation and returned a sf::Rect which has contain().

these will do exactly what you are trying to achieve.
« Last Edit: July 14, 2016, 12:18:10 am by Mortal »

TheGuerilla

  • Newbie
  • *
  • Posts: 27
  • Cynical Prick.exe
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #2 on: July 14, 2016, 03:47:47 am »
First off, I would make a function to check if a given coordinate is within a given bounding box; pointInRectangle is what I usually call it. That function would look like
inline int clamp(int val, int min, int max) {
    val = val < min ? min : val;
    val = val > max ? max : val;
    return val
}

inline bool pointInRectangle(int x, int y, int x1, int y1, int x2, int y2) {
    return (clamp(x, x1, x2) == x && clamp(y, y1, y2) == y);
(You need clamp to make pointInRectangle even easier to read)
With that function, you could just say
int x sf::Mouse::getPosition().x;
int y sf::Mouse::getPosition().y;
int x1 = sprite.getPosition().x;
int y1 = sprite.getPosition().y;
int x2 = sprite.getPosition().x + (sprite.getScale().x * 275);
int y2 = sprite.getPosition().y + (sprite.getScale().y * 275);
if (pointInRectangle(x, y, x1, y1, x2, y2) && sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
    // Do stuff...
}
Of course you could remove all the variables I set there, I just hate looking at that much within parameters.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Clicking on a Sprite to highlight it
« Reply #3 on: July 14, 2016, 03:17:23 pm »
(click to show/hide)
A custom, manual solution is not really required for this since - as Mortal already mentioned - SFML has methods to do this checking already.
  • getGlobalBounds() returns an sf::FloatRect of the object,
  • sf::FloatRect has method (contains()) to test if a point is inside it,
  • SFML can convert co-ordinates for the mouse position
Therefore:
// window is the sf::RenderWindow that you are using and sprite is the sf::Sprite
const sf::Vector2f mousePosition = window.mapPixelToCoords(sf::Mouse::getPosition(window));
const bool isMouseInSprite = sprite.getGlobalBounds().contains(mousePosition);
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #4 on: July 14, 2016, 09:44:19 pm »
Ive followed Hapax and Mortals tipps and reworked my code but now the tile below is highlighted

Mortal

  • Sr. Member
  • ****
  • Posts: 284
    • View Profile
Re: Clicking on a Sprite to highlight it
« Reply #5 on: July 14, 2016, 10:19:05 pm »
if your project is fairly small post the code or write minimal example to demonstrate the issue. this will help us to fix the problem in your code.

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #6 on: July 14, 2016, 10:45:56 pm »
#include "stdafx.h"
#include <SFML\Graphics.hpp>
#include <SFML\Window.hpp>
#include <iostream>
#include <string>

sf::RenderWindow window(sf::VideoMode(1600, 900), "Name");


int main()
{

        sf::Font font_freeSans;
        font_freeSans.loadFromFile("FreeSans.ttf");

        sf::Texture station_texture;
        station_texture.loadFromFile("station_cockpit_texture.png");

        sf::Texture selected;
        selected.loadFromFile("selected.png");

        sf::Texture unselected;
        unselected.loadFromFile("unselected.png");   //LOADING TEXTURES


        sf::Sprite unselectedGrid;
        unselectedGrid.setTexture(unselected);
        unselectedGrid.setScale(0.5, 0.5);

        while(window.isOpen())
        {
                sf::Vector2f mousePosition = window.mapPixelToCoords(sf::Mouse::getPosition(window));

                window.clear();

                sf::Event event;
                while(window.pollEvent(event))
                {
                        if(event.type == sf::Event::Closed)
                        {
                                window.close();
                        }
                }
                for(int x = 0; x < 5; x++)
                {
                        for(int y = 0; y < 5; y++)
                        {
                                if (unselectedGrid.getGlobalBounds().contains(mousePosition))
                                {
                                        unselectedGrid.setTexture(selected);
                                }
                                if(x == 2 && y == 2)
                                {
                                        unselectedGrid.setTexture(station_texture);
                                }
                                unselectedGrid.setPosition(x * 137.5, y * 137.5);
                                window.draw(unselectedGrid);
                                std::cout << "Tile created (" << x << "," << y << ")" <<  std::endl;
                                unselectedGrid.setTexture(unselected);
                        }
                }

                window_spaceport.display();
        }

    return 0;
}
 

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Clicking on a Sprite to highlight it
« Reply #7 on: July 14, 2016, 11:35:31 pm »
You need to do the bounds checking when the sprite is in the place that you want to check it with. You are currently checking one position and then moving it before drawing it. Set the position first.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #8 on: July 15, 2016, 12:26:59 am »
Thanks! worked.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Clicking on a Sprite to highlight it
« Reply #9 on: July 15, 2016, 01:03:50 am »
You're completely welcome! :)

It looks like you're attempting to draw a grid of tiles. Drawing a sf::Sprite multiple times (once for each tile) can be inefficient and you may want to consider having a look at sf::VertexArray. This way, you can draw all the tiles at once! There is a simple TileMap example on that tutorial page too.

However, you may want to consider something like Selba Ward's Tile Map. Not only does it use a form of vertex array internally, it also allow movement around the 'level' (or 'map' - the definition of which tiles go where) and, maybe more importantly in your case, can return which tile is any particular point, even after transformations such as rotation.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #10 on: July 15, 2016, 03:31:41 pm »
Is it possible to make the tile stay selected? (general)

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Clicking on a Sprite to highlight it
« Reply #11 on: July 17, 2016, 08:36:13 pm »
Yes. Store which ones have been selected and which ones haven't (a collection of booleans - one for each tile), or just a list of the ones that have (a collection of tile IDs - IDs for each tile selected).
Then consult that store when drawing them.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #12 on: July 19, 2016, 05:02:17 pm »
I wrote this:
        int TileID[] = {0};
        sf::Texture zero;
        sf::Texture TileTexture[] = {zero};

if (unselectedGrid.getGlobalBounds().contains(mousePosition) && sf::Mouse::isButtonPressed(sf::Mouse::Left))
                                {
                                        unselectedGrid.setTexture(station);
                                        int id = (x+1) * (y+1);
                                        TileID[sizeof(TileID)] = id;
                                        TileTexture[sizeof(TileTexture)] = station;
                                       
                                }
for(int i = 0; i < sizeof(TileID); i++)
                                {
                                        if((x + 1) * (y + 1) == TileID[i])
                                        {
                                                unselectedGrid.setTexture(TileTexture[i]);
                                        }
                                }

 

But i get "Access violation at memory..."
But just once.
If i run it again its not complaining but its running like without that code

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #13 on: July 19, 2016, 07:55:20 pm »
You cannot guess C++, you must learn it ;) The way you're trying to use arrays is totally wrong.
Laurent Gomila - SFML developer

epilepticPi

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: Clicking on a Sprite to highlight it
« Reply #14 on: July 19, 2016, 08:18:42 pm »
Thanks for the help!