SDL// Mouse input help

Started by
13 comments, last by Justindano 12 years, 7 months ago
Hey guys,
Could anyone please help me with this mouse input.. I have this problem over here..
My goal is to drag and drop the object somewhere.. I tried to hover over the mouse and when its clicked i changed the objects coordinates to the mouse co-ordinates... But that isnt event working.. I dont know if im doing right, or im wrong, can someone teach me how to do it??. Im really frustrated, ive been trying it for past 2 days,
Some one Please Help Me!!
Thanks, In advance :)

//Here is a example of what i tried

int x = event.motion.x;
int y = event.motion.y;
SDL_GetMouseState( &x, &y );
if( ( x > object.x ) && ( x < object.x + object.w ) && ( y > object.y ) && ( y < object.y + object.h ) )
{
if( SDL_GetMouseState( NULL, NULL )& SDL_BUTTON_LEFT )
{
object.x = event.motion.x;
object.y = event.motion.y;
}


But this aint working.. Someone help me, please.
Advertisement
event.motion gives how much the mouse moved. You may want event.button
It is unclear whether this code is part of your Poll/Wait event loop. If it is, then you shouldn't be calling SDL_GetMouseState(), you should read all your data from the event. If not, you should not rely on the event, but instead only use the information provided by SDL_GetMouseState().

You need to store the fact that you are dragging the object.

Here is a reasonably simple example, dragging a rectangle around the screen. It uses the event based model, for maximum clarity (at the expense of being maybe a little more verbose).

#include <iostream>
#include <cstdlib>

#include "SDL.h"

bool intersects(int objectX, int objectY, int dimensions, int mouseX, int mouseY)
{
if(mouseX < objectX || mouseY < objectY)
{
return false;
}

if(mouseX > objectX + dimensions || mouseY > objectY + dimensions)
{
return false;
}

return true;
}

int main(int, char **)
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cerr << "Failed to initialise SDL: " << SDL_GetError() << '\n';
return 1;
}

std::atexit(&SDL_Quit);

SDL_Surface *screen = SDL_SetVideoMode(600, 600, 0, 0);
if(!screen)
{
std::cerr << "Failed to set video mode: " << SDL_GetError() << '\n';
return 1;
}

const Uint8 Button = SDL_BUTTON_LEFT;
const int Dimensions = 30;
int x = (screen->w - Dimensions) / 2;
int y = (screen->h - Dimensions) / 2;
bool running = true;
bool dragging = false;
int offsetX = 0;
int offsetY = 0;
while(running)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
else if(event.type == SDL_KEYDOWN)
{
if(event.key.keysym.sym == SDLK_ESCAPE)
{
running = false;
}
}
else if(event.type == SDL_MOUSEBUTTONDOWN)
{
if((event.button.button & Button) == Button && intersects(x, y, Dimensions, event.button.x, event.button.y))
{
offsetX = event.button.x - x;
offsetY = event.button.y - y;
dragging = true;
}
}
else if(event.type == SDL_MOUSEBUTTONUP)
{
if((event.button.button & Button) == Button && dragging)
{
offsetX = 0;
offsetY = 0;
dragging = false;
}
}
else if(event.type == SDL_MOUSEMOTION)
{
if(dragging)
{
x = event.motion.x - offsetX;
y = event.motion.y - offsetY;
}
}
}

SDL_FillRect(screen, 0, 0);
SDL_Rect dest = { x, y, Dimensions, Dimensions };
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0xff, 0x00, 0x00));
SDL_Flip(screen);
}

return 0;
}

It is unclear whether this code is part of your Poll/Wait event loop. If it is, then you shouldn't be calling SDL_GetMouseState(), you should read all your data from the event. If not, you should not rely on the event, but instead only use the information provided by SDL_GetMouseState().

You need to store the fact that you are dragging the object.

Here is a reasonably simple example, dragging a rectangle around the screen. It uses the event based model, for maximum clarity (at the expense of being maybe a little more verbose).

#include <iostream>
#include <cstdlib>

#include "SDL.h"

bool intersects(int objectX, int objectY, int dimensions, int mouseX, int mouseY)
{
if(mouseX < objectX || mouseY < objectY)
{
return false;
}

if(mouseX > objectX + dimensions || mouseY > objectY + dimensions)
{
return false;
}

return true;
}

int main(int, char **)
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cerr << "Failed to initialise SDL: " << SDL_GetError() << '\n';
return 1;
}

std::atexit(&SDL_Quit);

SDL_Surface *screen = SDL_SetVideoMode(600, 600, 0, 0);
if(!screen)
{
std::cerr << "Failed to set video mode: " << SDL_GetError() << '\n';
return 1;
}

const Uint8 Button = SDL_BUTTON_LEFT;
const int Dimensions = 30;
int x = (screen->w - Dimensions) / 2;
int y = (screen->h - Dimensions) / 2;
bool running = true;
bool dragging = false;
int offsetX = 0;
int offsetY = 0;
while(running)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
{
running = false;
}
else if(event.type == SDL_KEYDOWN)
{
if(event.key.keysym.sym == SDLK_ESCAPE)
{
running = false;
}
}
else if(event.type == SDL_MOUSEBUTTONDOWN)
{
if((event.button.button & Button) == Button && intersects(x, y, Dimensions, event.button.x, event.button.y))
{
offsetX = event.button.x - x;
offsetY = event.button.y - y;
dragging = true;
}
}
else if(event.type == SDL_MOUSEBUTTONUP)
{
if((event.button.button & Button) == Button && dragging)
{
offsetX = 0;
offsetY = 0;
dragging = false;
}
}
else if(event.type == SDL_MOUSEMOTION)
{
if(dragging)
{
x = event.motion.x - offsetX;
y = event.motion.y - offsetY;
}
}
}

SDL_FillRect(screen, 0, 0);
SDL_Rect dest = { x, y, Dimensions, Dimensions };
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0xff, 0x00, 0x00));
SDL_Flip(screen);
}

return 0;
}



Thanks for your help, but unfortunately it couldnt help me, Sorry to say but im just a beginner, Let me get this clear.. Im planning on a simple game, where i need to drag an object, If your wondering what that object is, it is a arrow, " arrowdown " .. So its offsets are arrowdown.x and arrowdown.y .. I did everything i could as you said above in the code, I still cant get it working, Infact im not able to understand what im doing, Could you please explain more, on Should i post the entire code for your understanding?.. Please help, this is totally confusing. :/

Thanks for your help, but unfortunately it couldnt help me
[/quote]
What parts of my code do you have difficulty understanding? Have you tried running it? Playing with it, seeing how it works?


Sorry to say but im just a beginner...
[/quote]
It is OK to be a beginner, we all were beginners once. However, I will not just fix your code for you. I put quite a bit of effort into writing that example, I compiled and tested it too. You'll need to meet me half way, and the key step to doing this is to address the parts you don't understand.


Should i post the entire code for your understanding?..
[/quote]
If you want to post your code, you'll need to make a fairly minimal example (like mine), all in one file, no external assets. It should compile and run in isolation of your other files.

This will give me insight into how you are approaching the problem, and would inform me as to the best way to approach giving you hints.

What parts of my code do you have difficulty understanding? Have you tried running it? Playing with it, seeing how it works?
[/quote]
First of as you asked before im not polling events in the main loop, Im handling events in a class.. Maybe i could give you a idea on what my game is about.. I have a class for my player " class Car " .. I handle events, move the car etc.. In the handle events im trying to drag someother object which is initialized in the main loop, It's an arrow down object.. I have all its coordinates, width, height etc set.. My aim is when the car collides with the arrow, The car changes its direction downwards. I have all the collision working perfectly, But my problem is i cant drag the object to wherever i want, I hope you understand.


It is OK to be a beginner, we all were beginners once. However, I will not just fix your code for you. I put quite a bit of effort into writing that example, I compiled and tested it too. You'll need to meet me half way, and the key step to doing this is to address the parts you don't understand.
[/quote]
Im not asking you to fix my code, Im just asking help, It is just yesterday i started using mouse events, cause, i never use mouse events, only keyboard events, I somehow learnt the basics and i ended up with the code which is not working.. Here is my code to drag the object.

void Car::handle_events()
{
int x, y;
dragging = false;

if( event.type == SDL_MOUSEBUTTONDOWN )
{
if( event.button.button == SDL_BUTTON_LEFT )
{
x = event.motion.x;
y = event.motion.y;

if( ( x > arrowdown.x ) && ( x < arrowdown.x + arrowdown.w ) && ( y > arrowdown.y ) && ( y < arrowdown.y + arrowdown.h ) )
{
dragging = true;
}
}
}
if( event.type == SDL_MOUSEBUTTONUP )
{
if( event.button.button == SDL_BUTTON_LEFT )
{
dragging = false;
}
}

if( event.type == SDL_KEYDOWN )
{
switch( event.key.keysym.sym )
{
case SDLK_SPACE:
xVel = 0;

}
}
else if( event.type == SDL_KEYUP )
{
switch( event.key.keysym.sym )
{
case SDLK_SPACE:
xVel = 5;
}
}
}

void Car::drag()
{
if( dragging == true )
{
arrowdown.x = event.motion.x;
arrowdown.y = event.motion.y;
}
}

Should i be more precise..?

First of as you asked before im not polling events in the main loop, Im handling events in a class..
[/quote]
You need to poll events somewhere. Since it isn't in your car class, it must be in the code that calls handle_events(). If you aren't actively polling events, the values of a SDL_Event are meaningless - they will not reflect the current state of the inputs.


Maybe i could give you a idea on what my game is about.. I have a class for my player " class Car " .. I handle events, move the car etc.. In the handle events im trying to drag someother object which is initialized in the main loop, It's an arrow down object.. I have all its coordinates, width, height etc set.. My aim is when the car collides with the arrow, The car changes its direction downwards. I have all the collision working perfectly, But my problem is i cant drag the object to wherever i want, I hope you understand.
[/quote]
I'm not sure I really understand. I imagine you have a top down view. There is a little care that races around a maze or something. The player can start and stop the car, but perhaps not control its direction directly. They can instead place little arrows in the path of the car, that changes the car from moving horizontally to vertically. The players job is to build a set of arrows to get the car from the start to the destination, without hitting anything.

Is that your game?


Im not asking you to fix my code, Im just asking help, It is just yesterday i started using mouse events, cause, i never use mouse events, only keyboard events, I somehow learnt the basics and i ended up with the code which is not working.
[/quote]
My example code shows how to do it correctly. Your code needs to achieve the same overall "flow", even though it is structured differently.


Here is my code to drag the object.
[/quote]
Well, first of all you shouldn't unconditionally set dragging to false in handle_events(). This will result in the drag being "lost" after the event has been processed.

You need to be careful to match up the event types, when handling a SDL_MOUSEBUTTONDOWN event, do not access mouse.motion.x or mouse.motion.y. You can access mouse.button.x and mouse.button.y (if necessary).

Where is Car::drag() called from? How do you know that "event" contains the correct type of event? That code should be inside handle_events(), or called inside handle_events when event.type == SDL_MOUSEMOTION.

[hr]

I think having two classes would be better, one for the Car and one for the Arrow. The car can concentrate on reacting to keyboard events. The arrow can worry about getting dragged and dropped. Finally, you have the calling code that checks for collisions, and notifies the car (and the arrow, if necessary) about these collisions.

Should i be more precise..?


There is a couple of issues that could be the problem here.
You should post the code where you call Car::handle_events() and Car::drag().
Including the game loop...

You need to poll events somewhere. Since it isn't in your car class, it must be in the code that calls handle_events(). If you aren't actively polling events, the values of a SDL_Event are meaningless - they will not reflect the current state of the inputs.
[/quote]
I know, I handle events in the handle_events() functions and i poll it in the main loop by myCar.handle_events();


I'm not sure I really understand. I imagine you have a top down view. There is a little care that races around a maze or something. The player can start and stop the car, but perhaps not control its direction directly. They can instead place little arrows in the path of the car, that changes the car from moving horizontally to vertically. The players job is to build a set of arrows to get the car from the start to the destination, without hitting anything.
[/quote]
Yes you are right, There are 3 types of arrows, arrowdown, arrowright, arrowup, But the problem is i cant drag it..


My example code shows how to do it correctly. Your code needs to achieve the same overall "flow", even though it is structured differently.
[/quote]
I did exactly as you gave the example, Only thing i couldnt understand is.. What is offsetX and offsetY, i changed all the other things from the example to my project, Yet i cant get it working..


I think having two classes would be better, one for the Car and one for the Arrow. The car can concentrate on reacting to keyboard events. The arrow can worry about getting dragged and dropped. Finally, you have the calling code that checks for collisions, and notifies the car (and the arrow, if necessary) about these collisions.
[/quote]
Its tough to have classes for 3 different types of arrows and calling them in functions would be tough, so i just initialize them in the main loop, it doesnt make a big difference i guess..

I know, I handle events in the handle_events() functions and i poll it in the main loop by myCar.handle_events();
[/quote]
If you aren't calling SDL_PollEvent() or SDL_WaitEvent(), your code simply isn't going to work. The SDL_Event structure only has meaning when it has been recently filled by passing it to one of these structures.


Only thing i couldnt understand is.. What is offsetX and offsetY, i changed all the other things from the example to my project, Yet i cant get it working..
[/quote]
The offsetX and offsetY are just to make the program a little nicer. They record how far away the mouse pointer was from the middle when dragging begun. If you click in the middle of the arrow, using your code (were it to work), the arrow would jump so that its top-left corner is now on the mouse pointer.

If you compile and run my code, with the lines that assign to offsetX and offsetY commented out, you'll see the effect they have.


Its tough to have classes for 3 different types of arrows and calling them in functions would be tough, so i just initialize them in the main loop, it doesnt make a big difference i guess..
[/quote]
You should only need one Arrow class, if you do it correctly. You will need multiple arrow instances however. This is one problem you appear to have, you are referencing what appears to be a global arrow instance from your Car class. The Car class shouldn't need to know about arrow instances, or even about the Arrow class. Likewise, the Arrow class shouldn't know about the Car class.

These are a separate concerns. Currently your car event code is trying to drag and drop arrows. It should certainly not be doing that.

This topic is closed to new replies.

Advertisement