Handling input with LOGL::GLib:

What's a game without input?! Naturally, LOGL::GLib has made it quite easy to take care
of input with two static classes: Mouse and Keyboard.

Note: You should know the basics of LOGL::GLib and how to set it up. If you don't,
check out: Understanding LOGL_GLib

Types of input:

Keyboard:

Let's take our code from the previous tutorial and add some more code. Examine the
following:

#ifdef __APPLE__
    #include <glew.h>
    #include <SDL/SDL.h>
#else
    #include <GL/glew.h>
    #include <SDL.h>
#endif

#include <iostream>

#include "Game.h"

using namespace LOGL_GLib;
using namespace LOGL_GLib::Common;
using namespace LOGL_GLib::Input;
using namespace LOGL_GLib::Content;
using namespace LOGL_GLib::Math;
using namespace LOGL_GLib::Utilities;

class HandlingInput : public Game
{
public:
     HandlingInput();

     virtual GLvoid Initialize();
     virtual GLvoid LoadContent();
     virtual GLvoid Update();
     virtual GLvoid Draw();
     virtual GLvoid UnloadContent();

private:
     /* Nothing here yet. */
};


HandlingInput::HandlingInput()
{
     std::cout << "HandlingInput Constructor..." << std::endl;
}

GLvoid HandlingInput::Initialize()
{
     Game::Initialize();

     std::cout << "HandlingInput Initialize..." << std::endl;
}

GLvoid HandlingInput::LoadContent()
{
     std::cout << "HandlingInput Content Loading..." << std::endl;

     Game::LoadContent();
}

GLvoid HandlingInput::Update()
{
     /* Check if we need to exit. */
     if(Keyboard::IsKeyDown(Key_Escape))
          Exit();


     Game::Update();
}

GLvoid HandlingInput::Draw()
{
     /* Clear the buffers so we can draw again. */
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();


     Game::Draw();
}

GLvoid HandlingInput::UnloadContent()
{
     std::cout << "HandlingInput Unloading Content..." << std::endl;

     Game::UnloadContent();
}

GLint main()
{
     /* Create and run the game. */
     HandlingInput game;
     game.Run();

     return game.ExitCode;
}

You should notice that it's essentially the same exact code, but just a couple of lines have been added.

/* Check if we need to exit. */
if(Keyboard::IsKeyDown(Key_Escape))
     Exit();

Aha! Input at last! This condition checks if the Escape key is currently pressed. If it is, it exits the game.
Checking for input is very easy, and there are two functions we can use. For example, check this out.
Say we add the following lines to Update():

if(Keyboard::IsKeyDown(Key_J))
     std::cout << "J has been pressed!\n";

Sure, it displays a string if J is pressed... but is that all it does? Keyboard::IsKeyDown checks if the key
is currently down. That's great for a lot of things, but it can be really bad for some things. Say you wanted
to switch to full screen if the user pressed tab:

if(Keyboard::IsKeyDown(Key_Tab))
     ToggleFullscreen();

That doesn't wuite work as expected. You see, this checks every single update. When the player presses
a key, it's usually down longer than a 60th of a second, so this is going to get called more than once. We
don't want that at all. Here's where the next functio comes in handy:

if(Keyboard::IsNewKeyDown(Key_Tab))
     ToggleFullScreen();

Ahh... that's much better. This will only toggle full screen once a new key is pressed. In other words, I'd have
to lift Tab back up, and then press it again for it to toggle full screen again. That's exactly what we want!

So, we have these two functions to qurery keystates, what else can we do with keyboard input? Well,
LOGL::GLib allows you to specify a callback method that will be called whenever a key action occurs.
A key action would be the press OR the release of a key. The callback needs to follow this signature:

GLvoid FuncName(Key _Key, KeyState _State);

To get a better understanding of how this works, let's define one of these functions in our game
and display something when a key action occurs. Add the following code above your class declaration:

GLvoid KeyAction(Key _Key, KeyState _State)
{
     if(_State == Key_Pressed)
          std::cout << "Key pressed: " << _Key << std::endl;
     else
          std::cout << "Key released: << _Key << std::endl;
}

Then inside of Initialize, add the following line:

Keyboard::KeyFunc(KeyAction);

Run the game and press some keys. You should receive a nice notice for each press, along with each
corresponding release. Pretty nifty, huh?

Mouse

Handling mouse input is very much like handling keyboard input... without the keys.
Take a look:

Coord2 pos = Mouse::Position();

We can easily get the mouse position in the form of a Coord2 struct. We could then access it with

std::cout << pos.X << std::endl;
std::cout << pos.Y << std::endl;

However, if you only want to get one: X or Y, then you can easily do the following:

GLint posX = Mouse::X();
GLint posY = Mouse::Y();

Or display it directly:

std::cout << "Mouse X: " << Mouse::X();

LOGL::GLib aims to make it as easy as possible to do most things. Like querying the
mouse's position, we can also query its button states in a very similar way to querying
Keyboard states. Check it out:

if(Mouse::IsButtonDown(Mouse_Left))
     std::cout << "Left mouse is down!\n";

However, we run into the same problem as with the keyboard: What if we only want it
to check for new buttons? Naturally, we've the same solution as before:

if(Mouse::IsNewButtonDown(Mouse_Middle))
     std::cout << "Middle was pressed.\n";

Simple, huh?

Now, you can also specify a callback function for mouse actions. Its signature must be:

GLvoid FuncName(MouseButton _Button, MouseButtonState _State);

You can set the function by using:

Mouse::ClickFunc(FuncName);

On top of that, you can also specify a callback function for mouse movement alone:

GLvoid FuncName(GLint _X, GLint _Y, GLint _DeltaX, GLint _DeltaY);

While the other function arguments may have made sense right off, you might wonder
about the second two for this one. The first two specify the mouse's new location, and the
second two say how much the position has changed on each axis. Change is commonly referred
to as delta. This function can be set with:

Mouse::MotionFunc(FuncName);

That pretty much covers it. Handling input is made easy in LOGL::GLib, but it's also made to be
extendable.

Like with any other questions pertaining to LOGL::GLib, you're welcome to email me at lorgonjortle@gmail.com

Last edited Mar 9, 2011 at 3:03 AM by LorgonJortle, version 2

Comments

No comments yet.