Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
10. November 2017


In the first tutorial we looked at creating our initial application, while in the second tutorial we looked at events and a cleaner game loop then in the third tutorial we looked at drawing bitmaps on screen.  Today we are going to look at handling keyboard and mouse input.  We covered this slightly in earlier tutorials when we looked at event queues and enabled the application to exit when the user pressed a key.  This tutorial will go into a great deal more depth.  Without further ado, let’s jump into the code sample:

#include "stdafx.h"
#include <allegro5\allegro.h>
#include <allegro5\allegro_image.h>

int main()
{
	ALLEGRO_DISPLAY * display;
	ALLEGRO_EVENT_QUEUE *queue;
	ALLEGRO_BITMAP * bitmap = NULL;

	al_init();
	display = al_create_display(640, 480);
	queue = al_create_event_queue();

	al_install_keyboard();
	al_install_mouse();

	al_register_event_source(queue, al_get_keyboard_event_source());
	al_register_event_source(queue, al_get_display_event_source(display));
	al_register_event_source(queue, al_get_mouse_event_source());

	al_init_image_addon();
	
	bitmap = al_load_bitmap("image64x64.jpg");
	assert(bitmap != NULL);

	bool running = true;
	float x = 0, y = 0;

	int width = al_get_display_width(display);
	while (running) {
		al_clear_to_color(al_map_rgba_f(0, 0, 0, 1));
		al_draw_bitmap(bitmap, x, y, 0);
		al_flip_display();

		ALLEGRO_EVENT event;

		if (!al_is_event_queue_empty(queue)) {
			al_wait_for_event(queue, &event);
			if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
				running = false;


			if (event.type == ALLEGRO_EVENT_MOUSE_AXES) {
				x = event.mouse.x;
				y = event.mouse.y;
			}

			if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
				x = y = 0;
				al_set_mouse_xy(display, 0, 0);
			}
		}

		// Actively poll the keyboard
		ALLEGRO_KEYBOARD_STATE keyState;

		al_get_keyboard_state(&keyState);
		if (al_key_down(&keyState, ALLEGRO_KEY_RIGHT))
			if (al_key_down(&keyState, ALLEGRO_KEY_LCTRL))
				x += 0.1;
			else
				x += 0.01;
		if (al_key_down(&keyState, ALLEGRO_KEY_LEFT))
			if (al_key_down(&keyState, ALLEGRO_KEY_LCTRL))
				x -= 0.1;
			else
				x -= 0.01;
	}

	al_destroy_display(display);
	al_uninstall_keyboard();
	al_uninstall_mouse();
	al_destroy_bitmap(bitmap);

	return 0;
}


When you run this application, the sprite will be drawn in the position of the mouse cursor.  Clicking and mouse button will reset the sprite’s position back to (0,0).  You can also control the position of the sprite by using the left and right arrow keys.

GIF

As we can see mouse and keyboard functionality is optional, so we need to call the appropriate init() function for both devices, then later the appropriate uninstall() function to clean them up.  Just like earlier we create an event queue, and register additional event sources for both keyboard and mouse.  As you can see, multiple event types can exist in a single event queue.

Mouse handling is extremely straight forward, when the mouse is moved it will fire a ALLEGRO_MOUSE_AXES_EVENT with the mouse location stored in the events mouse.x and mouse.y properties.  You can also see that mouse button activity fire a ALLEGRO_MOUSE_BUTTON_UP_EVENT when a mouse button is released.  In this case we set the position of the mouse using al_set_mouse_xy().

We take a slightly different approach with keyboard handling.  We could use a similar approach, however it would only handle one key event at a time.  What we instead want to do is poll the current status of the keyboard every pass through our game loop.  We take this approach so we can detect multiple concurrent key presses.  This is done by populating a ALLEGRO_KEYBOARD_STATE structure with a call to al_get_keyboard_state().  We can then poll the status of individual keys by calling al_key_down().


Back to Table Of Contents

Programming


8. November 2017


In the first tutorial we looked at creating our initial application, while in the second tutorial we looked at events and a cleaner game loop.  Today we get to the fun stuff… drawing bitmaps to the screen.  If you are from another game engine, the term bitmap in Allegro might be a bit misleading as it generally represents an image on disk.  In Allegro terms a bitmap is much more, basically its an all in one term for images that can be load and displayed on screen, taking the role often reserved for sprites in other game libraries.  Let’s just jump into the example:

#include "stdafx.h"
#include <allegro5\allegro.h>
#include <allegro5\allegro_image.h>

int main()
{
	ALLEGRO_DISPLAY * display;
	ALLEGRO_EVENT_QUEUE *queue;
	ALLEGRO_BITMAP * bitmap = NULL;

	al_init();
	display = al_create_display(640, 480);
	queue = al_create_event_queue();

	al_install_keyboard();
	al_register_event_source(queue, al_get_keyboard_event_source());
	al_register_event_source(queue, al_get_display_event_source(display));

	al_init_image_addon();
	bitmap = al_load_bitmap("image.jpg");
	assert(bitmap != NULL);

	bool running = true;
	float x = 0;

	int width = al_get_display_width(display);
	while (running) {
		al_clear_to_color(al_map_rgba_f(1, 1, 1, 1));
		al_draw_bitmap(bitmap, x += 0.01, 0, 0);
		al_flip_display();


		if (x > width) x = -al_get_bitmap_width(bitmap);

		ALLEGRO_EVENT event;

		if (!al_is_event_queue_empty(queue)) {
			al_wait_for_event(queue, &event);
			if (event.type == ALLEGRO_EVENT_KEY_UP || event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
				running = false;
		}
	}

	al_destroy_display(display);
	al_uninstall_keyboard();
	al_destroy_bitmap(bitmap);

	return 0;
}


Most of the code has already been explained in the previous tutorials, so lets jump right into the new code.  You will notice we are using another add-on in this example, the image add on.  This is the module that enables us to load images from file and needs to be enabled in the same way we enabled the font and ttf add-ons earlier.

image


As always there is an init function al_init_image_addon() that needs to be called before any image code can be called.  One initialized we can load a bitmap from disk calling al_load_bitmap() passing in the name of the image file.  Be sure to place this file in debug directory, just like we did earlier with the font file.  The next critical call is the function al_draw_bitmap() which is used to draw our bitmap to the backbuffer at the given coordinates.  In this simple example we are simply incrementing the X coordinate every pass through the game loop.  We then check that the bitmap hasnt moved off screen, if it is, we move it back to the beginning, minus the width of our image and start the process again.  This will cause the image to smoothly scroll back on screen. 


Here is our application in action:

results


There are a few things that are important to note.  First off, notice the call to al_destroy_bitmap(), this is important to call when you are done with your bitmap or resources will leak.  Next notice how drawing coordinates work.  When drawing, the origin (0,0) is the top left corner of the window as well as the top left corner of the bitmap.


It’s also important to realize in addition to al_draw_bitmap() there are several other draw functions available such as al_draw_rotated_bitmap(), al_draw_scaled_bitmap() etc.


Back to Table Of Contents

Programming


6. November 2017


In the first tutorial we created a simple Hello World application using Allegro.  However, that application was very limited.  In fact, it couldn’t even be closed!  It simply looped forever.  In this example we are going to change that up slightly, by allowing the application to exit if the user hits a key or clicks the close icon on the app window.


In order to accomplish this we are going to cover the basics of handling events and keyboards.  To handle events of any kind we need to first create an event queue.  As we saw earlier with addons, in Allegro you enable the functionality you need, this includes the keyboard.  Without further ado, lets jump into our new example.

#include "stdafx.h"
#include <allegro5\allegro.h>

int main()
{
	ALLEGRO_DISPLAY * display;
	ALLEGRO_EVENT_QUEUE *queue;

	al_init();
	display = al_create_display(640, 480);
	queue = al_create_event_queue();

	al_install_keyboard();
	al_register_event_source(queue, al_get_keyboard_event_source());
	al_register_event_source(queue, al_get_display_event_source(display));


	bool running = true;
	while (running) {
		al_flip_display();

		ALLEGRO_EVENT event;
		al_wait_for_event(queue, &event);
		if (event.type == ALLEGRO_EVENT_KEY_UP || event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
			running = false;
	}

	al_destroy_display(display);
	al_uninstall_keyboard();

	return 0;
}


When run this example will simply display an empty window.  The big difference is now it can be closed using the X icon or by pressing (and releasing) any key on the keyboard.  You will also notice in this example that since we can now exit our main loop, after the main game loop we do some cleanup work.  Generally every create function has a corresponding destroy function to clean up resources used.  This is also true with install and uninstall functions.


It’s possible that you want your game loop to run at a fixed rate, for example 30 or 60 frames per second.  This is also dont using ALLEGRO_EVENT, in this case a timer.  Here is a simple tweak to the above example that causes the graphics to be updated 60 times per second.

#include "stdafx.h"
#include <allegro5\allegro.h>

int main()
{
	ALLEGRO_DISPLAY * display;
	ALLEGRO_EVENT_QUEUE *queue;
	ALLEGRO_TIMER *timer;

	al_init();
	display = al_create_display(640, 480);
	queue = al_create_event_queue();
	timer = al_create_timer(1.0 / 60.0);

	al_install_keyboard();
	al_register_event_source(queue, al_get_keyboard_event_source());
	al_register_event_source(queue, al_get_display_event_source(display));
	al_register_event_source(queue, al_get_timer_event_source(timer));

	bool running = true;
	while (running) {
		

		ALLEGRO_EVENT event;
		al_wait_for_event(queue, &event);
		if (event.type == ALLEGRO_EVENT_KEY_UP || event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
			running = false;

		if (event.type == ALLEGRO_EVENT_TIMER) {
			al_flip_display();
		}
	}

	al_destroy_display(display);
	al_uninstall_keyboard();
	al_destroy_timer(timer);

	return 0;
}


Back to Table Of Contents

Programming


3. November 2017


Welcome to part one in our tutorial series covering Allegro, an open source C game library/media framework.  For a bit more of an overview and a video version of this tutorial be sure to check out this video.  In this tutorial series we are going to cover the basics of getting started with Allegro, from creating your basic app, to drawing graphics and playing audio.


In this part we are going to illustrate creating a project using Visual Studio 2017.  Allegro is also available on Linux and Mac, but we are not going to cover the getting started process on these platforms.  All of the code in subsequent tutorials will be applicable for all platforms.


Allegro supports NuGet, which makes setting up a new project in Visual Studio incredibly easy.  Let’s start off by creating a Hello World example.  Let’s get started.


Start off by creating a new Windows application in Visual Studio.  Select File->New->Project…

image


Next select Visual C++, then Windows Console Application, name it and give it a location, then hit the OK button.

image


In the Solution Explorer, for your newly created project, right click References and select Manage NuGet Packages…

image


Next click Browse, enter Allegro in the text field, then click the download icon.  Click OK if prompted with an additional dialog.

image


And done!  You have now configured Allegro for use.  In this example however we are going to need two additional libraries.  Allegro is modular in nature and you only enable the functionality you need.  Our application is going to display Hello World on screen and this is going to require a pair of libraries for text and font support.  Don’t worry, it’s easy.


In the Solution Explorer, select your project, like so:

image

Now either right click and select Properties or press Alt + Enter.  This will bring up the Properties Window for your project.  On the left hand side, located and select Allegro 5, then locate and enable Truetype Font Addon and Font Addon, like so:

image


Click Apply then Ok to close the dialog.  We are now ready to code.


You should have a file created for you with the same name as your project, in my case it’s HelloWorld.cpp.  Double click it in the Project Explorer window and replace it with the following code:

#include "stdafx.h"
#include <allegro5/allegro.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_font.h>

int main()
{
	al_init();
	al_init_font_addon();
	al_init_ttf_addon();

	ALLEGRO_DISPLAY * display = al_create_display(640, 480);
	ALLEGRO_FONT * font = al_load_ttf_font("YARDSALE.ttf", 64, 0);

	while (true) {
		al_clear_to_color(al_map_rgb(255, 255, 255));
		al_draw_text(font, al_map_rgb(0, 0, 0), 0, 0, 0, "Hello World");
		al_flip_display();
	}
}


This code follows a pretty common pattern in Allegro.  We always start off by initializing the Allegro libraries with a call to al_init().  You will notice in this example we also need to init the two addons we included.  This is true for all addons use in Allegro as you will see shortly.

This code then creates a window 640x480 in size, loads a font named YARDSALE.ttf with a size of 64pt.  Next we run an infinite loop clearing the background to white ( in RBG format, each number from 0 – 255 is the amount of that could, Red, Green and Blue respectively ).  We then draw the text using our font and this time the color black.  All this time we have been drawing to an offscreen buffer.  Call al_flip_display() to make this offscreen buffer visible to the user.


There are a few things to note about this example… first it can’t be exited.  Don’t worry, we will cover that in a future tutorial.  It also leaks resources like a sieve.  Each load, create or init call has a corresponding call to free those resources up when we are done with them.  We will also cover this in a future tutorial.


The final thing you might notice is we used a font called YARDSALE.ttf…  guess we need that font don’t we?  That font is available for download here, simply download the zip file and copy the file YARDSALE.ttf.  Of course if you have your own TTF file, you can feel free to use it, just be sure to change the file name in the code.  Now the question remains… where do you copy it?  This is actually an area that Visual Studio C++ developers often get tripped up… I certainly do.  You want this file to be copied into the Working Directory of your application.  You can determine or set this directory in the Properties panel of your project. 

image


Copy the TTF file to this location.


Now you can run your code by hitting F5 or clicking Local Windows Debugger in the toolbar.  If everything went according to plan, you should see:

image


Congratulations, you’ve just created your first Allegro application!  On thing you might notice is a DOS window in the background, like so:

image


Don’t worry, getting rid of this window is pretty simple.  Once again, open up the Properties window of your project.  Now locate Linker->System on the left hand side.  Select SubSystem, then Windows instead of Console.

image


Voila, no more console window!  One other thing you may notice… due to the fact this application is an infinite loop, it never actually shuts down and you can’t close it using the X icon.  For now you can exit the application in Visual Studio using this button:

image


Or by hitting Shift F5.  Well that’s it for Part One, congratulations, you’ve created your very first Allegro application.  Next we will look a bit closer at our game loop and making exiting our game a lot easier.


Back to Table Of Contents

Programming


27. September 2017


Aseprite, a pixel based drawing and animation app, just released version 1.2.  New features include pixel aspect ratios, gradients, reference layers and more.  There were also several bug fixes and improvements.


From the release blog post:


Aseprite v1.2 is finally the new stable version (*). If you were already using the beta version, you will not notice substantial changes. But if you were using Aseprite v1.1.13, there are a lot of new features for you (like pixel aspect ratio, layer groups, overlapping frame tags, gradients, reference layers, etc.)

This is a list of the changes from v1.2-beta12 to the final v1.2:

  • Added new Addition, Subtract, Divide blending modes
  • Added support to change theme and UI scaling without restarting (#471)
  • Disable transformation handles in the selection when a Shift or Shift+Alt are pressed by default (reported here)
  • Fixed high CPU usage on Timeline when we copy layers/frames/cels (bug report)
  • Fixed snap to grid bug with selection tool
  • Fixed crash closing all files & opening a new one when preview window was playing an animation
  • Windows: New x64 version (included in the installer and on Steam, it’ll install the x64 version on x64 machines)
  • Windows: New --disable-wintab option to avoid loading wintab32.dll
  • Removed Windows XP support (Please contact us in case that you still need a previous version with Windows XP support.)
  • macOS: Use the native macOS menu bar (#135)
  • macOS: Now ⌘M and ⌘H will Minimize and Hide the window respectively. Use Ctrl+M for Color Curves, and Ctrl+H to change View > Show Extras options.
  • macOS: Fixed bug setting broken mouse cursors in some special cases
  • macOS: Retina support (#903)
  • Fixed other bugs (including #1569, and #1423 thanks to @cebolan)

Several new features were delayed just to create a more stable v1.2 version. So sorry for everybody that don’t get what they asked for :’( Soon I’ll release the first v1.3-beta1 with some crazy new stuff, so stay tuned.


We took a look at Aseprite in action in this video should you wish to learn more.

GameDev News Art


GFS On YouTube

See More Tutorials on DevGa.me!

Month List