In the previous tutorial we've added a graphics library to our project. So far, when we run the program, a blue screen is shown for two seconds. In this tutorial we are going to add keyboard features to our program: when we run it a blue screen will appear and the program won't terminate until we press Esc on the keyboard.
Adding keyboard and KBC source code
During class, you should have developed functions to interact with the
keyboard using the
kbc. Now it is time to add these to our
src folder and add them to the
Makefile SRCS tag - I usually declare them by alphabetical order. Below is a screenshot with the changes I have made so far.
Introducing objects in C
As you might know,
C++ is object-oriented, but
C is not. But there is a way to make C programs
resemble some object-oriented-like programming language. I think it is time for us to start implementing this in our project.
Let's create our main object, the engine of our application: flappy-nix. Create both
FlappyNix.c and
FlappyNix.h inside
src.
After that, what should our "object" FlappyNix contain and represent?
It will have
four methods any object should
always have:
- initialize;
- update;
- draw;
- terminate.
It should also have
three variables:
- done - tells if the program is done/is going to terminate;
- draw - a flag that tells the program needs to be redrawn;
- scancode - whenever a keyboard key is pressed, this will contain the code of that key.
There will also be another variable:
IRQ_SET_KB, which will be used to
detect keyboard interruptions.
Here is what my
FlappyNix.h looks like so far:
Now let's actually implement these methods in
FlappyNix.c.
startFlappyNix()
Side note: notice I have declared a global
const int FPS, which is the
Frames Per Second at which the application will be redrawn once we implement the timer. For now, don't worry about it.
Regarding
startFlappyNix(), this function returns a
pointer to a FlappyNix "object".
First I
allocate space for a new FlappyNix.
After that, I
subscribe the keyboard to activate keyboard interruptions.
Then, I
initialize the object
variables.
Finally, I
return the pointer to the newly created FlappyNix.
updateFlappyNix(FlappyNix* flappy)
This function should be familiar to you from the LCOM lectures. I'm not going to go into much detail about it: basically, we are checking for
hardware interruptions. At the moment we are only registering
keyboard interruptions and the code of the pressed key associated to that interruption (lines 32-34). Later we'll be adding code to this function in order to receive
timer and
mouse interruptions.
Afterwards, we check the
scancode, and if it is
different than zero, it means a key was pressed. We check if that key was the
Esc key. If it was, we tell that the program
is done! Easy, right?
Notice that, just like
color names, I also have some
key names - line 42 - because that way I don't have to remember every key code or check a table of codes, I just use the
key name. As you can see below, I declared these names in
Keyboard.h. You can use the
snippet below the screenshot in your own projects, it contains every possible
key of the keyboard and the respective
key code.
Note: the KEY_UP macro presented in the picture above should make use of '&' instead of '|'.
/// Keys
typedef enum {
KEY_NONE = 0x0000,
KEY_ESC = 0x0001,
KEY_1 = 0x0002,
KEY_2 = 0x0003,
KEY_3 = 0x0004,
KEY_4 = 0x0005,
KEY_5 = 0x0006,
KEY_6 = 0x0007,
KEY_7 = 0x0008,
KEY_8 = 0x0009,
KEY_9 = 0x000A,
KEY_0 = 0x000B,
KEY_APOSTROPHE = 0x000C,
KEY_ANGLE_QUOTES = 0x000D,
KEY_BKSP = 0x000E,
KEY_TAB = 0x000F,
KEY_Q = 0x0010,
KEY_W = 0x0011,
KEY_E = 0x0012,
KEY_R = 0x0013,
KEY_T = 0x0014,
KEY_Y = 0x0015,
KEY_U = 0x0016,
KEY_I = 0x0017,
KEY_O = 0x0018,
KEY_P = 0x0019,
KEY_PLUS = 0x001A,
KEY_ACCENT = 0x001B,
KEY_ENTER = 0x001C,
KEY_L_CTRL = 0x001D,
KEY_A = 0x001E,
KEY_S = 0x001F,
KEY_D = 0x0020,
KEY_F = 0x0021,
KEY_G = 0x0022,
KEY_H = 0x0023,
KEY_J = 0x0024,
KEY_K = 0x0025,
KEY_L = 0x0026,
KEY_C_CEDILLA = 0x0027,
KEY_ORDINAL = 0x0028,
KEY_BACKSLASH = 0x0029,
KEY_L_SHIFT = 0x002A,
KEY_TILDE = 0x002B,
KEY_Z = 0x002C,
KEY_X = 0x002D,
KEY_C = 0x002E,
KEY_V = 0x002F,
KEY_B = 0x0030,
KEY_N = 0x0031,
KEY_M = 0x0032,
KEY_COMMA = 0x0033,
KEY_DOT = 0x0034,
KEY_MINUS = 0x0035,
KEY_R_SHIFT = 0x0036,
KEY_ALT = 0x0038,
KEY_SPACE = 0x0039,
KEY_CAPS = 0x003A,
KEY_F1 = 0x003B,
KEY_F2 = 0x003C,
KEY_F3 = 0x003D,
KEY_F4 = 0x003E,
KEY_F5 = 0x003F,
KEY_F6 = 0x0040,
KEY_F7 = 0x0041,
KEY_F8 = 0x0042,
KEY_F9 = 0x0043,
KEY_F10 = 0x0044,
KEY_NUM = 0x0045,
KEY_SCRLL = 0x0046,
KEY_NUM_7 = 0x0047,
KEY_NUM_8 = 0x0048,
KEY_NUM_9 = 0x0049,
KEY_NUM_MINUS = 0x004A,
KEY_NUM_4 = 0x004B,
KEY_NUM_5 = 0x004C,
KEY_NUM_6 = 0x004D,
KEY_NUM_PLUS = 0x004E,
KEY_NUM_1 = 0x004F,
KEY_NUM_2 = 0x0050,
KEY_NUM_3 = 0x0051,
KEY_NUM_0 = 0x0052,
KEY_NUM_DEL = 0x0053,
KEY_MINOR = 0x0056,
KEY_F11 = 0x0057,
KEY_F12 = 0x0058,
KEY_NUM_ENTER = 0xE01C,
KEY_R_CTRL = 0xE01D,
KEY_NUM_SLASH = 0xE035,
KEY_ALT_GR = 0xE038,
KEY_HOME = 0xE047,
KEY_ARR_UP = 0xE048,
KEY_PGUP = 0xE049,
KEY_ARR_LEFT = 0xE04B,
KEY_ARR_RIGHT = 0xE04D,
KEY_ARR_DOWN = 0xE050,
KEY_PGDN = 0xE051,
KEY_INS = 0xE052,
KEY_DEL = 0xE053,
KEY_WIN = 0xE05B,
KEY_CNTX = 0xE05D,
KEY_END = 0xE04F
} KEY;
drawFlappyNix(FlappyNix* flappy)
This one is pretty straight forward: we fill the display with the color blue.
stopFlappyNix(FlappyNix* flappy)
Here we
unsubscribe the keyboard interruptions and
free the memory allocated to the FlappyNix "object".
Updating the Makefile
Do not forget to update the
Makefile each time you add a new source file!
I added a new line - line 8 - where, from now on, I will declare the source code of "objects" we create.
Improving main.c
Now comes the fun part: let's make use of everything we have been working on and see the results. Go to
main.c and edit it according to the screen below.
First,
declare and create a new FlappyNix object.
Then it is really simple:
while flappy is not done do the following indefinitely:
- Update flappy;
- If flappy is not done and draw flag is active - draw flappy.
When flappy is done, the while cycle terminates and so we
stop flappy. The rest of the code we already know.
Below is a
snippet with the current content of
main.c.
#include <minix/sysutil.h>
#include <minix/syslib.h>
#include <minix/drivers.h>
#include "FlappyNix.h"
#include "Graphics.h"
int main(int argc, char **argv) {
srand(time(NULL));
sef_startup();
/*
* -------------------
* VESA graphics modes
* 16-bit (5:6:5)
* -------------------
* 320×200 - 0x10E
* 640×480 - 0x111
* 800×600 - 0x114
* 1024×768 - 0x117
* 1280×1024 - 0x11A
* -------------------
*/
initGraphics(0x114);
FlappyNix* flappy = (FlappyNix*) startFlappyNix();
while (!flappy->done) {
updateFlappyNix(flappy);
if (!flappy->done) {
if (flappy->draw)
drawFlappyNix(flappy);
flipMBuffer();
flipDisplay();
}
}
stopFlappyNix(flappy);
exitGraphics();
return 0;
}
Testing our project so far
It's time to test our program! Go to minix, browse to the project folder,
compile and
run the project.
If everything went well, when you run the program, a blue screen should appear and should only go away when you press the
Esc key on the keyboard. And that terminates the program.
Back to index
Click
here to go back to the index post.