Updating two SDL_KEYDOWN for 2 players at once?

Hi there,

I have two players, I try and update them but only the first one works. Basically, code looks like this in my main:

1
2
3
4
5
6
7
8
9
while(!Done)
{
	{
	Player.Update();
	Player2.Update();
	Player.Draw();
        Player2.Draw();
        }
}


Both Players Draw but only the top one updates, so no matter what, only the top one moves.

Both my players code look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void Player::Update()
{
        while( SDL_PollEvent(&event) )
	{			
		if ( event.type == SDL_KEYDOWN )
		{
			switch(event.key.keysym.sym)
			{
			case SDLK_w:
		        upup = false;
		        Movement.m_fY = 0.2f;	
			break;

			case SDLK_s:
			downup = false;
			Movement.m_fY = -0.2f;
			break;

etc etc

So that is pretty much how everything is moved, just different keys. I heard I have to do different things, like key mapping or something? But I am pretty lost on what to do!

Any help would be appreciated, thanks

SDL, C++ running on Visual Studio 10

Thanks

Last edited on
The thing is, when an event happens the event is added to the event queue. When you call SDL_PollEvent it removes one event from the event queue (if the queue is not empty). So what happens is that Player.Update(); will handle all the events leaving the event queue empty so Player2.Update(); has no events to handle. They simply steal events from each other.

You will have the same problem if you try to handle other kinds of events like SDL_QUIT somewhere else in your program.

To fix all this you should only have one loop that handles all the events in the program. In that loop can of course call other functions. You can make the update function take an event as argument and pass the event from the event loop.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while(!Done)
{
	while(SDL_PollEvent(&event))
	{
		switch (event.type)
		{
		case SDL_QUIT:
			Done = true;
			break;
		}
		Player.Update(event);
		Player2.Update(event);
		
	}
	Player.Draw();
	Player2.Draw();
}

This will call Player::Update() each time you receive an event. That means that it might be called 0 or many times in each iteration of the outer loop. If you only want to have it called exactly once every iteration you could call the update function outside the event loop. In that case the update function should not handle events(!). Instead you can have a special Player member function for handling key events. Here is an example of what I mean.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
while(!Done)
{
	while(SDL_PollEvent(&event))
	{
		switch (event.type)
		{
		case SDL_QUIT:
			Done = true;
			break;
		case SDL_KEYDOWN:
			Player.onKeyDown(event.key.keysym.sym);
			Player2.onKeyDown(event.key.keysym.sym);
			break;
		}
	}
	Player.Update();
	Player2.Update();
	Player.Draw();
	Player2.Draw();
}
onKeyDown takes a SDLKey so it might look something like this
1
2
3
4
5
6
7
8
9
10
11
void Player::onKeyDown(SDLKey key)
{
	switch(key)
	{
	case SDLK_w:
		upup = false;
		break;
	case SDLK_s:
		downup = false;
		break;
	...
The actual movement you probably want to handle in the update function to get a smooth movement.


EDIT:
I can also mention that if all you want to do is check if a key is down or not you can use SDL_GetKeyState for that. http://www.libsdl.org/cgi/docwiki.cgi/SDL_GetKeyState
1
2
3
4
5
6
7
8
9
Uint8* keystate = SDL_GetKeyState(0);
if (keystate[SDLK_w])
{
	// the w key is down
}
if (keystate[SDLK_s])
{
	// the s key is down
}
This will not affect the event queue so it is safe to use anywhere. If you use SDL_GetKeyState it is important that you call SDL_PollEvent or SDL_PumpEvents somewhere in you program because otherwise the key state will not get updated.
Last edited on
Thanks a lot Peter87,

Just mucking around with it now, will report back when I get it working, I might be missing something but hopefully I can find what I did wrong.

Also, big thanks on linking that GetKeyState, that is awesome to use, cheers
Being a pain but it doesn't seem to be getting past the:

switch (event.type)

According to break points

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
	while(!Done)
	{

		//fps.Start();

		//glClear(GL_COLOR_BUFFER_BIT);
		//colorOffset += SDL_GetTicks();

		while(SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				{
					if ( event.type == SDL_QUIT )
					{
						Done = true;
					}

					if ( event.type == SDL_KEYDOWN )
					{
						if ( event.key.keysym.sym == SDLK_ESCAPE )
							Done = true;
					}
				}

				if (keystate[SDLK_w])
				{
					printf("w is down");
				}
				g_oPlayer.Update(event);
				g_oPlayer2.Update(event);
			}

		}

		g_oPlayer.Draw();
		g_oPlayer2.Draw();

		SDL_GL_SwapBuffers();
	}

	SDL_Quit();
	return 0;
}


I hope you can spot what I did wrong straight away...
You're using if/else in your switch.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
switch (event.type)
{
case SDL_QUIT: Done = true; break
case SDL_KEYDOWN:
  switch (event.key.keysym.sym)
  {
  case SDLK_ESCAPE: Done = true; break;
  }
  break;
case ...
}
//And then the update outside of the switch
g_oPlayer.Update(event);
g_oPlayer2.Update(event);
Last edited on
Beautiful, thank you LowestOne, worked perfectly, thanks Peter87
Topic archived. No new replies allowed.