Showing posts with label iteration10. Show all posts
Showing posts with label iteration10. Show all posts

Thursday, September 30, 2010

Chugging along on Magecrawl for SL...

Quick update:

I'm still chugging along on Magecrawl for Silverlight. I just finished ranged targetting with overlays, which makes melee/ranged attacks, inventory/spell use, and operate doors work.

I have a bunch of "easy" dialog work to do, a splash screen to make, animations for ranged attacks, etc. I also have the harder work of a skill tree, preferences, and such.

Monday, September 20, 2010

Magecrawl Status Update

I'm making good progress. I finished up the inventory dialogs tonight, and got started on targetting. Here is is my todo list as of tonight:

Other:
Health/Mana Bars
Status Effect/Monster list on character info
Handle player death
Icons in inventory
Hitting z to cast spell, z should target

Dialogs:
Splash Screen
Help

Hard:
Equipment
Skill Tree
Way to edit preferences
Reasignable keystrokes

Message Box:
Up/Down Stairs
Save
Quit
Welcome Message

Requires Targetting:
Operate
Draw ranged attack
Attack Melee/Ranged
Inventory w\ targetting


Obviously rewriting the skill tree viewer will take the most work, but most of the rest of them will fall into place quickly. Four them require targetting, which I'm currently working on, while 6 require dialog to be written (easy). 4-6 of them don't have to be done for the game to be playable, just nice to haves.

Tuesday, September 7, 2010

Silverlight fun and arcane "batteries"


While the open beta of Final Fantasy 14 has taken more programming time away that I'd like to admit, I haven't dropped off the face of the planet yet. I've made good progress so far on the new "tiles" GUI, using silverlight. See this video for a quick video of gameplay. There is a huge number of things needed to make it fully functional, ranging from picking up items to the skill tree.

Assuming I was able to make the tiles interface work on Windows/Mac/Linux, both in the web browser and in a stand alone application, I've been toying around with the idea of ditching the ascii interface. I personally enjoy playing the tiles version of crawl more than the ascii version, and I feel I could make either two decent front ends or one awesome one. There is a lot of "if"s still in the air, but would doing that enrage anybody out there? While in the end I'm programming this game for personal pleasure, I do care about the opinions of the players of my game.

Another idea floating around my head is redesigning the magic system in Magecrawl. Right now, it is a fantasy standard MP system, with the MP being generally recharged after every fight. This makes fights "front heavy" with the characters dumping most of their MP early on, and resorting to melee afterwards. Also, it generally devolves into spamming the most powerful attack spell over and over. When I think about arcane duels, this isn't how I imagine things. I imagine almost every round until exhaustion some spell being cast, whether it is a earth-shaking powerful effect or a simple cantrip.

It is hard to make such a wide spread of spell types and tempos effective in the current system. My idea is a take on recharge magic, with a twist. Each spell has a total amount of "energy" that is needed to cast it. The player has a "battery" of mana, which at the end of each turn (that isn't spent moving?) some is syphoned off to fill each skill not ready to cast.

With a property selection of spells, one could alternate between two relatively fast recharging spells, or cast a range of spells (damage, push back, damage, blink away). Long term effects could reduce either the total "battery" before spells start running dry or the rate that spells recharge. Playing arcane characters should be about casting spells and making things blow up :)

Tuesday, August 31, 2010

I can has magecrawl on the internets?


So it might not look like much, but that's magecrawl running in a web browser! Levels generated, items created, monsters waiting for time to start ticking. The only thing missing is drawing and control.

My good friend Ben inspired the idea and helped implement some the magic.

Roughly the magic entails removing all references to libtcod from the game engine. That way, we can load all that code inside a web browser via silverlight, (which can't load native code). I "ported" this code from libtcod:
  • Shadowcasting Line of Sight
  • A* Pathfinding
  • Bresenham Line Generation
"Porting" could be described as the twisted application of force needed to move C code to compile and run in C#. Since none of them used pointer math too heavily, it was reasonable to attempt. The code looks ugly for C# code, but it works.

In theory, it should even save and load! I can use my same serialization code, just point it to "isolated storage" and away we go.

Obviously, a lot of work is needed to make it a real game frontend. But the fact that I could even get this far (and not have to rewrite everything in flash) is pretty awesome.

Saturday, August 28, 2010

A simple way to reduce memory usage of structs/enums in Dictionaries

I can't take credit for this tip, it was pointed out here.

As pointed out here, by default if you use a struct or an enum inside a dictionary, you will alloc objects every time you access the dictionary to box/unbox things. For example this will allocate both a Point an object to box it in:

var squareLookup = new Dictionary<Point, SkillSquare>()
squareLookup[new Point(0,0)] = null;

I ran into issues because I used something like this for drawing the skill tree, and when you scrolled we hit the dictionary a huge number of time.

The linked hint suggests doing something like:
public class PointEqualityComparer : IEqualityComparer<Point>
    {
        public static PointEqualityComparer Instance = new PointEqualityComparer();

        public bool Equals(Point x, Point y)
        {
            return x == y;
        }

        public int GetHashCode(Point obj)
        {
            return obj.GetHashCode();
        }
    }

var squareLookup = new Dictionary<Point, SkillSquare>
    (PointEqualityComparer.Instance)
squareLookup[new Point(0,0)] = null; 

With this simple change, a profiled run of scrolled went from over 70% of all allocated memory being Points to so few it wasn't even broken out as an entry. This increased performance by a huge amount.

Friday, August 27, 2010

Testing - Baby Steps

I just committed the first nunit tests for magecrawl this morning. Automatic testing has been on my "nice to have, but not now" list for multiple releases. The reason in short is that writing tests isn't fun, which in some regards is a stupid reason, and in others is understandable (this project is my hobby, not my second job).

My first step into testing was 11 tests, testing the generators (Item, Monster, Map). They simply just poke each generator public API thousands of times, looking for a hang or crash. During development, I ran into a significant number of issues related to this, so this was a "low hanging fruit".

In the future, I'm planning on writing more tests, testing the game engine itself and more of the external libraries. However, I'm currently demotivated enough that I want/need to work on other more interesting things.

Tuesday, August 24, 2010

Modularization - The joys

Modularization, the process of breaking a monolithic software component into multiple separate components. To be honest, it isn't very much fun. For a year or so, I did a lot of it at work, enough so that my wife recognizes the word and knows it isn't very much fun. This is what I did all weekend.

The first question is why I would spend a significant portion of the weekend doing something I admit isn't fun as part of my "hobby". The truth is that in most hobbies there are parts that one does not enjoy. Runners don't always enjoy getting up early to run, some parts of video games are called "grinds", and practicing a skill or instrument isn't often fun.

Magecrawl during development had a few modular boundaries established early on, between the GameEngine and the UI, that has been honored. However, the "GameEngine" component has grown to include much of the games logic, enough that I felt for testability (more on that in further posts) and understandability, things had to be broken up.

Here is a picture of what I currently have:



A bit of explanation, everything that isn't MageCrawl.exe, GameUI, Interfaces, and Utilities used to be in GameEngine. Here's a rough idea of what everything does:

  • Utilities - Low level stuff, like the Point class, Preferences, and helper classes for saving and finding types at run time.
  • Interfaces - These are interfaces that the GameEngine as a whole provide that allow the GameUI and controls to query information about the current game state. Things like IPlayer, IMap, IGameEngine, etc.
  • GameUI - This is what draws the map, menus, etc.
  • MageCrawl - This is the game engine proper. It has an implicit dependency of GameEngine via MEF. It kicks everything off and runs the main game loop.
  • EngineInterfaces - This is a set of internal interfaces the game engine components use to talk about objects everyone needs to know about. For example IGameEngineCore describes the calls to the GameEngine the various modules can use to implement their behavior. For example, those interfaces might expose how to add a status effect to a creature, but to do that you need to know what a status effect is. But status effects live "above" this module, so we create an interfaces that we can expose at this low level, IStatusEffectCore (IStatusEffect is in Interfaces for the GUI).
  • Items - This guy technically existed last release. It was the newest written code, hence being formed as a separate module. This guy handles creating items and exposing their behavior via Attributes.
  • StatusEffect - This guy handles short and long term status effects, things like poison, haste, and the like. It acts by using the exposed interfaces in IGameEngineCore and attributes.
  • Actors - Technically, this module contains monsters (and their AI), along with the Character base class. Characters can wield equipment (Melee for all monsters right now though) and have StatusEffects upon them.  Player lives in GameEngine since it has a lot of other stuff (Spells, Skills, etc).
  • Maps - This was the guy I wanted to pull out. It exposes the map data structures, and the multiple ways to generate maps. Maps place monsters onto them self, and can contain items on the ground.
  • GameEngine - This is where everything else lives. It handles physics (who can move where, etc), combat (resolve attacks), magic (what does the spell do), and the like. 
This is a rough outline of MageCrawl's internal structure. I'll talk about it more in future posts.

Thursday, August 19, 2010

Iteration 10 - The long road to slices (want to get out and help push)?

So I've spent this week doing "research" on what next lies in store for Magecrawl.

The first thing I've realized is I now have a good "family tree" for Magecrawl. While Magecrawl isn't developed enough for Crawl to consider it a legitimize offspring, it provides much of the inspiration and root ideas. Things like tactical gameplay, high difficulty, removal of any "grinding" gameplay, and a crazy good auto-explore are all things I aspire to have. Borderlands takes the role of the crazy uncle that rubs of a little bit. It provides such a varied equipment set that playing the game a second (and third) playthrough is fun and interesting. Diablo can be considered one of the grandfather figures. It to me was one of the great dungeon delve games of my youth.

My serious hope is that is the last "iteration" in the series to build up a game engine. Tasks I want to finish to put me in a great place include:
  • 55 open issues in my bug database, mostly minor and a few major features. Some major ones include:
    • Better monster AI using sounds or smell
    • Status effects from various schools
    • Better use of spell effect areas to differentiate the schools
    • "Typed" damage, just as fire or physical. Resistances to various damage types.
  • Refactor the GameEngine library into multiple separate libraries, pulling out:
    • Monster creation/behavior
    • Status effects
    • Map creation
  • Some form of basic integration testing for common operations.
  • Some form of "arena" for testing the weights of various skill tree nodes, along with the possibility of an awesome screen saver.
So yeah, that's a lot of work. I'm in no hurry to start working a masses of content for a "slice" game, so if it takes me multiple months, it isn't the end of the world.

While I'm still planning on working on Magecrawl (a lot), I feel like I'm in a good place to open up development to others if they are interested. Developing on Magecrawl offers:
  • A relatively clean/nice C# codebase
  • Licensed BSD
  • Works on Windows/Mac/Linux, development is possible on any platform
  • The possibility to implement high level functionality on a working game, as opposed to starting at square one with an @ walking around the screen (not that there is anything wrong with that)
If this sounds interesting, feel free to contact me at chris dot hamons at gmail dot com.

One last thing, I re-realized how awesome Ascii Dreams is. The "Designing a Magic System" serious of articles and the follow ups should be on the required reading list for any future roguelike developer (or game developer in general). I wish he updated it more often these days, the content is golden.