Thursday, 29 January 2015

Procedural Generation - Part Four - Doors, Diamonds and Sound

Last time we set our Hero free to roam the dungeon but there wasn't much to do there. This time we will set a diamond that he can collect and we will mark this momentous find with a sound effect!

The code's layout is largely unchanged. If this was being developed into a full game, I'd seriously recommend splitting into several packages before it gets any larger! The slider controls are gone this time and instead of drawing the entire map at once, just a smaller view port is drawn centered round the hero character. One button - Refresh - is kept so that the dungeon can be rebuilt.

map_render.dart - Loading sounds is very similar to loading images. This is done in an async fashion and we wait for all to load up. The function drawMap has become a little more complicated too as we keep track of the section of the map to be drawn.

PGMap has a new method createDoor which goes through the room and adds a door to the room furthest to the top of the map. Our hero can now take a walk outside. The trees are rendered off their grid points. If the hero walks behind trees you will see a layered effect and it also helps break up the grid appearance of the map. Each block object that makes up the map now has a list of items for the Hero to interact with.

Code is available on Github and a live demo is available here. Use arrow keys to move!

Next time we will finish our dungeon adventures by putting some other characters in the dungeon.

Friday, 23 January 2015

Procedural Generation - Part Three - Hero Time!

Last time the Dungeon was looking much better after being drawn on an HTML5 Canvas - there's even been a version created on DartLab! - (compiles Dart to JS in the browser so be patient!). This time we are going to take a step back to look at how the dungeon structure was made and then add a keyboard controlled hero.

There are many algorithms available for maze and dungeon generation - some very complex. The more advanced have steps to ensure there is a valid path from start to end. Our maze is based on a simple algorithm of defining a rectangular 'room' in a given space multiple times (restricted by our parameters for height and width). This is then carried out X number of times.

The list of rooms is then traversed and a corridor is constructed from room A to room B. Then B to C and so on. This means all rooms are in some way acessible. The overlaps of rooms and corridors create more interesting shapes. At this point we have only laid down floor tiles. A second scan of this map determines where walls and corner stones should be put.

The code has been tidied up and rearranged again - the Dart Editor makes this really easy to refactor and rename items. The new version can be found under the partthree folder.

Code is available on Github and a live demo is available here.

Next time we will look at putting some items into the Dungeon, improving the generation and making more of a game display.

Friday, 9 January 2015

Procedural Generation - Part Two - Dungeon On A Canvas

Last time the Dungeon was rendered using a PRE tag - this time we will us an HTML5 canvas and use PNG files to render a better looking display. In 2014 I entered a game jam and from that I have a set of RPG graphics that will be used for this demo. The jam's theme was 8-bit so all the gfx tiles are 8 pixels by 8 pixels.

There are few changes since last time... The code has been tidied up and rearranged. The new version can be found under the parttwo folder. PGMap - has a new method addRandomObject that sets a block to a particular type if VOID. This is used to scatter some trees around the world.

render.dart - LoadImages() Starts the Load of images and waits for them to complete. drawMap() - renders onto the Canvas element. The new feature, trees, are deliberately irregularly place for a more organic look - this will be important when there are more of them and characters are moving past them.

A new addition to the User interface is a ZOOM slider to scale the display.

Code is available on Github and a live demo is available here.

Next time we will look at putting a hero and some items into the Dungeon.

Friday, 2 January 2015

Procedural Generation - Part One - Making A Dungeon

Procedural generation is a technique used in computer graphics, simulations and games to create content on demand. For example, the worlds in Minecraft are not installed with the game, they are created by algorithms whilst the game is being played. Often the algorithms introduce variations to allow unique content to be created every time the game is played. Fractals are an example of procedural generation as are many on the HTML5 demos on this blog.

This is the first in a series looking at Procedural Generation using Dart. The example will be generating a 2D dungeon as might be found in a game such as NetHack.

First step is to create some utility classes to create a map and store information at each point.

// Block is the smallest unit of a map.
class block {
  int base = VOID;
  block(this.base);
}

// Point - cell on the map.
class point {
  int x = 0;
  int y = 0;
  point(this.x, this.y) {}
}


// Rectangle - defines a rectangular area on the map.
class rectangle {

  int x = 0;
  int y = 0;
  int width = 0;
  int height = 0;
  int x2 = 0;
  int y2 = 0;

  rectangle(this.x, this.y, this.width, this.height) {update2ndPoints();}

  point getMidPoint() => (new point(x + (width / 2).round(), y + (height / 2).round()));

  void update2ndPoints() {
    x2 = x + width;
    y2 = y + height;
  }
}

The generation algorithm will add a requested number of rooms and then connect them via corridors. Walls will then be added around rooms and corridors. Finally corners where walls meet are marked on the map. Of course, we want to actually see the dungeon so to start with will display it in text in a much simplified form.

Code is available on Github and a live demo is available here. Hitting the button a few times shows how many varied dungeons can be.

Next time we will look at providing a Canvas display instead of text.