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

Author Topic: Sprites-mouse input  (Read 6068 times)

0 Members and 1 Guest are viewing this topic.

Bersuli

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Sprites-mouse input
« on: June 25, 2021, 09:17:59 pm »
I need to do something in my code and i need to know if it is possible and if it is maybe you can show me how to do it.I need so that whenever i click mouseleft an image(sprite/texture--i don't know what exactly i am new to sfml) appears on the screen in the place i clicked.I did this but when i release the mouse button the image dissapears.
I need it to stay,because i need to draw multiple of them(and all of them to stay) so i belive for this i should not use window.clear()

this what i did:
//the shape(it is an x image)
RectangleShape playerx(Vector2f(42, 42));
   playerx.setOrigin(21, 21);
   Texture playerxTexture;
   playerxTexture.loadFromFile("x.png");
   playerx.setTexture(&playerxTexture);


if (Mouse::isButtonPressed(Mouse::Left))
      {
      
         Vector2i mousePos = Mouse::getPosition(window);
         playerx.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
         window.draw(playerx);
      }

please Help


Update:
in my program i have a game that has a texture as the table game wich is like a chess table just bigger.Do i need to make like a 2D array for that texture?
I don't know how to make this either=)))
« Last Edit: June 25, 2021, 09:53:05 pm by Bersuli »

G.

  • Hero Member
  • *****
  • Posts: 1590
    • View Profile
Re: Sprites-mouse input
« Reply #1 on: June 25, 2021, 09:59:30 pm »
Create a list or vector or whatever of RectangleShape or sprite.
Then use events, the MouseButtonPressed event. When a mouse button is clicked, create a rectangle at the position of the click.
Finally, somewhere between your clear and display, draw all the rectangles contained in your list.
(as said in the tutorials, not using clear/draw/display sucks)

Bersuli

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Sprites-mouse input
« Reply #2 on: June 26, 2021, 03:04:35 pm »
Ok i will try this and come back.

Bersuli

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Sprites-mouse input
« Reply #3 on: June 26, 2021, 04:28:07 pm »
ok so i tried something but it doesn't work i don't understand whwat u told me to do exactly=)))
i would be very thankfull if u could show me how to do it.

G.

  • Hero Member
  • *****
  • Posts: 1590
    • View Profile
Re: Sprites-mouse input
« Reply #4 on: June 26, 2021, 06:35:23 pm »
It would be better to show what you tried and explain how it "doesn't work" so that we can correct it

Bersuli

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Sprites-mouse input
« Reply #5 on: June 26, 2021, 10:32:06 pm »
The thing is my friend i din't understand what u told me to do=))
So i tried something else that i tought might work which is adding a vector2f with the coordinates of the mouse and then draw my image at those coordinates.

this everithing i wrote down,if u want i can send u a picture of the board i am talking about(if it helps u helping me with my problem):

#include <SFML/Graphics.hpp>
#include<iostream>
using namespace std;
using namespace sf;
int main()
{
   int n = 500;
   RenderWindow window(VideoMode(600, 600), "X & 0 infinit", Style::Close | Style::Resize);
   RectangleShape player(Vector2f(600,600));
   player.setOrigin(0, 0);
   Texture playerTexture;
   playerTexture.loadFromFile("tabla.jpeg");
   player.setTexture(&playerTexture);

   RectangleShape playerx(Vector2f(42, 42));
   playerx.setOrigin(21, 21);
   Texture playerxTexture;
   playerxTexture.loadFromFile("x.png");
   playerx.setTexture(&playerxTexture);


   while (window.isOpen())
   {
      Event evnt;
      while (window.pollEvent(evnt))
      {
         switch (evnt.type)
         {
         case Event::Closed:
            window.close();
            break;
         }

      }
      window.draw(player);

      if (Mouse::isButtonPressed(Mouse::Left))
      {

         Vector2i mousePos = Mouse::getPosition(window);
         //playerx.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
         Vector2f position(mousePos.x, mousePos.y);
         playerx.setPosition(position);
         window.draw(playerx);


      }
      window.display();
   }

   return 0;
}

player is the board and playerx is the X i want to draw multiple times on the mouse click.

Bersuli

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Sprites-mouse input
« Reply #6 on: June 26, 2021, 10:40:03 pm »
ok so i think i get what u tried to tell me something about a list with the coordinates and then printing the shapes at the respectiv coordinates.
The thing is that the point of the game is to be "infinit" (i hope i got the word right i am not english) it is not really infint but i also don't think that would make much sense in making a list of 200 coordinates for 200 shapes=)))

Bersuli

  • Newbie
  • *
  • Posts: 7
    • View Profile
    • Email
Re: Sprites-mouse input
« Reply #7 on: June 26, 2021, 11:00:53 pm »
okokok i just did something,it is just half wrong=))

tha board of the game is comeing and going but the x images remain,is there any way i can make the board also stay?
BTW sorry if i am desparing u but i am new to this and really hyped=))

oh and also when an x gets printed it s actually more=)

#include <SFML/Graphics.hpp>
#include<iostream>
using namespace std;
using namespace sf;
int main()
{
   int n = 500;
   RenderWindow window(VideoMode(600, 600), "X & 0 infinit", Style::Close | Style::Resize);
   RectangleShape player(Vector2f(600,600));
   player.setOrigin(0, 0);
   Texture playerTexture;
   playerTexture.loadFromFile("tabla.jpeg");
   player.setTexture(&playerTexture);

   RectangleShape playerx(Vector2f(42, 42));
   playerx.setOrigin(21, 21);
   Texture playerxTexture;
   playerxTexture.loadFromFile("x.png");
   playerx.setTexture(&playerxTexture);

   window.draw(player);
   while (window.isOpen())
   {
      Event evnt;
      while (window.pollEvent(evnt))
      {
         switch (evnt.type)
         {
         case Event::Closed:
            window.close();
            break;
         }

      }
      //window.draw(player);
      if (Mouse::isButtonPressed(Mouse::Left))
      {

         Vector2i mousePos = Mouse::getPosition(window);
         playerx.setPosition(static_cast<float>(mousePos.x), static_cast<float>(mousePos.y));
         //float pozitiex = static_cast<float>(mousePos.x);
         //float pozitiey = static_cast<float>(mousePos.y);
         float x = mousePos.x;
         float y = mousePos.y;
         window.draw(playerx);
         playerx.setPosition(x, y);
      }
      //window.draw(playerx);
      //playerx.setPosition(x, y);
      window.display();
   }
« Last Edit: June 26, 2021, 11:18:41 pm by Bersuli »

G.

  • Hero Member
  • *****
  • Posts: 1590
    • View Profile
Re: Sprites-mouse input
« Reply #8 on: June 27, 2021, 12:09:58 am »
I barely understand now what you're trying to do.
You want to display an image at the position of your click, every time you click somewhere. Right? If not please be more explicit.

First things first, clearing the screen isn't some optional step. Every frame you clear the screen, you draw your shit, and you call display. There isn't any clear in your code.
If you want your board to "stay" on the screen, then draw it every frame.

If you want to react to a click, use the MouseButtonPressed event. Code inside the event will be triggered only once when you click. And that should probably be "add an X to this position".

To do that, you can create an empty std::vector of rectangles at the start of your program, and everytime the MouseButtonPressed event is triggered you create a new rectangle, set its size, color, texture or whatever, set its position to the position of the click, then you add it into you vector.
After your event loop, clear the window, draw your board, iterate through your vector to draw every rectangle, call display.


kojack

  • Sr. Member
  • ****
  • Posts: 300
  • C++/C# game dev teacher.
    • View Profile
Re: Sprites-mouse input
« Reply #9 on: June 27, 2021, 08:44:50 am »
The problem here is because SFML is doing double buffering.
Here's how it works: You have 2 buffers (memory for full windows). At any instance one will be the back buffer (where you draw) and one will be the front buffer (which is seen on the monitor). Calling the display() method swaps the two buffers. So you typically construct the scene entirely in the back buffer, then when finished do the display so that work becomes visible and you can wipe and start drawing again in the other buffer.

Usually this is fine since every frame you clear the buffer and draw everything, so after a swap (display() call) it all gets done again. But in your situation without the clear and only drawing everything once, half your draw calls go to one buffer and half to the other. Your tabla.jpeg is only drawn once, so it will flicker on and off because you only drew it in one buffer, not both.

Some solutions:
1 - stop double buffering. I have no idea if SFML allows that, I think it's hard coded to do it (had a quick look, didn't see a way) since 99% of use cases benefit from it.
2 - do everything twice. Draw, display, draw again, display again. That way both buffers will get everything. Not a nice solution but it would probably work.
3 - Render Texture. A render texture is like a back buffer but you own it and can draw into it when you want. You can put a render texture on a sprite or shape and draw it to the window like normal, but you can also draw into the render texture. Drawing to the render texture isn't double buffered.

Some rough pseudocode:
Draw board into the render texture
While window open
   If mouse pressed
      Draw tile into render texture
   End
   Clear window
   Draw render texture
   Display
End

Some code for render textures is shown here: https://www.sfml-dev.org/tutorials/2.5/graphics-draw.php under the off screen drawing section.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10801
    • View Profile
    • development blog
    • Email
Re: Sprites-mouse input
« Reply #10 on: June 30, 2021, 02:22:16 pm »
You have to call clear, (draw) and display on the render window every frame without exception, because of double buffering, as kojack correctly mentioned.

If you want to "persist" some drawing across multiple frames, without tracking the actual list of sprites, you should be using a render texture.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/