Sunday, April 25, 2010

Magecrawl on Mac Part II (libtcod, SDL, and init code...)

This is a bunch of technical details about getting libtcod working on the mac. You might just be interested in the announcement post.

As promised, this post is a breakdown of the work it took to make libtcod work natively on the mac. By "native", I am not knocking the wonderful work Michael De Rosa did for previous releases. I'm referring to ones produced auto-magically by the cmake system,  no manual xcodeprojs, .dylibs and all.

The wonderful part of generated xcodeprojs is that they will stay in date as further changes are made. Nobody has to figure out what changes were made, and manually update things. This hopefully means that mac ports of the new version should come out same day or very soon after releases.

Enough about that...getting libtcod working on the mac involved two major sections of work.

Part I: Build system

Getting cmake to play nicely with the mac wasn't too painful. I had noted places in my CMakeLists.txt where apple variables were needed when I created them, so the first step was filling them all in. Unlike the windows builds, the mac build currently uses the framework versions of libsdl and libpng. I'm unsure if this will require users installing those frameworks before use.... I did this since I wanted .dylibs of libtcod. The only other issue that SWIG apparently doesn't ship arrays_csharp.i built in for the mac. I had to download it from svn and copy it into the right place.

Part II: Crashes on launch, init code, and mac

This is where the pain started. The sample programs crashes on launch, due to an objective c exception about preconditions not being met. After some digging, I found this. Apparently, SDL does some funny business to get initially properly on the mac. You need to include an object c file in your build and use a particular version of a main function.

What happens on the mac is when you include the SDL headers, it renames your main via macros to something else. The objective c file defines its own main statement, which does the correct initing and then calls SDL_main which calls your main.

This obviously doesn't work very well if your a C# program who doesn't have a main! I had a friend at work who know objective c well to bounce ideas off of, and then I ran into this. It's a simple objective c method I could call from C code before initing SDL that would handle the mac stuff for me. No more renaming main nonsense for me. It worked great.

Just one note, all of this doesn't apply if your use the "unix" style SDL libraries. Those you can use just normally, they don't need extra setup. However, I wanted a "real" mac port, dylibs and all. There is now code in libtcod that will fixup the mac specific stuff when you call console init. Hence, it works fine no matter the calling language.

I normally try not to get this implementation specific when writing posts, however I couldn't find all this info in one place. If somebody is trying to get an SDL based library working on the mac, particularly in C#, I hope this info finds you well...

Magecrawl on Mac Part I (Announcement)

Success!


One libtcod had a working mac version, getting magecrawl working was trivial, thanks to the wonderful work by the mono team. Other than a bitness issue that was my own stupid mistake, all it took was dropping the native libtcod mac .dylib and. so, adding a single config file, and off it ran.

Getting libtcod to work on the mac was a bit more work, and a very technical breakdown of issues and solutions will follow in another post soon to come.

Now back to prototyping that skill tree viewer...

Thursday, April 22, 2010

CMake support for mac osx

So I said I was done screwing with libtcod for awhile, but my new laptop thinks otherwise. It is now obligatory to get magecrawl running on it. And so...

This morning I got samples_c to run under Mac OSX. There was a bunch of nonsense with sdl_main and such, but I got it working. Now I need to get the other tools working, clean up the patches, and then create libtcod-net for mac. Then I can get back to magecrawl.




Monday, April 19, 2010

Laptop l = new MacbookPro(13);

I wanted to write a quick post from my new laptop! I just purchased a 13-inch macbook pro and so far its pretty awesome. 

After I "move in" by copying all of my media and installing all the needed applications, my first task on it will be making a cmake native libtcod for OSX, so I can get libtcod-net working, so I can get Magecrawl running. :)

Saturday, April 17, 2010

Introduction to magecrawl's architecture

So magecrawl is broken up into three libraries and an executable that pulls everything togeather and provides "the game". Since I have a few minute between yard work excursions, it seemed like a good idea to write a quick introduction.

Utilities - This is the base library that the other three components depend upon. It provides a few common data structures that c# doesn't (Pair, Point), a few extension methods on basic types, and a Preferences infrastructure for reading config files. Mostly stuff that needs to go somewhere everyone depends upon.

GameEngine - This is the library that "runs" the game world. It provides an interface IGameEngine which other modules use to request data to display and input player actions. Right now, it handles everything not GUI related almost: level generation, save/load, monster AI, physics, etc. It provides interfaces like ISpell, IItem, ICharacter and such so the GUI doesn't have to depend on concrete implementation classes.

GameUI - This library handles displaying everything. From dialogs like inventory and spell listings, to the map and character info, there should be no other place that any drawing code goes (Exception, the title screen goes elsewhere).

Magecrawl - This is the executable that the user runs. It sets up the libtcod console and displays the "welcome window". After a game is started, it then creates a GameEngine instance and runs the game's main loop. There are multiple keyboard handlers, which switch off responsibility depending on the state of the game. They handle keyboard keystrokes, creating requests to the GUI to display various dialogs, and sending various action requests to the game engine.

One area I'd like to talk about is handling "psydo-asynchronous" events. Things like monsters using ranged attacks between player's turn. By default, after the player does an action that causes time to step forward, all the monsters to act before the player gets anther turn happen consecutively, without UI updates. This keeps the action going. However, seeing ranged attacks is really nice. They way we handle this is via a callback.

The main magecrawl event loop registers a few events delegates with the game engine, to be called when the player dies/wins or an event that needs to be drawn happens on a non-player turn. When the game engine runs across one of these, it calls this callback, which then draws the animation and return. It looks something like this.

Main Event Loop -> Handle Keystroke -> Game Engine Do Action - > Game Engine Pass Time -> Monsters Act -> Physics Engine Display Ranged Attack -> Main Event Loop Handle Animation.

After the animation is drawn, we can return back to the other monster's action, and back all the way to the handle keystroke and main event loop.

This is done so there is only one place we "pump messages", in terms of the draw/flush loop. We also don't have the game engine trying to either draw updates or call Magecrawl functions, causing a circular loop.

I am very happy with this design in general. The GameUI/GameEngine divide provides a strong UI/logic separation, and the Magecrawl executable is the only person running event loops. Previous attempts at writing magecrawl have floundered due to event loop or ui/logic problems.

I threw a bunch of ideas down in the space of a page of text, so I'm sure i glossed over a bunch of details. Let me know if there's parts that weren't clear.

Friday, April 16, 2010

System.Reboot(Magecrawl.Iteration8);

So I don't have the link the last two months of posting to make it apparent that I haven't been working on magecrawl lately. I'm hoping that now I've finished 95% of those other jobs, with just a few maintenance tasks to complete closer to the next release. This iteration has lasted way too long already, so this morning I'm separating the goat features from the sheep ones.

The original goal for iteration 8 was "different level monsters, a skill tree for the player, and increasing difficulty". I've booted what I consider the non-essential tasks out of this iteration and this is what I come up with:



Since it has been so long since my last beta of magecrawl, I'll kick out one after I get all of this done.

I haven't mentioned this lately, but magecrawl is open source. Feel free to download the source to take a look at how things work if you'd like. If you'd like to hack on a feature, let me know, there is plenty to do still.

As you can see, a skill tree is in the queue for this release. I'm hoping to flesh out an idea what that is going to look like in a a future upcoming post.

Thursday, April 15, 2010

Completed C# and Lua Swig Wrappers!

It has been a busy couple days since my "I'll get the wrapper up here that night" post. A few more last minute issues, including a weird race condition with different .NET runtimes that I think I ironed out, held this up, but now it is ready.

C# Wrapper

Lua Wrapper

The C# wrapper is now powering magecrawl, which is a pretty significant codebase, so hopefully most of the issues there are ironed out. With Lua, the "hello world" demo works, but I don't know lua well enough to test it beyond that.

Please note, that the libtcod these use is the svn of the upcoming 1.5.x release, and is therefor unstable. The API might change, it might crash, it could steal your girlfriend and watch TV while you're at work, so report bugs you find so they can ironed out early.

Beyond that, I finished all the C# documentation for the new release, so when that comes out, C# will be a first class citizen. My todo list for libtcod is just about done now, so expect a new post in the next few days talking about scheduling magecrawl and "rebooting" this iteration.

Saturday, April 10, 2010

libtcod -> swig -> magecrawl -> true

Today I finally got magecrawl working with the SWIGed wrappers. It was a 2800 or so line diff, but much if that is how noisy diff can get when you change only one line in a file. Much of these changes can be traced to the printLine changes that are inbound for the newest libtcod.

Beyond tracking down some bugs in libtcod (joys of living in bleeding edge svn), the changes where very mechanical. Find and replace will get users of libtcod-net 90% of the way there. For theses pains, they will receive APIs previously unwrapped (height map), new APIs as soon as they are released (the new textbox module hopefully), and much faster turnaround for new releases.

I will get together a C# and a lua demo zip later this evening, so people can tests things out if they want.

The obligatory magecrawl screenshot

Saturday, April 3, 2010

Quick status update...

I just finished getting the libtcod c# swig demo working. There are some performance places I'd like to work on at some point, but it's very reasonable (160fps vs 200fps on initial screen).

I'm going to walk over the diff, and figure out which places of the API could use some renames or cleaning up. I know the print/printRect functions need some love, and the noise functions, but beyond that I think I'm in good shape.

Post that, I'll port magecrawl to use the new API. I'm hoping that turns out to be straightforward. I'm guesstimating 4 hours of work. After that, I'll know that things work great, and I'll post a second version of the wrapper for public testing.