Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » When I tried Multiplayer in my Pong game, priority got to only one player.

This thread is locked; no one can reply to it. rss feed Print
When I tried Multiplayer in my Pong game, priority got to only one player.
Doctor Cop
Member #16,833
April 2018
avatar

I am making a PONG game for the compensation of Krampus hack 2018 and while implementing the AI part I got bored so I thought of making it multiplayer. I'm currently making my game with MinGW compiler but I thought of making my multiplayer prototype in my old Code Blocks. Allegro's 5.0.10 was already configured in it so I thought it will be quick to prototype but when I changed the lines of AI part with the following code the output was unexpected.

#SelectExpand
1 if(event.type == ALLEGRO_EVENT_KEY_DOWN) 2 { 3 switch(event.keyboard.keycode) 4 { 5 case ALLEGRO_KEY_R 6 :main(); 7 break; 8 case ALLEGRO_KEY_ESCAPE: 9 done = true; 10 break; 11 case ALLEGRO_KEY_UP: 12 13 keys[UP] = true; 14 break; 15 case ALLEGRO_KEY_DOWN: 16 17 keys[DOWN] = true; 18 break; 19 case ALLEGRO_KEY_W: 20 21 keys[W] = true; 22 break; 23 case ALLEGRO_KEY_S: 24 25 keys[S] = true; 26 break; 27 } 28 } 29 30 if(event.type == ALLEGRO_EVENT_KEY_UP) 31 { 32 switch(event.keyboard.keycode) 33 { 34 case ALLEGRO_KEY_UP: 35 keys[UP] = false; 36 break; 37 case ALLEGRO_KEY_DOWN: 38 keys[DOWN] = false; 39 break; 40 case ALLEGRO_KEY_W: 41 keys[W] = false; 42 break; 43 case ALLEGRO_KEY_S: 44 keys[S] = false; 45 break; 46 } 47 } 48 49 if(keys[UP]) 50 { 51 MovePaddleUp(&pad2); 52 } 53 else if(keys[DOWN]) 54 { 55 MovePaddleDown(&pad2); 56 } 57 else if(keys[W]) 58 { 59 MovePaddleUp(&pad1); 60 } 61 else if(keys[S]) 62 { 63 MovePaddleDown(&pad1); 64 }

When Arrow keys are pressed then W, S are not working. The Pad1 is getting priority instead of doing simultaneous movement. Is it because I used an older version of Allegro? Do I have to configure my MinGW compiler in Code Blocks to run it correctly or is there something wrong with my code?

Edit:

Now I have attached the game, its for Windows.
I'm going to compile it in 5.2.4 version.

Dizzy Egg
Member #10,824
March 2009
avatar

It never gets to see KEY_W if it sees KEY_UP, because you break; out before it gets there...:P

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Doctor Cop
Member #16,833
April 2018
avatar

I switched them but the output is still same.

Dizzy Egg
Member #10,824
March 2009
avatar

You can't "switch" them, you have to stop breaking!! Think about it logically...

IF KEY_W THEN BREAK
IF KEY_UP THEN BREAK <--NEVER GETS REACHED IF KEY_W!

IF KEY_UP THEN BREAK
IF KEY_W THEN BREAK <--NEVER GETS REACHED IF KEY_UP!

You can't break and expect more code in the switch/case to run!!

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Peter Hull
Member #1,136
March 2001

One event only contains info about one key state change. If you press 2 keys you have 2 events. Make sure you're processing all events each cycle of the main loop.
You might find al_get_keyboard_state is an easier API to use.

Also:

case ALLEGRO_KEY_R :main(); break;

I hope that doesn't mean that pressing 'R' will recursively call main()!

Audric
Member #907
January 2001

#SelectExpand
1 if(keys[UP]) 2 { 3 MovePaddleUp(&pad2); 4 } 5 else if(keys[DOWN]) 6 { 7 MovePaddleDown(&pad2); 8 } 9 // 10 // This else is what prevents pad1 from moving when pad2 is moving. Remove it 11 // 12 /**/else/**/ if(keys[W]) 13 { 14 MovePaddleUp(&pad1); 15 } 16 else if(keys[S]) 17 { 18 MovePaddleDown(&pad1); 19 }

Peter Hull
Member #1,136
March 2001

Audric said:

This else is what prevents pad1 from moving when pad2 is moving. Remove it

Nice one! 8-)

Doctor Cop
Member #16,833
April 2018
avatar

Ah! Ingenious of you Audric.

That got perfectly well.
I was focusing on the switch case part and was thinking that how can it possibly be stopping paddle 1 to move, and there you got it.

I have attached the executable.

Audric
Member #907
January 2001

There is still probably an issue that this entire block of if(keys[]) gets executed "every time an event is received, no matter the kind of event".
Do the paddles go faster if you hit random keys ?
If you are using a timer event to give the tempo of the game logic, the block should rather be here:

 if(event.type == ALLEGRO_EVENT_KEY_UP)
...
else if(event.type == ALLEGRO_EVENT_KEY_DOWN)
...
else if(event.type == ALLEGRO_EVENT_TIMER)
{
   // here
   // move paddles according to controllers
   // apply ball physics
}

Doctor Cop
Member #16,833
April 2018
avatar

Thanks Audric, I tried it but the ball still moves faster even when I move mouse over screen.

I must be doing it badly. I'm going to refactor it and look for possible blind spots.

Edit:
Thanks Audric, I was doing it indeed badly, now its much better, there is still some flickering but ball isn't going off just on every event passed to game.

I have attached the main program file, please look at it and tell me my mistakes and where I should I improve.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Doctor Cop
Member #16,833
April 2018
avatar

Yes Edgar, now i totally get it.

Please look at my main C file and tell me where I can improve. Everybody is welcome for positive criticism.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Okay, well, there are some problems.

I used Code::Blocks code folding feature to illustrate my point :

{"name":"611873","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/d\/fd014ca5d6760439816334c0211343ad.png","w":1920,"h":1080,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/d\/fd014ca5d6760439816334c0211343ad"}611873

You can clearly see how you're using your ALLEGRO_EVENT before it is valid.

The line :

Only allocates space on the stack for your object. Because in C object's don't have constructors, the memory held by event is uninitialized.

So when you ask on the following line,

if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {/*...*/};

You're accessing type, which is uninitialized.

In fact, you don't even have a valid value for your event until the end of your loop when you call al_wait_for_event and then you just ignore it!.

You've got to learn scoping rules.

Another questionable thing is mixing event handling and logic.

Peter Hull started a thread on the event loop, you should follow along there and take a look at the different kinds of loops there are.

The basic game loop is like this (Object Oriented and in C, for your viewing pleasure) :

#SelectExpand
1typedef struct Game {/*...blah...*/} *game; 2 3Game* CreateGame(/** parameters */) {/** make a game object */} 4void DestroyGame(Game** g) {/** destroy game */} 5 6void UpdateGame(Game* g , double dt) {/** ... */} 7 8int HandleEvent(Game* g , ALLEGRO_EVENT ev) { 9 if (ev.type == ALLEGRO_EVENT_TIMER) { 10 UpdateGame(g , al_get_timer_speed(ev.timer.source)); 11 } 12 /** Handle other events here */ 13} 14void Redraw(Game* g) {/**...*/} 15 16 17 18int main(int argc , char** argv) { 19 (void)argc; 20 (void)argv; 21 22 Game* game = CreateGame(); 23 if (!game) {return 1;} 24 25 while (!game->quit) { 26 if (game->redraw) { 27 Redraw(game); 28 game->redraw = false; 29 } 30 do { 31 ALLEGRO_EVENT ev; 32 al_wait_for_event(queue , &ev); 33 /// We're now guaranteed a valid event. al_get_next_event makes no such guarantee 34 HandleEvent(game , ev); 35 } while (!al_is_event_queue_empty(queue)); 36 } 37 38 /// Clean up 39 DestroyGame(&game); 40 41 return 0; 42}

Doctor Cop
Member #16,833
April 2018
avatar

Thanks for all this. I got this wrong way from a website I was learning so I thought that it was somehow OK.

Right now I'm listening "Pray for me" and i'm all fired up to correct my mistakes.
thanks for the link I'll correct all the mistakes right away and learn what is necessary.

How did you made the image to display?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Doctor Cop
Member #16,833
April 2018
avatar

No, I was talking about the images in attachments.
How to show images from attachments.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Just use the URL of the attachment as the URL of the img tag, like so :

<img src="https://d1cxvcw9gjxu2x.cloudfront.net/attachments/611874" />

Gives you :

{"name":"611874","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/5\/f5b9d682a1f3459e1b61a8fdf8162116.png","w":1920,"h":1080,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/5\/f5b9d682a1f3459e1b61a8fdf8162116"}611874

Protip : When you upload attachments, they turn blue and become a link. Right click on them and select "copy link location" and then paste it into your src tag.

Doctor Cop
Member #16,833
April 2018
avatar

Like this :
{"name":"611875","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/d\/6d4e65f5083f5b765ab638f267b70e02.png","w":814,"h":639,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/6\/d\/6d4e65f5083f5b765ab638f267b70e02"}611875

Thanks!

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

princeofspace
Member #11,874
April 2010
avatar

Continuing on Edgar's suggestion:

   while (!game->quit) {
      if (game->redraw) {
         Redraw(game);
         game->redraw = false;
      }

Most games separate the logic from the draw code. In a nice, small pong game like this one, that probably isn't necessary, but in bigger projects, you'll want to have an update function prior to the Redraw.

   while (!game->quit) {
      if (game->redraw) {
         Update(game);
         Redraw(game);
         game->redraw = false;
      }

The update function handles the "business logic" of the game --- moving paddles and the ball, for instance. This gives you a number of advantages; one is that you can now pause the game, simply by omitting the update call whilst the game state is paused.

   while (!game->quit) {
      if (game->redraw) {
         if (!game->paused) {
            Update(game);
         }
         Redraw(game);
         game->redraw = false;
      }

Note that the main game loop will still call Redraw whether the game is paused or not. Because you've separated the event loop from the game logic, you can now manipulate the game pause state with an input event.

Doctor Cop
Member #16,833
April 2018
avatar

Now try to draw tails behind the ball as it travels

I already have a challenge of completing the AI part and now completing the menu.
It's almost done, maybe I'll be able to upload my entry today. Kudos!

I'll come to the tail part tomorrow.

Go to: