Wednesday, December 19, 2012

Novel game play mechanics in the roguelike "Tales of Maj'Eyal"

Yesterday I downloaded Tales of Maj'Eyal, a new rogue-like game that's just had it's first release candidate announced.

Rogue-like games take their name from the original Rogue game, an ascii, turn-based dungeon delver with roots that trace back to very beginning of video games and electronic computer history. They're usually heavily inspired by Dungeons and Dragons and Tolkien, have RPG elements and often permadeath (if your character dies - that's it - restart, which makes games far more tense, frustrating and rewarding).

The original Rogue.


Two of the more popular rogue-likes are Nethack (under active development since 1987) and and ADOM (recently funded on Indie-go-go for a facelift). Roguelikes are quite a lively genre of games, with a lot of interesting and experimental development, see the Doom rogue-like, or the cyperpunk roguelikes, vampire roguelikes, anime mech roguelike, space trading rogue likes, serial killer roguelike, there's a lot of healthy variation and experimentation.

Tales of Maj'Eyal

Tales of Maj'Eyal Rogue-like Innovations 


Tales of Maj'Eyal does some innovative things which I think are worth a closer look. It's not necessarily the first rogue-like to do any of these but it's does them all well.

1. It uses the Lua programming language

It uses a Lua-based engine because Lua is awesome, this means development can proceed far, far faster than something like Nethack written in C. It also allows easy to load modifications that can extend the game word. I'm a big Lua fan, so that's why I've highlighted this one!

2. Social elements

The game has some asynchronous online features, first you (optionally I think) have an online account that stores information about your character and game progress. You can share this with other people. It's like the profile page in an MMORPG.

There are online leaderboards.

By default you have a chat window on your screen with people chatting as they play the game.

You're notified when people die (and how) in realtime.

This all makes the game more competitive, social and makes the experience easier to share. Social elements are really quite important and because it has these, it would be very easy to monetise the game (though I don't think that's the plan)

3. Unlockable Content

When you first play the game half the races are locked - you don't know what they are, the same for the classes. As you play and achieve certain things in the game world, you unlock these starting options (there are also birth-options you can unlock which allow you to alter the story). This not only adds a sense of progression to the metagame while giving individual game-play-throughs more value, it also introduces a natural learning curve. Easier race / class combinations are available at the start, more exotic one's later when you have your bearing.

4. Achievements - which are social

There are various achievements in the game - and when you get one - it's broadcast to the everyone else playing. I think this encourages a number of behaviours
  • Achievements are more valuable, as they are social and demonstrate how good you are at the game.
  • Seeing other peoples achievements become unlock informs you about what achievements are available and encourages you to seek them out.
  • Provides progression and value beyond each single game.

5. Accessible interface and graphics

Most roguelikes are ASCII and use all the keys on the keyboard. As a roguelike player I found it natural to play Tales of Maj'Eyal with the mouse. Annoyingly some of the standard roguelike keys don't work (, - to pick up and that kind of thing). The graphics are passable and the rendering engine handles graphics that are larger than a single tile.


I'd love to see some of these elements extended - warping in other characters to help you with a boss (like Demon Souls), fighting other players previously killed characters and working characters that have done well into the game lore.

Friday, December 14, 2012

Playing around with Adventure Game interfaces again

I was thinking of maybe coming at Ludum Dare from an adventure game angle, so I've been playing around with interface code. This amounts basically to copying the Monkey Island 2 interface - down to the colour scheme :D Couldn't get quite the right fonts though which was annoying. If you know of a ttf font that looks like the Monkey Island 2 command buttons please let me know! :)


Here's some of the code:


Of course depending on the theme I may have to abandon my adventure game interface aspirations!

Sunday, December 09, 2012

Ludum Dare 25


I'll be taking in part in Ludum Dare again - this time I think I'll avoid spending an entire day on the intro sequence, as cool as it was! Hopefully I'll get some youtube videos up of game play.

I'm using the same engine as last time but I've rebuilt it, it's now much faster and more clever about when to reload assets during development. Last time I ended up wasting hours adding keyboard support, so today I'm going to make sure everything is up to scratch by getting my previous Ludum Dare entry working (it's very close already so that shouldn't take too long!).

...

Well it's the end of weekend and I didn't get my previous Ludum Dare entry compatible with my current engine but I've moved in the right direction. It shouldn't effect any features I need for next week (and I'll probably do some checks to make sure everything is ok).

Tuesday, November 13, 2012

If you have to refer to the documentation every time you use a module, find or build a new module

I recently checked out this slide deck called "Python For Humans" by Kenneth Reitz  which takes Python's Http library and rewrites it in a much more intuitive way. (I've used the Python http lib - it's not particularly straight forward). The deck is not really about Python, it's more about good API design. One of the slides says:


If you have to refer to the documentation every time you use a module, find or build a new module

Which I think can be generalised for API designers to 

If you have to refer to the documentation every time you use an API, change the API

This is excellent advice and something I could immediately apply to my own code. Even if you're using an API (rather than writing one), it's worth building an abstraction layer on top of the API you're using if it sucks - Win32 I'm looking at you :) I seem to vaguely remember in Win32 to move a window you have to call a function named ResizeWindow or something equally obscure. Anyway I looked at my own code and made a few changes. In Dancing Squid (my small game engine) my scripting API text alignment functions are called:

Renderer.SetFontAlignmentHorz and Renderer.SetFontAlignmentVert

I could never remember these function names, never - I always had to look them up! Also do you really align a font? Surely it's the text you're aligning?

It just seems a bad name all over. After reading the Kenneth's slides I decided at least this one part of the codebase needed a rename and I went for

Renederer.AlignTextX and Renderer.AlignTextY

Which I find far easier to remember - even as I was coding just now, and came to do some text alignment, I had a brief moment of syntax joy as I knew I'd be able to type out the functions without having to go to the docs or search my code. Good advice, that deep down we all know, but occasionally need reminding about!

Sunday, November 11, 2012

Emedding Binary data in an executable

I have a fast little game engine that I've written called Dancing Squid. Recently I thought it would be nice to make it a little more user-friendly and print debug text to the screen of the render window. This way the user wouldn't have to keep looking at the console to see what's gone wrong. It'd also be useful for instrumentation type things like FPS and memory used.

If I 'm going to be rendering out error messages - I need a font but those error messages might include "Font file missing!", what's a programmer to do?

Well the way that immediately springs to mind for me is to embed the binary data in the .exe file directly. Can't lose the font then! (I decided to use silkscreen which has a permissive license and looks nice and minimal)


Here's how it's done using the standard gcc toolset.

ld -r -b binary -o [output_name].o [binary_file_to_embed]

This outputs an object file which can be linked into the exe at compile time. But then how do you reference the data? Well you need to get a special reference keyword and this can be done with another tool.

objdump -x [output_name].o

Which in my case outputs something like:

SYMBOL TABLE:
[  0](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 _binary_[data_id]_start
[  1](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000480c _binary_[data_id]_size
[  2](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000480c _binary_[data_id]_en
d

[data_id] is a name generated from the file being embedded. You can then use these names to get your data.

//embed_test.c
#include
#include

extern char binary_[data_id]_start[];

int main(int argc, char* argv[])
{
    char* p = binary_[data_id]_start;
    return 0;
}

Then to compile this:

gcc -o embed_test.exe embed_test.c [output_name].o

And that's fine, I managed to add that into my makefile and everything worked fine.

But I also compile to Android and I'd like this to work there too. Android make file's for C/C++ projects are some non-standard script and you can't add object data :( Somewhere hidden in a maze of different makefile and bashscripts Android uses the same tools, it uses gcc or g++ so it's possible but I didn't feel like trying to untangle all that so I looked for a different approach.

(I did get as far as making the object file for android - this is pretty simple and just requires you to use the arm version of ld that comes with android-ndk)

Second Approach to embedding data in a executable

If that fails - how about whacking the binary data into a header file as an array of bytes (unsigned chars). It's not a hard tool to write but I suspected someone had already written it - and they had; jetro

I ended up using that to generate my header file.

size_t data_len = 18444;
unsigned char data[18444]=
{
    0x00,0x01,0x00,0x00,0x00,0x0F,0x00,0x30,0x00,0x03,0x00,

And there we go - embedded data that works on both windows, android and any other platform that I think to add in the future.

Thursday, November 08, 2012

Getting paid as a UK company from America

To get paid by an American company, if you're in the UK, you need an EIN number. If you don't have an EIN number then 30% of your payment gets withheld as a tax in America! You don't want that. I got this number a while back for my company and recently a friend was asking about how to go about getting one. I thought it'd be a good piece of information to share more widely!

In order to get the EIN number you need to get form W-8.  I didn't have to send the form in, I just phoned this number (00)1-267-941-1099 the woman asked me the questions that were on the form, then gave me the EIN number. While on the phone I made it clear the I could speak on behalf of the business. A week or two later they sent confirmation out to my business address. I was able to use the EIN number immediately.

The guys on the end of the phone obviously deal with people from the UK phoning up about this number all the time - so they can easily guide you through it all.

When filling the form in, there's a PDF of instructions for filling it in here: http://www.irs.gov/pub/irs-pdf/iss4.pdf which I missed initially! The W8 form itself is available here: http://www.irs.gov/pub/irs-pdf/fw8ben.pdf

I found this thread quite helpful when I was researching how everything worked:  https://www.createspace.com/en/community/thread/17723

Thursday, November 01, 2012

C# for Game Development

I recently had an email asking how C# stands up as a game development language these days. I thought that was quite an interesting question; I'm very optimistic for the future of C# as a game dev language. Here's a cleaned-up version of my full reply.

Since I wrote the book C# Game Programming; the the landscape has changed; Tao has been renamed http://www.opentk.com/ now and XNA support has been dropped by Microsoft (just like they dropped the original C# bindings for DirectX, I can imagine it being deeply frustrating for people who have spent time learning the API. There's a story here: http://www.wpcentral.com/xna-dead-long-live-xna . Though, of course, XNA games will still work for sometime yet, just there will be no updates.)


On the growth side; game engines like Unity use C# and have become
really prominent in the games industry. Sony has recently released the PlayStation Mobile Suite for indies to develop on Vita (and other mobile devices), that's also C#. It's great to see that C# has now become quite a viable language for console and mobile development. 

Unity games are released on all sorts of platforms - the games can definitely be competitive with handcrafted C engines ( http://www.interstellarmarines.com/media-section/ ). It has excellent support and resources but it's a closed platform, it too could go the way of XNA one day (though I don't think that's particularly likely anytime soon). There's monogame, an opensource version of XNA, as well but I haven't looked at it. Overall since a year ago C# has become a more popular language for game development.

C# is very fast, enough for a blockbuster type game. The code that really needs - down to the hardware fast - has slowly been migrating from the CPU to the GPU and is all handled through shaders. The language used for the gameplay code is becoming less about speed and more about ease of expression for the developer. A lot of big name games use scripting languages to run the game logic - Lua is popular and that's much slower than C# (but far easier to embed in C programs and very portable) 


If I was starting a new game project today - I'd use Unity, unless it was 2d, then I might have a look around and see if there's anything more suitable - moai? The general way 2d games are made in Unity involves setting everything up in 3d space and it seems a bit of a faff to me, though it can allow for some nice effects.

My main issue with C# and Tao/OpenTK is deployment - it's fine if you write an installer but if you just want to throw someone an exe to try it out - then you need to make sure they have the correct version of C# installed and send them all the relevant dlls. It wasn't particularly easy for a non-technical user to get everything running.  In my current projects deployment is something I try and make as smooth as possible. Unity does this very well because of it's webplayer - there's no barrier to overcome for the player, they just have to click a link and they're in the game!


Overall I think the future is looking quite bright for C#, it's not the perfect language but it's pretty good. I think it suffers the same disease as C++, each release adds some more features, more keywords and it makes the language less elegant, clean and easier to intuit. Despite growing in complexity I think it has quite a good future in games until multicores CPU's become more and more prevalent and we need something that can handle parallel programming better.

Monday, October 29, 2012

One of the few cases where I'll use the ternary operator.

The ternary operator in C/C++ is of the form "? : " and is mainly used to cram an if-statement into one line and write unreadable code :)

I generally steer clear of it but there is one type of situation where I'm willing to use it. Printing out the state of a boolean in a printf statement. C didn't have a boolean type, printf is from C, so there's no support in printf for boolean types. But booleans are an everyday type now and you'll often find yourself wanting to print out the state of a bool.

You can't do this:

printf("isSoundOn = %b", isSoundOn);

There's no escape character for bools but you can use the ternary operator.

printf("isSoundOn = %s", isSoundOn? "true" : "false");

That will do the trick. I think it's reasonably straight forward and actually doing a full if statement across multiple lines would make things harder to read for such a simple action. I did see an interesting alternative on Stackoverflow with no branch, from memory it was this:

&"false\0true"+6*isSoundOn

That probably needs some braces and maybe some casts to compile but basically it's moving the pointer to the start of the "true" substring if isSoundOn is true. If isSoundOn is true it will have a value of 1 otherwise 0, 6 is the length of false including the termination character. So 6 * 1 moves the pointer to "true", 6 * 0 keeps the pointer at the start of the string and printing will end when it reaches the terminating character \0. Clever but too magical for regular code I think.

Monday, October 22, 2012

GCC's new Local Register Allocator

Some messy code was cleared up the new GCC (GNU's C compiler) and apparently is used to be refered to as Satan. I thought that sounded a worth a skim. It's here for the interested: reload.c

I was about 1/3 of the way down, thinking - this isn't too bad, I've seen worse - then I reached this beauty of an if statement.

  if (out != 0 && GET_CODE (out) == SUBREG
      && (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
      && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, rclass)
#endif
      && contains_reg_of_mode[(int) rclass][(int) GET_MODE (SUBREG_REG (out))]
      && (CONSTANT_P (SUBREG_REG (out))
   || strict_low
   || (((REG_P (SUBREG_REG (out))
  && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
        || MEM_P (SUBREG_REG (out)))
       && ((GET_MODE_PRECISION (outmode)
     > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
#ifdef WORD_REGISTER_OPERATIONS
    || ((GET_MODE_PRECISION (outmode)
         < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
        && ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
     ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
      / UNITS_PER_WORD)))
#endif
    ))
   || (REG_P (SUBREG_REG (out))
       && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
       /* The case of a word mode subreg
   is handled differently in the following statement.  */
       && ! (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
      && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
          > UNITS_PER_WORD))
       && ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode))
   || (secondary_reload_class (0, rclass, outmode, out) != NO_REGS
       && (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
       SUBREG_REG (out))
    == NO_REGS))
#ifdef CANNOT_CHANGE_MODE_CLASS
   || (REG_P (SUBREG_REG (out))
       && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
       && REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
        GET_MODE (SUBREG_REG (out)),
        outmode))
#endif
   ))
    {
#ifdef LIMIT_RELOAD_CLASS
      out_subreg_loc = outloc;
#endif

I've never even seen if-defs in a if statement before! Mind-boggling - seems like the clause itself should be it's own small domain language. I've not even tried to pick it apart, and as usual blogger has messed up some characters escaping them but I'm sure the insanity shines through!

Thursday, October 04, 2012

September Review

This month, among many others things, I ported my small engine over to Android. Android development went much smoother when I totally ignored Eclipse and did everything from the commandline under cygwin. The development experience compared to Windows (or Console dev generally) isn't very friendly but I'm able to run the same program on my desktop and phone which is cool. I don't really have to touch the Android internals again, unless I want device specific features, such as camera access or something. I've not submitted the working build to any public source control but I have updated my github with android ports of all versions I've committed so far.

Monday, September 03, 2012

The Swerve : How the world became modern

I tend to be mid-way through several books at once, I think this worked fine when I read physical books but it's become a problem with using a e-reader. There's no real limit to the number of books I can start and still be able to keep track of where I am, which means I never finish anything!

To try and avoid this problem, I've changed-up my reading style on the e-reader and I'm only reading a single book at a time. Most recently I read "The Swerve: How the World became modern"



I enjoyed this book a lot. I know very little about the early Greek city states or European history, so a lot of content was new and interesting for me. It's well written and easy to read. Unfortunately it doesn't even attempt to answer the question posed in the title "How the world became modern" (Although it does put forward an entertaining thesis). This is a shame because I think it's an interesting question; it seems we were so close to being modern several times in history but we fell short.Such as:

Hero of Alexandria (a city in Egypt named after Alexander the Great), around 30 A.D. invented a steam engine (and automons, vending machines and a whole host of other bits and pieces)
Hero's Steam Engine


The Indus Valley civilisation (in modern day Pakistan) had underground sewers and plumbing in 2700 B.C. London didn't get something similar until 1800s A.D!










Monday, August 27, 2012

Ludum Dare

I participated in my first Ludum Date (a 48 hour game making competition).

The game can be downloaded here: http://t.co/NPsZNvsk
(It has not been widely tested)

The theme was Evolution. I made Darwin: Second Strike, it's a very (very) simple platformer. I made all the graphics ... as you can probably tell :D I used vectors to represent the level geometry and the level itself it was just one big image.

I went for Zombie Darwin back from the grave to pelt unbelievers with his Origin of the Species opus.

I probably spent too much time on the title screen - there's a cool intro animation through :D


I think the key for success in the future is to have a bigger library of code that I can draw on and to have a more featured game engine so I don't waste time adding things like keyboard support :D

Friday, August 24, 2012

August: In review

August seemed to go by pretty fast! And I'm a little disappointed that I didn't get more stuff done!

I started playing with a bit more web-programming and I've got a virtual linux server from linode to experiment with.

When I lived in Japan I kept a simple blog howtojapan.blogspot.com which I update now and again. I enabled adsense ads and it makes a small amount of money each month. I'm sure many people have had this idea but I thought it would be great if I could have fun learning some web development and also create some sites that might also generate some income. After looking at some similar sites I created: http://www.buy-for-life.com/ using wordpress and some themes. It just a collection of products that are well made and should last a lifetime with affiliate links to amazon. I was also playing with one or two other sites but I haven't launched anything else yet. Finally, I also messed around with the Google Checkout API and found it very frustrating eventually getting nowhere :( I will probably try again in the future.

I entered the Ludum Dare challenge and actually created something. While the game wasn't great it was well worth doing I think. I used the old version of my rapid-prototyping engine for this.

The second version of my rapid-prototyping engine hasn't had much love this month. I added a little more code this weekend. It has better support for reloading assets.

Tuesday, August 21, 2012

One Click : The Rise Of Amazon


I finished off this book yesterday (the ebook version), it was quite short but I enjoyed it. Jeff Bezos seems like an interesting guy. He went to a Montessori primary school which I've always thought sounded like a ideal way to teach. Will Wright, creator of Sim City, also attended a Montessori school. (Here's a Wikipedia page on Montessori)

Jeff Bezos' type of lifestyle, at least as it's presented in the book, doesn't appeal to me. It seems too much living to work rather than working to live but I enjoyed the insight. I think to do something world changing like make a company like Amazon - by definition - you can't be 'normal'. Normal people don't start companies, generally, they get a job, a house, married, have kids, watch a lot of TV and retire. One of Jeff Bezos' eccentricities in the book was to apply business methods, not just to his business but to his life - for example a decision flow chart for deciding who date!

Another part that stood out had a quote about hiring, which reminded me of Valve; each person you hire should be better than previous hires and raise the bar. After a few years people who've been working there will think "I'm glad I don't have to apply now - I wouldn't be able to get it!"

I also discovered that he, too, is interested in space exploration which is cool (along with the likes of Richard Gariott, Richard Branson, Elon Musk and probably others). Being a billionaire he set up a company called Blue Origin with the ultimate goal of extra terrestrial colonies. Neal Stephenson author of the System of the World Trilogy, Cryptonomicon (I think a must read if you're from Computer Science background, or a programmer) and fun cyperpunk novel Snow Crash (which was released in 1992 and really did a pretty good job of predicting the next 20 years, and beyond, I think) also worked a Blue Origin for a time. It's not mentioned in the One Click but I thought it was an interesting little fact. Maybe this was partly the inspiration for his recent talk about writing sci-fiction to inspire big engineering project like space colonies. Worth a watch if you've got the time:



If you want to find out more about the Amazon book here, appropriately enough, is the amazon link.



Thursday, August 02, 2012

July in review

I've been playing around with a few side projects last month. I'm trying to rebuild a small game prototyping application I have in a cleaner, more efficient way. The goal is rapid prototyping, easy distribution and to not be intolerably slow. I've submitted the starting steps of this under Git
  1. https://github.com/balaam/1-GameLoop
  2. https://github.com/balaam/2-LuaGameLoop
  3. https://github.com/balaam/3-CGGameLoop
It started to get a little messing when I came to automatically reloading assets (not quite as messy as my current "complete" version though). Anyway half way through this I decided Lua intergration would go a lot smoother with nice a reflection system. I remember working on kjAPI (which unfortunately doesn't seem to be being updated publicly anymore.) there was a cool reflection system, Classes and their properties could be registered and without any additional code you could interact with the object in the game editor. Very cool.

I looked at kjAPI's reflection code at the time but I definitely didn't understand it and didn't take the time to break it apart, so I was a bit of loss how to start. I found some excellent articles by over here: http://altdevblogaday.com/2011/09/25/reflection-in-c-part-1-introduction/ which gave a nice overview. Then I spent some time getting back up to speed with templates and member function pointers and was able to get some proof of concepts up and running.
  1. https://github.com/balaam/CppReflect
I intend to come back to that but in the meantime I've been trying to focus on programming that actually brings in some cash. So my current side project is more profit focused and at the moment involves some very basic natural language processing in Python. I don't think I'll be publishing this code publicly for the time being. One reason being; each time I come back to the code, I rewrite how it works from the ground up. I think this third iteration is here to stay for a while though. It's currently parsing text with a 35%(ish) accuracy and I want to bring that up to 80%. My aim is to complete this asap.

Sunday, July 29, 2012

Installing Twisted Python / Scrapy using Mingw


I kept getting errors about -mno-cygwin, not being defined or deprecate or something using either pip install scrapy or easy_install scrapy. It wasn't particularly easy to find the solution but a stackover post suggested this:
After more some googling, I found guidance that recommended removing -mno-cygwin fromC:\Python27\Lib\distutils\cygwinccompiler.py because of a distutils bug.
Removing -mno-cygwin from C:\Python27\Lib\distutils\cygwinccompiler.py

Which finally worked for me.

Or even better use the excellent prebuilt libraries from here: http://www.lfd.uci.edu/~gohlke/pythonlibs/

Monday, July 23, 2012

Vampire the Maquerade : Bloodlines

I bought this game in the Steam Sale recently after hearing good things about it. I've always loved Trokia's logo, it's so fitting!

Their games always had bugs and design was obviously prized higher than art or code but they were very good - perhaps that's a good trade-off - although perhaps not, as the company did go under (Makes me wonder who gets the money when it's sold on Steam). And that's not to knock their code they were doing advanced stuff and a sprawling RPG is hard to do, especially Trokia types where there are so many different variables - what have you done in the past, what stats do you have, what is your character background etc, etc all these affect the current plot line.

Bloodline's reminds me of Deus Ex a bit, the games have a similar grammar. Locked down 3d areas, skill specialization, computers to hack, doors to lock pick and feuding NPCs. I had to get the community patch to get the HUD textures to stop being a blurry mess and I still ran into a bug where a location was supposed to open up but didn't.

The really pain of having a bug in games like this is the you're not sure if you're just stuck or the game has broken. That means you either waste time to ultimately discover you have to restart or hack your way out of the bug or you check online and ending spoiling part of the game.

The writing is very good, the characters have distinct voices and interesting personalities which isn't the case in a lot of games. A lot of the interface has obviously been thrown together with little thought. Sometimes escape removes hud items, sometimes it takes you to the main menu. Where on a Windows OS you'd expect the OK button to be is the delete save game button! Also if you get trapped in the physics collision sound effects are continually fired off - this is a really easy bug to fix and it's hard to understand why it wasn't (even with deadline pressure, it's the kind of thing that would take a couple of minutes and could be done while thinking about how to tackle something more serious. This article goes someway to answering that I guess.)

One of my pet projects is a type of quest designer or adventure game designer where everything is spelt out as a dependency - basically a mini-version of Prolog with a nicer interface. Then the tree of possible options can just be brute-forced (or something more clever if I can think of it) and that will guarantee there can be no broken quests.

Saturday, July 21, 2012

Git / GitHub Cheat Sheet

This mainly for my reference!

Checkout a repo from GitHub
git clone git@github.com:[username]/[project name].git
 
Add single file 
git add [FILENAME] 
Add everything and all sub dirs  
git add .
Also wild characters
git add *.c

Locally commit the files / staging 
git commit -m "commit message goes here" 
 
Commit back to github
git push origin master 

Get the latest changes from github
git pull
 
Forking your own git project
- Make a new project (don't auto generate a readme)
- Clone it locally
- Navigate to the dir and 
git remote add upstream https://github.com/[repo name]/[Project want to clone] 
git fetch upstream




Monday, July 02, 2012

Git Repo

I registered for Github a while back but only recently started using it. I'm still getting use to Git and I'm still quite new but I've been slowly adding the code for a little Lua based game engine. I guess it's similar to Love2d but in a way I prefer to program, better code reloading and I'll probably add some 3d stuff. My main sticking point is choosing a 3d file format.

https://github.com/balaam

This codebase is mainly for quickly prototyping games and it should run on everything. If that game's fast enough then that's cool. There's only a game loop at the moment.

This is a good getting started post: http://ryanlowdermilk.com/2012/01/the-quickest-and-easiest-getting-started-w-github-article-youll-ever-read/

Monday, June 18, 2012

Game Loop and Frame Capping

This is probably something I should have known to do - but for all my C++ code I've never capped the frame rate of my gameloop. Oh I've thrown the odd Sleep(0) or Sleep(1) in there but it's never really done anything.

My applications use 100% of the CPU and eat up as many of the cycles as they can. Windows shows 25% CPU use for my programs - due to it be a quad core underneath. Also it invariably causes the fan to spin up - either on my CPU or the graphics card and I hate that! Really hate it. I'd take silence over power everytime I think.

In SDL it's easy enough to cap the game loop to a certain no of frames per second and not overheat  the GPU / CPU.

As it turns out the SDL_Delay on Win32 is just a call to Sleep which is included with windows.h

void SDL_Delay(Uint32 ms)
{
    Sleep(ms)
}

In the game loop I use it like this.

unsigned int fpsTicks = 0;

while(mRunning)
{
    fpsTicks = SDL_GetTicks();
    UpdateInput();
    Update();
    Render();

    fpsTicks = SDL_GetTicks() - fpsTicks;

    if (fpsTicks < 1000 / frames_per_second)
    {
        SDL_Delay((1000 / frames_per_second) - fpsTicks);
    }

    SDL_GL_SwapBuffers();
}

On most Windows systems SDL_GetTicks() is defined:

Uint32 SDL_GetTicks(void)
{
    LARGE_INTEGER hires_now;

    QueryPerformanceCounter(&hires_now);

    hires_now.QuadPart -= hires_start_ticks.QuadPart;
    hires_now.QuadPart *= 1000;
    hires_now.QuadPart /= hires_ticks_per_second.QuadPart;

    return (DWORD)hires_now.QuadPart;
}

Both LARGE_INTEGER and QueryPerformanceCounter come from windows.h
They're in SDL_systimer.c if you fancy a look.

Wednesday, June 13, 2012

Mongoose - you may not know it yet but your game really needs an embedded Http server!

Mongoose a tiny embeddable Http server made from only a single .h and .c  file. How awesome is that?


Very awesome! And it leads me to something I've wanted to implement for a while now. I like Lua as a programming language it's great, it's basically Scheme with a C-style interface, it's really easy to embed and is a on it's way to becoming the lingua franca scripting language of the game industry.

For my projects I usually embed Lua in some OpenGL graphics engine. The game runs the Lua scripts and displays the nice graphics. I edit Lua scripts using Sublime Text 2, a really slick text editor. (I hope that screencast shows Ctrl-D and the alt-shift-downkey shortcuts because they are Sublime Text's winning feature for me).

When I make my projects I usually use a little trick to make development go a little more smoothly. If you press a certain key - I use F2 - the project resets it's internal state and reloads it's Lua script. So you don't need to restart the program - no compile times or anything like that. You just edit the script, press F2 and almost instantaneously your new code is running. This is a feature I really missed from Love2d when I played with it (so if your listening Love2d contributors please add this feature :)).

But that's not good enough! We can do better!


The current development process goes like this:
  1. Boot project
  2. Move focus to sublime text
  3. Edit Lua
  4. Move focus to project
  5. Press F2
  6. If there's an error go back to sublime text
  7. Play game and see what needs to be done next

And this brings me to how I'd like to improve this work flow. I want to be able to reload my script files in my project from Sublime Text. On one screen I could be hacking away and on the other screen have my project running. I hit F2 and glance at the project screen - it says there's an error - so I find it, fix it up and continue hacking away. Much more streamline! The project could even be running on a totally separate computer!


I've been toying with this for a bit, initially I was using sockets and also looking a enet but I wanted something cross-platform, more highlevel and easy to use from the Sublime-side. This is where Mongoose comes in - I can simply add a small HttpServer to my project. Sublime Text 2 uses python as an extension language and it's easy to send Http requests from python, including postdata.

Once this basic system is in place it could be extended in a number of interesting ways:
  • Send over selected code to be updated on the fly. Like single functions or globals.
  • If there's an error have the project send the line number back to sublime and have it jump there.
  • Have a webpage where I can see the _G table
  • Have some ajax where I can modify the values in the _G table
I'm not there yet but it's something I've found myself playing around with. Here's my current version of the Mongoose server. To get it to build under mingw I had to add

#define _strtoi64(a,b,c) strtoll(a,b,c)

to the header file. I'm far more comfortable in an IDE so it always takes me far to long to work out the correct way to build this type of stuff in mingw. Here's the build command I use to g++ to embed it. (There are loads of warnings mainly due to C / C++ differences)

g++ -W -Wall -mthreads -I../lib/mongoose/ -DNDEBUG -Os ../lib/mongoose/mongoose.c httpserver.cpp main.cpp -lws2_32 -ladvapi32 -fpermissive -Wunused-parameter -static-libgcc -static-libstdc++ -o servern.exe

Here's the server code .h file. As usual moving my code to Blogger has upset the indentation :(

#ifndef HTTPSERVER_H
#define HTTPSERVER_H

#include 
#include 
struct mg_context;
struct mg_request_info;
enum mg_event;

struct HttpRequest
{
 std::string mURI;
 std::string mPostData;
};

//
// Creates a HttpServer to listen on a port for incoming requests.
// If there's a request pending PopRequest will return true and fill in the HttpRequest struct.
//
class HttpServer
{
private:
 mg_context* mContext;
 std::queue mMsgQueue;
 static void* callback(enum mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info); 
public:

 bool PopRequest(HttpRequest& request);

 HttpServer(int port);
 ~HttpServer();
};

#endif
Pretty simple and here's the .cpp actual implementation.
#include 
#include 
#include 
#include 
#include "HttpServer.h"
#include 

static void* HttpServer::callback(enum mg_event event,
                      struct mg_connection *conn,
                      const struct mg_request_info *request_info) 
{
 printf("Callback\n");

 if (event == MG_NEW_REQUEST) 
 {
  char content[1024];
  int content_length = snprintf(content, sizeof(content),
                                "Hello from servern! Remote port: %d",
                                request_info->remote_port);

  assert(request_info->user_data);
  HttpServer* server = static_cast(request_info->user_data);
  const char* cl = mg_get_header(conn, "Content-Length");

  if(!strcmp(request_info->request_method, "POST")
   && cl != NULL)
  {
   // handle post data
   size_t buf_len = atoi(cl);
   char* buffer = (char*) malloc(buf_len+1);
   mg_read(conn, buffer, buf_len); 
buffer[buf_len] = '\0';
   HttpRequest request;
   request.mURI = request_info->uri;
   request.mPostData = buffer;
   // Lock stack while a write is done
   server->mMsgQueue.push(request);
   free(buffer);
  }

  mg_printf(conn,
            "HTTP/1.1 200 OK\r\n"
            "Content-Type: text/plain\r\n"
            "Content-Length: %d\r\n"        // Always set Content-Length
            "\r\n"
            "%s",
            content_length, content);
  // Mark as processed
  return (void*)"";
 } 
 else 
 {
  return NULL;
 }
}

bool HttpServer::PopRequest(HttpRequest& request)
{
 if(mMsgQueue.empty())
 {
  return false;
 }

 // Copy data request.
 // 1. Simple  - one pop operation instead of a peek and pop
 //        or passing over memory management
 // 2. This is going to be used for developement with low / throughput. 
 //   If this changes then this should also change.
 request = mMsgQueue.front();
 mMsgQueue.pop();
 return true;
}

HttpServer::HttpServer(int port)
{
 const char *options[] = {"listening_ports", "8080", NULL};
 mContext = mg_start(&HttpServer::callback, this, options);
}


HttpServer::~HttpServer()
{
 mg_stop(mContext);
}

I found the Mongoose docs to be a bit lacking but I think the static callback function maybe being called from a different thread and if that's the case there needs to be a lock around the access to the queue. Everything else should be pretty straightforward I think. It's been a while since I've used C++ so if there's any glaringly wrong here, please let me know!

The use case is very simple - check if it has a message, if it does, then do something with it. There's no RESTful interface stuff here! But it wouldn't be hard to build in.

Here's my main loop.

HttpRequest request;
HttpServer httpServer(8080);

while(true)
{
 if(httpServer.PopRequest(request))
 {
  printf("Request made:%s\n", request.mPostData.c_str());
 }
}

To test the postdata I use a small python program.

import urllib
import httplib2
import sys

if len(sys.argv) != 2:
    print "Please enter message"
    raise SystemExit

msg = sys.argv[1]

username = "user"
password = "pass"

http = httplib2.Http()
#http.add_credentials(username, password)

response = None
try:
 response = http.request(
     "http://127.0.0.1:8080", 
     "POST", 
     urllib.urlencode({"status": msg})
 )
except:
    print "Unexpected error:", sys.exc_info()[0]


I'm not too far away from getting this all together, it's been pretty fun so far and will hopefully make my development process faster. I suffer strongly from the Babbage curse and I'm really feeling some pressure to release a game instead of constantly working on little bits of random projects! :D

It seems Sublime Text 2 doesn't use the standard installed Python, instead it has it's own local copy of python 2.6. This python doesn't have httplib2 but it does have httplib which is near enough. Creating a plugin is pretty simple in Sublime Text - just create a .py file in your user folder:

C:\Users\MyUsername\AppData\Roaming\Sublime Text 2\Packages\User

Whatever you call that .py file will be how you refer to it later, to call it. I called this one "reload" for now. Here's the plugin code. I've hacked this together quickly it could be prettier.

import sublime
import sublime_plugin
import urllib
import httplib
import sys

print('plugin loaded')


class Reload(sublime_plugin.TextCommand):
 def run(self, edit):
  try:
   msg = "reload"
   host = "127.0.0.1:8080"
   http = httplib.HTTPConnection(host)
   # additional path goes below like /reload/
   http.putrequest("POST", "/")
   http.putheader("content-length", str(len(msg)))
   http.endheaders()

   http.send(msg)
   response = http.getresponse()
   print self.view.file_name(), "Reload command sent."
  except:
   print self.view.file_name(), "Reload failed. %s" % sys.exc_info()[0]

In the Sublime menu select View→Show Console. Then in the console you can type "view.run_command('reload')" and that will run it. But a key shortcut would be better. In the menu select Preferences→Key Bindings (User) and add the following shortcut:

[
 { "keys": ["f2"], "command": "reload" }
]

Now when you press F2 you'll send a message to your server!

Monday, May 28, 2012

Some quick notes on running Cg on OpenGL under MingW

This is more a post for my own reference.

The Cg library and include files are installed here:
C:\Program Files (x86)\NVIDIA Corporation\Cg\lib

For MingW they should be copied here:
C:\MinGW\lib
C:\MinGW\include

Then they can be referred to when building like so:
g++ -Wall main.cpp -o OpenGLFake  -lopengl32 -lcg -lcgGL

And referenced in the code:
#include "Cg/Cg.h"
#include "Cg/cgGL.h"

These should be angle brackets above but blogger really can't handle escaping them so I can't use that character!
CGprofile cgFragmentProfile;
CGprogram cgVertexShader;
CGprogram cgFragmentShader;
Here's a quick print error function, to find out why your shader doesn't compile :D

void printCGError(CGcontext cgContext)
{
    CGerror err = cgGetError();
    printf("Error:%s\n", cgGetErrorString(err));
    printf("\n%s", cgGetLastListing(cgContext));
} 


Friday, May 18, 2012

The trick to reading in text files (or any file) using PlayStation Suite

If you've attempted to use System.IO.File or similar to read a file into your PlayStation Suite project - you may have found it doesn't work very well. It turns out to be quite hard to get the currently executing directory and even then I'm not sure how well that method would work once it's packaged to run on a phone or Vita.

I did a little searching and found this blog post (it's in Japanese) but he uses GetManifestResourceStream from the Assembly class to get access to embedded files.

First off you need to add your file, I'm using a json file called overworld.json it's in my directory structure like so:


Then you need to make the file into an "Embedded Resource"




We are now ready to go!

You can reference the file starting with the the default namespace name. My project is called "Overworld" and that's my default namespace. I reference my overworld file using this string:

"Overworld.data.overworld.json"

There aren't any slashes to denote directories instead you use dots (I don't know why :D I mean generally dots are better because you don't have forward and backward dots but it seems a bit late in the date to be adding some new syntax!)

Here's the code that I've copied from the previous blog then sloppily hacked into an example that works for me. This is in my Initialise function just after the graphics context is created  but I really don't think it matters where you do this.

System.Reflection.Assembly myAssembly = System.Reflection.Assembly.GetExecutingAssembly();


var resourceStream = myAssembly.GetManifestResourceStream("Overworld.data.overworld.json");

System.IO.StreamReader IN = new System.IO.StreamReader(
    resourceStream, 
    System.Text.Encoding.GetEncoding("utf-8")); 

var scenario = IN.ReadToEnd();

IN.Close ();

System.Console.WriteLine(scenario);


The most important part is the path to the resource "Overworld.data.overworld.json"

And with that you should be able to load any files you want! I haven't tried this out on actual hardware yet so I'd be very interested to hear how that went if anyone wants to try it.

Monday, April 23, 2012

Interesting Snippet from the Value New Employee Handbook


Engineers: code is only the beginning 

If you were hired as a software engineer, you’re now surrounded by a multidisciplinary group of experts in all kinds of fields—creative, legal, financial, even psychological. Many of these people are probably sitting in the same room as you every day, so the opportunities for learning are huge.Take advantage of this fact whenever possible: the more you can learn about the mechanics, vocabulary, and analysis within other disciplines, the more valuable you become.


Non-Engineers: program or be programmed

Valve’s core competency is making software. Obviously different disciplines are part of making our products, but  we’re still an engineering-centric company. That’s because the core of the software-building process is engineering. As in, writing code. If your expertise is not in writing code, then every bit of energy you put into understanding the code-writing part of making software is to your (and Valve’s) benefit. You don’t need to become an engineer, and there’s nothing that says an engineer is more valuable than you. But broadening your awareness in a highly technical direction is never a bad thing. It’ll either increase the quality or quantity of bits you can put “into boxes,” which means affecting customers more, which means you’re valuable

On Hiring

Hiring well is the most important thing in the universe.Nothing else comes close. It’s more important than breath-ing. So when you’re working on hiring—participating inan interview loop or innovating in the general area of recruiting—everything else you could be doing is stupid and should be ignored!


•Would I want this person to be my boss?
•Would I learn a significant amount from him or her?
•What if this person went to work for our competition? (there are definitely a few times where I'd see it as a boon to see someone go to the competition!)

Valuable employees

We value “T-shaped” people.  That is, people who are both generalists (highly skilled at a broad set of valuable things—the top of the T) and alsoexperts (among the best in their field within a narrow disci-pline—the vertical leg of the T).

I think it's definitely beneficial to ask yourself - what is your expertise?

Friday, April 20, 2012

Final Lundum Dare Categories

Ludum Dare is a game jam competition - try to make a game in 48 hours. It's happening this weekend. I want to take place but I don't think I'll be able to this weekend. But the categories are great for generating ideas on there own.

Alchemy
Alternate Reality
Artificial Life
Build It, Then Use It
Castles
Castles In The Sky
Death Is A New Beginning
Discovery
Evolution
Exploration
Explore The Universe
Growth
Indirect Control
Limited Resources
Minimalism
One Room
Parallel Universes
Randomly Generated
Survival
Tiny World

These are final categories and one will be the theme for this weekend. If you're interested here's the link.

Thursday, April 19, 2012

PlayStation Suite SDK

The PlayStation Development Suite has put into open beta today. There's a link here: http://www.playstation.com/pss/

You may be asking "What is the PlayStation Development Suite" well it's C# based API for writing games, fast games. If you read this site that could be something of interest to you!

It lets you publish to PlayStation Vita and PlayStation Endorsed Android Devices. The API (from my quick look) seems pretty good - low level vertex buffer access and shaders - as well as a high level sprite engine.

So if you ever wanted to make a game and perhaps release it for sale - this might be worth a look!

I'm playing with it now and I may post again in the future about how I'm finding it! (Also the documentation is really quite good!)

I've made a linkedin group here.

Monday, April 09, 2012

Adventure Game Musings: Yesterday

I saw Jane Jenson's Kickstarter and after reading it decided I'd quite like to play her most recently finished game - Grey Matter. Unfortunately it wasn't on Steam so I bought "Yesterday" instead, another point and click adventure game. 

The art style and sound in Yesterday are pretty good and most of the puzzles are logical but there was one that slightly irked me. It seems like a bad design decision that could have easily been corrected. Don't read on if you don't want spoilers.



At one point in the game you're in a mountain retreat and you have to "Retrieve a truth flower", at least that's why you're told to do, what you actually have to do is ring a bell but that's not my gripe. There are about four rooms and plenty of things to interact with. In one rooms there's a monk, your master, and you among various conversation options you can choose "Let's play a game".

Let's play a game opens a menu and prompts you to choose how many fingers to hold out, you then choose a number. Once you've done that, the monk guesses a number and holds out some fingers. If the monk gets the total number of fingers held out correctly he says you owe him a glass of water. I played for a bit and didn't beat the monk and didn't really think anything of it. 

A little later I was stuck, as far I was concerned I had to do something to get a truth flower but I didn't really see any way forward to do that. There's a hint button in the game and that led me to use a sword on a window next to the monk to open the window. The hint was "Maybe you need more light". Still I wasn't quite why I would have wanted that. It turns out when you go to "Play game" with monk, you can see the shadow of the monks fingers from behind his back and use that to guess the correct number of total fingers.

Still I'm not sure why I'd want to win this game with the monk. But I do it and at the end he says I can choose one of the his treasures. One of the treasures turns out to be screws.

That wasn't a good puzzle - I didn't know why I was doing the things I did, I had no plan, no idea of the outcome! 

It could have been fixed pretty easily. In front of the monk he could have laid out his three treasures. If the player tried to get one, then the monk could have said "Beat me in the game and you can have it". Suddenly it would have made sense to try and beat monk.

I think the general lesson is always consider the point of view of the player, without any foreknowledge would he think to do this action if he stumble on the correct chain of deduction? This fails that test.

Thursday, March 22, 2012

My very brief overview of developing for Android


Hello! Recently I was looking at developing for Android and I thought it might to helpful to share my experiences. It's a show down of Corona vs Unity vs Coco2s-x vs Adobe Air.

I had my mobile game idea and I prototyped it in Love2d in an afternoon. Love2d is a pretty good little 2d engine with a lua scripting layer. Then I wanted to port it to android add some webservices and stuff, maybe some in app transactions. My aims were / are rapid development and publishing.

I'm on a Galaxy S phone.

Corona

This is the first middleware I tried, I picked it because it was also using Lua.

The bads
  • 400ish dollars a year
  • You send your code to their servers to compile!
  • Documentation is out of date
  • The company goes down - your code is useless
  • The servers go down - you can't compile or publish
  • Debugging is poor
  • The emulator doesn't act the same actual hardware :(
  • Poor choice of memory model for Lua means really easy memory leaks. This probably due to being overly influenced by flash. 
  • (No 3d - but I don't really care about this!)
The Goods
  • Lua!
  • I ported my game in an afternoon
  • Lots of features
  • Cross platform
  • Regularly updated
  • Reasonably active community
  • Simple and easy to iterate with the emulator.
  • Easy to publish.
Why I gave up

My (very very simple) program worked fine in the emulator but after 3 play throughs of my game on the device it started to get visual artifacts.

No idea how to debug this issue and I suspect it was below my lua-code in the big scene graph that is Corona's rendering engine. I checked I had no memory leaks - which I didn't so not really sure how to solve it. I couldn't find a work around and I didn't want to waste time creating a nice error case app for the developers - I don't have the time to do it, it's a very simple program and if I'm having trouble here I know I'll have trouble with bigger projects.

Unity

At the time of testing Unity were giving out free mobile licenses so I thought - sure why not! I don't think I gave it a good shake though.

The bads
  • No easy 2d
  • Setting up a 2d scene in Unity's visual editor is tedious
  • To much exploring menus and not enough getting things done
The goods
  • It's Unity - visual editor, nice languages, massive community
  • Very visual, you can see in real time how your scene exists
I gave up after my 2d button was scaling it's width and height on the x and z axis. My canvas axis were also incorrect and I couldn't be bother to fix it by manually rotating things around. Too much setup faff. I also felt pretty confident the later stuff I'd want (in app purchases) would require an expensive license.

Coco2ds-x

Next up - a library that runs on the Android using the Native Development Kit (NDK). This a little more to the bones.

The bads
  • Eclipse, I heard it had become better in the last 10 years but it's still terrible. An IDE abomination; everyone involved with  Eclipse should feel a deep personal shame, you're actively making the world a worst place. (see this blog post from 2007 "Is it me or is Eclipse a piece of shit?" and the many comments still coming in to this day, each with their own separate horror story)
  • Cygwin, gbd, logcat, you all suck
    • I'm a games developer 80% of us, use Visual C++ don't throw us back into this 80s unix terminal world!
    • The Unix world of "Oh you want to do A? Well first you need to do B?", "Oh you want to do B? Well first you need to do C!", "Oh you want to do C? Well first you need to recompile D which won't work for your system so you'll need to do E but E requires tool G, sorry that's tool G version 1.323 you have G 1.34. Yes G can only be built from source, yes you'll need dependencies F.1 to F.6d to build it." And so on until you want to smash something. 
    • I had to root my phone because Samsung put a file in a different place than is standard
      • It was incredibly hard to find that this was the source of my problems
    • Did I mention Eclipse?
    • The common suggestion is use Linux or a virtual machine running Ubuntu. I tried Ubuntu, I tried cygwin they both but it's stepping into a entire development ecosystem I don't know (it's something I should learn though).
  • None of this is actually about Coco2ds-x yet let's start
    • Poor documentation - 5 or 6 vastly different quickstart pages linked from the wiki, none of which work
    • Many, many makefiles, script and templates and general cruft
    • The Hello World app works but the source files never seem to be in my eclipse project
    • There's a Lua project ... but printing out _G hard crashes my phone
    • It's C++ so build times suck (Actually it's worse it's a C++ with a Java bridge)
    • It's a Chinese project - which is cool but the forum support sometimes seems more like a riddle than actually help.
The goods
  • Close to the metal so easy to add extra libraries
  • Fast (probably)
  • Games have been made in it

I made a button appear on screen with the Lua project but printing out the _G would hard crash my phone and I couldn't get it to go in portrait mode. The best  I could do was get a portrait screen in the middle of landscape layout - very squashed. 

Adobe Air

This is where I am now.

The bads
  • It's Flash, so actionscript, why did you look at C++ and think "Me too"!
    • Hex values for colours? What were you thinking here? Wasn't flash aimed at non-programmers?
  • The whole touch interface doesn't really work as advertised for my phone
  • The convert mouse to touch doesn't seem to work at all for the emulator.
The goods
  • Flashdevelop is a one click install that lets you immediately develop on the phone
  • It has an emulator
  • It's easy to launch to the device (though I've yet to get remote debugging working)
  • Code complete, break points all those good modern IDE features
  • Cross platform
So it's looking like Flash is winning at the moment. Though I haven't ported in a day because I'm finding Flash a bit unfamiliar I thought it was untyped and garbage collected and maybe it was once but it seems to be one of the languages that's had a million and one things bolted on. I haven't taken the time to understand it's scene graph so I'm just kind of winging it and hoping I'm not memory leaking to hell or doing very inefficent things. 

Conclusion

Flash wins - if you want to make a game today download FlashDevelop. I'm not Flash's biggest fan but it seems the best way to do Android development. 

Secretly I think the very best way to do Android development is this 3 step process.
  1. Buy a Mac
  2. Write a game using Coco2d
  3. If the game does well, pay someone else to port it to Android.
Job done.

Friday, March 02, 2012

Video Chat about Making Adventure Games Ron Gilbert - Monkey Island, Indiana Jones and the Last Crusade


Did I say "fraud" I meant "opportunity"
Here's some random notes:

  What are the most common problems adventure games have?

  •  Given the key before you see the locked door.
  •  Completely ridiculous solutions that would have only come through trial and error. 
  • A solution the inventor hasn't thought of, or a perfectly legitimate reordering of steps that isn't accepted.
  •  Testing is important. 
  • What I learnt on Monkey Island was more than three lines of dialog is a bad idea. 


Why did adventure game die?

I don't think they died. I think they're just as popular as they ever were but other games have over taken them in popularity.

Is it that modern gamers don't have the patient for adventure games? When I play adventure games it's about quiet contemplation. I think a lot of the puzzle solving for adventure games happens when you're not at the computer.

 In most development environments it's not considered okay to be stuck in a game.

The internet is an always available hint book - does that take some of the enjoyment out of the game. (Dan: I think so) Adventure games have purposeful backtracking. It's a fine line between frustrating confusion and entertaining confusion.

  What makes adventure games good?

 There's more than one puzzle that you can work on at any one time. That way you're not totally stuck and have other puzzles to work on.

As you progress and go to new puzzles previous people you've met should have updated dialog with more hints for the current situation.

Screen writers from Hollywood don't transition into games well. There's a real trick to writing interactive dialog - it's not writing cutscenes. The dialog in Monkey are the good - you're really interacting with these people. You feel like you're have a conversation. When we put up four lines for Guybrush that was an opportunity to put up four jokes that the user could read at once. People who write dialog should be programmers - or at least have programmed. So they know how to wire it up.

Think about the character and the puzzle and story at the same time. Part of really good design is being able to quickly iterate. The ability to go in and change things and see the changes.

 Full Throttle has 20 main puzzles. For Grim Fandango aimed for 40. Monkey Island budget was $130,000.


What's you favourite puzzle?

 It's the grog puzzles where you have to transfer the grog from cup to cup before it's melts the container.

  On thing I would never do in an adventure game. Pixel hunting. Just waving the cursor from top to bottom of the screen for a 4x4 pixel area.

Dan : A lot of the talk centers on Limbo which means I should check it out!