Archived

This topic is now archived and is closed to further replies.

sdlprorammer

SDL_PollEvent in a loop? why???

Recommended Posts

The quwestion is, why do i need the inner while loop. That's the code:
while( !done ) {
        SDL_Event event;

        while ( SDL_PollEvent(&event) ) {  //WHY THIS LOOP?
        if ( event.type == SDL_QUIT ) 
            done = true;
        if ( event.type == SDL_KEYDOWN )
            if ( event.key.keysym.sym == SDLK_ESCAPE ) done = true; 
        }
    
        keys = SDL_GetKeyState(NULL);
        
        if ( keys[SDLK_UP] )    ypos -= 1;
        if ( keys[SDLK_DOWN] )  ypos += 1;
        if ( keys[SDLK_LEFT] )  xpos -= 1;
        if ( keys[SDLK_RIGHT] ) xpos += 1;

        DrawScene();
    }
 
if i press the key arrows something moves in the screen. Why do we need the loop? Basicaly, we does it work? According to my reasoning it should work. And that's why: Suppose that i move the mouse all the time, then an event will be generated all the time, and the inside loop will never end, because every time a new event is generated, it it placed in the queue and PollEvent returns 1. That means that i can't get the state of the keybord, which means i can not move the image. However it works. Why? if you move the mouse (or do something similar) all the time ( and press the arrow key at the same time) the inside loop should be endless. However it is not. Why???? thanks [edited by - sdlprorammer on May 26, 2004 2:27:54 PM]

Share this post


Link to post
Share on other sites

Well... suppose for example that the player was mashing 2 keys down per frame and you did not have the inner while loop. Every frame, 2 events would be appended to the queue, but only 1 would be taken off. If this happened, your game would get farther and farther behind on it's input processing. The while loop is there to process every event that has occured since the last frame, not just the first event that happens to be in the queue. I hope this helps to answer your question...


[edited by - evilsteve on May 26, 2004 3:16:31 PM]

Share this post


Link to post
Share on other sites
I have a relating question.

How do you use SDL_PumpEvent() within your gameloop?
It doesn''t return anything nor does it accepts any arguements but yet its explicitly called by SDL_PollEvent(SDL_Event);

Share this post


Link to post
Share on other sites
EvilSteve, ok it makes more sence now. Not for the particular example, but in another situation placing it in a loop would help. However the question about the endless loop is still there. Why the loop is not endless according to what i have said in the first post??
thanks

Share this post


Link to post
Share on other sites

Vumaq,

I think that in most cases, you do not need to use SDL_PumpEvent, as it is used by SDL internally. It looks like SDL_PumpEvent does the work of querying the input devices, building the SDL_event structures, and placing them on the queue that is accessed by SDL_PollEvent. From the documentation, it sounds like the only time you would need to use SDL_PumpEvent yourself is if you were processing events using an "event filter" (see SDL_SetEventFilter) rather than SDL_PollEvent.

Share this post


Link to post
Share on other sites

Travis is correct, but this is difficult to explain...

I believe the mouse itself is limited in how many events it can send to the computer in a certain amount of time. To see this, open up MSPaint, select the pencil tool, and draw a sharp curve as quickly as you can. You will notice that the curve is not smooth and is instead made up of several line segments. The mouse only had enough time to send as many movement events to the computer as there are line segments in that curve. If you had drawn the curve more slowly, there would be time for more mouse movement events to be sent to the computer, and therefore more line segments in the curve. So the inner loop will never loop indefinitly because the mouse itself is limited in how many events it can send per frame.


[edited by - evilsteve on May 26, 2004 3:50:40 PM]

Share this post


Link to post
Share on other sites
SDL may have more than one event to return. For example, if I press "up arrow" and "left mouse button" at the same time, that is two events. In order to get all the information about every event that occured you must call SDL_PollEvents(...) until it returns 0, meaning that it has gotten every event.

Share this post


Link to post
Share on other sites
ok thanks for all the help
One more question:
if i press 2 keys, and click my mouse too. In the event queue i''ll have trhee events waiting right?, or just the last one? I think i''ll have all the events. Am i right or wrong? If i am right, then i don''t need the inner loop cause the queue contains all the events...
so?

Share this post


Link to post
Share on other sites
quote:
Original post by sdlprorammer
If i am right, then i don''t need the inner loop cause the queue contains all the events...
so?


so? what is it good for to have all the events in the queue if you let them rot for half an eternity because you handle only one event per frame? everytime you get more than one event per frame your queue gets longer and longer, your event handling is getting more and more behind and at some point sdl will say "forget it, queue is full" and you start losing events.

pollevents is meant to GET events from the queue. that it also calls pumpevents to "fill" the queue is nothing but an annoying side effect so you dont have to do it yourself (and reason why tend to stay away from it and instead call pump events once and then use getevent).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The SDL_PumpEvents() function is there if you dont want to use SDL''s event loop. You can just poll the keyboard/joystick/mouse instead. The PumpEvents function updates the state of the keyboard/joystick/mouse etc.

Share this post


Link to post
Share on other sites
When you''re doing a tight loop waiting for the mouse state (SDL_GetMouseState or whatever) to change. It will not change unless SDL_PumpEvents() is called in that loop.

Share this post


Link to post
Share on other sites
sorry, everybody i am trying to move around a map along with several other problem that affictl my program i have a post in this forum maybe you can check. anyway your discussion it is interesting for me because i am trying to use two sdl_mousebutton down and sdl_mousemotion. what i am trying to do it is using sdl button down as a flag and sdl_mousemotion to calculate the offset.
i have create a header file done like this [CODE]
#ifndef TILE_H_INCLUDED
#define TILE_H_INCLUDED
#define TILE_SIZE 40
#include"wrconv 0.01.h"
#include <vector>

using namespace std;

class Tile
{
struct tiledef
{
int tileID, typeID;
};
typedef vector<tiledef> LineType;
typedef vector<LineType> GridType;
GridType grid;
public:
enum { TILE_TYPE_NONE = 0, TILE_TYPE_VILLAGE, TILE_TYPE_GRASS};
SDL_Surface* Surf_Tile;
SDL_Surface* Surf_backgroundtwo;

Tile();
public:
void LoadFromFile(string filename);
void SaveToFile(string filename);
void tilerender(SDL_Surface* screen,int camerax, int cameray);
bool grabthemouse(SDL_Event* event,int ghrt);
void movethemouse(SDL_Event* event,SDL_Surface* screen);
};
[/CODE]

and a cpp like this

[CODE]
#include "tile.h"
#include"wrconv 0.01.h"
#include <math.h>
using namespace std;
Tile::Tile() {
Surf_Tile = NULL;
Surf_backgroundtwo = NULL;

}
void Tile::LoadFromFile(std::string filename)
{
ifstream infile(filename.c_str()); // open the file as an input stream
string line;
while (getline(infile, line)) // read the next line from the stream into a string
{
LineType row;
istringstream ss(line); // create an input stream from the string we read from the file
tiledef value;
char c;
while (ss >> value.tileID >> c >> value.typeID) // read the next set of coordinates from the file
{
row.push_back(value); // push the value pair onto a row
}
grid.push_back(row); // push the row onto the grid
}
}
void Tile::SaveToFile(string filename)
{
ofstream outfile(filename.c_str()); // create the output file as a stream
for (size_t row = 0; row < grid.size(); ++row)
{
for (size_t col = 0; col < grid[row].size(); ++col)
{
if (col != 0)
outfile << " ";
outfile << grid[row][col].tileID << ":" << grid[row][col].typeID;
}
outfile << endl;
}
}
void Tile::tilerender(SDL_Surface* screen,int camerax, int cameray)
{

Surf_Tile = IMG_Load( "C:/wrconv 0.01/bin/Debug/images/tile2.bmp" );
ofstream testfile("C:/wrconv 0.01/bin/Debug/maps/inf.txt");
int TilesetWidth = Surf_Tile->w /TILE_SIZE ;
int TilesetHeight = Surf_Tile->h /TILE_SIZE ;

for (size_t row = 0; row < grid.size(); ++row)
{
for (size_t col = 0; col < grid[row].size(); ++col)
{

int ID = grid[row][col].tileID;
int TilesetX = (ID % TilesetWidth) * TILE_SIZE;
int TilesetY = (ID / TilesetWidth) * TILE_SIZE;
int mapwidth = grid[row].size() * TILE_SIZE;
int mapheight = grid[col].size() * TILE_SIZE;
int centermapx = mapwidth / 2 ;
int centermapy = mapheight / 2;
int x = (col * TILE_SIZE + ( 320 - centermapx))- camerax;
int y = (row * TILE_SIZE + (240 - centermapy))- cameray;
testfile << camerax << " "<< cameray << endl;
wrconw tli;
tli.map(screen,Surf_Tile,x,y,TilesetX,TilesetY, TILE_SIZE, TILE_SIZE);

}
}
}
bool Tile::grabthemouse(SDL_Event* event){
if(event->type == SDL_MOUSEBUTTONDOWN){
if (event->button.button == SDL_BUTTON_LEFT){
int c = event->button.x;
int d = event->button.y;
if( ( c > 0 ) && ( c < 640 ) && ( d > 0) && ( d < 480 ) ){ return true; }
}
}
if(event->type == SDL_MOUSEBUTTONUP){
if (event->button.button == SDL_BUTTON_LEFT){
int c = event->button.x;
int d = event->button.y;
if( ( c > 0 ) && ( c < 640 ) && ( d > 0) && ( d < 480 ) ){ return false; }

}
}

}


void Tile::movethemouse(SDL_Event* event, SDL_Surface* screen){
if(event->type == SDL_MOUSEMOTION){
int camerax=0;
int cameray=0;
int x1 = event->motion.xrel;
int y1 = event->motion.yrel;
int x2 = event->motion.x;
int y2 = event->motion.y;

//-----------------------------
if (x1 == x2) {
if (y1 > y2){ camerax = 0; cameray= y2-y1;
}
if (y1 < y2){ camerax = 0; cameray= y1-y2;
}
}
//------------------------------
if (y1 == y2) {
if (x1 > x2){ cameray = 0; camerax= x2-x1;
}
if (x1 < x2){ cameray = 0; camerax= x1-x2;
}
}
//---------------------------------------1
if (( x1 > x2 ) and (y1 > y2)){
camerax = cameray = sqrt(pow ((x1 - x2),2) + pow ((y1 - y2),2));
}
//-----------------------------------------------------2
if (( x1 < x2 ) and (y1 > y2)){
camerax -= sqrt(pow ((x2 - x1),2) + pow ((y1 - y2),2));
cameray = sqrt(pow ((x2 - x1),2) + pow ((y1 - y2),2));
}
//-----------------------------------------------------3
if (( x1 > x2 ) and (y1 < y2)){
camerax = sqrt(pow ((x1 - x2),2) + pow ((y2 - y1),2));
cameray -= sqrt(pow ((x1 - x2),2) + pow ((y2 - y1),2));
}
//-----------------------------------------------------4
if (( x1 < x2 ) and (y1 < y2)){
camerax -= sqrt(pow ((x2 - x1),2) + pow ((y2 - y1),2));
cameray -= sqrt(pow ((x2 - x1),2) + pow ((y2 - y1),2));
}
//-----------------------------------------------------
tilerender(screen,camerax,cameray);
}

}

[/CODE]


how would you put the main? something like that doesn't work


while( t.grabthemouse(&event) == true ){ //while the left button it is pressed
t.movethemouse(&event,screen);//calculate the map offset and move the map around

SDL_Flip(screen);
}

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.