More “Adventure”

I started thinking about two goals today: how can I add more opportunities for narrative, and how can I make the game as easy to control as possible. To this end I spent the day adding mouse control, and the ability to examine objects (currently only the ground).

I noticed that my camera was not perfectly centered on the player, so I got that figured out. Next I probably spent a couple of hours just making a pixel glove cursor, but as a non-artist I’m happy with how it came out. I tweaked the dialog area a bit too. I made it so that when the user clicks the ground, “hero” walks to that spot. I wouldn’t even call it pathfinding because it doesn’t deal with obstacles at all. If the user clicks the ground under hero the dialog box will pop up and some hard coded text will appear. I’ll make this more generic at some point.

Before today adding true adventure game concepts to the game didn’t really occur to me, but it kind of feels like a good fit to experiment with. That’s not to say I’m making an adventure game, but it might be a good mash-up with the other action rpg elements. We’ll see how it pans out, but I like the fluid nature of the process.

I also installed Fraps, and captured a video before I made my changes. I need to install Movie Maker so I can compress it, then I’ll start posting videos and linking to them here.

Next I think I’d like to add a merchant NPC and see how it feels to start a dialog by clicking on him.

One thing that struck me about Diablo 3 is how transparent the control scheme is. You can pick that game up after not playing for months and know exactly how to procede. That’s really rare, and I’d like to emulate that aspect of it.

Narrative

I thought it would be interesting if narrative text could be displayed regularly after certain events. In order to try this, I changed the dialog scripting system into a more generic scripting system that is used for character dialog. On map load I’m running a script that displays narrative. I’d also like to add other script triggers. These could also be used for tutorials.

A Blank Canvas

I removed the rest of the tutorial content from the game, and added a simple 40×30 map that consists of just grass, and the player character. The grass tile is from FF6. I’m still debating whether or not I want to continue using their art to mock things up, or my own programmer art. I would be kind of rewarding to build up my own art, but it would be more motivating (and faster) to use theirs :)

I spent a couple of evenings trying out various tile map editors, and experimenting with ripping FF6 tile sets. I worked out a decent workflow to start with. Next I need to add a foreground layer to the tile map so the characters can walk behind things.

I also added a character visibility check, and character depth sorting.

FF6 Sprites

I decided to replace the tutorial sprites with Final Fantasy 6 sprites. The tile map and tile set are next. This is only temporary of course. FF6 sprites are 24×24, rather than the current 16×16, so I had to define an offset. This creates a nice perception of depth as the character walks around the world. FF6 sprites are also offset up on their current tile by 8 pixels to make it appear that they’re standing roughly on the center of their current tile. Together these two offsets can make crowds of people appear to have height, and nice effects like that. One problem it creates though is that sprites now have to be depth sorted and or z-buffered, otherwise a sprite further from the camera may render in front of a sprite that is closer to the camera.

 

Inventory & Dialog Scripting

I’ve finally finished converting the AS3 tutorial’s code to C++

I added the inventory, along with the pencil and letter from the tutorial.

I also wrote a basic text based scripting system that allows me to script dialog trees similar to the tutorial. The tutorial was able to embed AS3 directly into the strings, split the strings by tokens, and then execute it directly. Unfortunately that’s not possible in C++ so I had to write a custom solution. I thought embedding a LUA parser would be a bit overkill.

I set it up so that each dialog has some number of lines. Each line starts with a script command, and some number of string or integer parameters. The most common command would be “prnt” as in “prnt, Hello World!\n”. My parser will match “prnt” up with an internal function, and since it knows that prnt accepts a single parameter that is a string, it then parses the remainder of the string, minus the newline, and passes it to the Prnt function written in C++.

The tutorial, and my C++ port use several commands to do things like branch the dialog, add or remove inventory items, teleport the character, etc. For example, there is a pencil laying on the ground. It is implemented as a character that has dialog, but then internally there is also a pencil item that can draw in the inventory.

The pencil character’s dialog script looks like this:

  • “ainv, pencil\n”
  • “tprt, -1, -1\n”
  • “prnt, *You found a pencil.*\n”

In English this says:

  • Add the pencil item to the inventory
  • Teleport the pencil character to -1, -1, so it appears to have been picked up
  • Print “*You found a pencil.*” in the dialog UI area

So, that’s about it. I’m more or less caught up to where I was with the Flixel version of the game. Time to start poking around with my own game scenario!

Doors, Frame Time, Clipping & Dialog

I got doors working. A door defines an exterior and interior world position. If you step onto one you teleport to the other, giving the effect that you entered or exited a house, etc.

I spent some time experimenting with a fixed frametime versus the usual variable frametime. I wanted to see if it would smooth out the character movement \ map panning. That led to me noticing and tracking down a small hitch where the player character would stop moving for a single frame while holding a directional key down. Fixed.

I added tile map clipping. Previously I was just sending every tile in the world to the renderer, and now I’m just sending in the ones that are visible.

Finally, I got the dialog system functioning. This required some string parsing so that I can define a characters entire dialog in a single string. Eventually I can push that out to a data file. I also had to get text box word wrap working for the longer lines of dialog.

I’m pretty happy with my progress for the day. I was hoping I’d be ready to start on game scenario stuff or pixel art tomorrow, but I’m not quite there yet. I still have to get scripting commands embedded in the dialog, and add the inventory.

 

Camera Tracking

I got the camera to track a specified target. It allows a user defined tether length so that the player is able to walk around in a small area without the camera moving, but when he gets to the end of the tether, the camera starts tracking to keep him in view. It also clips against the edges of the map.

It just about feels like the original Flixel tutorial. Next I need to implement the dialog system. This will probably be a bit different from the AS3 equivalent. AS3 allows you to specify function names and parameters in a string that can be extracted and called. The adventure tutorial uses this to embed script within character dialog strings. I’ll have to write a basic parser and have a big if\else block to find tokens, convert parameter strings to values of appropriate types, and call the appropriate functions.

Here’s another screenshot – I’m finally able to walk to another area of the map. A bit later, I’ll be able to enter the house.

 

Walking & Collision

I got most of the adventure tutorial’s AS3 character class implemented in C++. This allows the player character to walk around and collide with NPCs and the world. I also added the two NPCs, one of which is off-screen.

I created a World class that stores lists of objects in the world – it’s effectively a scene. I’m passing that in to the Character class so that it has the ability to search for other collidable characters. This is the first time I’ve dealt with world entities in this way and I kind of like how clean and logical it is. In the past what I’ve done is try to push such functionality up to some inter-object coordinator class in order to keep it out of the individual object level. For example, I would insist that an object should only know about itself. If interactions need to occur between multiple objects, there should be some system or manager at a higher scope to coordinate their interactions.

There are advantages and disadvantages to both approaches, but for this particular project, I’m liking the world\scene approach. It seems to model real world behavior more accurately.

Alpha & Color Key

I got alpha working through the material diffuse, and am using it to create a dialog box behind the text. I also got color keyed alpha testing to work on the sprites.

I think the last things I need are camera tracking and collision. I’m going to go ahead and add the game logic next since that will help test the other two things.

Font & Text

Up until about 15 minutes ago I had a quick and dirty D3DX based font & text solution in place. I ripped that out and replaced it with my own bitmapped font system. I had plenty of reference from an older iteration of the engine so it didn’t take too long to get it refactored and cleaned up. Aside from the more general texture alpha issue, the only thing I really need to do is word wrapping, but that’s a minor detail.