Wednesday, 4 August 2010

Indie Flash Games 101

My buddy Adam, who has just started teaching interactive media at university in Denmark, emailed me some questions about how to get his students started with publishing their own indie Flash games. These days I can't write anything without making it into a blog post, so here's my getting started guide:

What technical issues should students be aware of?
- You need both a copy of Flash Professional (CS3, 4, or 5) AND a code editor. If you are on Windows download FlashDevelop - it's free. Otherwise try FDT, InteliJ IDEa or FlashBuilder, which all have free/cheap options for students/beginners.
- Use ActionScript3, Flash player 9 or 10.
-If you are confident with programming and want to make more advanced games in a short space of time, consider using Flixel or Box2D.
- Filesize should be less than 8MB
- Dimensions should be width: 400-720 pixels, height: 300-600 pixels.
- Game should be a single self-contained swf file.

What are the top sites to submit a game to, and how can they judge how good their game is?
- Kongregate - Signs of success: score 2.8 or higher on the user rating, get more than 500 plays, get some positive comments. Kongregate audience are very particular and are much more forgiving to long form fantasy RPG type games than other genres. Expect mini-games to get a roasting / be ignored. Getting featured on the front page or winning any weekly contests very unlikely for a beginner. Game can include Mochiads, which Kong will automatically disable, and instead give you nice share of their ad revenue.
- Newgrounds - Signs of success: score 3.2 or higher on the user rating, get more than 1000 plays, get some positive comments. Newground audience are lovable scamps with an open mind about any type of game. Front page feature unlikely but getting featured on any page or finishing in the daily/weekly top games is something to aim for. Game can include Mochiads.
- FlashGameLicense - in the current FGL market, beginner and mini-games are unlikely to sell at all, but it's still worth investigating this site.
- Add the Mochi analytics APIs, (and mochi ads obviously) and submit to Mochi distribution to see how a game does virally. Signs of success: 5000 plays, large number of sites featuring game.
- More portals can be found on this handy list.

What should students aspire to?
- Front page of Digg.com
- featured on mainstream games blog e.g. Kotaku.
- featured in print publication e.g. Edge, .net
- Front page on Newgrounds or Kongregate
- Millions of plays across various sites
- attract sponsorship from big name e.g. ArmorGames, Kongregate
- players produce fan art

Hope this is useful to someone. Remember not to take the negative criticism from comments too personally. Learn from it and move on to your next game!

Monday, 26 July 2010

Understanding Game Time Steps - Your 3 Options

I was just answering a question over at the gamedev Stack Exchange beta site and I realised I was pretty much writing a blog post about time steps for games. How you handle your time step has big implications on how your game architecture needs to be set up. There's a lot of confusion and misinformation in this space, but I think I've pretty much got my head around it. Here are your 3 options:

Option 1 - Do Nothing

Do nothing. Attempt to update and render at a certain interval, e.g. 30 times per second. If it falls behind, let it and don't worry. The game will slow down into jerky slow motion if the CPU can't keep up with your game, but there will be no jarring jumps across the screen. This option won't work at all for real-time multi-user games, but is fine for single player games and has been used successfully in many games.

Option 2 - Delta Time

Use the delta time between each update to vary the movement of objects. In Flash this is just a matter of calling getTimer() and deducting the value of the previous frame's getTimer() call. This tells you how much time has elapsed since the last frame. Now you can factor this value in to all your maths. Great in theory, especially if nothing in your game accelerates or decelerates, but just moves at a constant speed. In practice, many developers implement this badly, and it can lead to inconsistent collision detection and physics. It seems some developers think this method is easier than it is. If you want to use this option you need to step your game up considerably and bring out some big-gun maths and algorithms, for example using a Verlet physics integrator (rather than the standard Euler that most people use) and using rays for collision detection rather than simple Pythagoras distance checks. I asked a question about this on Stack Overflow a while back and got some great answers:

http://stackoverflow.com/questions/153507/calculate-the-position-of-an-accelerating-body-after-a-certain-time

Option 3 - Fix Your Time Step

Use Gaffer's "fix your time step" approach. Update the game in fixed steps as in option 1, but do so multiple times per frame rendered - based on how much time has elapsed - so that the game logic keeps up with real time, while remaining in discrete steps. This way, easy to implement game logic like Euler integrators and simple collision detection still work. You also have the option of interpolating graphical animations based on delta time, but this is only for visual effects, and nothing that affects your core game logic. You can potentially get in trouble if your updates are very intensive - if the updates fall behind, you will need more and more of them to keep up, potential making your game even less responsive. I'm now going to try and explain how to implement this in Flash - concentrate!

Firstly, one implication of this approach is that you cannot rely on ENTER_FRAME to update each object. You must have a single ENTER_FRAME for the whole game that loops through each object and calls a public update() method. Each ENTER_FRAME tick you may have to call these update functions 0, 1, 2, 3 or even more times in order to get back in sync with real time. To work out how many times to update, you call getTimer() and take away the value of getTimer() from the start of the game. This tells you how much time has elapsed since the game started. Now work out how up-to-date your game logic is, by multiplying the number times you have called update (you'll need to keep track of this) by the length of 1 frame (e.g. 1/30 seconds for 30fps) - this is how much time has passed in your game world. Compare how much time has elapsed in real life to how much has elapsed in the game world. If they are different by more than 1 time step (e.g. 1/30 seconds) then call update until they are in sync to within less than 1 time step. This may seem pretty full-on, but it's really pretty simple - I will try to get a code demo up soon.

Personally, I like Option 1 - Do Nothing, when I can get away with it, and Option 3 - Fix your Time Step, when I need to sync to real time. I respect that Option 2 can be a good option when you know what you're doing, but I know my limitations well enough to stay well away from it.

Friday, 23 July 2010

A code review of PewPew by Mike Chambers


A very rare event has occurred - the chance to look at, discuss and play with the full source for a Flash game! I've worked with the source to dozens of games by different developers, but I'm normally under a non-disclosure agreement so I cannot divulge the full horrors of what I found there. But Mike Chambers from Adobe has kindly released the full source to his game under MIT open source license, and I thought this could be a great spring-board to open up discussion on the architecture and best practice of making Flash games.

but you also need to download is framework from here: http://github.com/mikechambers/Simple-Game-Framework/archives/master

Mike, hasn't made a game since Flash 4, so if you read this Mike, please take it in the scholarly spirit in which it is intended :)

and to everyone else, remember I am just one guy with some strong opinions, weakly held.

Ok here's my thoughts...

Repository - Mike has not included his framework in the game repository. I'd consider this a bad idea for 2 reasons.
  • A developer coming to the project cold cannot compile it. I believe that the repo of a project should contain everything you need to get started.
  • There is a strong chance that API changes could be made to the framework code that break the build of the game. You really want to use a stable version of a framework rather than having to fix errors every time an update is made to the framework. Then if you want to update to the latest version of the framework you grab the new version and fix all the problems at once. You don't want to come back to make a quick change to your game in 6 months, only to find that you can longer compile because you have changed the API of your framework.
Compiling
  • Mike has chosen to compile from the Flash IDE, which is fine with me and most design-driven agencies. Some developers won't like it, but who cares.
  • Mike has unticked the "include hidden layers" option in the Flash publish settings tab. This is one of my absolute no-nos as it means you can break the build just by hiding and unhiding layers while you're looking around the timeline. If I hadn't encountered this lunacy before, I might have spent hours figuring out why it suddenly wasn't compiling. In the end I had to revert to the original version because I couldn't remember exactly what should and shouldn't be hidden. This is what guides are for, people.
  • One mistake Mike's made that I see quite a lot is that he hasn't put his Main.as document class file in his package structure, it's just in the root of src with the fla. The Main class is just as much a part of the project as anything else, and should be in the package with it's friends.
Game Design
  • the game is a pretty basic asteroid-type shoot 'em up.
  • the home-made visual and audio style is acceptable in the Flash game world, although Mike could have chosen a more hand-written looking font, rather than Helvetica. There are lots of free handwriting fonts out there, and there's always Comic Sans!
  • the controls are optimised for a touchscreen mobile device, with a little virtual joystick in the bottom corner, so it doesn't control well on the desktop.
  • the joystick doesn't allow you to set speed, only direction. A simulated analogue stick would have been nicer.
  • There is some commented-out code for making the ship follow the mouse for browser play, but it is incomplete. Mike would have done better to have a boolean for isMouseControlled which could be switched when targeting the browser, rather than completely commenting out the code. I rarely delete or comment out working code, I'm much more likely to keep it in my class as a switched-off option.
  • At 480x800 it's too tall for a browser game, as you have to consider users with a minimum 1024x768 display.
  • The movement of the ship is not very graceful - it doesn't seem to accelerate or decelerate.
  • The speed of the bullets is way too slow.
  • The collision detection between the bullets and enemies is inconsistent, and bullets often sail under the wings of the UFOs without scoring a hit.
  • There are no roll-overs or even finger cursors on any buttons - again this is probably an artefact of originally being a touch-screen game.
  • There aren't any transitions between screens.
  • The enemies bounce around the screen like asteroids, but they are UFOs, which doesn't make any sense, as you would expect UFOs to know you are there and either attack or make defensive manoeuvres.
Library
  • Mike's library is beautifully arranged into folders with all the items named properly, and no Symbol 1's lying around. I rarely organise my libraries into folders any more - I just rely on the invaluable CS4/5 library search box.
  • Mike has linked library items directly to classes. This is what I often do as it is fast and makes it easy to understand what code relates to what graphics. It can have it's draw-backs though, for example if you want to runtime load assets from multiple swfs without having to republish them with every code change, and I'm coming round to the idea that it is often better to treat movieclips as "skins", with no code of there own, and have another class that controls them. It would be nice if at runtime you could tell Flash - take this movieclip and make it an instance of this class. That would be cool right, and totally feasible, Adobe engineers?
Code style
  • All Mike's code is beautifully organised, with well-named full-word function and variable names like isOnStage, displayTitleGraphic and onGameOver. This is painfully rare to see, so I salute you Mike!
  • Mike has commented to the point of obsession, which is great, but as his code is so well named and self documenting, most are unnecessary, such as:
    //start the game
    gameArea.start();
    //added to enemies vector
    enemies.push(enemy);
  • Throughout his code Mike has used // double slash comments on his public vars and functions, where he should have used /* slash star */ JavaDoc style comments. This would have allowed code editors like FlashDevelop to give the comment as a hint / tooltip. Really useful when working with an unfamiliar API.
  • There are some slightly strange things with splitting single lines of code over multiple carriage returns, with orphans tabbed weirdly across the page. This is either a Mac/PC formatting issue, or a sign of madness.
Architecture
  • Mike wrote in his blog that he thought he had over-engineered the game and he's not wrong. I ran a little app called cloc (count lines of code) on the folder and it told me that not including white space and comments there are 2420 lines of ActionScript. That's quite a lot when you consider that I managed to get a similar game running in 25 lines of code. Not all the code in a framework needs to be used on every project though, so it's not as bad as it sounds! If you ignore the framework it's only 1644 :) I have a feeling cloc might be over reporting because of block comments, but I might be wrong. So where is all that code going?
  • The GameArea class contains most the game logic, and is a fairly typical well organised game class. I has more white space and comments than it does code though, which I think makes it less readable. Overall this class is very sane though and doesn't include anything particularly wacky.
  • SoundManager doesn't do much - it doesn't even play sounds! Instead it returns and instance of a sound which you can then call play() on. It also contains constants for each sound class name in his library. This might sound like a good idea, but it isn't. Either use the class reference directly or just put the string in your function call. Not every string you ever type has to be put in a constant.
  • For entities there is an inheritance chain of MovieClip > GameObject > PewPewGameObject > Enemy > ChaserEnemy. I've used this kind of approach on many games, and it works up to a point, but it doesn't make your code very reusable, and you often have to hunt around different inheritance levels to find code. These days I use a very simple component system (nothing to do with native Flash components by the way) where functionality is broken down into modules which are owned by objects. So you would have a health component, a weapon component, a position/movement component, a sprite component etc. In Flash we lurve inheritance because it makes us feel like proper programmers, but composition is often a much better approach. This has taken me literally years to come to terms with, so I won't be surprised if lots of people disagree with me. Mike would also be in trouble if he wanted to adapt his game to use Away3D for rendering for example, as he has extended MovieClip. That said, you should always focus on the game you are making rather than worry about "what if" scenarios that will never happen.
  • Mike is using standard Flash events in his game. Again, I've done this many times myself, but since AS3Signals comes out I just use that - but TurboSignals is supposed to be even faster and so probably more appropriate for games. If you want real speed don't use eventing at all - give each entity a reference to your game class and call methods directly on that.
  • Mike has a reusable GameObjectPool class for object pooling, which is nice. However, when you ask it for e.g. a ChaserEnemy, it returns an instance of GameObject which must then be cast back to ChaserEnemy anyway, so he might as well of made an object pool that supports any class type, not just GameObjects.
  • Mike also has the start of some nice util classes for useful Maths functions, but they're not particularly extensive.
Conclusions

Overall PewPew has the hallmarks of a disciplined programmer with good style. Unfortunately it also has many of the limitations that 90% of Flash games suffer, which is a lack of some basic features that you would have seen in games from 20 years ago:
  • A health bar rather than instant death.
  • A scrolling world.
  • A solid world with walls, rooms, corridors etc, rather than just an open void.
  • Basic physics like momentum
  • Ability to pause the game
  • Particle effects for trails and explosions
  • Animated sprites
Good on Mike for releasing his code for public scrutiny - I worry that this is the extent of Adobe's knowledge of game development though. Their gamedev hub http://www.adobe.com/devnet/games/ seems to have been mostly contributed by 3rd parties, and it even includes some advice on such topics as making games with Cairngorm, which is never going to end well. Flash is badly in need of an official gaming API/framework on the scale of Flex. I don't see that happening any time soon, so until then we're all just going to keep re-solving solved problems and repeating the mistakes of the past.




Wednesday, 21 July 2010

Goals, missions and quests

Games with little in the way of narrative tend to have quite abstract goals for the player to aim for. I've written before that "games are about the relationships between objects in space", and in a pure game like Tetris or Connect 4, the goal is simply to get some objects into a particular spatial relationship, for example a straight line. Most action/adventure games however, use three basic goals :
  • Kill enemies (like Space Invaders)
  • Collect items (like Pacman)
  • Reach Location (like Mario - although he also collects items and kills enemies)
Even a game like Gears of War is basically made up of just these goals - get to the extraction point while picking up weapons and ammo and killing locusts. But that's not what makes GoW exciting or fun - it's the obstacles that get in your way - environmental puzzles to solve, enemy behaviour to study and overcome, and the twitch skill you need to survive.

The problem with RPG quests, like you find in World of Warcraft, is that they often remove all the obstacles, puzzle solving and skill that GoW requires, so that all that's left is repetitive"grind" - fighting, collecting and trudging around, without any real thought going on. If the quest designer has the tools to make an interesting journey for the player, they can make something rewarding - if they are only able to define basic kill 10 rats scenarios, then the experience will be a chore.

Kill Enemies

It's worth noting before I get into this topic that "killing" doesn't really have to be as violent as it sounds. Killing an enemy can be as metaphorical as you want to make it. Maybe your enemies are only stunned, maybe you're freeing them from some king of mind control (wasn't Sonic like that?), maybe they're not really enemies at all but customers in your cafe that you need to serve. The gameplay effect is the same: you have tapped into the part of the human brain that has evolved to deal with understanding the behaviour of another sentient creature, in order to get what you want from it, be that to eat it, not be eaten by it, get it's money or win it's affections. In The Sims for example, aren't each character's enemies really their neighbours and housemates? They must be charmed and seduced in order for the character to get what they want from them. Failure to do so will send your character into a spiral of depression, which is ultimately the closest The Sims has to losing.

Each type of enemy should have a unique appearance, but most importantly should have a unique behaviour, way of moving and interacting. Encountering an enemy for the first time should be a mini-puzzle, where the player must figure out how they need to manipulate their avatar in order to avoid the enemy's attacks and hit with their own, even if that mental process happens deep in the reptile brain rather than through a concious decision. If the player has different types of weapons, abilities, special moves or unit types to control, then each should have a different effect and effectiveness against a particular enemy. Real time strategy games do this really well, where, for example, a commando can take out a person in a single shot, but is useless against vehicles, forcing the player to think strategically about which enemies to attack with which of their own units.

Collect Items

Collecting items can be for its own sake, or it can be because they confer some ability that is useful in achieving the player's other goals. A game like Farmville uses only this goal - the aim is to accumulate as many coins, crops and animals as possible. There are is no location to reach or enemies to kill or avoid along the way, and you are never in any peril. The only thing you can do wrong is to not login to the game to harvest your crops, but this doesn't require skill or strategy, only a tireless devotion to the game. This is how Farmville is so successful in attracting a non-gamer audience. The player is only rewarded and never punished, unless they decide they have something better to do.

In a game like Gears of War, the main purpose of items is to make the player more effective in killing enemies. A gun or ammo pack has no sense of worth, other than as a means of eviscerating the enemy, and a player will happily toss it aside when something else comes along. Now compare this to an RPG where a weapon also has a monetary value and might have been difficult to acquire, and you'll find that a weapon becomes much more a prized possession. RPG's are very materialistic in this regard - every item has a price and the player spends a lot of time studying and organising their "inventory" and shopping for new items. As in The Sims, there's a lot of playing dress-up/playing with dolls here, and this is something which actually appeals to boys as well as girl gamers.

Collecting items can also be used as a way to test the players skill at the game and knowledge of the levels, with items placed in hidden or hard to reach places. Even Gears of War has it's Cog Tags, which serve no purpose other than to demonstrate that a player has a trawled every virtual inch of the game, which brings me onto the next topic...

Reach Locations

Since the earliest recorded times, stories have used a journey structure, where the protagonist sets out to reach a particular place and has an adventure along the way. Humans evolved to be semi-nomadic, and even the biggest homebody has a wanderlust somewhere deep inside. We love to travel, or climb trees or see what's around the next corner, even if we have no need to. Ever since the technology has permitted games with a playing area larger than a single screen, videogames have used this urge. But we tend not to make it too easy for the player to go exploring. Aside from enemies in the player's way, there are also environmental obstacles. I personally get nothing out of having to perform a set of perfectly timed jumps on every screen, but there are also environmental puzzles to test the player's logical brain, as you see perfectly executed in games like Half Life 2 and Portal.

So that's my breakdown of what I see as the 3 main goals a player has in a typical videogame: kill enemies, collect items, reach locations. Or if you wanted to be really reductionist, you could say that the goal of games is to keep some objects far apart and some close together.

Go any thoughts on this? Post them in the comments.

Tuesday, 20 July 2010

Gamedev and Indie Games Podcasts

Some decent podcasts about designing, developing and playing games:

Audio

Another Castle - Professionals talk game design.

Game Developers Radio - Great guests, a different game or development platform discussed each week.

Brainy Gamer - Game design from designer, journalist, academic and player perspectives.

DigiPen - Professionals and educators talk games.

IndieGamePod Interviews with developers about their games.

A life well wasted Arty, philosophical trip around gaming culture.

Video

Bytejacker - Fun video reviews of great indie games.

Co-op - Fun video reviews and chat.

Monday, 19 July 2010

Some thoughts on character design

Some random things I remember reading about character design, and some things that have worked for me. Thomas the Tank Engine breaks both my first two rules, so should be an example of the bad character design, but somehow kids love it!

  • a character should be recognisable from just their silhouette.
  • Each character in a group should have their own colour scheme.
  • Simply-drawn characters are easier for the player/viewer/reader to relate to, because they are less specifically one person, and more of a vessel for the player to project themselves onto.
  • For the same reason as above, characters shouldn't say much - that's the Gordon Freeman effect. Most game characters don't talk, and when they do talk, on spin-off cartoons etc (e.g. Sonic), it's annoying.
  • In games you can express a lot about the character from the way they move and interact with the environment.
  • For unique costumes, raid the history books for crazy armour, uniforms, hats and dresses, and adapt to fit your setting.
  • Don't use anything that is too reminiscent of another famous character, e.g. blue spiky hair, red overalls etc
  • If your game/whatever is very focussed on the main character, name it after that character, as this will avoid confusion later. For example, all the Indiana Jones movies are called, "Indiana Jones and the..." except the first one is just called "Raiders of the Lost Ark", which could be a bit confusing. This is also true of Rambo - the first movie was just called First Blood, but most people think it was called Rambo. Possibly the worst naming decision ever made was Nintendo making a series of games called Zelda where that wasn't even the name of the character. This has confused the hell out of kids for 2 decades now!

Thursday, 1 July 2010

Now I have a games portal too! (DullDudeGames.com)




Now I have a portal. There are a lot of Flash games portals out there. Maybe a million, maybe a billion; who can say? And does the world need another one? Probably not. So why have I made one? (OK, enough rhetorical questions now!)

In case you don't know, a summary of how the indie Flash games business works is this:

- Developer makes a game
- Developer licenses game to a primary sponsor and adds branding and links back to sponsor site within the game.
- Sponsor pays developer, and as long as developer didn't spend too long making the game, developer makes a profit.
- Sponsor sells advertising on their site. The advertising (hopefully) generates more revenue than the sponsor paid for the game, so they make a profit.

If you create a game, but don't have a sponsor, you have some surplus value, which is the traffic your game could generate, that doesn't go anywhere. So make your own portal and put some ads on it! Which is what I've done, because I didn't manage to get a sponsor for a little game I knocked up to coincide with the world cup called World Class Keep Ups. Of course, business wise, there's a strong possibility I'm just chasing the loss from World Class Keep Ups and will never get back the (very modest) time investment I've put into setting up a portal.

But there's more to life (and games) than money, which is why I've taken the opportunity to put right some things I think are wrong with many existing portals...

- Too many games. Have you ever heard that truism that if you give someone a choice of 30 flavours of jam they'll end up not buying any of them? The cognitive stress of weighing up all the options actually puts them off buying anything. I think this is true of portals as well. If you have a screen with 100 games in it, how are you supposed to know which one you want?

- Organising games by genre. Personally, I don't like sports games, or arcade games, or platform games, or any other arbitrary category of games. I just like good games, I don't care how you categorise them! I'm not really into sports but I loved NBA Jam, I'm not especially into gory violence but I love Gears of War. I honestly don't believe anyone starts a visit to a games portal by thinking "hmmm... I'm in the mood for a driving game!". I think they just want to play the best game that's out there.

- Tiny thumbnails. Average file sizes for Flash games are at least 2mb these days, even some pre-game/banner adds are nearly that big if they include video. So why do games portals give you a tiny 100x100 pixel thumbnail for each game? This is too small to actually fit a screenshot on, so designers end up just using a logo or headshot of the main character, which doesn't actually tell the gamer much about the game. So I've allowed enough space on my trading-card shaped thumbnail to fit a decent gameplay screenshot.


- Rubbish games. I know as well as anyone that making fun games is very hit and miss. Some games are great on paper, but just don't work when you come to play them. Portals that rely on users to filter and rate games to determine which game are shown, by definition show a lot of duff games to players. This is fine if you have a lot of users, like Kongregate, but doesn't work if you only have a small amount of traffic - it just looks like you'll shovel any s*** on there. Which is why I have hand-picked only games that I enjoyed the hell out of.

- Games get lost on the page. Many portals cram a lot of junk onto a busy layout, meaning the poor games are pretty lost within the page. I've stripped it down to just the essentials: my logo, game title, ad units, game, instructions, more games . I've made everything nice and big and not worried about "the fold" as I trust users to scroll. And best of all my site can handle a custom background and colour scheme for each game, meaning each game gets a full page "takeover" and the whole sites transforms to be sympathetic to the look of the game.

- Burying games too deep. Some sites are hard to navigate because it can take 4 or more clicks to find the game you are looking for. My site has a completely flat structure - there's not even a browse games page or even a homepage! Each page contains thumbnails to the full roster of games, which is never going to get so big that I can't fit it all on one page (after all I have to play and love any game that gets on there).

So there you have it. Enjoy DullDudeGames.com and maybe have a think about what you think a games portal should be?

Tuesday, 29 June 2010

Unity Game Development Essentials - Book Review


The publishers of Unity Game Development Essentials, Packt, were kind enough to send me a review copy of the book at the end of last year, but I have been so stupidly busy I didn't have much time to read the book let alone post my review. I had originally planned to only read the book while sat in front of Unity so that I could work along with the tutorials, but again time got me so I ended up just reading it on the train. As it turned out this didn't actually cause any problems, and I managed to turn an unproductive commute into some very productive learning time.

The book is basically one long tutorial that shows you how to make a tropical island, set up a first-person camera to walk around it, and create some interaction with the environment, such as collecting objects, opening doors and (don't ask me why) throwing coconuts. Between this book, Unity3d.com's tropical paradise demo and Offroad Velociraptor Safari, you will be forgiven for thinking Unity can only make games set on tropical islands. I assure you this is not true.

Going through these kinds of tutorials is not how I normally learn a technology. My normal approach is to just fire up the editor and start hacking code until something moves on the screen - as I did with Unity last year. However, I have to say that for Unity, which is a very unique, graphical interface driven technology, the approach of going through tutorials is actually better. I learned many techniques from the book (e.g. using the terrain editor, setting up the skybox) that aren't immediately obvious from just poking around the IDE.

The book is meant for a wide audience, including designers, and the code is quite basic, and not necessarily the most "correct" way of working if you're coming from the world of design patterns, MVC frameworks etc. However, I don't see this as an issue, as if you know a better way of doing things it will be trivial for you to refactor the code to meet your needs. The caveat, however, is that the code is all JavaScript, and many Flash guys will be more inclined to take the C# route, despite the obvious similarities between AS3 and Unity's implementation of JavaScript.

The book's main drawback is that at the end of it you haven't really made a "game" in the sense that I understand it. You've made a kind of interactive environment with some coconut throwing. The book's main benefit, however, is that it gives you a nice introduction to all the facets of Unity, from terrain, cameras, physics and prefabs to adding a user interface and menu. Many parts of the book are written just for people coming from Flash, and if that's you, you will definitely be able to go off and make your first game after reading it. Overall, if you're just getting into Unity I think this is a great place to start.

Thursday, 20 May 2010

Gamepad ported to Processing / JAVA

Gamepad, my opensource keyboard input utility, has received a great reaction so far, with many retweets, over 1000 views, and some great partnerships with other libraries in the pipeline. And now it's not just for Flash, because Michael Heuer has ported the whole project to JAVA for use with processing. So, if that's how you get down, go check out Gamepad for Processing on Github. Big thanks to Michael for taking the time to create this.


Thursday, 13 May 2010

Geometry Wars in 25 lines of ActionScript source code

I recently noticed that Keith Peters' 25 lines competition and all the entries have been purged from the internet, so in case you missed it first time, here's my port of a Geometry Wars style game, with source code below.



Here's the source, under free for commercial or non-commercial use MIT license. It gets cut off quite badly by blogger, so you're better off just clicking here to download. To run, just paste it into the timeline of CS4/CS5. I know that's a bad way to do things, but it was the rules of the original competition. If someone wants to make the necessary tweaks to compile it under the Flex compiler, I'd be very happy to post their code. Enjoy!

/**
* 25-Line ActionScript Contest Entry
*
* Project: Trigonometry Wars
* Author: Iain Lobb - iainlobb@googlemail.com
* Date: 27 NOVEMBER 08
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

// 3 free lines! Alter the parameters of the following lines or remove them.
// Do not substitute other code for the three lines in this section
[SWF(width=400, height=400, backgroundColor=0x000000, frameRate=24)]
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

// INSTRUCTIONS: PLEASE NOTE IT CAN TAKE A WHILE BEFORE ENEMIES APPEAR SO PLEASE BE PATIENT!

// 25 lines begins here!

var enemies:Array = [];

function createOrUpdateEntity(props:Object, entity:MovieClip = null, updateFunction:Function = null, drawCommands:Vector.<int> = null, drawShapes:Vector.<Number> = null, colour:uint = 0x000000):void
{
if (!entity) entity = MovieClip(addChild(new MovieClip()));
if (colour) entity.graphics.lineStyle(1, colour, 1.0, false, "normal", null, null,3);
if (drawCommands) entity.graphics.drawPath(drawCommands, drawShapes, GraphicsPathWinding.NON_ZERO);
if (updateFunction != null) entity.addEventListener(Event.ENTER_FRAME, updateFunction);
for (var thing:String in props) entity[thing] = props[thing];
if (props.array) {props.array.push(entity)};
}

function updateShip(event:Event):void
{
createOrUpdateEntity({x:MovieClip(event.target).x + ((mouseX - MovieClip(event.target).x) / 5), y:MovieClip(event.target).y + ((mouseY - MovieClip(event.target).y) / 5), rotation:(Math.atan2(mouseY - MovieClip(event.target).y, mouseX - MovieClip(event.target).x) * (180 / Math.PI)) + 90}, MovieClip(event.target));
createOrUpdateEntity({x:MovieClip(event.target).x, y:MovieClip(event.target).y, rotation:MovieClip(event.target).rotation, updateFunction:updateBullet, filters:[new GlowFilter(0xFFFF00)]}, null, updateBullet, Vector.<int>([1,2,2,2]), Vector.<Number>([0, 0, 3, 7, -3, 7, 0, 0]), 0xFFFF00);
if (Math.random() > 0.985) for (var i:int = 0; i < 20; i++) createOrUpdateEntity({x:300 + (Math.sin((i/20)*2*Math.PI) * 400), y:300 + (Math.cos((i/20)*2*Math.PI) * 400), rotation:0, array:enemies, updateFunction:updateEnemy, filters:[new GlowFilter(0xFF0000, 1, 12, 12, 4)]}, null, updateEnemy, Vector.<int>([1,2,2,2,2]), Vector.<Number>([0, 0, 10, 10, 0, 20, -10, 10, 0, 0]), 0xFF0000);
}

function updateBullet(event:Event):void
{
createOrUpdateEntity({x:MovieClip(event.target).x + (Math.cos((MovieClip(event.target).rotation - 90) * (Math.PI / 180)) * 12.5), y:MovieClip(event.target).y + (Math.sin((MovieClip(event.target).rotation - 90) * (Math.PI / 180)) * 12.5), rotation:MovieClip(event.target).rotation}, MovieClip(event.target));
if (MovieClip(event.target).x > 400 || MovieClip(event.target).x < 0 || MovieClip(event.target).y > 400 || MovieClip(event.target).y < 0) killEntity(MovieClip(event.target), false);
for (var i:int = 0; i < enemies.length; i++) if (Math.sqrt((((enemies[i].x - MovieClip(event.target).x))*((enemies[i].x - MovieClip(event.target).x))) + (((enemies[i].y - MovieClip(event.target).y))*((enemies[i].y - MovieClip(event.target).y)))) < 10 && this.contains(enemies[i])) killEntity(enemies[i], true);
}

function killEntity(entity:MovieClip, doExplosion:Boolean):void
{
if (this.contains(entity)) { removeChild(entity) };
entity.removeEventListener(Event.ENTER_FRAME, entity.updateFunction)
if (doExplosion) { for (var i:int = 0; i < 10; i++) createOrUpdateEntity({x:entity.x, y:entity.y, rotation:i * 36, updateFunction:updateSpark, filters:[new GlowFilter(0xFFFFFF)]}, null, updateSpark, Vector.<int>([1,2]), Vector.<Number>([0, 0, 0, -10]), 0xFFFFFF) };
}

function updateSpark(event:Event):void
{
createOrUpdateEntity({x:MovieClip(event.target).x + (Math.cos((MovieClip(event.target).rotation - 90) * (Math.PI / 180)) * 12.5), y:MovieClip(event.target).y + (Math.sin((MovieClip(event.target).rotation - 90) * (Math.PI / 180)) * 12.5), rotation:MovieClip(event.target).rotation}, MovieClip(event.target));
if (MovieClip(event.target).x > 400 || MovieClip(event.target).x < 0 || MovieClip(event.target).y > 400 || MovieClip(event.target).y < 0) killEntity(MovieClip(event.target), false);
}

function updateEnemy(event:Event):void {createOrUpdateEntity({x:MovieClip(event.target).x + ((mouseX - MovieClip(event.target).x) / 45), y:MovieClip(event.target).y + ((mouseY - MovieClip(event.target).y) / 45), rotation:0}, MovieClip(event.target))};

createOrUpdateEntity({x:300, y:300, rotation:0, filters:[new GlowFilter(0x00FF00)]}, null, updateShip, Vector.<int>([1,2,2,2,2, 2, 2, 2, 2, 2, 2]), Vector.<Number>([-7.3, -10.3, -5.5, -10.3, -7, -0.6, -0.5, 2.8, 6.2, -0.3, 4.5, -10.3, 6.3, -10.3, 11.1, 1.4, -0.2, 9.6, -11.9, 1.3, -7.3, -10.3]), 0x00FF00);


// 25 lines ends here!

Monday, 10 May 2010

The Essential Guide To Flash Games... infomercial?!

Just wow. For a couple of months I spent many of my evenings writing the "technical review" for "The Essential Guide to Flash Games" a new book about programming games with AS3, by Jeff Fulton and Steve Fulton, aka 8bitrocket. Which basically means Jeff and Steve wrote it, and I marked their homework. I'm still waiting for my copy to arrive from the publisher, but now I really can't wait, because there's a full-on infomercial?!? This is freakin' awesome...



http://www.youtube.com/watch?v=T4WXmv-JtAY&feature=player_embedded

I learned some neat new tricks from Jeff and Steve, and I also added some of my own suggestions, so you've got at least 3 brains worth of knowledge right there. More about the book at 8bitrocket: http://www.8bitrocket.com/book/

Tuesday, 4 May 2010

Help! How do I generate classes for a new project?

Ok readers, I gave you my indispensable Gamepad class, now I need something back: Whenever I start a new game, I make a whole bunch of classes that extend my base classes, so:

  • com.blah.Game extends com.iainlobb.Game and has some setup code
  • com.blah.Player extends com.iainlobb.Player, and has some setup code
  • etc
Now all I need is a way to generate these classes at the start of the project so I don't have to create each one manually. It will save me at least an hour of faffing around per game. So how do I do it? I normally use FlashDevelop but I also have FlexBuilder 3, or I'm happy to download whatever other software I need (PC). Thanks. I'm looking forward to your thoughts - check back to this post for the solution soon (hopefully!)


Update1:

In FlashDevelop there is an option called "templates" that lets you generate classes. Explained here: http://catfacegames.com/2009/01/19/flashdevelop-templates/

"First, inside of FlashDevelop access “Tools > Application Files” from the menu. This should open an explorer window where you see a few folders. Drill down into the following folders: Templates > ProjectFiles > AS3Project."

Adds options to the right click menu. Doesn't add all the classes at once like I originally wanted though...

Update 2:

I think we have a winner! No lesser person than Philippe from the FlashDevelop team has suggested this in the comments:

Duplicate FlashDevelop's AS3 project and add whatever classes you need (FD/Projects in Program Files).
At first I thought he meant look in the AppData>Local>FlashDevelop>Projects but there was nothing there. So, I re-read and found what I was looking for in C:\Program Files\FlashDevelop\Projects. I copied this folder and pasted it into the AppData>Local>FlashDevelop>Projects, and renamed to "001 Game". Now when I hit new project, I have an option called "Game" which builds the folder structure I need, creates and names my classes, etc. This is really powerful! Thanks again Philippe for an amazing bit of software and for your help. Readers who haven't used FlashDevelop: you have no idea what you're missing (and it's free ffs!)

Friday, 30 April 2010

Introducing Gamepad.

Gamepad is a free, open source project by me, Iain Lobb, with the aim of greatly simplifying keyboard input for Flash games. The idea was born out of 2 realisations – first, that since key.isDown was removed from ActionScript it has been more work for game developers to handle keyboard input, and second – that developers, me included, were not working with keyboard input at a sufficient level of abstraction. Trust me, if you make Flash games, you need this in your life. Update: I've had some feedback that it's hard to see the download button on Github, so please CLICK HERE TO DOWNLOAD if you prefer.



What does it do?

Gamepad simulates an analog joystick input using the keyboard. Many times when we access key presses, what we are really doing is pretending that WASD, the arrow keys or some other combination are actually a D-pad or joystick with an X and Y axis, and 1 or 2 fire buttons. Gamepad handles the event capture, maths and other details of this for you, so you only have to think about how you want your game to respond to this input. A detailed explanation follows, but why not just download the source code and play around?



A simple example

First we create a gamepad. It needs a reference to the stage so it can capture keyboard events, and it needs to know whether it is simulating a circular movement space, like a thumb-stick, or a square one, like a flight-stick. This argument is called “isCircle” I’ll get into this distinction later.

var gamepad:Gamepad = new Gamepad(stage, false);

Then in your update / enterFrame function, you simply adjust to the position of your character based on the “x” and “y” values of your gamepad. The “x” and “y” values are always between -1 and 1, so x = -1 would be mean the virtual D-pad is pushed all the way to the left, and x = 1 would mean it would be pushed all the way to the right. I have chosen to use y = -1 as up and y = 1 as down, so that it matches Flash’s screen coordinate system.

character.x += gamepad.x * 5;
character.y += gamepad.y * 5;

And to access the fire buttons, we simply look at the “isDown” property of the “fire1” button.

if (gamepad.fire1.isDown) fire();

That’s it! Your character will now happily walk around the screen using the arrow keys and fire when you press the CTRL key. As Gamepad also has easing by default, the character will also accelerate and decelerate smoothly!

The “isCircle” property

A common mistake that developers make in top-down perspective games, is to allow the player to move too fast diagonally. They say “If the up key is pressed, move up 5 pixels, and if the left key is pressed, move left 5 pixels, so if both are pressed move up 5 pixels and left 5 pixels”. This is wrong! Pythagoras tells us that the speed of their character would now be the square root of five squared plus five squared, which is the square root of fifty, which is about seven. So now their character moves 5 pixels per frame horizontally or vertically, but 7 pixels per frame diagonally. Disaster. Once you know this you can handle it yourself, but Gamepad makes it easy by giving you the isCircle option on creation. When you create your gamepad, simply pass in true for the second argument:

var gamepad:Gamepad = new Gamepad(stage, true);

Now the “nub” of the virtual joystick is limited to a circular area, meaning if you hold the “down” and “right” key together, it will report values of roughly x=0.7 and y= 0.7, instead of x=1 and x=1, and movement speed will be equal in all directions. Typically you would use this option is arena shooters and Zelda-style adventure games, and you may want to use it in scrolling shmups, but that’s a greyer area in terms of “realism”, as your vehicle is already supposed to be moving at a high velocity.

The “ease” property

By default, gamepad will give you a nice easing motion. One advantage it brings is that the player can “tap” the keys to achieve the effect of a half press on an analog input such as the XBOX 360 thumb-stick. Often, though, you won’t actually want to use this. You can easily turn it off by passing in 0, or pass in some other value for more/less responsiveness. Typically you’ll want easing activated for simple games, but in more complex simulations you handle acceleration elsewhere, so you may want it deactivated. To deactivate easing:
var gamepad:Gamepad = new Gamepad(stage, false, 0);

The “autoStep” property.

Gamepad needs to update at the same rate as your game, so that the easing, and the “downTicks” and “upTicks” properties (which I’ll cover later) always keep in sync with your game. If you are simply using Event.ENTER_FRAME for your update, you don’t need to do anything, as this is the default. However, if you have some other system, you should pass in false for the autoStep property and manually call the public “step()” method every time you update.

I advocate using a frame-based tick, and using the “fix your timestep” methodology if you need to stay in sync with real time. This way your game is deterministic, you will have far fewer inconsistencies with collision detection, and you can safely use basic Euler calculations for acceleration. However, I understand that some developers, and some game engines, such as Flixel, use a deltaTime based approach. If you are using a time-based approach, you should use the “fix your timestep” principle with gamepad, by calling the “step()” function an appropriate number of times each update, based on how much time has passed since the user started the game.

The GamepadInput class.

Each Gamepad instance has a set of GamepadInput objects that represent individual “buttons” on a virtual joypad. These are up, down, left, right, fire1 and fire2. However, these do not map one-to-one with keys on the keyboard – one GamepadInput can be linked to one, two or more keys, so that you can easily provide simultaneous alternate control schemes. The classic example would be having both WASD and the arrow keys control your character, so that players can use whichever scheme they prefer without having to set any menu options.

For setting up keys, GamepadInput has the “mapKey” function. It takes two arguments: “keyCode” – an integer representing the key, for which you should use the constants in the handy “com.cheezeworld.utils.KeyCode” class - and “replaceAll” which specifies whether to overwrite existing mappings. If you want to have multiple keys mapped to the same input, pass in false.

In many cases, you will never need to call the “mapKey” function, as there are presets for the most popular configurations in the Gamepad class. These are the functions “useArrows”, “useWASD”, “useIJKL”, and “useZQSD” (which is for the French “AZERTY” keyboard layout, where WASD doesn’t work). All of these methods take a “replaceExisting” argument which specifies whether you want duplicate mappings, as discussed earlier.

Unfortunately, the keys developers use for fire buttons don’t seem to be as standardised, but I have done my best, by providing the methods: “useChevrons”, “useGH”, “useZX”, “useXY” (for German QWERTZ keyboard) and “useControlSpace”. These are all taken from popular Flash games, for example Nitrome’s “Double Edged” which handles 2 players by giving one player WASD for movement and GH for attacking, and the other player arrow keys for movement and chevrons, “<” and” >” for attacking. Gampad’s default: Arrow keys, CONTROL and SPACEBAR should be fairly safe for all players, but there are many, many issues around international keyboards, so it may be advisable to allow the player to set their own keys.

Once you have your inputs set up, you can get information about their state: “isDown” simply tells you if a key is being held down, “isPressed” tells you if a key was pressed this frame/tick/update, and should be used instead of listening for KEY_DOWN events, “isReleased” tells you if the key was released this frame/tick/update, and should be used instead of the KEY_UP event, and “upTicks” and “downTicks” tell you how long the key has been held or released for. Basically, “isDown” is your go-to, but the others are there when you need more info. Generally, you should use the x and y properties of Gamepad for movement, but sometimes you may want to access the D-pad as “buttons” instead, for example using “up” for jump.

The GamepadMulitInput class.

There are also a further set of “buttons” represented by GamePadMultiInput objects. These are special as they aggregate the inputs of multiple other “buttons”. These are “upLeft”, “downLeft”, “upRight” and “downRight”, which let you treat these combined directions as if they were individual inputs on an 8-way controller, and “anyDirection”, which lets you know whether the player is pressing in any direction on the D-pad.

The angle, rotation and magnitude properties.

You may need these additional properties from time to time: “angle” gives you the direction in which the stick is pointed as radians, “rotation” is the same value but expressed in degrees and “magnitude” is the scalar distance of the “nub” from the origin, ignoring the angle. For example, if you set the rotation of a character MovieClip to negative the rotation property of your gamepad, your character will face in the right direction when they move!

The GamepadView class

If you want to visually see what your gamepad is doing, simply create an instance of the handy GamepadView class, and initialise it with a reference to your gamepad and optionally a colour.

var gamepadView:GamepadView = new GamepadView();
gamepadView.init(gamepad, 0xFF6600);
addChild(gamepadView);

GamePadTester and PlatformGamePadTester

In with the source code, you will find two visual “tester” classes. It’s not quite test-driven development, but these are the classes I use to ensure all the functionality of Gamepad is working – they’re also great documentation for Gamepad’s APIs, or could even be the starting point for your own game! If you’re using the Flash IDE simply open GamepadTester.fla or PlatformGamePadTester.fla and publish. If you’re using the Flex compiler you’ll need to create a new project and set the “always compile” / document class to com.iainlobb.gamepadtesters.GamePadTester.as or com.iainlobb.gamepadtesters.PlatformGamePadTester.as.

GamePadTester shows the basics of doing car-style movement and top-down character movement. It also demonstrates duplicate controls, with both WASD and IJKL controlling the character. PlatformGamePadTester shows the basics of a two player platform game, including variable height jumps (although in the end it transpired that these are mostly handled outside of the gamepad class). It also shows how you can create two instances of the same character class with different control schemes, without a single “if” statement or use of polymorphism. Composition FTW!



Final thoughts

Well done, you have made it through all the Gamepad documentation! Please start using it and submit feedback to my blog, or on github. I’ve had versions of this class kicking around for almost 2 years, but I had no idea how much work it would be to actually pull it all together, test and document it to a state where I was happy to release it as an open source project. I have insane new levels of respect for anyone else out there running an open source library. The license is MIT, which basically means you can do whatever you like with it, as long as you don’t blame me when it goes wrong. I’d appreciate it if you didn’t change the package names, and removing the copyright notice is forbidden. There’s a sweet gamepad logo that you can add to your game if you like, but it’s by no means compulsorily, and if you want to hit up the donate button on github, I’m not going to stop you. Enjoy!

Oh yeah, follow me on twitter: http://twitter.com/iainlobb

Friday, 23 April 2010

Start Repeating Yourself

On the latest Game Developers Radio is a great nugget of advice from Manuel Saint-Victor of infiniteunity3d.com, which is basically that you need to tweet / blog something 3 times before all the potential audience will actually see it. At first this seems like it might be annoying, but I decided to try it out, by repeatedly posting the youtube video of my Flash on the Beach Elevator Pitch from last year. The results were good. The first tweet took it from just 15 views to 29, then the next from 29 to 49. At this point some other people retweeted it, taking it up to 69, and it's still going up. That's 54 new viewers, when I had assumed that everyone who follows my output had already seen it, as I had already posted the Vimeo version here on my blog. (Update: a few hours later and it is up to 150 views). The crazy thing is that, even more people will watch it now after reading this post. And so far nobody has complained that I'm repeating myself annoyingly. One thing that you can't say enough though, is if you want people to respect you, *don't sell anything* - just educate and entertain. In my experience the rest will sort itself out.

http://www.youtube.com/watch?v=HUxAqjbmoic

Tuesday, 20 April 2010

Play Monster Ball on Kongregate and NewGrounds


Who knows what will happen to the Flash iPhone packager in the future (I hope it survives), but for now Monster Ball, the game I made for iPhone is still available on iTunes for free.

True to the write-once, deploy anywhere spirit of Flash, you can now also play it free online at:


or


Adobe has invited me to the AIR Android beta: unfortunately I don't have an Android phone to test on, but I'm pretty certain it would just package and run without any changes. Besides, you should soon be able to play it in-browser on your Android anyway, yay!