Tuesday, 10 March 2009

SSAO again

Because I suck, I haven't done any real work on the game again. As usual, I did waste some time messing with useless stuff though!

Behold the power of the resurrected SSAO fakery. I really like the way it looks from a top-down perspective... probably a best-case use of this kind of hack, as the view-dependence is not readily apparent.


The starry-bloom is turned off again... somehow I've introduced a NaN-producing step to it, which propogates through the post process pipeline to make gigantic hexagonal black areas on the final render. 'Cos I suck.

Wednesday, 18 February 2009

Still here...

Eek, no updates for yonks! In my defense, the day job is winding up towards some serious deadlines, and I'm still wrestling with immutable entities rather than making gameplay progress. Despite my desire to learn, I'm not sure I'm capable of using it in this project. I may admit defeat and return to the world of imperative updates on mutable state, but it'll make me sad if I have to.

Anyway, one of the things I've been playing with is post-processing, and generally sorting out the rendering architecture. The rendering framework started as a clone of my previous C++ efforts, and I think it's a bit ugly because of that.

Here's the current look with a post-process slapped on top. I wanted a bloom type effect, but went for a six-pointed star rather than a normal separable Gaussian affair. Sparkles should fit with the way I want to render magical spells and suchlike...


And yes, the stars aren't actually that visible with such large bright areas. And yes, it is hugely overdone for testing purposes. Expect a little more subtlety... eventually. For now, huge glow was damn satisfying!

Hmm. Just noticed the water appears to be glowing, too. That's not right.

Friday, 16 January 2009

Type Frustrations

Warning: this entry is largely a rant about my own ignorance.

I should have remembered this, but there's a big annoying thing that crops up whenever I try to get overly-generic in Scala.

Type erasure.

My understanding of this is that it's a pain in the arse. It has something to do with brutally discarding useful type information at runtime, such that List[Int] has the type List (or possibly List[Object]). Never mind that List is not even a type, it's a type constructor, some combination of the JVM and the writhing tentacles of an entire herd of shoggoths1 renders it a nigh-useless blob. Dark magic makes it work perfectly when all manipulations are done at compile time, but just try pattern matching or reflection with it...

What this means is that the following code will not compile:

//NB: Will not compile, type of [A] is unchecked due to erasure
def propTest( p: Property ) = p match {
case li:ListProperty[Int] => println( li.value.toString )
case lf:ListProperty[Float] => println( lf.value.mkString(":") )
case _ => println( "unknown property: "+p.toString )
}


Of course, this non-compilation is slightly less annoying than when you only try to pattern-match against a single instance of a parametrised type. In this case the compiler will emit a warning, but still compile to (apparently) working bytecode. If we dispense with the ListProperty[Float] case, the above will compile, li will match any ListProperty, and ClassCastExceptions or similar evil will almost certainly ensue.

Ignoring compilation warnings is (as we all know) incredibly dumb, and re-running compilation with the -unchecked flag will produce more helpful messages about what exactly is completely broken. It's still somewhat vexing that this compiles at all, when the chances of it doing anything useful are effectively zero.

I guess I can't complain overmuch, pattern matching against arbitrary type constructors appears to be something Haskell chokes on too, although with less smelly default behaviour and a different reason. I'm not sure how much of this is down to my downright shoddy understanding of type systems in both languages, so I'll be fiddling with this a lot more. In the interim, without some method for defining simple container properties, including type checking and pattern matching against them, the 'property bag' model appears dead in the water for my chosen implementation language.

As I said before: arse.

1What the hell is the plural of 'shoggoth'? For that matter, what's the collective noun for 'em?

Tuesday, 13 January 2009

More references

I sometimes (often) feel the Internet is too damn big to be useful.

But it is possible to find some really good stuff...

Like these fascinating posts dealing with writing retro games in functional languages. I linked the last part in the mini-series, because it posits a solution to one of my many current problems. Rather than allowing game logic to modify game state directly, emit a list of 'actions' which can be dealt with in a more or less atomic fashion at the end of a frame.

Initially this smacks of just moving hard work elsewhere, but I think it does help more than that. Your world state/list of entities becomes static for the bulk of a frame, so the order in which you process things is irrelevant, and consequently dereferencing entity handles becomes slightly more tractable. Of course there's a real danger that by the end of a frame, you may have accumulated mutually incompatible actions. However, imposing an ordering over actions and allowing them to be tolerant of faults seems like a better solution than threading the complete game state through everything related to an update - which essentially allows these supposedly transparent areas to side effect by fiddling with the world state directly.

Hmm.

Another fascinating post calls out the lack of a simple dictionary type as a major implementation headache for games in the chosen functional language (Erlang). That seems to be tacit support for the 'property bag' model of game entities in a functional context. I wonder how many other game programmers are lurking out there in the wilds of the internet, ready and willing to provide useful feedback from the experience of using these patterns in functional languages, if only my Google-fu were strong enough to find them.

Monday, 12 January 2009

More Entity Broken-ness

Haskell is weird.

Having dispensed with that, I got some great comments about ways to approach entity composition after my Doing it Wrong post a couple of days ago. Something which I'd given little attention was brought up, and I'm thinking I should give it a second chance: representing entities as name/value pairs.

A bit of stumbling around later, and I found this huge post by Steve Yegge talking about the same thing, with extra bonus links at the end for additional reading. I'm still digesting it.

There do seem to be some unique challenges attached, though, in addition to the inherent oddity that are types in such a scheme (I'd also like to take this opportunity to bitch about type erasure under the JVM: bitch bitch bitch whine hate hate).

For starters, entities want to be able to refer to each other. At the very least, many will want a reference to a 'parent' so I can implement a simple scheme for inheriting properties. That's all fine, apart from the fact that I can't actually store references to objects because they're immutable, constantly subject to being deleted and recreated with different data. So there must be some kind of handle or ID system built in - no big problem, it's a useful thing to have in the scheme of things. Except then you need to provide a some kind of reference to the list of current objects, somewhere, for the handle/ID to search within and produce an entity object when really needed. Urgh, OK, we can do that... a simple function which returns the current world state's entity list will do, and provided entities and their clients behave that should be kindof safe.

Except it's not, of course. When a given entity acts, several other entities may be changed in an indeterminate order (invalidating the old list), and the world itself might pass through several intermediate steps during the update process - I can't currently see a way to ensure that entities always deal with the correct list of entities. It's possible an implicit variable might be a way ahead in Scala, providing a kind of weakly dynamic scope for the entity list. That doesn't sound like a good solution though, it sounds like a hack.

Of course, there's also some unrelated bookkeeping attached to ensuring that entity handles/IDs are always valid, unique, and easily generated. Eww.

On the plus side, if I vaccillate back to wanting Lua scripting, it would probably integrate very nicely with Lua's solitary data structure (last I checked, anyway, everything was an associative array in Lua). But then, ensuring or even pretending immutability in the presence of Lua could be a whole different kettle of fish...

Do other roguelikes ever use a scripting language? Choosing to have one is a pretty big step for any game, even if you don't roll your own and produce a hideous abomination (I'm currently using some middleware at work that provides it's own scripting language, somehow combining the concision of VB with all the elegance of COBOL, speed of Ruby, rapid iteration capabilties of C++ and expressiveness of a wheelbarrow of dead badgers) and most roguelikes appear to be more amenable to being data- rather than script-driven.

Pfft. I should go write some code. This is all getting a bit abstract.

Saturday, 10 January 2009

Meanderings


The festive season never seems to be a good time to get any coding done...

With that out of the way, I'm going to press on with my crazy schemes. Over the past few days, I've been trying to recreate the skeleton of my game in Haskell using Nanocurses (this was mostly an excuse to learn Haskell, having tried and failed many, many times already).

I still think in altogether too imperative a fashion for Haskell to look on approvingly, especially when doing things with Curses involves slipping into 'do' notation all the time. Ah well, it'll be interesting to see if rendering my problem in a more pure language will help me spot any solutions.

Wednesday, 17 December 2008

Entity Composition: Doing It Wrong

So, despite the lack of updates I've been working on this quietly. Unfortunately recent progress has been entirely on the game logic and architecture, rather than anything readily screenshotable, hence no real drive to blog.

But here I am, writing a new post. This can only mean one thing: rambling, waffly code-oriented braindump!

My current obsession is the structure of entities, going right back to basics. Entity is a deliberately ambiguous term, which I'm taking to mean any gameplay-relevant object that can be affected by the actions of agents in the game. Doors, monsters, AI, buffs... many things potentially fall under this umbrella.

I tried splitting the potential abilities of an entity into traits/mixins:

abstract class EntityAbility
trait HasPosition extends EntityAbility {
val position : Vector
val blocksTravel : Boolean
}
trait HasHealth extends EntityAbility {
val currentHealth : Int
val maxHealth : Int
}
abstract class Entity extends EntityAbility {
val id : Int
}

class Character(val id:Int) extends Entity with HasPosition with HasHealth {
val (position,blocksTravel) = ((2,2),true)
val (currentHealth,maxHealth) = (100,100)
}


This is nicer in many ways than a traditional hierarchy, allowing for more code reuse and less chance that required functionality will come with a bundle of meaningless state.

Unfortunately there are also some interesting problems with this approach. Mainly they concern the immutable update step. If only the position (say) is changed in a given timestep, objects can be dealt with as instances of the HasPosition trait. However this trait has no concept of the entity that it's being mixed into, and so cannot instantiate a copy of the entity with an updated position. Dropping the requirement for immutable world state allows for this easily, but that's no fun.

In addition, information about capabilities of an entity are defined at compile time, bound up in the type system. There's no way to define these things in a data file read at runtime. Whilst this isn't as big a concern for me (this is a small game and only needs a handful of basic types to define most of the game) it is an unfortunate restriction.

Another approach is to use actual composition...

sealed abstract class Position
final case class HasPosition( position: Vector, block: Boolean ) extends Position
final object NonPositional extends Position

sealed abstract class Health
final case class HasHealth( current: Int, max: Int ) extends Health
final object Invulnerable extends Health

final case class Entity( id: Int, position: Position, health: Health )

//Elsewhere...
def move( e: Entity, newPos: Vector ) = e.position match {
case HasPosition( _, b ) => Entity( e.id, HasPosition(newPos,b), e.health )
case NonPositional => error("can't move nonpositional entities")
}


Well, changing entities becomes trivial (and supports using a Builder pattern or helper methods to remove those ugly constructor calls everywhere, plus enabling runtime construction of new entity 'types') but I end up having pattern matching all over the place. When you're operating on several components that becomes very messy, very quickly. There's also the issue that there seem to be vastly more potential runtime errors visible in the code, even if in practise I always check that a given component is of the correct type the compiler will whinge if pattern matching is not exhaustive (and correctly so).

I've fiddled with some other approaches such as conventional inheritance and a slightly COM-like abomination, but so far the above two feel most natural in Scala. I can't help but think that I'm missing some obvious alternatives though, as neither is particularly elegant when implementing common operations. Clearly I'm doing something wrong...