The Allegro Wiki is migrating to github at https://github.com/liballeg/allegro_wiki/wiki

Create/Chapter 3

From Allegro Wiki
< Create
Revision as of 23:34, January 8, 2012 by OICW (talk | contribs) (Created the third article)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Create logo.png

This article is a part of the Create series, originally by Richard Phipps. The article content may have been edited from its original form.

Chapter 2 | Chapter 4

Building levels

We will now start to display a full level as promised in the last article. The first thing we need to do is to make an actual level, and for this I have converted the original first level of Dandy into a bitmap for us to use. I have also created a folder called Levels within which we will have separate Pack folders to store each level pack. This lets us make it easier to organise levels.

So our first level has a filepath of "Levels/Pack1/1.bmp" and is 60 x 30 pixels in size, made up of 16 colours (0-15) representing the 16 different tile types.

We will add two new source files to our project: level.c & level.h, in which we will put all level related functions. One of the first things we will do in the header file is to make it easier to recognise which pixel colours represent which tile. We will do this with a define list as it is much easier to remember names and understand what they mean than with numbers:

#define FLOOR              0
#define WALL               1
#define LOCK               2
#define START              3
#define EXIT               4
#define KEY                5
#define FIRST_AID_PACK     6
#define CASH               7
#define SMART_BOMB         8
#define MONSTER_1          9
#define MONSTER_2          10
#define MONSTER_3          11
#define HEART              12
#define SKULL_1            13
#define SKULL_2            14
#define SKULL_3            15


We now need to define two new bitmaps in free_dungeons.h to hold our map and the image of the whole level:

BITMAP *level;
BITMAP *map;


We will now add a load_level function to try to load in the level bitmap into map and abort if there are any errors. If this has been loaded correctly then we also create a bitmap large enough to cover the whole view of the level. We will use this level image to blit a smaller section of the level to the screen.

By adding calls to a setup level function and out load_level function we have now loaded a level map bitmap. However we still need to draw a view of the level based on the map information. This is surprisingly easy:

void draw_all_level(void)
{
 // Using the map and tile gfx we now draw the whole level to our big level bitmap.
 int x, y, c;
 
 for (y = 0 ; y < map->h ; y++)
 {
  for (x = 0 ; x < map->w ; x++)
  {
   // Get the colour or tile number.
   c = getpixel(map, x, y);
   
   // Because we have stored the tile gfx in a horizontal strip, in a specific order
   // we can use the colour of the pixel (i.e. the tile number) to draw the tile gfx
   // for each position in our level.
   blit(tiles, level, c * 32, 0, x * 32, y * 32, 32, 32);    
  }    
 }     
}


We now have a fully drawn level which we can draw to the screen! But we won't stop there, as we are going to add scrolling so we can get a feel for moving around the whole level. First of all we need to create a structure to hold a camera position, as we need a camera which can move around the level keeping all the players in view. This is easy to do if we use camera.x and camera.y values when drawing the level to the screen. However we can now move the camera beyond the edges of the level, so we need to keep the camera within the level boundaries which we will do with this function:

void clip_camera_within_level(void)
{
 // Simply keep the camera within the boundaries of the level.
 if (camera.x < 0) camera.x = 0;
 if (camera.y < 0) camera.y = 0;
 
 if (camera.x + screen->w > level->w) camera.x = level->w - screen->w;
 if (camera.y + screen->h > level->h) camera.y = level->h - screen->h;    
}


Now to really show the scrolling we can do, we will link the camera position directly into the mouse movement! This code will be stripped out in the future, but is present now to provide visual interaction and let people imagine what playing the game will be like. As discussed in the previous article, this visual feedback and interactive element should help increase motivation for continuing development.

For now we will tie the scrolling movement logic and level drawing section directly into a simple main loop. This is not something we will keep in the future, but it does work for now:

// Loop until we hit Escape.
 do
 {
  // Find out how much we have moved the mouse.
  get_mouse_mickeys(&x, &y);
  
  // Move the camera accordingly.
  camera.x = camera.x + x;
  camera.y = camera.y + y;
  
  // But keep it within the level.
  clip_camera_within_level();
  
  // Draw the level to our drawing buffer and then show to the screen when needed.
  blit(level, find_drawing_buffer(), camera.x, camera.y, 0, 0, screen->w, screen->h); 
  do_screen_update();
 
  // Wait until we press Escape.
 } while (!key[KEY_ESC]);


Now we can move around the level with our mouse and feel much more like this is the start of a game. Finally we are going to increase that feeling a little bit more by starting the program with the camera positioned over the Start position in the level. This involves a little bit of logic and we with this new function can see how much easier it is to use words rather than numbers for the tile number:

void position_camera_on_start(void)
{
 int x, y, c;
 
 // Reset camera in case we find no start!
 camera.x = 0;
 camera.y = 0;
 
 // Ok, let's try to find the first Start tile.
 for (y = 0 ; y < map->h ; y++)
 {
  for (x = 0 ; x < map->w ; x++)
  {
   // Get the colour or tile number.
   c = getpixel(map, x, y);
   
   // Is this tile a Start tile?
   if (c == START)
   {
    // Yes, we've found a Start! Centre camera on this position, clip the camera and return.
    camera.x = (x * 32) - (screen->w / 2) + 16;
    camera.y = (y * 32) - (screen->h / 2) + 16;
    
    clip_camera_within_level();
    
    return;   
   }
  }    
 }   
}


Now when we run the program we have the camera nicely postioned over the Start tile, and we can use the mouse to move around the level as if we were moving our player. Once we start imagining it then we can see what we need to do to actually make that happen. In the next article we will put a player character in the level and let us move him around the map.

Free Dungeons files for Article 3