Tutorial 6
Our last ping-pong game from tutorial 5 uses fixed keyboard keys to move the player-rackets.
Here we add a system-menu, in which we have the possibility to change these keys.
We add a file menu.c with its menu.h.
- Step 1
At first we show the modifications in the main-program and player-object.
- Step 1.1
The individual game structure will get more elements:
- a pointer to the system-menu structure
- an integer containing the gamecontroller-/joystick-ID (or 0 = keyboard)
Differences green-highlighted in main.h:/* individual game structure */ struct game { struct vg3_window *wstruct; /* window structure */ int winw, winh; /* size of window */ struct vg3_ofunc *ofstruct; /* common VgaGames3-object structure */ struct vg3_quadtree *qdtr; /* collision-quadtree */ struct vg3_sysmenu *sysm; /* system-menu structure */ int jid; /* gamecontroller-/joystick-ID or 0 = keyboard */ int key_up, key_down; /* keyboard keys for moving the player-racket */ struct vg3_nwclient *nwclnt; /* network structure */ int endgame; /* flag to end the game */ };
- Step 1.2
In the main-program we
- we include the file menu.h
- call the creation of the system-menu create_menu()
- replace 0 with game->jid when defining the network keys
- call the system-menu with VG3_sysmenu_exec() when pressing the escape-key
- destroy the system-menu when cleaning up
Differences green-highlighted in main.c:
We include the file menu.h
#include <vgagames3.h> #include "main.h" #include "menu.h"
Call the creation of the system-menu create_menu()
/* create collision-quadtree with size of window */ rect.x = rect.y = 0; rect.w = game.winw; rect.h = game.winh; game.qdtr = VG3_coll_q_new(&rect, 0, 0); if (game.qdtr == NULL) { fprintf(stderr, "%s\n", VG3_error()); goto endgame; } /* define keyboard keys */ game.key_up = VGAG3_KEY_UCURS; game.key_down = VGAG3_KEY_DCURS; /* create system-menu */ create_menu(&game); game.nwclnt = NULL; game.endgame = 0;
Replace 0 with game->jid when defining the network keys
/* open network */ game.nwclnt = VG3_nw_open(game.wstruct); /* define network-keys */ VG3_nw_addkey(game.nwclnt, game.jid, game.key_up); VG3_nw_addkey(game.nwclnt, game.jid, game.key_down); /* connect to network-server with default port and name = hostname * and return own client-number, * we only want two players to connect */
Call the system-menu with VG3_sysmenu_exec() when pressing the escape-key
/* ALT+Q: exit */ VG3_key_ispressed(game.wstruct, VGAG3_KEY_Q, VGAG3_IS_NEW_PRESSED) && VG3_key_ispressed(game.wstruct, VGAG3_KEY_LALT, VGAG3_IS_PRESSED)) { break; } /* Escape: system-menu */ if (VG3_key_ispressed(game.wstruct, VGAG3_KEY_ESC, VGAG3_IS_NEW_PRESSED)) { if (VG3_sysmenu_exec(game.sysm)) { break; } change_nw_keys(&game); /* eventually actualize network-keys */ } /* clear window with halfdark blue background */
Destroy the system-menu when cleaning up
/* close network connection */ VG3_nw_close(game.nwclnt); /* free system-menu */ VG3_sysmenu_free(game.sysm); endgame: /* close window and exit */
- Step 1.3
In the player-object we just replace the 0 with game->jid when checking the pressed keys.
Differences green-highlighted in obj-player.c:/* +++ check for key-strokes and set moving direction +++ */ gobj->ydelta = 0; if (VG3_nw_key_ispressed(game->nwclnt, gobj->clnr, game->jid, game->key_up, VGAG3_IS_PRESSED)) { gobj->ydelta = -100; /* set moving upwards: full y-direction, no x-direction */ } if (VG3_nw_key_ispressed(game->nwclnt, gobj->clnr, game->jid, game->key_down, VGAG3_IS_PRESSED)) { gobj->ydelta = 100; /* set moving downwards: full y-direction, no x-direction */ } /* +++ move player according to moving direction and check for collisions +++ */
- Step 2
We add the file menu.c with its menu.h.
- Step 2.1
menu.h:#ifndef MENU_H_ #define MENU_H_ void create_menu(struct game *); void change_nw_keys(struct game *); #endif /* MENU_H_ */
- Step 2.2
Instead of dealing with real key-definitions (VGAG3_KEYS) we use an abstract enumeration (KEY_UP, KEY_DOWN).
create_menu():
We create a system-menu and insert an exit-menu, a volume-menu and a keyboard-menu.
The keyboard-menu has submenus for each defined key, here we install two of them, where KEY_UP and KEY_DOWN refer to.
change_nw_keys():
When the system-menu was called we check for changed keys comparing the new ones with our saved previous.
menu.c:#include <vgagames3.h> #include "main.h" void create_menu(struct game *); void change_nw_keys(struct game *); /* set enumeration for keyboard keys in struct game: key_up and key_down */ enum { KEY_UP, KEY_DOWN }; /* create system-menu */ void create_menu(struct game *game) { struct vg3_text stxt; struct vg3_sysmenu_submenu *inputmenu, *submenu; game->sysm = VG3_sysmenu_new(game->wstruct, NULL, VG3_color_brightness(VGAG3_COLOR_GREEN, 50), VGAG3_COLOR_GREEN); /* insert exit-menu */ VG3_sysmenu_simple_exitmenu(game->sysm, NULL, "Exit game"); /* insert volume-menu with only main-, sound- and music-volume */ VG3_sysmenu_simple_volumemenu(game->sysm, NULL, "Main volume", "Sound volume", NULL, NULL); /* insert a sub-menu for input-settings */ VGAG3_TEXT_ATTRIBUTES_SET(&stxt, NULL, 0, 0, "Input settings"); inputmenu = VG3_sysmenu_insert_menuentry(game->sysm, NULL, &stxt); /* insert keyboard-menu into input settings sub-menu */ submenu = VG3_sysmenu_simple_keyboardmenu(game->sysm, inputmenu); /* add key-settings KEY_UP and KEY_DOWN to keyboard-menu */ game->jid = 0; /* keyboard */ game->key_up = VGAG3_KEY_UCURS; game->key_down = VGAG3_KEY_DCURS; VG3_sysmenu_simple_keyboardentry(game->sysm, submenu, KEY_UP, "move upwards", game->key_up, "Upwards moving"); VG3_sysmenu_simple_keyboardentry(game->sysm, submenu, KEY_DOWN, "move downwards", game->key_down, "Downwards moving"); } /* if keyboard keys were changed, actualize network-structure */ void change_nw_keys(struct game *game) { int keyidx; /* KEY_UP has been changed? */ keyidx = VG3_sysmenu_getkeyval(game->sysm, game->jid, KEY_UP); /* get actual key for KEY_UP */ if (keyidx != game->key_up) { VG3_nw_changekey(game->nwclnt, game->jid, game->key_up, keyidx); /* replace network-key */ game->key_up = keyidx; } /* KEY_DOWN has been changed? */ keyidx = VG3_sysmenu_getkeyval(game->sysm, game->jid, KEY_DOWN); /* get actual key for KEY_DOWN */ if (keyidx != game->key_down) { VG3_nw_changekey(game->nwclnt, game->jid, game->key_down, keyidx); /* replace network-key */ game->key_down = keyidx; } }
- Step 3
Now we enhance our system-menu to replace the keyboard with a gamecontroller/joystick if one exits.
- Step 3.1
create_menu():
We check whether exactly one gamecontroller/joystick is connected,
if yes, we use it instead of the keyboard.
change_nw_keys():
No changes needed.
menu.c:#include <vgagames3.h> #include "main.h" void create_menu(struct game *); void change_nw_keys(struct game *); /* set enumeration for keyboard keys in struct game: key_up and key_down */ enum { KEY_UP, KEY_DOWN }; /* create system-menu */ void create_menu(struct game *game) { struct vg3_text stxt; struct vg3_sysmenu_submenu *inputmenu, *submenu; int *fjid; game->sysm = VG3_sysmenu_new(game->wstruct, NULL, VG3_color_brightness(VGAG3_COLOR_GREEN, 50), VGAG3_COLOR_GREEN); /* insert exit-menu */ VG3_sysmenu_simple_exitmenu(game->sysm, NULL, "Exit game"); /* insert volume-menu with only main-, sound- and music-volume */ VG3_sysmenu_simple_volumemenu(game->sysm, NULL, "Main volume", "Sound volume", NULL, NULL); /* insert a sub-menu for input-settings */ VGAG3_TEXT_ATTRIBUTES_SET(&stxt, NULL, 0, 0, "Input settings"); inputmenu = VG3_sysmenu_insert_menuentry(game->sysm, NULL, &stxt); /* get number of found gamecontrollers/joysticks */ VG3_gamecontroller_getall(game->wstruct, &fjid); if (fjid[0] == 1) { /* exactly one gamecontroller/joystick found */ game->jid = fjid[1]; } else { /* no or more than one gamecontrollers/joysticks found: we use keyboard */ game->jid = 0; } free(fjid); /* insert keyboard-menu or gamecontroller-/joystick-menu if exactly one is found */ if (game->jid > 0) { /* gamecontroller/joystick */ struct vg3_gamecontroller gcs; /* insert gamecontroller-/joystick-menu into input settings sub-menu */ submenu = VG3_sysmenu_simple_gcmenu(game->sysm, inputmenu); /* get information about connected gamecontroller/joystick */ VG3_gamecontroller_getinfo(game->wstruct, game->jid, &gcs); /* add KEY_UP to gamecontroller-/joystick-menu */ if (gcs.is_gamecontroller) { /* gamecontroller */ game->key_up = VGAG3_GC_AXIS_RIGHTY_UP; } else { /* joystick */ game->key_up = 1; /* just an unknown key */ } VG3_sysmenu_simple_gcentry(game->sysm, submenu, game->jid, KEY_UP, "move upwards", game->key_up, "Upwards moving"); /* add KEY_DOWN to gamecontroller-/joystick-menu */ if (gcs.is_gamecontroller) { /* gamecontroller */ game->key_down = VGAG3_GC_AXIS_RIGHTY_DOWN; } else { /* joystick */ game->key_down = 2; /* just an unknown key */ } VG3_sysmenu_simple_gcentry(game->sysm, submenu, game->jid, KEY_DOWN, "move downwards", game->key_down, "Downwards moving"); } else { /* keyboard */ /* insert keyboard-menu into input settings sub-menu */ submenu = VG3_sysmenu_simple_keyboardmenu(game->sysm, inputmenu); /* add key-settings KEY_UP and KEY_DOWN to keyboard-menu */ game->key_up = VGAG3_KEY_UCURS; game->key_down = VGAG3_KEY_DCURS; VG3_sysmenu_simple_keyboardentry(game->sysm, submenu, KEY_UP, "move upwards", game->key_up, "Upwards moving"); VG3_sysmenu_simple_keyboardentry(game->sysm, submenu, KEY_DOWN, "move downwards", game->key_down, "Downwards moving"); } } /* if keyboard keys were changed, actualize network-structure */ void change_nw_keys(struct game *game) { int keyidx; /* KEY_UP has been changed? */ keyidx = VG3_sysmenu_getkeyval(game->sysm, game->jid, KEY_UP); /* get actual key for KEY_UP */ if (keyidx != game->key_up) { VG3_nw_changekey(game->nwclnt, game->jid, game->key_up, keyidx); /* replace network-key */ game->key_up = keyidx; } /* KEY_DOWN has been changed? */ keyidx = VG3_sysmenu_getkeyval(game->sysm, game->jid, KEY_DOWN); /* get actual key for KEY_DOWN */ if (keyidx != game->key_down) { VG3_nw_changekey(game->nwclnt, game->jid, game->key_down, keyidx); /* replace network-key */ game->key_down = keyidx; } }
- Putting together
See the files in example-games/tutorial6/ - Executing the system-menu
Main menuInput menuFound gamecontrollersSetting for gamecontroller
<<Prev | Top | Next>> |