SDL mouse position with multiple sdl windows - c++

With these lines I managed to get the mouse coordinates only inside my sdl window. This code is inside the "draw" function.
SDL_SetHintWithPriority(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1", SDL_HINT_OVERRIDE);
SDL_GetMouseState(&mxx, &myy);
//other code
SDL_GL_SwapWindow(window);
Now I draw two windows: there is a way to obtain mouse position only when it is inside the first window? (when the mouse inside the second window consider it as out of border of the first window and coordinates are not updated)
void draw(){
//common part
if (windowId == 0) {
//draw something in the first window
}
else {
//draw other things in the second window
}
SDL_GL_SwapWindow(window);
}
This is my draw function this structure, called in the main like this after creating 2 SDL windows object
window1.draw()
window2.draw()

Related

Positioning a sprite at (0, 0) places the sprite off screen by a few pixels

When I position a sprite at 0, 0 (top left corner of the screen) it doesn't show. It's off screen by a few pixels. Here is a sample of my code.
Sprite s;
Texture t;
t.loadFromFile("Tiles.png");
t.setSmooth(false);
s.setTexture(t);
s.setTextureRect(IntRect(0, 0, 16, 16));
s.setPosition(0, 0);
window.draw(s);
window.display();
If I add
Style::None
to my RenderWindow, then the sprite is positioned properly at the top left of the screen.
Is there a way to position sprites ignoring the windows title bar? Or another way to fix this issue? The only way I can seem to get the sprite positioned correctly is if I guess how many pixels off it is and manually add an offset to the sprites position, but this is a very bad way of doing it and I can't get it positioned perfectly. If I set the position to (11, 64), the sprite is at about the top left of the screen.
Edit: Here is a full example piece of code I used to recreate the issue:
#include <SFML/Graphics.hpp>
using namespace sf;
const int WIDTH = 1000;
const int HEIGHT = 1000;
int main()
{
RenderWindow window(VideoMode(WIDTH, HEIGHT), "Window", Style::Titlebar | Style::Close);
RectangleShape square(Vector2f(100.f, 100.f));
square.setFillColor(Color::Red);
square.setPosition(0, 0);
while (window.isOpen())
{
Event windowEvent;
while (window.pollEvent(windowEvent))
{
if (windowEvent.type == Event::Closed)
{
window.close();
}
}
window.clear(Color::White);
window.draw(square);
window.display();
}
return 0;
}
When I run it, this is the result I get. https://i.imgur.com/bIOnb4L.png
Since posting this issue, I've realized that the problem is that when the title bar is enabled, it takes up space on my window, (0, 0) is behind the title bar. I still don't know how to fix it, though.

SFML splash logo window transparent

SFML only allows creating a window of a rectangular(boxy) shape and all other actions are done within it. I am making a Monopoly game and I basically want Monopoly Logo to flash on a screen when the user clicks the executable file and it han’t has to be inside any window(just logo with transparent background).After the logo, the rectangular window then appears. Is there any way to do this?
SFML doesn't have any integrated feature to make window background transparent.
In order to achieve this, you should use some OS specific functions. But this won't work either. If you change window attributes to have a transparent window, SFML will render correctly, but you won't see anything because everything, background and foreground, will be transparent.
What's the solution then? The easiest way to do this is by not having any background, making your logo fit perfectly into your window. Then you only need to remove the title bar and borders, with sf::Style::None.
This is how I reach this:
int main()
{
// First, I load the logo and create an sprite
sf::Texture logo;
if (!logo.loadFromFile("monopoly.png")){
exit(1);
}
sf::Sprite sp;
sp.setTexture(logo);
sp.scale(0.2, 0.2); // My logo is quite big in fact (1st google result btw)
int logoWidth = sp.getGlobalBounds().width;
int logoHeight = sp.getGlobalBounds().height;
// With the logo loaded, I know its size, so i create the window accordingly
sf::RenderWindow window(sf::VideoMode(logoWidth, logoHeight), "SFML", sf::Style::None); // <- Important!! Style=None removes title
// To close splash window by timeout, I just suppose you want something like this, don't you?
sf::Clock timer;
sf::Time time = timer.restart();
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
// event loop is always needed
}
// Window closed by time
time += timer.restart();
if (time >= sf::seconds(2.f)){
window.close();
}
window.clear();
window.draw(sp);
window.display();
}
// Then, reuse the window and do things again
window.create(sf::VideoMode(600, 400), "SFML");
while (window.isOpen()){
sf::Event event;
while (window.pollEvent(event)){
}
window.clear();
window.draw(sp);
window.display();
}
return 0;
}
Note that you can re-use your window again just by re-creating with create method.
Results:
and then the other window :

GLFW camera and mouse control

So basically am learning OpenGL and the GLFW libraries from the tutorial on page: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-6-keyboard-and-mouse/
My problems is with this less lesson showing the control of camera movement with mouse.
Basicaly it makes the application to get "FPS" like camera, with disabled cursor being moved on center of screen with each frame. But the camera gets crazy when we lose focus on the window and then it regains. For example if we click on the window to regain focus away from the middle of view, the camera will be moved by big amount. I tried to fix this issue with adding window focus callback:
void window_focus_callback(GLFWwindow* window, int focused){
if (focused)
{
//center mouse on screen
int width, height;
glfwGetWindowSize(window, &width, &height);
glfwSetCursorPos(window, 1024 / 2, 768 / 2);
windowFocused = true;
}
else
{
windowFocused = false;
}
And in the main application loop:
if(windowFocused) computeMatricesFromInputs();
But for some reason this solution doesnt work.
Is there any way to fix this issue using glfw?
Question is a bit old, but I recently suffered a similar issue. So just sharing, more solutions exist.
I use GLFW_CURSOR_DISABLED. In this mode the mouse position is not (yet) updated when you receive the 'on' focus event, so call to GetCursorPos delivers the previous value. The new cursor position arrives in the MouseMove callback AFTER the 'on' focus event.
I solved it by keeping track of the regain of focus and use this int he OnMouseMove callback to either dispatch a MouseInit (to snap the cursor) or a regular MouseMove.
This way I can ALT+TAB out of my window and return with the cursor somewhere else without nasty jumps/rotations of the camera.
void InputManagerGLFW::Callback_OnMouseMove(
GLFWwindow* window,
double xpos, //
double ypos) //
{
if (!mFocusRegained)
{
mMouseBuffer.Move(xpos, ypos);
}
else
{
mFocusRegained = false;
mMouseBuffer.Init(xpos, ypos);
}
}
void InputManagerGLFW::Callback_OnFocus(
GLFWwindow* window,
int focused)
{
if (focused)
{
// The window gained input focus
// Note: the mouse position is not yet updated
// the new position is provided by the mousemove callback AFTER this callback
Log::Info("focus");
// use flag to indicate the OnMouseMove that we just regained focus,
// so the first mouse move must be handled differently
mFocusRegained = true;
// this will NOT work!!!
// double x,y;
// glfwGetCursorPos(window,&x,&y);
// mMouseBuffer.Init(x,y);
}
else
{
// The window lost input focus
Log::Info("focus lost");
}
}

how to display pixel coordinates in mousepressEvent() function and then how to use them in paintGL() function everytime the mouse is clicked

I am creating a gui on opengl in qt4 IDE.I have created an widget with opengl window and there I became able to display the [b]curves[/b]. Here I use [b]paintGL()[/b] and within this I call my Drawing function for display.But my problem is that, I here use the[b] mousePressEvent(QMouseEvent *event)[/b] for getting the pixel coordinates so that clicking on the opengl window I can generate the curve at that particular clicking position. but after running the program I found that the initial drawing function and the curve generated. but after clicking the window could not be updated, but in the console application all calculations executed, only the display is not updated.
So how can I update the opengl window after clicking mouse on this window?
Here is my source code:
GlWidget.cpp
//////Mouse Click Event for finding the pixel values//////
void GLWidget::mousePressEvent(QMouseEvent *event)
{
float window_width,window_height;
float ratio_x,ratio_y,cy;
click_x=event->x();
click_y=event->y();
// qDebug()<<"screen cx1==="<<cx1;
// qDebug()<<"screen cy1==="<<cy1;
window_width = 800;
window_height = 600;
ratio_x=30.0/window_width;
ratio_y=30.0/window_height;
cy=window_height-click_y;
click_x=click_x*ratio_x-10;
click_y=cy*ratio_y-10;
qDebug()<<"original_position_on_screen x==="<<click_x;
qDebug()<<"original_position_on_screen y==="<<click_y;
count=count+1;
qDebug()<<"count==="<<count;
func();
}
void GLWidget::func()
{
Draw_Curve(); //Drawing function
}
void GLWidget::Draw_Curve()
{
//Draw The Curve
}
void GLWidget:: paintGL() // paintGL() function
{
glClear(GL_COLOR_BUFFER_BIT);
Draw_Axes(); //Draw 3d coordinate axes
func(); //in this function we get the pixel coordinates everytime the mouse is clicked in the window
}
There are few things:
instead of calling a function to render anything from the mouse event handler, you should request update
void GLWidget::mousePressEvent(QMouseEvent *event)
{
float window_width,window_height;
float ratio_x,ratio_y,cy;
click_x=event->x();
click_y=event->y();
// qDebug()<<"screen cx1==="<<cx1;
// qDebug()<<"screen cy1==="<<cy1;
window_width = 800;
window_height = 600;
ratio_x=30.0/window_width;
ratio_y=30.0/window_height;
cy=window_height-click_y;
click_x=click_x*ratio_x-10;
click_y=cy*ratio_y-10;
qDebug()<<"original_position_on_screen x==="<<click_x;
qDebug()<<"original_position_on_screen y==="<<click_y;
count=count+1;
qDebug()<<"count==="<<count;
update(); // to request image update
}
your paintGL() method does all the rendering. So, whatever you want to display goes here.

Moving a sprite and handling events

I'm learning the SFML library at the moment but I'm a little lost on moving the sprite. Here's my main.cpp file:
#include <SFML/Graphics.hpp>
int main()
{
// Create the main window
sf::RenderWindow App(sf::VideoMode(800, 600), "SFML window");
// Load a sprite to display
sf::Texture Image;
if (!Image.LoadFromFile("cb.bmp"))
return EXIT_FAILURE;
sf::Sprite Sprite(Image);
// Define the spead of the sprite
float spriteSpeed = 10.f;
// Start the game loop
while (App.IsOpened())
{
// Process events
sf::Event Event;
while (App.PollEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
if (sf::Keyboard::IsKeyPressed(sf::Keyboard::Up))
Sprite.Move(spriteSpeed * App.GetFrameTime(), 0);
}
// Clear screen
App.Clear();
// Draw the sprite
App.Draw(Sprite);
// Update the window
App.Display();
}
return EXIT_SUCCESS;
}
But I get really slow, inconsistent movements, why isn't the sprite moving steadily around the screen? Also, seeing as how I plan to use the mouse to control the character how will I use the loop to make the character move towards where the user clicks?
You shouldn't be checking if the key is held down in the event loop.
SFML only posts one event when the key is first pressed down, and then another event when the key is released. In this case, your code is only checking if the key is held when an event occurs (such as moving your mouse, clicking, or anything else).
Moving the IsKeyPressed check out of the event loop, preferably below it, should fix the issue.
Making the sprite move towards your mouse is a more complicated issue, better suited for the Game Development StackExchange.