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

Author Topic: Help using mouse to draw onto grid and collision help  (Read 3564 times)

0 Members and 1 Guest are viewing this topic.

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Help using mouse to draw onto grid and collision help
« on: August 22, 2014, 05:03:30 am »
I have been trying to do this for 2 days now and I just cant seem to get it to work. I know how it should be done in my head, I just have a very hard time translating that to code. I need the mouse to get the current sprite it's over and then set the texture to a different one, but I cannot figure out how to do it, I looked all through the documentation, the forums here, google I just cant find anything that helps me. The code below is taken from my game project, but I made it so that it will work correctly if you just copy and paste it into your IDE


#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>

using std::cout;
using std::endl;

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Window");

    sf::Mouse mouse;
    while(window.isOpen())
    {
        window.clear(sf::Color::White);
        sf::Event event;
        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                {
                    window.close();
                }break;
                case sf::Event::Resized:
                {
                    sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                    window.setView(sf::View(visibleArea));
                }break;
            }
        }

        //Set Tiles to Grid Test
        sf::Texture setGridTexture;
        sf::Sprite setGridSprite;
        setGridSprite.setTexture(setGridTexture);
        setGridSprite.setColor(sf::Color::Black);

        sf::Vector2i Grid(15,15);

        sf::Texture tempGridTexture;
        sf::Sprite tempGridSprite;
        tempGridSprite.setTexture(tempGridTexture);
        tempGridSprite.setColor(sf::Color::Green);

        sf::Vector2i setTilesOnGridX(mouse.getPosition(window).x, Grid.x);
        sf::Vector2i setTilesOnGridY(mouse.getPosition(window).y, Grid.y);

        //Draw Grid
        for(int i = 0; i < Grid.x; i++)
        {
            for(int j = 0; j < Grid.y; j++)
            {
                tempGridSprite.setPosition(j * 32, i * 32);
                tempGridSprite.setTextureRect(sf::IntRect(Grid.x * 32, Grid.y * 32, 32, 32));
                window.draw(tempGridSprite);
            }
        }

        //Place Tiles
        if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
        {
            cout << "Clicked" << endl;
            window.draw(setGridSprite);
            setGridSprite.setPosition(setTilesOnGridX.x * 32, setTilesOnGridY.y * 32);
            setGridSprite.setTextureRect(sf::IntRect(Grid.x * 32, Grid.y * 32, 32, 32));
            }
            else
            {
                cout << "Let go" << endl;
            }

        //End set tiles to Grid Test.
        window.display();
    }
}
 



Also I cannot figure out collision either. I looked at the documents about the intersecting function, but that did nothing. Here is the code for the current collision I have.

#include <iostream>
#include <math.h>
#include <vector>
#include <SFML/Graphics.hpp>

using namespace std;

int main()
{
    sf::Vector2f position;
    sf::Vector2f velocity;
    float maxspeed = 4.0f;
    float accel = 4.5f;
    float decel = 0.01f;
    bool vSyncEnabled = true;
    sf::FloatRect bottom, left, right, top;

    sf::Vector2f dsize;
    sf::Color color;
    sf::RectangleShape rect;


    //Setup Window and Framerate
    sf::RenderWindow window(sf::VideoMode(800, 600), "Bounding Box (Collision)");
    window.setFramerateLimit(60);
    window.setVerticalSyncEnabled(vSyncEnabled);

    //Load Texture
    sf::Texture character;
    if(!character.loadFromFile("Resources/Textures/triangle.png"))
    {
        cout << "Error loading resource 'triangle.png'" << endl;
    }
    else
    {
        cout << "triangle.png texture loaded" << endl;
    }

    //Set Sprite for Character Object
    sf::Sprite characterSprite;
    characterSprite.setTexture(character);
    //characterSprite.setOrigin(sf::Vector2f(0, 0));dsa
    characterSprite.setPosition(400, 300);

    //Load Red Block Texture
    sf::Texture redBlock;
    if(!redBlock.loadFromFile("Resources/Textures/RedBlock.png"))
    {
        cout << "Error loading 'RedBlock.png" << endl;
    }
    else
    {
        cout << "RedBlock.png texture loaded" << endl;
    }

    //Set Sprite for Red Block Object
    sf::Sprite redBlockSprite;
    redBlockSprite.setTexture(redBlock);
    redBlockSprite.setOrigin(sf::Vector2f(0, 0));
    redBlockSprite.setPosition(200, 200);

    sf::Vector2f RBSposition;

    while(window.isOpen())
    {

        window.clear(sf::Color::White);
        sf::Event event;

        while(window.pollEvent(event))
        {
            switch(event.type)
            {
                case sf::Event::Closed:
                {
                    window.close();
                }
                break;
                //Dont stretch the window contents when its resized
                case sf::Event::Resized:
                {
                    sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
                    window.setView(sf::View(visibleArea));
                }
                break;
            }
        }

        rect.setPosition(position);
        rect.setSize(dsize);
        rect.setFillColor(color);

        //WASD Movement
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
        {
            velocity.x -= accel;
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
        {
            velocity.x += accel;
        }
        else
        {
            velocity.x *= decel;
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
        {
            velocity.y -= accel;
        }
        else if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
        {
            velocity.y += accel;
        }
        else
        {
            velocity.y *= decel;
        }

        //Make sure the sprite isn't going too fast
        if(velocity.x < -maxspeed) velocity.x = -maxspeed;
        if(velocity.x >  maxspeed) velocity.x =  maxspeed;
        if(velocity.y < -maxspeed) velocity.y = -maxspeed;
        if(velocity.y >  maxspeed) velocity.y =  maxspeed;

        //Update sprite position and move sprite
        position += velocity;

        //Get the window's size
        sf::Vector2u currWSize = window.getSize();

        if(position.x <= 0)
        {
            position.x = 0;
        }
        if(position.y <= 0)
        {
            position.y = 0;
        }
        if(position.x >= currWSize.x - characterSprite.getGlobalBounds().width)
        {
            position.x = currWSize.x - characterSprite.getGlobalBounds().width;
        }
        if(position.y >= currWSize.y - characterSprite.getGlobalBounds().height)
        {
            position.y = currWSize.y - characterSprite.getGlobalBounds().height;
        }


        float x, y, BoundsX, BoundsY;
        float CharX, CharY, CharBoundsY, CharBoundsX;

        x = redBlockSprite.getPosition().x;
        y = redBlockSprite.getPosition().y;

        BoundsX = redBlockSprite.getGlobalBounds().width;
        BoundsY = redBlockSprite.getGlobalBounds().height;

        CharX = characterSprite.getPosition().x;
        CharY = characterSprite.getPosition().y;


    //Collision
    if(characterSprite.getGlobalBounds().intersects(redBlockSprite.getGlobalBounds()))
    {
         //If player hits right side of block, go right
        if(CharX <= x)
        {
            position.x = x - BoundsX;
        }
        else if(CharX >= x)
        {
            position.x = x + BoundsX;
        }
        else if(CharY <= y)
        {
            position.x = y - BoundsY;
        }
        else if(CharY >= y)
        {
            position.x = y + BoundsY;
        }
    }

        sf::FloatRect rectToMove(position, {characterSprite.getGlobalBounds().width, characterSprite.getGlobalBounds().height});


        characterSprite.setPosition(position);
        velocity *= decel;
        window.draw(characterSprite);
        window.draw(redBlockSprite);

        window.display();
    }

    return 0;
}
 

If I can at least get these 2 things figured out, then I can finally get somewhere with my project.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #1 on: August 22, 2014, 09:48:21 am »
When you do
sf::Vector2i setTilesOnGridX(mouse.getPosition(window).x, Grid.x);
you'll end up with the position of your mouse relative to the window. So it might for example be a the pixel position 142, but if you now do
setTilesOnGridX.x * 32
you're multiplying that 142 pixel position by 32, so you end up with 4544, which of course is not the position you want your sprite at. ;)

The basic idea is:
  • Get the mouse position (if necessary use mapPixelToCoords).
  • Add/remove any offset of your grid's position.
  • Divide the new position by the tile size.
  • Round down to an integer number.
  • You've the grid position now.
  • Multiply the grid position with the tile size.
  • Re-add/remove the grid offset
  • You've the sprite position now.

For the collision you might want to be a bit more specific what you're trying to do exactly.
« Last Edit: August 22, 2014, 11:18:29 am by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #2 on: August 22, 2014, 11:12:41 am »
"Add/remove any offset of your grid's position."

How do I do that?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #3 on: August 22, 2014, 11:18:02 am »
Since your grid seems to start at position (0, 0) there's no offset thus you don't need to add anything. If your grid were placed at for example (200, 200), you'd have to subtract 200 first.

Just notice that I forgot to mention that you'd need to re-add the offset to get the new position.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #4 on: August 22, 2014, 11:21:57 am »
Oh ok so you said:

"Divide the new position by the tile size.
Round down to an integer number."

So In this case since I have no offset i would do 15 X 15 / 32?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #5 on: August 22, 2014, 11:26:13 am »
Well what's "15 X 15"?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #6 on: August 22, 2014, 11:36:05 am »
15 x 15 225, so I did this:

sf::Vector2i Grid(15,15);
        sf::Vector2u MouseCurrPos(gameVars.mouse.getPosition(winVars.window).x, gameVars.mouse.getPosition(winVars.window).y);
        float sum;
        sf::Vector2i setTilesOnGridX(gameVars.mouse.getPosition(winVars.window).x, Grid.x);
        sf::Vector2i setTilesOnGridY(gameVars.mouse.getPosition(winVars.window).y, Grid.y);


        //Draw Grid
        for(int i = 0; i < Grid.x; i++)
        {
            for(int j = 0; j < Grid.y; j++)
            {
                tempMapTileSprite.setPosition(j * 32, i * 32);
                tempMapTileSprite.setTextureRect(sf::IntRect(Grid.x * 32, Grid.y * 32, 32, 32));
                winVars.window.draw(tempMapTileSprite);
            }
        }

        //Set tiles on grid - setMapTileSprite
        if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
        {
            sum = rint(Grid.x * Grid.y / 32);
            sum * 32;

            //setMapTileSprite.setPosition(tempMapTileSprite.getPosition().x, tempMapTileSprite.getPosition().y);
            setMapTileSprite.setPosition(gameVars.mouse.getPosition(winVars.window).x, gameVars.mouse.getPosition(winVars.window).y);
        }
 

what do I do next?

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #7 on: August 22, 2014, 12:30:32 pm »
Alright I got this:

//Set tiles on grid - setMapTileSprite
        if(sf::Mouse::isButtonPressed(sf::Mouse::Left))
        {
            sum = Grid.x * Grid.y / 32;
            cout << sum * 32 + 1<< endl;;
            setMapTileSprite.setPosition(setMapTileSprite.getPosition().x, setMapTileSprite.getPosition().y);
            setMapTileSprite.setPosition(sum, sum);
            tempMapTileSprite.setTexture(setMapTileTexture);
        }
 

So next I have to get the current mouse position over the grid, how would I do that? Mouse position.x * y / Grid.x * Grid.y / 32?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10819
    • View Profile
    • development blog
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #8 on: August 22, 2014, 01:25:30 pm »
Well I'm not gonna hold your hand through all of your programming. The task of a programmer is to turn a description into actual code. ;)

However it seems you're kind of mixed up in all the different types.
You've a grid of 15 x 15 tiles. Your indices range from 0 to 14 for the X and Y axis. Each tile is 32px x 32px in size. So the first tile is at the position (0, 0), because 0*32. The 15th tile is at the position (448, 0) because 14*32 = 448. Your 225th tile is at the position (448, 448).
When your mouse is for example at the position (236, 132), you subtract the offset which is 0, you then divide by the tile size so you do 236/32 and 132/32 and then round down to integers, which gives you (7, 4). (7, 4) is your position on the grid itself. To get the position of your new sprite you have to multiply it by the tile size, that is (7,4) x 32 = (224, 128). If you had any offset to your grid, you'd now add it back to the position.

It's really not that hard. ;)
For other things you seem to be stuck I can only recommend to take out a piece of paper and a pen and write down what you have and figure out on paper how to combine what to get where you want. Playing around with code pieces without really knowing what you want to do, usually doesn't play out well.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #9 on: August 23, 2014, 03:47:23 am »
Alright so I get the offset, I did a test and I think I know how to get it but the pronblem is it doesnt get the windows offset it gets my computer screens offset... I think I may have got it working but idk, I think its changing the texture for the entire map, I dont know how to chnage if for that particular tile. more research...
« Last Edit: August 23, 2014, 04:34:07 am by Chay Hawk »

Chay Hawk

  • Full Member
  • ***
  • Posts: 101
    • View Profile
    • Email
Re: Help using mouse to draw onto grid and collision help
« Reply #10 on: August 23, 2014, 06:21:56 am »
Ok I figured it out, something is wrong with the way the grid is draw. I tried to draw an image that wasnt a solid color and it came out looking wierd so thats why it wasnt working. I actually probably had the code right at one point too D: So there is a problem with this for loop:

for(int i = 0; i < Grid.x; i++)
        {
            for(int j = 0; j < Grid.y; j++)
            {
                purpleBlockSprite.setPosition(j * 32, i * 32);
                purpleBlockSprite.setTextureRect(sf::IntRect(Grid.x * 32, Grid.y * 32, 32, 32));
                winVars.window.draw(purpleBlockSprite);
            }
        }
 
I had to remove this line: purpleBlockSprite.setTextureRect(sf::IntRect(Grid.x * 32, Grid.y * 32, 32, 32)); and then now it draws correctly. well, now I just need to re do the grid draw part :(