Create variable from memory - c++

I'm using sfml. I need to write a function that will create a type sf::RectangleShape and return a new sf::RectangleShape with the position of the mouse at the current time and stay there after I use window.draw() Right now my code is:
sf::RectangleShape functions::Map(sf::RectangleShape wall0){
wall0.setPosition(0,0);
wall0.setSize(sf::Vector2f(200,200));
wall0.setFillColor(sf::Color::Green);
wall0 = this->wall0;
return wall0;
}
void functions::Draw(){
window.clear();
window.draw(logo);
if (menu){
window.draw(menuStart);
window.draw(menuOptions);
window.draw(menuExit);
}
if (playing){
void Map();
window.draw(wall0);
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)){
}
}
I want to return wall0 with the new mouse position when the left mouse button is pressed. I know how to get the mouse input but not how to draw the object and keep it on the window. I've gotten it to where it draws the object while the mouse button is clicked but it doesn't stay.

I'm not familiar with sfml - but briefly looking at your code this is what I think you want to do:
void functions::Map(sf::RectangleShape & wall0){
wall0.setPosition(0,0);
wall0.setSize(sf::Vector2f(200,200));
wall0.setFillColor(sf::Color::Green);
}
Then functions::Draw method:
...
if (playing){
window.draw( Map(wall00) );
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)){
...

Related

How do I capture(trap) a mouse in a window in c++?

I am writing a tile map editor in SFML and C++. I have been having all sorts of troubles with the mouse. I am using the built in SFML Mouse:: static functions and recently managed to get a custom cursor moving on the screen and pointing accurately to a tile by doing as follows:`
Sprite cursor;
bool focus = false;
RenderWindow window(VideoMode(512, 288), "Tilemap editor");
window.setFramerateLimit(60);
Texture cursorTexture;
if(!cursorTexture.loadFromFile("Graphics/Cursor.png")) {
std::cout << "Failed to load cursor texture\n";
return 0;
}
cursor.setTexture(cursorTexture);
Mouse::setPosition(mousePos);
While(window.isOpen()) {
window.setMouseCursorVisible(focus);
if(Mouse::getPosition().x != lastMousePos.x) {
mousePos.x = mousePos.x + (Mouse::getPosition().x - lastMousePos.x);
}
if(Mouse::getPosition().y != lastMousePos.y) {
mousePos.y = mousePos.y + (Mouse::getPosition().y - lastMousePos.y);
}
cursor.setPosition(mousePos.x, mousePos.y);
lastMousePos = Mouse::getPosition();
window.clear();
window.draw(cursor)
window.display()
}
The built-in Mouse functions only display relativity to the desktop or the window and as I am using this app in a small window in which my view moves, I can't use either. The solution above moves a cursor independent of the desktop and with the ability to move the cursor if and when I want to move my view.
The issue is that my mouse will move off the side of the app when I try to click items in the top left corner.
Is there a good cross-platform (I'm on Linux BTW) way to trap the mouse inside of the window unless I enter a keystroke (like a VM window)? Also, is there a better way to do cross-platform mouse support in general? SFML kinda sucks. (Code obviously needs to be in a main function and the namespace must be sf with SFML/Graphics.hpp included)
There is already a method for that.
void setMouseCursorGrabbed (bool grabbed)
// Grab or release the mouse cursor.
You can also use these methods to convert your screen coordinates to mouse coordinates and vice versa.
Vector2f mapPixelToCoords (const Vector2i &point) const
// Convert a point from target coordinates to world coordinates, using the current view.
Vector2f mapPixelToCoords (const Vector2i &point, const View &view) const
// Convert a point from target coordinates to world coordinates.
Vector2i mapCoordsToPixel (const Vector2f &point) const
// Convert a point from world coordinates to target coordinates, using the current view.
Vector2i mapCoordsToPixel (const Vector2f &point, const View &view) const
// Convert a point from world coordinates to target coordinates.
sf::RenderWindow Class Reference

How to know a sprite position inside a view, relative to window?

I have this sprite of a car that moves with varied speed.
It is inside a view and the view is moved to the left to keep the car always in the center of the window.
The view accompanies the displacement of the car, ie it is shifted to the left as the car accelerates or brakes.
This way the car will always appear in the center.
But if for example it is overtaken by another car, it will be left behind.
For it not to disappear from the window, I have to zoom in the view so that all the cars appear.
But for this, I need to know the position of the car in relation to the window (not in relation to the view).
getGlobalBounds().left or getPosition().x show the same value, which is the position relative to the view, not relative to the window, as shown in the image.
How to know a sprite position inside a view, relative to window?
After several hours of research, I finally find the easy way of achieve this. And yes, it was ridiculously easy.
But first, I would like to clear up some misconceptions.
getGlobalBounds().left or getPosition().x show the same value,
which is the position relative to the view, not relative to the
window, as shown in the image.
In fact, those methods return the position in the world, not in the view nor in the window.
You can have, for instance, a 500x500 window, with a 400x400 view, in a 10000x10000 world. You can place things in the world, outside of the view or the window. When the world is rendered, then the transformations of the view (translations, rotations, zoom, ...) are applied to the world and things are finally shown in the window.
To know where a coordinate in the world is represented in the window (or any other RenderTarget) and vice versa, SFML actually have a couple of functions:
RenderTarget.mapCoordsToPixel(Vector2f point)
Given a point in the world gives you the corresponding point in the RenderTarget.
RenderTarget.mapPixelToCoords(Vector2f point)
Given a point in the RenderTarget gives you the corresponding point in the world. (this is useful to map mouse clicks to corresponding points in your world)
Result
Code
int main()
{
RenderWindow window({ 500, 500 }, "SFML Views", Style::Close);
sf::View camera(sf::FloatRect(0, 0, window.getSize().x, window.getSize().y));
sf::Vector2f orig(window.getSize().x / 2, window.getSize().y / 2);
camera.setCenter(orig);
sf::Font f;
f.loadFromFile("C:/Windows/Fonts/Arial.ttf");
sf::Text t;
t.setFont(f);
sf::RectangleShape r;
r.setPosition(10, 10);
r.setSize(sf::Vector2f(20, 20));
r.setOutlineColor(sf::Color::Blue);
r.setFillColor(sf::Color::Blue);
t.setPosition(10, 40);
while (window.isOpen())
{
for (Event event; window.pollEvent(event);)
if (event.type == Event::Closed)
window.close();
else if (event.type == Event::KeyPressed){
camera.move(-3, 0);
camera.rotate(5.0);
camera.zoom(1.1);
}
auto realPos = window.mapCoordsToPixel(r.getPosition());
std::string str = "Pos: (" + std::to_string(realPos.x) +","+ std::to_string(realPos.y) + ")";
t.setString(str);
window.clear();
window.setView(camera);
window.draw(r);
window.draw(t);
window.display();
}
return EXIT_SUCCESS;
}

Moving sprites in a vector

I move sprites stored in a formationvector by holding the mousebutton. Problem is: Whenever i move the sprite onto another one, i move both sprites at the same time.
What i want: Moving the sprite1 over the other sprites2 without changing the position of sprite 2 or with other words:
-Testing in a loop if a sprite of a vector is clicked on
-If sprite is clicked on:
Move this sprite around while button is pressed but somehow stop this move while this movement in order to avoid moving more than this one sprite.
Here is my try so far:
while (App.pollEvent(Event))
{
// Window closed
if (Event.type == sf::Event::Closed)
{
return (-1);
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
for (size_t k = 0; k < formation.size(); k++)
{
if (isMouseOver(formation[k], App) == true)
{
Mouseposition = sf::Vector2f(sf::Mouse::getPosition(App));
Mouseposition.x = Mouseposition.x - formation[k].getLocalBounds().width / 2;
Mouseposition.y = Mouseposition.y - formation[k].getLocalBounds().height / 2;
formation[k].setPosition(sf::Vector2f(Mouseposition));
Formation_playernames.clear();
Formation_playerinformation.clear();
Formation_Playernames(Font, Formation_playernames, formation, playerlist);
Formation_Playerinformation(Font, Formation_playerinformation, formation, playerlist);
}
}
}
}
The Formation-functions store the correct new positions of the sprites and their colors based on the positions into the formation vector
The problem is the for-loop, i could do it without but that would lead to a much longer code. How could i do it ?
Instead of simply checking whether or not the mouse button is pressed, you should structure your code so you can check exactly when the button is pressed, and when it is released. You can then structure your code such that different presses of the button are distinguished from each other. semi-pseudocode follows
bool button_is_pressed = false;
Sprite* currently_selected_sprite = nullptr;
// main application loop
while (...)
{
...
// other application logic
...
if (!button_is_pressed)
{
if (CheckIfButtonIsPressed())
{
button_is_pressed = true;
// Button was just pressed.
// Select the appropriate sprite by checking
// the mouse coordinates against the positions
// of the sprites.
}
else
{
// Button not being pressed.
// Likely no logic needed here.
}
}
else // button_is_pressed == true
{
if (CheckIfButtonIsPressed())
{
// Button is being held down.
// Implement dragging logic using the
// pointer to the selected sprite.
}
else
{
button_is_pressed = false;
// Button was just released.
// Deselect the sprite.
currently_selected_sprite = nullptr;
}
}
}
Alternatively, you could handle mouse events, which will take care of much of this logic for you. http://sfml-dev.org/documentation/2.0/classsf_1_1Event.php
In a more English like pseudo code, this is what your function is doing:
if the mouse button is currently pressed
move all the sprites which are under the mouse to be centered on the mouse cursor
else
do nothing
This is what I'm suggesting
at the moment the mouse button is pressed down
select the sprite which is under the mouse cursor
at the moment the mouse button is released
deselect the selected sprite
if the mouse button is currently pressed, and a sprite is selected
move the selected sprite to the position of the mouse cursor

Draw new line every time mouse is moved in c++ builder

I have a code I want to load every time I move my mouse cursor; it draws line to direction of mouse and beyond, and every time it the line gets to certain x coordinate, the line reflects. The problem is that now the program only draws line when I click on the PaintBox.
Here is my code so far:
void __fastcall TForm2::PaintBox1Click(TObject *Sender)
{
Form2->Refresh();
TPoint P;
::GetCursorPos( &P );
P = ScreenToClient( P );
int XX;
int YY;
if (P.x<240)
{
XX=15;
YY= ((445-P.y)*(XX-P.x)/(240-P.x)+P.y);
}
else if(P.x==240)
{
XX=240;YY=-5;
}
else
{
XX=465;
YY= ((445-P.y)*(XX-P.x)/(240-P.x)+P.y);
}
int delta=2*(445-YY);
this->Canvas->MoveTo(240, 445);
this->Canvas->LineTo(XX,YY);
while(0<YY&&YY<480&&YY!=445)
{
XX=abs(480-XX);
YY-=delta;
this->Canvas->LineTo(XX,YY);
}
}
You are trying to paint in an OnClick event handler. That's the wrong place to paint. The only correct place to paint to a VCL paint box is from its OnPaint event handler.
You will need to respond to OnClick though. Make a note of the location of the click and update any state that you need to maintain. Then call Invalidate on the paint box to force a paint cycle.

SFML 2.1 - Detecting a single mouse click and changing a texture

What I'm trying to do is:
I have a sprite. And this sprite has 3 textures. First texture, let's call it "not-visited", is the initial one. Now, when I click on the sprite it should change it texture to "clicked" meaning that the sprite was clicked. And this texture should remain until I click somewhere else on the screen. When I do this, the texture should change to the third one, "visited". And if I click on the sprite again it should change its texture to "clicked"...
So, I should have here a bool function called "ClickDetected" and its code should do this:
if (event.type == Event::MouseButtonReleased && event.mouseButton.button == Left)
if (mouse_over_sprite)
return true;
Right? OK, then, I have a class Node. This class has a method "Clicked":
bool Clicked {
if (ClickDetected) { return true; }
}
I know it may be unnecessary, but let it stay for now. Next, in Update() method of this class:
if (Clicked) { change_texture_to_"clicked"; if (!visited) visited=true; }
else {
if (!visited) change_texture_to_"not-visited";
if (visited) change_texture_to_"visited";
}
But this doesn't work how it should. When I click on sprite texture changes to "clicked". When I release the mouse button the "clicked" texture stays... But when I move the mouse texture changes to "visited". And it should remain "clicked", until I click somewhere else. I tried to use a while loop here, but it didn't work. What can I do?
I've put this code to Graph class (method Update()) to manage many Nodes. I've change it a little bit and now it works fine.