Tuesday, 26 July 2011

What I did with my Weekend (a one-man Game Jam retrospective)

Having missed yet another game jam (TIGJam UK 5, this time) by being at a LARP event, and suddenly finding myself with an unexpectedly free weekend, I decided to have a gamejam of my own (because that's just how cool I am). I'd been mulling over some ideas for a Dwarf Fortress-meets-The Sims-meets-Day of the Triffids game - a sort of Survival Strategy - since watching the 2009 remake of Triffids, so I sat myself down on Friday night and started coding - and here's what I learned from the experience:


Writing Design Notes

It's kind of obvious that writing a design is useful, but the hard part (I've always found) is knowing what to write down. When I have a code architecture in mind, it's tricky to try and work out which bits are obvious and which bits I'll forget and wish I'd written down. Equally, it's often as quick for me to write the code framework, and then use the code as the documentation; which is fine for me, because I've more practice of reading and writing code than reading and writing English, but other people less so.

Over the course of the weekend, I was making the whole thing up as I went; there was no grand design in mind, I just wrote down a list of features and tackled them one at a time. That level of focus (and the particular focus on How Do I Do This Quickly over How Do I Mix All These Into One Unified Symphony Of Code) meant those individual notes flowed more organically into a fleshed-out design, even if that design was just a tree of This Feature needs ==> This Features needs ==> This Feature; and probably This Feature, too. It was also more obvious which design decisions needed to be recorded for future reference when the code was less structured and self-describing.

Coder's Block

Realisation of the weekend: The more you know about something, the harder it is to code it. I know all about AI & Pathfinding - it was the topic of my degree - but somehow the language in which I understand those academic topics is very different from the language in which I express code. Equally, when I'm writing game code (I've hit this block a few times before) my mind jumps ahead, because I already know the (implementation) answer to the questions I've not quite reached yet; but that means that rather than smoothly grow my code base, I'm stuck trying to work out how to plug together the code I've written, and the code I know I'm going to have to write in the near future.

So I stopped thinking ahead. The emphasis on "just get it working, it doesn't have to be pretty" finally pushed me through the block, as I stopped thinking in terms of a grander design and just focused on the bit of code right in front of me. Of course, just getting it to work means that the pathfinding code I have now is nothing like as efficient as it could be, but it works, and it'll be easier now to go back and polish it up, now that I've tied it in to the rest of the code.

Take better care of yourself

Staying up too late on Friday night (by which I mean 8am Saturday) threw my whole sleep cycle off; I wasn't properly focused on Saturday/Sunday & would estimate I hit a 50% velocity for the whole weekend, when I should really have managed 70-80%. What I got right was my eating habits, for once; plenty of caffeine shots to keep me alert, glucose drinks and "energy" snacks (mmm pistachios) to replenish my blood sugar (continuous mental activity can really drop your blood sugar levels) and only eat "heavy" foods with complex carbs at main meals (I'll confess I cheated and ordered in pizzas, but hey, time saved cooking, right?) because the effort of digestion makes you sluggish.

Prep your materials in advance

Ye gods, the time I lost searching for isometric sprites. I'm not an artist by any stretch of the imagination, so all the art I used is downloaded from very generous people on the 'net; but there's a lot of dross out there, and to make things worse, many of the sites that do publish free sprites are horrific to navigate and search. I was really lucky to find OpenGameArt, from where I got most of the artwork that I used in the game, but ultimately the time I spent searching for and prepping sprites (especially given my lack of skill or experience) was time I couldn't spend building features. So next time, I'm working out a shopping list of the artwork I'm likely to need and getting it together before I start.

Play games before you write games

The first thing I did was to sit down with a notebook and write out a few key phrases and ideas about the game. The second thing I did was to think of all the games that those reminded me of and see if I could have a quick playthough of each; which meant that the first hour or so of Friday evening was spent playing X-COM & The Sims, re-learning the interfaces and "vocab" of an isometric UI. I guess this point (for me) is more about user experience and interface; I don't have anything new to bring to the table in those fields, so I'd rather point to previous games and say "They got it right, so I followed their example." and focus on gameplay, which is what I'm trying to improve.


Of course, having talked about all this I should mention what I actually achieved over the weekend, which is admittedly not a great deal. The game idea I had was quite grand for two-day sprint, so the result is more of a simple tech demo than a playable game, but I've uploaded it for now and will see about turning into something actually fun at the next jam; or maybe at the next CB2 Indies meet (there's one tomorrow, actually, will see about heading along).

Go here to get the current download; when you run it up, you'll see the example map with a single survivor. There is code in place for ambling/hunting/killing zombies (hence the red health bar about the survivor's head) but I need to wire up a button or something to spawn one on the map. A task for tomorrow, I guess.

Anyhow, middle-click somewhere on the map to refocus the camera on that spot, and the scroll wheel moves the camera up and down levels - note the basement under the house.
Left click the survivor to select them, then right-click to tell them to move; sorry about the lack of animations...
With the survivor selected, click the wall button in the top-left to select the Build Wall tool; then right-click on two locations on the map (two clicks, not click & drag) (also, two locations in a straight line) to tell the survivor to start building a new wall. It is a slow action, so don't worry if they seem to move to the site of the new wall and stare blankly at it for a few seconds - they're working, honest!

I'm fairly pleased to have got all that working in a single weekend; it's not exactly fun, but it's broken the back of building a simple Tower Defense vs Zombies game, and from there is just a matter of adding ever more awesome.

Monday, 25 July 2011

Epilogue install

Prereqs

The game is built on v4 of the .NET Framework (Client Profile) & the XNA Framework - that makes it Windows-only, I'm afraid (XP SP3 or later).

Download & Install

You can download the game from here. There's no installer, so just run the Expilogue.exe file in situ.

Tuesday, 31 May 2011

Core MSIL Assembler

This post contains instructions for downloading/installing the current prototype of the Core MSIL Assembler, and will be updated as new versions are published; explanations of what the assembler is and what it does will appear in later posts.

Prereqs

The assembler is built on version 4 of the .NET Framework. This is automatically installed by Windows Update on Windows 7 & Vista, and is an optional update for Windows XP; you can also download it here.

Download & Install

You can download the assembler here. There's currently no installation step, just unzip and run the CoreAssembler.exe app where it is by dragging a xxx.core file onto it. There's also a CompileAll.bat file that you can run to automatically compile all the example code.

Tuesday, 6 October 2009

AxumMUD

Just a quick note to say that the code for AxumMUD is online at CodePlex. The network layer is basically complete, though I'll likely go back and refactor when I've got some time, but I'm currently working on the Character/Location design and event communication; hopefully I'll get that checked in later in the week.

Monday, 5 October 2009

New keyboard shortcuts

The fn key on my new laptop has shifted all the ctrl/alt/et cetera keys one to the right, so I keep hitting the wrong ones and discovering new keyboard shortcuts. So I'll note them here as I discover them:

In Visual Studio 2008
Shift+Alt+Left/Right Arrow: Same as Ctrl+Shift+Left/Right Arrow (selects whole tokens at a time), except it selects words within the token, delimited by capitals. E.g. if the carat were at the end of the token "BuildNewConnection", pressing Shift+Alt+Left Arrow would select "Connection".

In Windows 7
Win + Left Arrow: Aero Snaps the current window to the left of the screen, then rotates through Aero Snap Right, Restore, Aero Snap Left et cetera.
Win + Right Arrow: Aero Snaps the current window to the right of the screen, then rotates through Aero Snap Left, Restore, Aero Snap Right et cetera.
Win + Up Arrow: Maximises the current window.
Win + Down Arrow: Minimises the current window.
Shift + Win + Up Arrow: Stretches the current window to the top and bottom of the screen.
Win + Home: Aero Shake (minimises all windows except the current window).

Thursday, 3 September 2009

Axum!

I've been on a bit of a hiatus, both from this blog and from doing any major work on my Codeplex projects, since around April; guess the day job's been taking up all my valuable coding time :-D.

But a few days ago, I downloaded the latest version of Axum (now v0.2), Microsoft's new .NET language/incubation project for introducing actor-based, highly-scalable and massively concurrent code to the .NET framework, and thought I'd post some of my experiences. I first heard about this back in November 2008 at TechEd EMEA, when it was called Maestro, and I was really excited - the work I'd been doing on Lite was in the same vein, trying to make distributed, concurrent code both trivial, implicit and powerful for programmers to use, whilst retaining all the good stuff that you get with .NET. Since the first CTP came out, I've been converting a few of my projects and writing some sandbox code to find out what works, and what doesn't, in the Axum programming model.

I don't want to get to much into the design philosophy, as it's fully explored elsewhere on the web, particularly on the Axum blog (here); instead, I'll be uploading code snippets that do interesting things or exploit the features of the language, and useful code patterns for developing in Axum. So yeah, expect some Axum-related goodness in the next few posts. In the meantime, I'd recommend downloading the preview, trying out some experiments of your own and giving the dev team feedback; as an incubation project, they need all the community support they can get.

Saturday, 21 February 2009

Lazy Evaluation Gotcha!

Note: I'm assuming a vague knowledge of LINQ, and I'd recommend reading up on Lazy Evaluation on other blogs as I only skim over the concept here.

Code-writing for the Conquest project is currently paused while I do some research around the subject area (RTS games), particularly around the unit AI, which is my immediate bugbear; in the meantime, I've been focusing my efforts on Setun, a project that I started early last year. I'll go into more detail on exactly what I'm aiming to achieve with the project in a later post, but for now I can summarise it as a Balanced Ternary virtual machine simulated at the logical electronics level; that is, I'm simulating And and Or gates, Decoders and other similar-sized components, but not going all the way down to transistors and shifting voltages. This is lower-level than a typical VM, but not a strict physical simulation.

I've been increasingly using LINQ in this project; each large-scale component (like registers and the ALU) is typically joined to the next by a bus, or a collection of electronic lines (i.e. wires) and I'm simulating this with an IEnumerable of ILine. Now, when you're handling lots of IEnumerable objects, concatenating them, picking out individual items, taking subsets and so-on, then LINQ is perfect; manipulation of sets is exactly what it's designed for.

However, one of the features of LINQ that often catches people out is Lazy Evaluation, which, if you're not familiar with it, simply means that any LINQ query you create (e.g. pick the fifth object out a list of strings) is not executed (or evaluated) until the results of the query are actually needed. In most cases, this is really useful; queries that are declared but never used are never evaluated and optimisations are performed once the full query is declared and applied, which is better than optimising piecemeal as the query is constructed.

But...

If the timing of the query is important, Lazy Evaluation can catch you out. If you declare a query to pick the first three items of a List, clear the list then try and display the items that you just queried for, you'll find that your query returns nothing. This is because the query now points to an empty list, as it was evaluated after the list was cleared.

Now, I've pretty heavily summarised Lazy Evaluation, because there's plenty of blogs that explain it in enough detail, so instead I'll focus on the behaviour that caught me out; that is, multiple evaluation.

I've been using the Select method to create sets of objects from other sets of objects - for example, I could take an IEnumerable of ILines, and wrap them all in Not gates, like this:


var lines = new List<ILine>();

//Insert some ILines here!

var invertedLines = lines.Select(line => new NotGate(line));


Which gives me a set of NotGates, one for each input line - this is all well and good. But, I tried the same trick with registers; unlike Not gates, which are pretty simple (inverting whatever their input is) registers store a value, only changing on clock ticks. When I tried to display the contents of the set of registers, they always came out as 0 - the initial value. No matter what input I gave, they wouldn't change.

A little investigation later, and I realised the problem: because Lazy Evaluation occurs when you use the result of a query, it happens every time you use it. Each time I iterated over the IEnumerable of registers to output the contents, the LINQ query was creating a new set of register objects, which of course contained the initial value.

So remember, if you're using Select to create sets of objects (for which it is very useful), always remember to stick a ToArray() call at the end; this forces the query to evaluate immediately, and only once.