Monday, October 31, 2011

Randomized metroidvania 05: map specials

I was going to create the player and rooms to move around in but I decided to add a little more to the map. The very crowded map now shows bonus items in dead ends and secret rooms. You can also mouseover a room to see details about it's region, name, and contents.




There's a limited amount of keys and locks so if you add enough regions then you'll see "key #33" or something like that.

Here are some things I added:
    for each unlocked dead end, there's a chance of adding a random lock and bonus
    when placing a room, there's a chance of adding a secret room
    when placing a room, there's a chance of a name and or some item

I'm not sure what theme or items I want in the final game, the ones here are just examples. Once I get the mechanics figured out (like how to create an interesting map) then I can figure out what theme I want to have.

I think I've crammed all I can into the map for now; time to start on actual gameplay.

Sunday, October 30, 2011

Randomized metroidvania bugs

My last post had a bug where new regions may not connect to a neighboring room. I thought about fixing it before posting but decided to post it anyway. Now I hate buggy software as much as anyone, and this bug makes the map unsolveable since there can be rooms you can't get to, so why did I post it anyway?

  1. This is a work in progress and sometimes - most of the time - those are messy. Sometimes it's good to see how things are made, bugs and all.
  2. I already fixed it when I changed that part of the code for my next iteration.
So what caused the bug in the first place? I changed the code that connects a room when it is placed. I made it keep placing connections until the new room is connected to another room in the same region unless it was the first room in that region. Otherwise a room could be placed and it would connect to a neighboring room from a different region and not connect to a room in it's own region. If that was the room that had the key and it was locked with that corresponding lock, then there was no way to get the key. In fixing that bug I introduced a new one.

Randomized metroidvania 04: map keys and locks

It took a few hours and I had to rewrite the code for doors, but I've got keys and locks working. A major part of any metroidvania is exploring new areas and finding some kind of impassable barrier -  a wide pit, a wall of metal blocks, a force field, etc. It's only later when you find some new ability or item - double jump, rocket launcher, field disabler, etc - that you can go past the barrier to a new region. You can abstract this idea of obstacles and items as "locks" and matching "keys". In one game the "red locks" and "red key" might represent actual locked doors and a key, in another game they might be security cameras and a disguise, and in another game they might be tall walls and the ability to climb walls.

You can see the locks and keys in my latest update. The icons are ugly and hard to distinguish, but it's just for example and will be redone many times before the project is over. Consider this the "alpha version" artwork.



[I just noticed that sometimes the first room in a region doesn't connect to the other rooms. A bug I just fixed when I redid that code for my latest work.]

when visiting a region for locks and keys:
    place an unused key
    put the matching lock on one door to each unvisited adjacent region
    any unlocked doors to adjacent regions are added to a "to do" list
    visit each unvisited adjacent region

after visiting all regions for locks and keys:
    for each unlocked door on the "to do" list, put a random used lock

This ensures that each region has a key that you need to proceed to the neighboring regions. Although; since each region can connect with its neighboring regions multiple times, it's theoretically possible that getting the first key would be enough to explore all regions.

Saturday, October 29, 2011

Randomized metroidvania 03: map regions

Different regions! It was easier than I thought it would be - of course it has been in the back of my head for a while so I didn't jump in with my first thought.




to start a new region:
    create a list of all frontiers for all rooms
    randomly pick one to start the new region
    clear all other frontiers
    place a room as normal

The current region determines the room color and a randomly chosen maximum height and width and can easily be used to control more things like the artwork, items, bad guys, secrets, and other things. Like placing doors, this algorithm is guaranteed to connect with existing regions and could even connect multiple other regions.

Randomized metroidvania 02: map connections

The rooms are now connected! I used a very simple method that's guaranteed to connect and will even create loops to join different "branches" that happen to be near by.




to connect a room:
    after placing a room
    get a list of all adjacent cells that are in a room
    randomly pick some cells to create doors

This can create multiple opening between two rooms. That's not a problem yet but it could be tweaked later on. This should be enough to create the gameplay portion but I'd like to work on defining different regions at the world-gen level before I move on to creating a player to run around.

Friday, October 28, 2011

Randomized metroidvania 01: map rooms

So I've decided to make a randomized metroidvania game; sort of a cross between a roguelike and one of the greatest games ever, Castlevania: Symphony Of The Night. Since I want this to be a flash game, I'll use Eclipse and Flixel.

I spent a few hours getting Eclipse to work with Actionscript and playing with Flixel a bit. For my game I decided to start with generating a random world map.




Here's the basic algorithm, which took less time than setting up Eclipse and Actionscript:

to start:
    add a 1x1 "frontier" space
    add a room

to add a room:
    randomly pick a frontier space
    start a room there
    randomly grow it for a while
    remove frontiers under it
    add its empty neighboring cells to the list of frontiers

roguelike tutorial retrospective

Time for a retrospective! I think retrospectives are probably the most important thing a developer could do since reflecting on what you've done is the difference between someone with 10 years of experience and someone with 1 year of experience repeated 10 times. There are as many different styles of retrospectives as there are teams who do them but I've found that these few questions are usually good enough for me.

What does this retrospective cover? For this roguelike tutorial I tried a few new and different things; the most obvious one being that this was a series of blog posts. This is also the first time I had something of a magic system. There were also a few tweaks to how I normally code things. The roguelike itself is not meant to be a complete and fun game - it's just a basic example of a few different things that may help some roguelike developers - so I'm not going to review the game as a game.

What worked well? As far as code goes, the Screen interface worked really well. Having goblins pickup and use items is neat, as is learning the identity of things by watching others use them. As far as a tutorial goes, I think it can be useful for some people. Even though like there are, at most, a handful of people who read each post, I did get more feedback than I expected, including a reference to behavior trees - something I didn't know about. I'm also pleased that my posts were a mix of code, references to other sources, and some of my own thoughts about why I'm doing what I'm doing. It's not as authoritative as saying "THIS IS THE ONE TRUE AND RIGHT WAY TO DO THIS", and some of it was probably a bad idea, but I've always found that the most instructive guides show the uncertainties and mistakes we run into and how to deal with them.

What needs to work better? One thing I've learned about building something via blog posts is that refactoring is very difficult to show; it's easy to show new code to add, especially if you have small classes and methods, but I don't know of any easy way to show removing, rewriting, and refactoring. This means that the final code, although mostly small pieces, could use a lot of cleanup work and this isn't representative of my best code and may even be a bad example. Oops. Using no globals was a laudable goal but lead to some things I'm not to happy about, like the path finder using a collection of points rather than a fixed size 2D array since I didn't have an easy way to tell the path finder what the map size is. There are a few minor annoyances with the code, like the creature class becoming a behemoth, but most of that is from adding features without refactoring. The spell-related code is quite ugly and clunky too - mostly because I'm not familiar with writing magic systems and couldn't refractor so it was just charging ahead with little idea what I was doing.

What should be done differently next time? I still think a series of blog posts can make a good tutorial but it needs something that makes it easier to show refactoring - perhaps putting everything on github and discussing the changes each time. That would be a slight improvement but still not quite good enough. I tried to be very structured to make sure I followed through and didn't lose interest halfway through but it would have been better to break it into more than 20 parts. I've used Ninject to make it easier to wire things together and something like that would work well for this kind of project; I thought about it but didn't want to add another post about how to use a dependency injection framework.

In summary
  • Use something to counter the limits to show refactoring on a series of blog posts.
  • Don't limit yourself to a fixed number of posts.
  • The Screen interface was the best thing I did: keep doing that.
  • The AsciiPanel was useful but it needs work to avoid flickering and to support animations.
  • Each post should have code, narration, references, and details about the author's thought process.
  • I liked getting comments from readers even more than I thought I would.
Any feedback from you, readers? What did you like? What did you not like? What could be done differently?