Michael Pidde

Fire in the Dark

I've been working on Boreal Darkness now semi-regularly as time and desire allow. I've made some fairly good progress, muddled through a bunch of hang-ups, unearthed more problems that need solving yet, and I've enjoyed the learning experience so far. Here are some notes so far.

Sound Sucks

Sound is not easy to work with. I started with OpenAL recently and so far it's nothing but trouble since I had been looking into using ALUT (AL Utility Toolkit) but that's now deprecated, so unless you're trying to use a different third-party toolkit, you have to code a lot of cruft yourself. I frankly just don't feel like doing that right now. I had looked into using Alure, but the setup for that on Windows sounds painful. So for now I've downloaded the right version of SFML for my Visual C++ compiler version and will pull in whatever headers I need for sound processing from that. It's probably overkill, but I'm looking for a simple overkill solution right now so I can keep making progress.

Map Movement Mangling

The movement in my game follows the common pattern where the player is centered in the window until they approach the edges of the map at which point the player sprite will move off-center to reach the edge. I'm not sure if this style of movement has a traditional name (I'm sure it does), but this is the first time that I've tried to implement it. I had a sort of working implementation, but I botched it up a bit when I added linear interpolation to my player sprite (I think) and I haven't gone back to fix it yet. It's a bit roundabout to keep track of whether to move the map around the player sprite or move the player sprite within the map bounds. I may need to rework my whole scheme because for whatever reason I thought it would be a good idea to keep track of the player's relative offset from the top left corner as well as the global position. If the global position is such that you're approaching the edge of the map and there's nothing more to render then the relative offset kicks in and allows the player sprite to move relative to the window's edge. This adds some confusion and I think I should be able to do all of my calculations based on the player's global position. I can determine well enough by that whether or not the player sprite needs to be off-center.

You've Got Mail

I felt the need to cobble together an object messaging system so I don't blur the lines so much between which objects can talk to which. I don't want to keep a reference to the map in my player object and a reference to the player in the map object and references to both in my engine object, and so forth. I do have some global objects, and I'm simply not changing that for right now because why make improvements that don't need to be done yet just for the sake of someone else's sense of programming propriety? Whatever the case, my messaging system is a pretty simple queue that accepts object registrations, and objects can push events with values onto the queue. Any other object registered to handle the event will do so. The event queue is iterated and cleared on every update of the game loop. For example, I can register my player object to listen for a certain event as such:

_event_.registration("INCREMENT_PLAYER_HEALTH", *this);

In another part of the code I'm able to trigger that event, passing in a value:

_event_.push("INCREMENT_PLAYER_HEALTH", -.25);

The player object itself must have a function called handleEvent which can process incoming events and dole them out to the correct private member functions:

void Player::handleEvent(string event, float value) {
	if(event == "INCREMENT_PLAYER_WOOD")
		wood(value);
	else if(event == "INCREMENT_PLAYER_HEALTH")
		health(value);
}

To tie it all together, the messaging queue's notify function gets fired off every update of the game loop, as noted above. It iterates a multimap and triggers the aforementioned handleEvent function in the registered object reference:

void EventStack::notify() {
	multimap::iterator itr;
	for(itr = events.begin(); itr != events.end(); ++itr) {
		// Get registrations for key (there can be multiple, in theory)
		pair::iterator, multimap::iterator> ret;
		ret = registers.equal_range(itr->first);
		for(multimap::iterator reg = ret.first; reg != ret.second; ++reg) {
			// Run handler in WorldObject reference
			reg->second.handleEvent(itr->first, itr->second);
		}
	}

	// Clear event stack
	events.clear();
}

More Meta than Meta

The acute observer will note that all of the objects registered in the event queue are of the WorldObject type. Basically every object that is renderable on the map is a subclassed from this. This kind of abstraction is rather hacky feeling to me, but I wasn't sure how else to handle having varying types of objects in a queue being able to accept input in a generic kind of way. This is either due to bad design on my part, ignorance of certain techniques that one would use in C++ to accomplish this kind of task, or a desire to not destroy my code with even more complex abstractions that could otherwise become a nightmare to comprehend and debug later on.

Shut Up and Show Us Something

Fine, here's a video of my current progress. The game is still very rough, but right now you can "chop" down trees (sans player chopping animation at the moment) which adds a random amount of wood to your inventory between a certain range, build a fire with the F key when you reach 50+ pieces of wood (though this functionality is sporatic at times as to whether it wants to render the fire sprite, I think due to a memory problem), and that's about it. The player walk animation skips when you hold down a directional key for some reason, but smooths out. Hopefully that's a simple matter to address, among a host of others...

Code Stats

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C++                             16            223             52           1192
C/C++ Header                    22            105             11            753
PHP                              1              2              1            107
Lua                              1              0              0             42
DOS Batch                        3              9              0             34
make                             1              0              0              5
-------------------------------------------------------------------------------
SUM:                            44            339             64           2133
-------------------------------------------------------------------------------