CSS & JavaScript Pacman

2011 November 29
by FlashMonkey

Anyone who has been on this site recently will know I’ve been playing around with a lot of little JavaScript and Canvas experiments. I’ve had fun porting some of my old Flash stuff over to Canvas and some of them have generated a fair bit of interest with my HTML5 ColorWall featured on Chrome Experiments (go and vote for it!) and my Simple JavaScript Physics post getting a lot of hits.

One thing I’ve found frustrating is how poorly these experiments run on iOS, especially before the recently released iOS5. Apple are against adding web plugins, such as Adobe Flash, to their devices claiming people should be using HTML5 tags such as Canvas. However, constantly clearing and re-drawing to a Canvas element on an iPhone running iOS4 gives you about 3 or 4 fps (it’s slightly better on iOS5 but still not good enough to write a game).

I then stumbled across this article on Seb Lee-Delisles site about a JavaScript hack day they held at Plugin Media where they made the infector game using CSS and JavaScript to see if they could get a fast browser game running on iOS. Inspired by this and wanting to learn a bit more CSS/JavaScript I decided to try putting my own game together using the same techniques. This post will explain how I went about it and stuff I learnt.

Before I continue I should mention that this isn’t a full version of Pacman, it’s merely a prototype to see if I could get a browser game working smoothly on an iPad and other touch devices. I never intended to finish it fully as I feel the world already has enough Pacman games floating about and we don’t really need another one. I am planning on creating a more original game with a Designer friend of mine early next year and will post about that when it’s ready.

First up click here to play the game. Right click and have a glance over the source code then read on below and I’ll explain the main talking points of the game structure.

Moving and animating the characters

The movement of the characters is fairly simple. The Player and Ghost Classes (I’m going to call them Classes even though they aren’t strictly Classes, not in the way AS3 Developers would be used to anyway) both contain an instance of the Animation Class. This Class was adapted from the Plugin Media experiment and basically uses CSS transforms to position the game characters as seen in the code below. I updated the Class so it also incorporated rotation, which I needed for my Pacman game.

var xp = Math.round(this.x + this.offsetX);
var yp = Math.round(this.y + this.offsetY);
styleStr = "translate(" + xp + "px, " + yp + "px)";
dom.style.webkitTransform = styleStr;
dom.style.MozTransform = styleStr;
dom.style.OTransform = styleStr;
dom.style.transform = styleStr;

styleStr = "rotate(" + this.rotation + "deg)";
dom.style.webkitTransform += styleStr;
dom.style.MozTransform += styleStr;
dom.style.OTransform += styleStr;
dom.style.transform += styleStr;

The character animations are done using simple Sprite sheets as seen below.

I liked the way Plugin Media wrote their Animation Class so the API worked in a similar way to ActionScript with play(), stop() and gotoAndStop() functions. View my adapted version of the Class here.

Collision Detection / Level Generator

The hit detection for when Pacman touches a wall is actually very simple. The level background is a transparent png as shown below.

I create a Canvas element and give it a green background. I then load the image on top of it, divide the image up into a grid and loop through to check if the pixel color is green using “getImageData” with the canvas tag. If it is I know it’s a space, otherwise it’s a wall. From this I can create an Array with info on the level and I use this throughout the game.

To see the full Level Class where this Array is generated click here. You may remember me criticising the performance of the Canvas tag and be wondering why I am using it. It only performs badly when you are constantly clearing it and writing to it. Once graphics have been written to Canvas it’s performance is no better or worse than simply loading an image.

If you have downloaded the source and are running it locally you may find that it doesn’t work and you get a security error. That is due to the line of code below – “getImageData”. You won’t get this if you install and run a local webserver such as Apache – this post on stackoverflow will explain further.

cellData[w][h] = (context.getImageData(xp, yp, 1, 1).data[1] == 255) ? 1 : 0;

The second bit of collision detection is between Pacman and the Ghost. This was much simpler and is done using a distance calculation.

var dx = Math.abs(player.xp - ghost.xp);
var dy = Math.abs(player.yp - ghost.yp);
var dist = Math.sqrt(dx * dx + dy * dy);

if(dist < CELL_SIZE)
{
  onGameOver(false);
}

For the Ghost AI I have written a simple implementation of the good old A* algorithm. Keith Peters wrote a great chapter on pathfinding in his ActionScript 3.0 Advanced Animation book, which is well worth a read if you’re completely new to pathfinding. A* is by far the most used pathfinding algorithm. You’ll find it being used from simple games like Pacman right up to complex PS3/Xbox games. You can see my implementation in the updateGhost function within the index.html source.

Touch screen devices

For the touch screen controls I used Modernizr to detect if the device supports touch.

if(Modernizr.touch)
{
  isTouch = true;
  makeControls();
}

Then I create onscreen controls using divs and the HTML touch events. I combined the event listener for key presses and touches as shown below.

function onKeyPress(e)
{
  if(!isPlaying && !isKeyDown) onClicked();
  isKeyDown = (isTouch) ? (e.type == "touchstart") : (e.type == "keydown");  
 
  switch((isTouch) ? e.target : e.keyCode)
  {
    case KEY_LEFT :
    case leftButton :
      leftDown = isKeyDown;
      break;
       
    case KEY_RIGHT :
    case rightButton :
      rightDown = isKeyDown;
      break;
       
    case KEY_UP :
    case upButton :
      upDown = isKeyDown;
      break;
       
    case KEY_DOWN :
    case downButton :
      downDown = isKeyDown;
      break;
  }
}

Fixed timestep

The final issue I experienced was a noticeable difference in frame rate between certain browsers and devices. This is an expected issue when running game physics on an interval and there is a simple solution: fix your timestep! I won’t go too much into this as you can read all you need to know in this great article from Glenn Fiedler. I have written an implementation of what is described in Glenn’s article in JavaScript and the game now runs at pretty much the same speed across all browsers and devices, it’s just smoother on some.

So with a fixed timestep and using CSS transformations on divs rather than constantly writing to Canvas I have succeeded in creating a simple browser based game that runs at an optimum speed on an iPhone/iPad and across other devices such as Android phones.

Conclusion

I really enjoyed creating this and learnt a lot about JavaScript and CSS. Reading books/online articles is a great way to learn but sometimes you just need to get stuck into code, and what better way than to make a simple game.

I want to say a little thanks to Seb and the guys at Plugin Media whose code I used a bit of. Also, my current employers Specialmoves, who were happy for me to do a bit of work on the game during my downtime. Finally, thanks to Richard Hallows who gave me some advice on CSS and best practises (check out my alphabetically ordered CSS style sheet).

Go ahead and try it out on your phone and let me know if you have any issues. As always advice and comments are welcome so let me know what you think.

Star Particles

2011 November 7
by FlashMonkey

Two posts in two days! Just made a star version of the fun particle thing I made yesterday! Check it out here. The stars are drawn with code - check the source code to see how. I’ve got a few other ideas for these little particles so watch this space! ;)

Fun with JavaScript and particles

2011 November 6
by FlashMonkey

So since my last post exactly 2 months ago it’s remained fairly quiet on the site. The reason being that I’m currently tech lead on a big project at Specialmoves that is due to go live really soon (more on that later). However, I’ve had a rare quiet weekend and somehow found the motivation to fire up the Macbook and write some code.

The project I’m currently working on features a fair amount of particles (it’s a Christmas site, need I say more). For the vast majority of them I’ve used Richard Lord’s brilliant Flint library but there was a couple of loaders on the site where I used my own simple particle system. I’ve always enjoyed playing around with particles as you can see from the posts featured on this blog, e.g. ColorWall, WobbleWall and Simple JavaScript Physics.

So with yesterday being November 5th (bonfire night here in the UK) I started playing around with creating a sparkler effect using JavaScript and Canvas. It didn’t really look exactly how I hoped but in creating it I stumbled across some other cool effects, the best being the one below. Click here to view the particles in action, move your mouse around and click anywhere on the screen.

I’ve always enjoyed creating simple visual effects that are nice to interact with and fun to watch and I think this one is just that. It’s a simple effect but I found myself dragging the mouse around for ages playing with it.

I plan to write a simple particle tutorial soon (ambitious for me since I’m currently averaging 1 post every 4 or so months) where I’ll explain the basics of creating a simple particle effect. Many developers think particle effect are really hard to create but once you’ve got the basics down it’s easy peasy.

Below are some of the other particles experiments I made yesterday. The first is the sort of sparkler effect. The second a slower more mellow version of the above and finally the sparkler effect without the canvas being cleared.

It’s all gone quiet over there…

2011 September 6
by FlashMonkey

Indeed it has all gone quiet over here on the site but not because I’ve buggered off travelling around the world again, oh no, I’ve been working hard actually. In fact a lot has changed since my last post way back in mid March.

I have a new job! Well, maybe not so new anymore as I have been here for 3 months. After returning from travelling I soon realised that I needed a fresh start at a new company to really get me excited about programming again. After deciding it was time to move on one company instantly sprang to mind as the sort of place I’d love to work… Specialmoves. Having worked with them on a Lynx project whilst at TMW I knew a few people at the company and thought I’d send my CV over and much to my delight - I got the job!

Specialmoves is very different to my previous jobs. The company is a studio rather than agency with little over 20 employees, and focuses primary on development. In my first week we had a Studio meeting and Darrell (one of the founders of the company) said that 10 years ago him and Pascal (you guessed it, the other founder) set the company up because they wanted to do “cool sh*t”, and it’s safe to say that is pretty much still the inspiration for all things Specialmoves. It’s an exciting place to work and the company are always trying to push the boundaries and be innovative. I hope to learn a lot working here.

Check out the video below for something I made in my first couple of weeks at Specialmoves. To read more about the project click here.

The other great thing about my new job is that it’s an Interactive Developer role, so not Flash/Actionscript specific. I like programming with Flash, it’s where I started out as a developer and I think AS3 is a fun language to write in. However, I’ve always believed as a developer it’s important not to get tied down to technologies and to remain open minded and keep learning/experimenting with new stuff. My role at Specialmoves will involve a lot of Flash, especially at the start, but I will also get an opportunity to work on other platforms like JavaScript and mobile development etc.

In other news my HTML5 version of ColorWall was recently added to the Chrome Experiments site. Check it out here and give it a 5 star rating! ;)

I plan to re-ignite the website over the next few months so expect some more blog posts soon!

HTML5 Snake

2011 March 16
by FlashMonkey

This is something I made this morning. I wanted to see if I could make a simple game in a couple of hours and I use to love playing snake on my old Nokia back when I was at school (yep mobile phones where invented before I left school - I’m not that old!!). Originally I was going to make it in Flash but a simple game like this is perfect for canvas and it’s an example of using the right technology for the job, rather than just sticking to something you know well.

Click here to play and see if you can beat my high score of 44. I’ll probably update it with a scoreboard soon. Oh and don’t try and run it in IE as it won’t work (no canvas support).

PS. It probably won’t work on your Nokia either but a mobile version could be an option in the future.

Space Monkey

2011 March 9
by FlashMonkey

You might play this game and think “this is just a copy of that iPhone game Doodle Jump”, and you’d be completely right. I was bored the other weekend and thought I’d make a game. I like Doodle Jump and there isn’t really any good online alternatives (google it, the top link is pretty poor, I’m not even going to link to it) so I thought I’d make one. I really enjoy programming physics and since it’s fairly simple for this game I did it all myself rather than using a library such as Box2D.

Normally I’d get the game to a certain level, like this early demo of Space Monkey, then move onto something else but I liked this one and thought I’d see it through to a properly finished game I’d be happy to post here. One thing I noticed was the game play is only a small part of a simple online game like this. It probably took roughly the same time to build the shell and score board etc.

Apart from the Monkey character (who I bought off iStock) I did all the graphics myself. I’m really pleased with the way this game turned out and I hope you have fun playing it.

ColorWall gets half a million hits

2011 March 4
by FlashMonkey

So last night, while I was tucked away in bed in London, somewhere in the world (possibly even in London) someone viewed ColorWall, and little did they know they where the 500,000th unique person to see it. Madness.

I made ColorWall purely as an example of how to re-create Yugo Nakamura’s great wonderwall effect. It was really just to see if I could do it using particles rather than a 3D engine but I was so happy with the result I thought I’d post it here on FlashMonkey, along with an explanation of how I did it and some source code.

I got some nice comments here such as Sourav Bhargava’s - “great analysis man . I appreciate your work. thanx the work helped me a lot”, and I did some spin off work such as WobbleWall and ColorSnake, but eventually I moved onto the next thing and started to forget about ColorWall.

However, whilst away travelling in Latin America last year I decided to check my Google Analytics (as you do) and couldn’t believe my eyes! ColorWall was starting to get a lot of hits, one day alone it got over 20,000. A little further investigation in GA showed me that most of these hits came from StumbleUpon.com, and a fair few from other social media sites such as Twitter, Facebook and Tumblr. It seems ColorWall (not ColourWall - I’ve taken a fair bit of stick from my compatriots for spelling it the American/programming way) has entertained people in a way I never intended/expected. Although 250 of the hits came from shroomery.org so that might go some way to explaining things.

Anyway, I’ll leave you with some comments people have made on StumbleUpon, I’ll start with the nice stuff, and end with some comments from people who ‘didn’t get it’! ;)

He should check out WobbleWall

No. It’s Flash. I have done a crappy HTML5 version though: HTML5 ColorWall

addFrameScript and currentLabels

2011 February 9
by FlashMonkey

Today I’ve been setting up a very simple project - an intro animation and then some text/links fade in. The designers are making the animation and I’m just writing some basic code for the links etc (it’s CMS driven, many languages).

The client often like to change their minds (just a regular client then) and I know that the animation may change quite a bit. To fade the content in after the animation I am using addFrameScript.

However, a problem, I know the frame that the fading should take place on could change several (hundred) times before the project goes live. I could just tell the designers where in the code to change the frame number, but I thought of a nicer solution than that.

The code was a simple combo of addFrameScript and currentLabels. I got the designer to add a label on the frame they want the fading to take place and then used this simple code:

function addLabelScript(mc:MovieClip, label:String, func:Function):void
{
  var labels:Array = mc.currentLabels;
  var i:int = labels.length;
 
  while(--i > -1)
  {
    if(FrameLabel(labels[i]).name == label)
    {
      mc.addFrameScript(FrameLabel(labels[i]).frame, func);
      return;
    }
  }
 
  trace("WARNING: The label '" + label + "' does not exist in the MovieClip '" + mc.name + "'");
}

OK it’s not going to make you fall off your chair with wonder but could be useful in the future. I’ve chucked it in a utils Class so it can be used like this:

function init():void
{
  Utils.addLabelScript(animation, "animation-complete", onComplete);
}

function onComplete():void
{
  trace("hello monkey I'm finished, do your fading thing");
}

In the above example the frame label the designer adds is “animation-complete”.

Simple image physics with HTML5 Canvas

2011 January 19
by FlashMonkey

I must admit that since returning from over 7 months travelling I’ve lost a little of my motivation for programming. However this afternoon at work I had a little downtime and decided to read through some of my emails and comments I’ve received on this blog for some inspiration.

One such comment I found was on my Simple JavaScript Physics post which asked about doing something similar with images. I quite enjoyed playing around with JavaScript and the canvas tag earlier in the year so thought I’d chuck something together. I still need to do collision detection but the throw physics is there. Click here to view it and as with my other JS experiments all the code can be found in the source code.

Using MouseEvent.DOUBLE_CLICK in AS3

2010 December 30
by FlashMonkey

Surprisingly I have never had a need to use the double click event in ActionScript 3.0 until this morning. I presumed it would work exactly like the single click event so at first I just used this:

item.addEventListener(MouseEvent.DOUBLE_CLICK, listener);

But nothing happened! A little look at the docs revealed why, you just need to add this line:

item.doubleClickEnabled = true;
item.addEventListener(MouseEvent.DOUBLE_CLICK, listener);

Simple.