Making an HTML5 version of the Game Pente: Part 2 Drawing Stones

Last week I opened a new series documenting how we are going about writing a HTML5 version of Pente for a class project. The first part focused on creating a Pente board, which is a simple series of lines forming a grid. Today I want to do a quick demo on how to draw circles on a Canvas to represent the stones. In the process I will utilize a JavaScript pattern I love to use to accomplish method overloading

Drawing a Solid Circle on an HTML Canvas

Before I get into code refactoring let's look at how to draw a circle on a Canvas element. Recalling what we learned last week to draw on Canvas you need to get a reference to it's context. Which looks like the following:

var

canvas = document.getElementById (

"PenteBoard"

),
context = canvas.getContext (

"2d"

);

Also like last week you need to use the beginPath method to initiate the drawing process. Before creating the circle you need to designate what the object's fill color should be using the fillStyle property. In this case we want a solid black circle. I am using the rgb() method here, passing in 0 for red, green and blue. You can also use the common #000 syntax, just remember to wrap the value in "".

context.beginPath();
context.fillStyle =

"rgb(0,0,0)"

;
context.arc(100, 100, 25 + 0.01,
0, 2 * Math.PI

true

);
context.fill();

Next to create the circle we need to call the arc method. This method has multiple parameters. The first two are the x & y coordinates for the center of the circle. The third parameter is the circle's radius. The next two parameters are for the start and stop angles. Having control over the start and stop gives you the power to create arcs and semi-circles as well as a full circle like we need for Pente stones. The final parameter designates if the arc will be drawn in a clockwise direction or reverse. It is optional and assumes clockwise by default.

To complete the circle call the context's fill method. This fills in the desired color, making the circle a solid element. Otherwise we would just have the circle's circumference drawn. Note if you do not designate a fillStyle it will default to black.

Refactoring To A Reusable Method

Now if you know me you know I am satisfied with this. I see a common pattern I plan on using over and over again. So let's refactor all this into a method we can reuse with some default values. Because the steps to draw a circle require multiple values I chose to use an anonymous object to manage these values. I love using this pattern because it makes a method extremely flexible, while providing much needed defaults. It utilizes the jQuery $.extend method. This is one of the jQuery utility methods I use all the time. There are other variations available in other libraries, like underscore.js that you may prefer.

The advantage this technique gives you is the ability to define the default settings and merge them with any corresponding values passed to the method. You can have as many objects as you want passed into the $.extend method. I will apply the values from left to right. In the example below the first object is empty, to guarantee an empty slate to start with. The next parameter is an object defining all the defaults needed to make the drawCircle method work. The final object is the options parameter, which is the method's only parameter. Any member values included in the options object will be merged with the defaults and override them. If there is not a value for one of the properties the default is retained. The $.extend method returns the fully merged object, which in this example is set to the options variable.

function

drawCircle( options){

options = $.extend ({}, {
context : undefined ,
fillStyle :

"rgb(0,0,0)"

,
x : 100 ,
y : 100 ,
radius : 25 ,
startAngle : 0 ,
endAngle : 2 * Math.PI ,
clockwise :

true


}, options );

if

( !options.context ){

return

;
}

var

context = options.context ;

context.beginPath ();
context.fillStyle = options.fillStyle ;
context.arc (options.x ,
options.y ,
options.radius + 0. 01 ,
options.startAngle ,
options.endAngle ,
options.clockwise );
context.fill ();

};

After the options have been set the method checks to make sure we have a context to work against. If not it simply returns and no circle will be drawn. Notice the default context value is undefined. This means the calling method must at least pass in a context for a circle to be drawn. The remaining values can use the default values if nothing was defined. The rest of the drawCircle code is the code to draw the stone. Notice we do not use any hard coded values, but rather the members of the options object.

Now that we have a nice reusable method we can start drawing circles. The following examples draw a semi-circle and a full circle.

drawCircle ({
context : context ,
x : 100 ,
y : 100 ,
radius : 35 ,
startAngle : 0 ,
endAngle : 1 * Math.PI ,
clockwise :

false


});

drawCircle ({
context : context ,
x : 200 ,
y : 100 ,
radius : 15
});


In the next step we will examine how to place the circles on the board in response to a user selecting a position on the Pente board. This will involve working with both mouse and touch events and some math.

Share This Article With Your Friends!

Googles Ads Facebook Pixel Bing Pixel LinkedIn Pixel