Building a level editor for a shoot em up – JSON issue

We have a number of in-house tools written through a combination of Javascript and PHP. The data from the editors is written to a MySQL database and much of the workflow is handled within a single page – i.e. AJAX requests firing off to the back end to retrieve and update data.

Something that we hurl around a fair bit is JSON.

Currently the focus is on building an interface for designing levels for our forthcoming shoot ’em up; Akari: Battle Star.

What we’re after is precision. That is, we want to place entities within the game to be triggered at specific times during the game’s progress.

We call this tool Neo.

The Neo data is stored in a database table that is pretty straight forward in its design.

Within the editor we select the game and level to work on and an AJAX request pulls the data from the database. The result of which is a PHP array.

We then encode the array into a JSON format via PHP’s json_encode() method. This presents us with the Javascript that we can then use to write the front end.

Manipulating the JSON within the Neo front end is straight forward and we use jQuery for much of this.

Once we’re happy with the data we then fire off another AJAX call to post the data to the back end. This is were we ran into problems.

In short we were struggling to decode the JSON into a PHP array.

The JSON format we pass in looks something like this:

    {"gameid":1,"level":1,"trigger":100,"entityType":"formation",alienRow:1}

There’s much more to the data than that but essentially this is the format. The trigger value is the stage of the game (in ticks) at which point the entity data is triggered.

When we attempt to decode this JSON string and form the PHP array it’s successful.

But when we add another object to the string, it fails.

Something like this:

    {"gameid":1,"level":1,"trigger":100,"entityType":"formation",alienRow:1},
    {"gameid":1,"level":1,"trigger":150,"entityType":"island",alienRow:0}

We couldn’t for the life of us figure out why this wouldn’t work. So we employed PHP’s json_last_error() method which captures the last attempt at decoding JSON.

    json_decode($string);

    switch (json_last_error()) {
        case JSON_ERROR_NONE:
            echo ' - No errors';
        break;
        case JSON_ERROR_DEPTH:
            echo ' - Maximum stack depth exceeded';
        break;
        case JSON_ERROR_STATE_MISMATCH:
            echo ' - Underflow or the modes mismatch';
        break;
        case JSON_ERROR_CTRL_CHAR:
            echo ' - Unexpected control character found';
        break;
        case JSON_ERROR_SYNTAX:
            echo ' - Syntax error, malformed JSON';
        break;
        case JSON_ERROR_UTF8:
            echo ' - Malformed UTF-8 characters, possibly incorrectly encoded';
        break;
        default:
            echo ' - Unknown error';
        break;
    }

We received the error

 - Syntax error, malformed JSON

Some of you seasoned eagle-eyed Javascript gurus will have already noticed the problem.

We were trying to construct a Javascript array by formatting it badly.

The JSON we should have been passing looks something like this:

    {"data":[{"gameid":1,"level":1,"trigger":100,"entityType":"formation",alienRow:1},
    {"gameid":1,"level":1,"trigger":150,"entityType":"island",alienRow:0}]}

Once we’d defined the Javascript properly in an array format the decoding worked.

Neo development is now moving forward at pace and we’re having a huge amount of fun designing the levels and graphics.

 

 

Defining alien attack formations in a retro shoot em up

In our last game, Thundergun, we adopted a purely randomised approach to generating the levels. That is, the alien formations were predefined prior to the game loading but their formations for completely random.

For our next game, Akari: Battlestar (working title), we’re looking to plan the action with far more precision.

Our inspiration for this game is from the early 1990’s and games like Raiden.

Raiden was a tough game. Very tough. Our game will hopefully be a little more forgiving in the style of what were once referred to as manic shootersDo Don Pachi epitomised this style in which you pitched your fighter against hordes of formation-based adversaries who sprayed bombs (with some elegance) around the screen. Under normal circumstances avoiding the bombs would be nigh on impossible. But this genre used much tighter collision detection; often using just a single pixel in the centre of the player’s ship for collision reference.

We’ve already adopted a similar approach.

But it’s the fighter formations we’re keen to establish up front by way of an in-house level design system. The placement of aliens, cannons, collectables, mini bosses, tanks; you name it, will be handled by this system. Each entity will have all attributes defined and the resulting output stored in a JSON format to be read by the game.

The attack formations for Thundergun were based largely on Capcom’s 1943.

Fighters swooped in, curled around and then flew off. If you took the entire formation down you were presented with a bonus item.

For Akari we want to have a lot more variation.

Fighters will adopt one of several attack formations.
e.g.

  • Drift down from the top of the screen, pause, fire, drift off to the side
  • Drift in from the side, fire bursts, drift off to the side
  • (Tanks) trundle in from the side and follow a set path
  • Squadron formations from the bottom of the screen that fly off screen and return in slow formation

For Thundergun we introduced the concept of a game progress ticker. In code this was defined as part of the global namespace g{} and referred to as g.progress

g.progress bumps with every tick of the game’s main loop. This is consistent and in tune with everything else that the game loop handles (movement, animation, collision etc) so it’s a good base for defining the introduction of alien formations.

As g.progress counts its way through to several thousands for each level it passes what we refer to as waypoints. As each waypoint is triggered a new randomly but predefined alien formation is spawned.

The difference with Akari is that there will be no randomisation. Everything will be delivered from a level data file.

At set intervals in Thundergun the action was interspersed with a mini boss; a larger fighter that drifted into view and bullied the player. Formations continued to spawn around it.

For Akari we’ll suppress the formations and halt the bumping of g.progress while the mini boss action plays out.

With the mechanics for the mini boss developed we have pretty much 90% of the code written to handle a proper end-of-level boss. The main difference will be in defining the scale of the boss and any sub-elements such as wing-mounted cannons.

Level structuring isn’t a new thing for us. We’ve employed it for our platform games and the C64 style shooter Crossfire.

Hopefully we can get a demo up and running in the near future. Exciting times in arcade game development!

WKWebView, WebAudio and PhoneGap for iOS games

Here’s a handy little tip for anyone wanting to load files via AJAX in their PhoneGap apps that run on iOS courtesy of PhoneGap.

Our first attempts at creating games with PhoneGap were satisfactory but not brilliant. The frame rates were awful though the music and sound effects seemed to work fine. So we did a little digging and found that by default PhoneGap will use UIWebView, the default web view, on iOS.

You can change this to use the far more advanced and polished WKWebView (Web Kit Web View) which makes great use of such things as requestAnimationFrame. Something that is hopefully familiar to HTML5 game developers.
With WKWebView you also get to run against the superior JavaScript Nitro Engine which will massively increase the performance of your games.

Here’s how to implement WKWebView via your config.xml.

Add the following just beneath your <widget> declaration:

 <feature name="CDVWKWebViewEngine">
 <param name="ios-package" value="CDVWKWebViewEngine" />
 </feature>
 <preference name="CordovaWebViewEngine" value="CDVWKWebViewEngine" />

 

But we found that our audio now failed to load.

We use AJAX (XMLHttpRequest) to load our audio. To date it’s worked a treat. The reason we use it is because it’s a neat way to asynchronously load and capture the onload event and act upon it as we configure each audio file (volume, for example).

This works using a relative path.

Here’s some code:

 var request = new XMLHttpRequest();
 var url = "sfx/" + o.soundname + "." + AUDIOFORMAT;
 request.open('GET', url, true);
 request.responseType = 'arraybuffer';

You can see that our mp3 files are sat in a sub-directory called /sfx.

But WKWebView doesn’t like this. It wants its AJAX calls to be fully qualified from the http://

The change to the config.xml file is simple.

Add the following amongst your plugin declarations:

<plugin name="cordova-plugin-wkwebview-engine-localhost" spec="https://github.com/apache/cordova-plugins.git#wkwebview-engine-localhost" />

And change your content definition from

<content src="index.html" />

to

<content src="http://localhost" />

Hope that helps somebody!

Adding dynamic tweet functionality to HTML5 games

My current focus is with the PlayStar Arcade. I’m keen to push it as a platform for playing my HTML5 games. A lot of work has been carried out “under the bonnet” as we say in the UK and now I’m in to the slightly more entertaining areas of adding bells and whistles.

Something I was always keen to pursue was the ability for players to share their scores via social media. Twitter was my first port of call.
Thanks to their Tweet button script placing a button inside the game was a fairly simple exercise.
The flow that I wanted would see the player complete the game and reach the “GAMEOVER” status. At this point I would present the <div> containing the Twitter code.
The player would then be prompted to share their score and tap the Twitter “Tweet” button. All I had to do at this point was switch the text inside of the code that Twitter gave me with my own text. This replaced text would be what appears in the dialogue box for the player to tweet.

tweet score from html5 game

But there was a problem.

The attribute that I need to change to achieve this is the data-text attribute of the <a> tag in the Twitter script. But dynamically changing this attribute proves useless. 

When the Twitter script executes it converts the <a> tag in to a <div>. Any subsequent calls that I make to amend the tag fail.

I appreciate that this is largely theory so rather than post my own code solutions I’m going to link a site that covers it neatly with code examples.

http://tumblr.christophercamps.com/post/4072517874/dynamic-tweet-button-text-using-jquery

This guy had the exact same problem and solved it beautifully. 
I now have the ability to let the player complete a game, rack up a score and then share it with the world courtesy of Twitter. Facebook is next.

The importance of quickly proving a game concept with JavaScript

I have what I’m sure is probably considered a primitive style of coding JavaScript. It’s never really evolved in to anything that a purist would adopt over the years. To be frank it doesn’t concern me. What’s most important to me is that I understand my code and more importantly perhaps; it works.

The benefits of knowing my own code and the intimate relationship that I have developed with it have time and again proven useful. Not least when I’m approached by clients and 3rd parties to implement their own code and / or extract data from the game. Simple modifications and tweaks are simpler because I know my code inside out and the upside to all of that is of course that such changes are quick. Or at least quicker than they would have been if I’d had to first figure out how the code works.

There’s another huge benefit to writing and understanding my own code which for me comes in to its own when I’m considering a new game. I often daydream about a game or take inspiration from the most random things. I’ve got sketch books full of ideas and documents on my computer full of code snippets and high concepts.

HTML5 arcade game screenshot

To try and explain I’ll briefly explain the process of developing one game.

Some time last year I was driving home after a long journey across country. Not too far from home I remember pulling off the motorway and as I approached the traffic lights on the slip road I watched the striped yellow lines on the road. As I slowed to stop I remember clearly thinking how cool it would be to create a game in which the player controls a jet fighter that flies low over a striped landscape. Inspired by the illusion of the lines cascading beneath the car I turned over in my mind how the code might look. It didn’t take much to figure it out and that game turned out to be Distant Orbit (pictured).
I could prove the concept quickly because I knew how to adapt my code base to implement the stripe objects that form the planet floor. Better yet I visualised the game loop and could understand how to scale the alien bugs as they emerged over the horizon. There was nothing overly complicated in it and using the same approach I could quickly implement the tower that forms the player’s primary target in the game. The thought processes in understanding scale rates and how to manipulate such events per game “tick” came to me pretty quickly and because I understood the underlying code that handles the drawing and moving / scaling of objects I knew pretty much how the code would look.

What’s valuable to me is being able to take a concept, process it in my mind (and therefore visualise it on screen) and then move quickly in to code. It’s only by being able to do this that I can quickly dismiss an idea or take it to the next step – design. I like to have one quirky feature per game:  striped floors, scrolling terrain, 3D trench, starfield; and it’s generally this feature that I’m focusing on at the concept stage.

Much of this is always done using “defaults” for sprite art and defaults for audio. All objects have default behaviours as sprites in my code and adapting them to behave differently is 5 minutes work. At least to prove the concept. Fine-tuning can happen much later on as part of a balancing process.

So in short it’s crucial for me to be able to very quickly get in to coding. When I have a vision for something I spend a short amount of time poring over the approach that I’ll take and then it’s all about cutting code.

In future posts I’m going to break with my own tradition of not sharing my code. You can see for yourself just how ugly code can render some pretty cool looking arcade games :)

A quick look at the potential for HTML5 gaming on Nintendo’s Wii U

Once upon a time I worked as an artist for a company that developed games for Nintendo’s handheld devices, amongst other things. I remember back then (2001 ish) wondering whether web technologies would/could ever produce the kind of environment suitable for good quality gaming. I suppose looking back then it must have seemed ludicrous that you could pull up a web browser and play a pretty performant arcade game with fluid animation and full audio support. We certainly wouldn’t have imagined such an experience being available on the consoles we were developing for – Gameboy, Gameboy Advance. Not even the next-gen stuff of the day – PS2, Xbox (1st generation).

Desert Rescue HTML5 game on Wii U

Desert Rescue HTML5 game on Wii U

So it’s with some interest that I continue to read about the level of JavaScript support within Nintendo’s Wii U:

Nintendo itself is clearly keen to push the capabilities of its browser out to the indie community. What’s more with a considerably lower barrier to entry than traditional console development, it’d be great to think that Nintendo could pave the way for bedroom programmers the world over to find a new route to market.

Quite how Nintendo would control this potential demand from developers is another question but it’s certainly encouraging to see that there is once again huge potential for carving out a livelihood for yourself from the comfort of your own home.

A cool looking retro-styled game called CrossCode appears to be in consideration for publishing on Nintendo platforms.
You can play a sample of the game here: http://www.cross-code.com/en/play

Viewports and the scaling & positioning of the canvas

Having just spent a couple of hours poring over my code for scaling & positioning the game canvas I thought I’d share the experience.

Despite having made several HTML5 games over the last couple of years I’ve never experienced any real issues with scaling or positioning. Just recently however I’ve started to notice inconsistencies between browsers and OS versions.

In some cases the canvas would scale perfectly but not position properly. In other cases the canvas would not scale properly yet position well in the centre of the screen.

My criteria is simple – I want the games to be played in any orientation and to fit consistently in the centre of the screen.
Where full screen is available in either width (landscape orientation games) or height (portrait) I will also aim for that.

It’s 90% there. On Galaxy S2+ and iPhone4+ portrait games load and scale to fit fine in portrait and landscape games load fine and scale in landscape.
The problem arises on iOS when the games are loaded in the wrong orientation.

e.g. if the game is a portrait game and it loads up in portrait mode then it scales to fit just fine, as you would expect. (illustration 1)

ipadscale-portraitload

illustration 1 – game loads in portrait mode

But if the player then decides to play it in landscape it scales fine but doesn’t centre correctly. Just sits to the left of centre. (illustration 2)

illustration 2 - game loaded in portrait and rotated to landscape

illustration 2 – game loaded in portrait and rotated to landscape – note white space where HTML BODY is simply untouched.

If the game loads up in landscape then it centers beautifully and is playable (illustration 3)

iPad HTML5

illustration 3 – game loaded whilst tablet in landscape mode

If the player then rotates to portrait the game scales just fine on iPhone to fit the screen but on iPad it sits rather awkwardly to the right of the screen with about a third of the content out of sight. (illustration 4)

ipadscale-landscapeload-rotate

illustration 4 – loaded in landscape and rotated to portrait

This has an impact on my regional touchEvent code that I use for driving menus and other in-game features.

I no longer present a banner message instructing the player to rotate. It seems clunky and my clients hate it.

Of course it’s far too easy to suggest that as long as the games load up in their preferred orientation then surely I’ll be OK.
The reality is it needs to work and work properly.

So what’s my code doing?

Well surprisingly little.
I certainly don’t sniff the device. It’s 2013. So I don’t actually know I’m dealing with iOS any more than I know it’s a desktop or mobile browser.

The first thing I do is record the screen’s physical width less any scrollbars.

var w = window.innerWidth;
var h = window.innerHeight;

I also record the game’s intended canvas dimensions.

var rw =320;
var rh = 480;

Then to accurately scale the canvas I use the Math.min() method to first determine how best to scale the canvas to preserve the aspect ratio.

multiplier = Math.min((h / rh), (w / rw));
var actualCanvasWidth = rw * multiplier;
var actualCanvasHeight = rh * multiplier;

Fairly simple stuff there just to keep the aspect ratio of the game’s canvas intact and as previously stipulated aim for full screen in the preferred orientation.

To actually position the canvas on the screen I use CSS.

So first I’ve already got a handle on the canvas and stored it within my global namespace (g):

HTML

<body>
<div id="game">
<canvas class="canvas"></canvas>
</div>
</body>

JavaScript

g.gamecanvas = document.getElementById('game');

CSS

.canvas { width: 100%; height: 100%; }

I then make sure that the canvas parent is displaying as a block level element, assign a width to it and use the margin property to centre it. The canvas fits its parent to the pixel.

g.gamecanvas.style.display = "block";
g.gamecanvas.style.width = actualCanvasWidth + "px";
g.gamecanvas.style.height = actualCanvasHeight + "px";
g.gamecanvas.style.margin = "0px auto 0px auto";

My scaling function is called every time the onresize() or onorientationchange() events are fired. It is also called at the very top of the code before the assets are loaded.

So when we tie all this together we get a perfect presentation the first time the game is loaded.
The canvas scales to fit the orientation and centers perfectly in the centre of the screen.

So why on earth do I get that “dead” area when the tablet is rotated from portrait to landscape? (illustration 2 above)
Why does the canvas shift over to the right when the tablet is rotated from landscape to portrait? (illustration 4 above)
There has to be something else to look at.

The answer lay in the META description for the VIEWPORT.

Here’s what I used to present in the index.html of every game:

<meta name="viewport" content="width=320, height=440, user-scalable=no, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />

What a mess. I’d never touched this in almost two years.
Understanding the viewport is essential to understanding mobile presentation. Generally speaking the rule is if you don’t understand how it works don’t use it. The results can be undesirable.

Rather than go to the trouble of fully understanding what the viewport definitions are and do I decided to look at what I actually want to achieve. The answer here is very simple – a) stretch content to screen dimensions, b) suppress ability to pinch / zoom.

There is no need to specify the physical width or height in pixels of the device screen. There is also no need to restrict user scaling with the user-scalable attribute. Finally there is no need to set a maximum-scale, which I must admit I found surprising.

The only code I need here is:

<meta name="viewport" content="width=device-width, initial-scale=1">

The scaling of the canvas and positioning of the parent element within the document body are now perfect. No more “dead” regions and no more strange horizontal positioning.

There appears to be more sympathy for my lousy meta code within Android browsers than there is with iOS and Safari.

Creating a very basic “Star Wars” style trench scene viewed from above

Prototyping new game ideas is a lot of fun. Thanks to some serious enhancements to my game framework it’s also pretty quick.

I enjoy day-dreaming new ideas and recently I was watching something on TV that put me in mind of the film Star Wars. It was a fast paced scene in a TV show with cars, helicopters and trucks all viewed from above. I was struck by how effective the shot was in portraying speed with the buildings that lined the streets.

The Star Wars link came with the closing scenes in the first film as the fighters raced down the trench. It occured to me that this scene viewed from above might work quite well for a (yet another !) shooting game. I quite liked the claustrophobia of it, amongst other things.

So I had a bash at putting together a short test.
The theory was quite simple. I would use a simple fillRect() to block out the 5 key areas of the trench. The lighter shades at the edge would of course be the top of the trench (the surface if you will of the Death Star) and the darker shades would represent the inner walls and the trench’s floor.
You can see the rectangular divisions highlighted in the image below.

All I needed to do was give the impression of movement.
For this I am using lines and paths.

I created a trenchLine() class and initiated it with 2 y values. Nothing more is needed at the moment.
The first y co-ordinate is for the first 2 points and the last 2 points (see the image below).
the second co-ordinate is for the middle points which will be moving that bit slower.

As the game begins I initiate around 4 trench lines to be drawn over the grey background at equidistant intervals down the screen. (In the illustration below the 4th line is just off the top of the canvas so not yet visible)
The key here is in how the trench line breaks up to represent the pseudo-3D nature of the trench.

click to enlarge

So I originate the line at x = 0.
The line itself is broken in to 5 shorter lines.
On a 320 wide play area I draw the line’s points at

1. x=0, // left hand side
2. x=32, // edge of trench – about to drop to floor
3. x=48, // left hand side of the 192px wide floor
4. x=240, // right hand side of trench floor
5. x=288 // edge of trench on right hand side

Each point moves at a set speed down the screen.
I set the trench speed to be, say, 4 pixels per frame.
This affects points 1,2, 5 and 6.

But the trench floor needs to move slower and for these points (3 and 4) I move them at 3 pixels per frame.

I have a simple line drawing routine:


function drawLine(x1,y1,x2,y2,c)
{
 try
 {
 g.ctx.beginPath();
 g.ctx.moveTo(x1, y1);
 g.ctx.lineTo(x2, y2);
 g.ctx.closePath();
 g.ctx.strokeStyle = c;
 g.ctx.stroke();
 }
 catch (e)
 {
 write("drawline: " + e.message);
 }
};

Quite straight forward in that it accepts the start and end points of the line and the colour that you wish to draw it.
I then pass the following 5 draw instructions to it to create my trench line:


drawLine(0,o.y,32,o.y,"#aaaaaa");
drawLine(32,o.y,64,o.y2,"#666666");
drawLine(64,o.y2,256,o.y2,"#444444");
drawLine(256,o.y2,288,o.y,"#666666");
drawLine(288,o.y,g.canvaswidth,o.y,"#aaaaaa");

The overall effect here is that the outer lines effectively overtake the inner lines and you get the impression of a moving trench from above – as per the screen shot.

I created some placeholder sprites and threw them around to see how effective playing the game in a narrow 192px corridor might be. So far so good.

Watch this space :)

HTML5 Canvas Text Wrap Tutorial

I’m using a small amount of dialogue in Distant Orbit to help tell the story. One thing that I wanted to maintain was simplicity when it comes to handing over the text files for localisation.

So to this end I needed to allow for text to wrap across lines within the canvas.
Some languages are quite a bit longer and more complex than English. German and French in particular can have some lengthy translations. So I wanted to be able to give the translator freedom when it comes to choosing the appropriate words to tell the story.

There isn’t a native textBlock functionality within the Canvas text API so I looked around for a solution and found this one pretty much straight away.
The key here is in understanding what context.measureText() is doing for you. I think it’s pretty self explanatory.

1.8.7 HTML5 Canvas Text Wrap Tutorial.

Distant Orbit screenshot

Playing with fillStyle to create some neat game effects and text

Creating games using HTML5 and the Canvas isn’t always all about using drawImage(). For the most part it is of course because we want to display our lovingly drawn sprites and environments but there are plenty of legitimate cases where we might opt for using the primitive drawing methods such as fillRect().

I use fillRect and fillText consistently in my games and have never found it to be a performance killer. At least not using the canvas dimensions 320 x 480 which I use for mobile gaming. But you should be careful. The more you ask the API to do the more of a load you place on it and at some point something has to give. Namely your framerate !
But with a bit of planning and some consideration for what you are actually presenting it can be very visually rewarding.

Distant Orbit screenshot

Distant Orbit

In Distant Orbit I’m actually using rectangles to construct the pseudo 3D tumbling landscape. It’s a very old and well-used method of creating a moving terrain.
The theory is quite simple in that the lower half of the game screen is first filled with a solid colour and the striped terrain is then a series of rectangular ‘sprites’ that scale upwards as they fall down the screen. The effect is quite nice and I save on having to draw two sets of stripes by having the underlying layer as the alternate colour.
So the underlying layer is drawn in the lighter shade and then the striped layers are drawn over the top.

I refer to the stripes as sprites since they are derived from my base sprite class. That is they inherit specific behaviours and attributes that allow me to position and present them on the screen.
It’s just that when I get to actually drawing them I’m using fillRect instead of drawImage.

Here’s an example of how you would display a rectangle.

function drawRectangle(o) // o is the incoming sprite object from which I shall derive co-ordinates and size
{
 g.ctx.fillStyle = '#bf0000';
 g.ctx.fillRect(o.x,o.y,o.w,o.h);
};

(You can see that I store the canvas context within the global namespace g)
So g.ctx.fillStyle has a hex colour value assigned to it and the following draw instruction honours it.
When I draw the rectangle I have already passed through a move() function to return the new position and dimensions of the stripe.
It is also important to note that the fillRect method uses width and height as opposed to locations in terms of scaling your shape.

Example

g.ctx.fillRect(20,20,30,30);

produces a 30×30 square with its origin at 20,20 NOT as you might expect a 10×10 square that starts at 20,20 and finishes at 30,30.

To achieve the scaling terrain effect in Distant Orbit I initialise each stripe with a height attribute of 1 pixel. As it falls down the canvas it scales until by the time it falls off the bottom it’s around 48 pixels deep.
Rather than scale the stripes by a fixed number of pixels each time (e.g. 2px) I use a modifier. This stops the stripes looking horribly uniform. By incrementing the height attribute by a modifier that itself increments with smaller numbers I get the effect that the stripe remains quite narrow for a while as if it where lost toward the horizon:

o.modifier += 0.1;
o.h += o.modifier;

So the height of the stripe would change something like this:

0.1
0.3
0.6
1.0
1.5

which gives a far nicer effect than a uniform increment such as 1, 2, 3 etc.

The beauty of this approach to drawing on screen is that it is reflected in other forms of presentation such as writing text. Instead of fillRect you just use fillText but the style is set in the exact same way.

Take a look at this code.

<!doctype html>
<html lang=en>
<head>
	<title> fillRect() </title>
	<meta charset=utf-8>
	<script>

		var g = {};
		function init()
		{
			g.ctx = document.querySelector('canvas').getContext('2d');
			fill(0,0,320,480,"#0000ff"); // Blue background
			fill(20,20,30,30,"#ffff00"); // Yellow square (10x10)
			filla(0,80,320,20,"255,255,0",0.6); // Yellow stripe with 0.6 alpha
			write("Hello, World !",160,94,"center","#ffffff",12,null,"bold");
		};

		function fill(x,y,w,h,c)
		{
			c = c ? c : "#000000";
			g.ctx.fillStyle = c;
			g.ctx.fillRect(x,y,w,h);
		};

		function filla(x,y,w,h,c,a)
		{
			c = c ? c : "0,0,0";
			a = a ? a : 0.5;
			g.ctx.fillStyle = "rgba(" + c + "," + a + ")";
			g.ctx.fillRect(x,y,w,h);
		};

		function write(t,x,y,a,c,s,f,w)
		{
			c = c ? c : "#ffffff";
			a = a ? a : "left";
			s = s ? s : 10;
			f = f ? f : "Sans-Serif";
			w = w ? w : "normal";
			g.ctx.font = w + " " + s + "px " + f;
			g.ctx.textAlign = a;
			g.ctx.fillStyle = c;
			g.ctx.fillText(t,x,y);
		};

	</script>
</head>
<body onload="init();">

	<canvas width="320" height="480"></canvas>

</body>
</html>

The basic rectangle drawing is there along with a slightly different version that allows us to provide an alpha value. This alpha range is from 0 (100% transparency, i.e. non-existant) to 1 (opaque). So for example if you provided a value of 0.5 you’d see a 50/50 blend of the background colour and your rectangle’s colour.
The key thing to remember here is that for rgba values you must specify your colours numerically.
So for White rather than #ffffff you’d specify 255,255,255.
For White with 50% alpha opacity you’d use rgba(255,255,255,0.5);

Visit this link: fillrect.html to see the above code in action.

You can see that the text also has the standard CSS attributes of alignment, font-size, font-family and font-weight. This is extremely useful when you consider that you can pull fonts from Google’s web font repository for use in your games.

By simply adding the following line to my markup I can use the “Bangers” web font family in my game.

<link href='http://fonts.googleapis.com/css?family=Bangers' rel='stylesheet' type='text/css'>

Visit this link to see the change: fillrect-newfont.html

You can see that in my code the order in which the items are drawn is important.
Starting with the blue background is important since it allows subsequent items to be drawn over the top. If the blue background were drawn last it would simply overlay everything else.
That said there is an instance where you may wish to present a solid block of colour over your content and that’s when you wish to fade your content in and/or out.
To do this we simply draw a rectangle with progressive alpha opacity as the last draw item in our draw order.

Take a look at this code for the necessary adaptations:

<!doctype html>
<html lang=en>
<head>
	<title> Fade In/Out </title>
	<meta charset=utf-8>
	<link href='http://fonts.googleapis.com/css?family=Bangers' rel='stylesheet' type='text/css'>
	<script>

		var g = {};
		function init()
		{
			g.ctx = document.querySelector('canvas').getContext('2d');
			load();
		};

		function load()
		{
			g.img = new Image();
			g.img.onload = function() {
				g.fade = 0;
				g.ticker = setTimeout("loop()", 40); 
			};
			g.img.src = "sun.jpg";
		};
		
		function loop()
		{
			clearTimeout(g.ticker);

			g.ctx.drawImage(g.img,0,0);
			filla(0,0,320,480,"0,0,0",g.fade);
			writea("Hello, World !",160,110,"center","255,255,255",32,"Bangers","normal",g.fade);
			if (g.fade < 1) { g.fade += 0.01; }

			setTimeout("loop()", 40);
		};

		function fill(x,y,w,h,c)
		{
			c = c ? c : "#000000";
			g.ctx.fillStyle = c;
			g.ctx.fillRect(x,y,w,h);
		};

		function filla(x,y,w,h,c,a)
		{
			c = c ? c : "0,0,0";
			a = a ? a : 0.5;
			g.ctx.fillStyle = "rgba(" + c + "," + a + ")";
			g.ctx.fillRect(x,y,w,h);
		};

		function write(t,x,y,a,c,s,f,w)
		{
			c = c ? c : "#ffffff";
			a = a ? a : "left";
			s = s ? s : 10;
			f = f ? "'" + f + "'" : "Sans-Serif";
			w = w ? w : "normal";
			g.ctx.font = w + " " + s + "px " + f;
			g.ctx.textAlign = a;
			g.ctx.fillStyle = c;
			g.ctx.fillText(t,x,y);
		};

		function writea(t,x,y,a,c,s,f,w,alpha)
		{
			c = c ? c : "255,255,255";
			a = a ? a : "left";
			s = s ? s : 10;
			f = f ? f : "Sans-Serif";
			w = w ? w : "normal";
			alpha = alpha ? alpha : 1;
			g.ctx.font = w + " " + s + "px " + f;
			g.ctx.textAlign = a;
			g.ctx.fillStyle = "rgba(" + c + "," + alpha + ")";
			g.ctx.fillText(t,x,y);
		};

	</script>
</head>
<body onload="init();">

	<canvas width="320" height="480"></canvas>

</body>
</html>

Very straight forward. You can see that I set a variable called fade and have it increment slowly from zero to 1. By assigning this value to the new text writing function I achieve the effect of the background fading out whilst the foreground text fades in.

Visit this link to see it in action: fadeinout.html

This was only ever intended to be a basic introduction to using shapes and text. I’d like to elaborate on it a bit in a future post and cover gradients and arcs. Anyone familiar with my games will have seen me use gradients for sky transitions in a couple of cases. I am a big fan of them as I think they offer a useful programmatic solution to something that is typically controlled by the artist.

When Distant Orbit is complete I hope to offer a bit more of an insight in to the game’s structure with regard to the drawing.

%d bloggers like this: