Sunday 25 January 2015

Making a Game in a Weekend with MonoGame.

Early last week, I was chatting to a close friend of mine - (Dean Ellis) about Game development and we discussed the possibility of participating in a weekend GameJam. Dean and I having written games in the past, but never together (or at least those shared ventures were never completed).

We had no theme, we had no plan. Just come over to my house on Friday evening with your laptop and let's make a game.

Dean arrived around 6pm with his 8yr old Son in tow. Laptop at the ready and it was clear early on that we were going to need supplies for this adventure. We were going to need beer! Lots of Beer... and snacks.

After cleaning the local shop almost out of junk food and beer, we set to the hard task of deciding what to build - and who was going to do what.

Who does what?
It is an important step in any team to decide what role each of you is to play and to stick with it. Otherwise chaos ensues. We decided to step a little out of our comfort zones with this. We'd use a platform I wasn't familiar with and Dean would provide the artwork (normally my role).

The platform we decided on was Monogame. For those who may not know, Monogame is the opensource cross platform implementation of the Microsoft XNA framework (now sadly discontinued by the big M - but lives on with an incedibly strong community thanks in no small part to Monogame, especially with it's cross platform capability (more on that later).

I'm used to using the MOAI framework, but if there were any parallels - It shouldn't be too hard.

The language of choice would be C#. I'm familiar with C# - Many years of and Windows Mobile development have given me those skills, however I will admit a little rust, what better way to polish my metal than with an intensive game development session?. 

Dean on the other hand works at Xamarin and is a C# guru - which is handy when said polishing was needed. Thanks Dean :-)

Dean was in charge of Art. He wasn't to take an active role in coding, Instead, he'd be providing a suit of assets needed for the game. His tool chain was Inkscape, Textturepacker and Spine.

To help out and save time however, Dean did provide a library and example class to handle the Spine animation.

So began the evening. We ordered a curry from my local Indian and began the brainstorming process.

We'd need a game we could handle in the weekend - preferably something we could get to "first light"* in the evening.

*First light is the point when you first see something on screen resembling the thing you're trying to make - it's the first piece of visual progress after what can seem like an eternity of coding. It may be as rough as a bears back end, but it's a thing of beauty.

We decided on an endless runner - similar to Canabalt - in which you play a Kangaroo named ROO! (upper case deliberate, and pronounced in a death metal voice). The story being a parody on the old Skippy the bush kangaroo TV show from the 1960's - in which little Timmy has fallen down the well (again) and ROO must race across the outback to inform ranger Bruce - Crikey!

A very simple story, simple game play requiring a single key-press, button or screen touch. Hold down the control to increase the jump height up to a maximum and clear any obstacles.

The curry arrived, we had our idea - it was time to load up with Curry Power and get to work.

Installing Tools
I installed Xamarin Studio and the Monogame framework. Dean created a Git repo on BitBucket so we could collaborate effectively. I used SourceTree by Atlassian as my Git manager - Dean used the command line.  

It was time to create the project. Thankfully Dean had access to a project template for Xamarin to create Monogame projects. That was easy.

Now faced with a blank canvas - no game, no menu system, just an empty XNA game class.

...and we're off!
It was now around 9pm - Installing tools and setting up environments had taken it's toll.
So the first thing we were going to need was a Kangaroo. Dean set about drawing a Kangaroo which he could then break into pieces and animate using Spine.

He built a skeleton for the marsupial and made a decent hop animation.

In the meantime, I created a state stack to allow us to have different game screens. e.g. a Splash Screen and Menu as well as a gameplay screen. This would allow us to separate the game code out into other classes as we needed to and have the main game code control them as if they were the main game code.

This meant creating an object oriented structure of game objects which catered for everything, states which inherited from game objects, an animated sprite class which would handle the spine animation and a level manager to provide the endless running level... which at this time I had no idea how to accomplish.

I had an idea, an endless runner doesn't care about what was past and what's to come, only what is now. This meant that we could have a queue of only the details needed to display the map queuing and de-queuing items as the player moved through it. 
The levels would be random so there would be no level data to store, only a set of rules which would govern the pieces to place in front of the player as they progressed.

By 2am, we had a level being rendered and an animated ROO! 5 Hours of coding and several beers had brought us to first light. We could see where we needed to go from this point on.

The next morning,
I cooked a breakfast of bratwursts, bacon, eggs and beans - we were going to need the energy. We had a lot to do. The game ran in a demonstration capacity, but there was no gameplay and no level.

So after breakfast we continued. Dean created death animations for the kangaroo and I set about implementing a collision detection system against the level. Normally, collision detection is done against objects with position and size within a level. These items are normally loaded and are generally treated as real things according to the game engine. This game had no physical objects created within the game world. Objects would exist for at most a few seconds before being deleted. This meant that we needed to make sure that the objects were as simple as possible. To that end, I created a class which held the texture names for 4 rows and a height to position the entire column on the screen in relation to the rest of the level. This meant that we could draw challenging levels, but there was no level geometry to test. However as the data was predictable, it did mean that we could perform bounds tests on rectangles which were near to the kangaroo. We'd generate the bounding rectangles for each of the levels near-by tiles on the fly, but it would be fast enough.

I progressed on making the kangaroo collide with the level accurately, ensuring that he stayed on the top of the level's terrain. I've feel so spoiled lately using Box2d to handle all of this stuff properly for me.

As Dean made more animations, I put them into the game. ROO can trip on rocks, faceplant, hit sheer cliffs or even just run into a wall - each needed their own animation. Thanks to Spine, Dean was able to build all of them.

At lunchtime, we took a break and went to the local pub - for a post morning debrief and to gather our thoughts on the remaining work.

And with that in mind, we played the Artemis Bridge Simulator for an hour - Awesome game.

After Lunch
This was mostly putting things into place. Animations, Jumping and the all important Level generation.

With Dean busy tweaking animations, drawing backgrounds and recording some initial game audio, I had to figure out how to make a responsive jump action. In endless runners, the player has to judge how high to make the player jump. He has a maximum height beyond which, he'll fall to the ground. The player must feel like they are in control of the character at all times and that any failure in the game is entirely the fault of the player. This is how addictive gameplay is born. If you make the game feel unresponsive, the player will blame the game and will not become as engaged. Making the player feel completely in control adds to the immersion and therefore into the addictiveness of the game. 

To do this, I'd need to know whether it was possible for ROO to jump. If so, then he'd pay attention to the jump command. However, as soon as the command was halted, he'd ignore any further requests to jump until he was eligible to jump once more - basically, when he was on the ground and hadn't hit anything.

Another decision I made was to place all of ROO's jump logic before anything else in the update methods. So you'd always get to jump. It may not seem like much, but if the update loop runs every 60th of a second, that means that there's an entire 60th of a second where you may have pressed the jump button - but if the level is allowed to move before you've had your command registered, you could hit something instead. The player has to come first, so the controls need to be processed first.

ROO is very responsive.

The day wore on and we made more and more progress on the game and consumed quite a lot of tea. The animations improved, Dean worked hard on the tile set and ROO himself to make gaps in the sprite from being shown. He also built clouds and mountains to act as parallax  backgrounds to add depth.

I wrestled with the level generator - I'd made an assumption about the peek method of the queue in that it would give me the first element in the queue, in fact it gave the element about to be dequeued. On retrospect, it was sensible, however I really wanted the most recent addition to the queue. Afterwards the level generation was working great.

By about midnight, we'd got the game running nicely.

The Next Day
So very tired. Dean and Myself were pulling from resources we didn't know we had. Late nights, beer and game development does not make for happy mornings. Still, we got on with the work of polishing the game. We only had a few hours to make a difference, Dean would have to leave in a few hours so we'd have to make the most of it.

I recorded some additional sounds for Roo while Dean made more animations - basically ROO would be able to run at two faster speeds to keep up with the ever increasing level speed. This coupled with shouts from Timmy in the well to boost ROO's resolve added to the atmosphere. I used BFXR to make simple bounding and jumping sounds while recording the voice of Dean's son for the voice of Timmy.

I altered the generation code to make the later levels harder while in the meantime, Dean took a hiatus from the pure graphical side and worked on the high score table. He'd held out for 2 days without coding anything, an amazing feat.

He also worked on the additional build targets so that the game would compile on other platforms.

By the end of the day. Dean had iOS, OSx, OUYA, Android and Windows via OpenGL and DirectX working. With a little luck the Android version would be relatively simple to put onto the market.

Testing on a few different android devices revealed some graphical bugs which were quickly resolved.

I worked on the music for the game. I only had a couple of hours to spend, so I used a tried and trusted tool Mixcraft. Mixcraft has a vast library of samples as well as virtual instruments to call upon. So I made a piece of music which became more intense as time went on. I feel it complements the mood. But then I wrote it.

So in the end,
We have a completed game with a failure state, sound effects, music and animation. It's fun, addictive and accessible.

It took us about 20 hours from nothing to game.
The tools we used were:

Xamarin Studio
Source Tree

No comments:

Post a Comment