Placing the Airports and Planes | Modern Ludo

Compared with the regular tiles or ‘stations’ we talked about, the airport is not a regular shape. So a lot of math is involved in the creation of the airport. First of all, we want the airport to appear as a rounded rectangle. So we add a method to the canvas object. Reference: http://stackoverflow.com/questions/1255512/how-to-draw-a-rounded-rectangle-on-html-canvas.

CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) {
    if (w < 2 * r) r = w / 2;
    if (h < 2 * r) r = h / 2;
    this.beginPath();
    this.moveTo(x + r, y);
    this.arcTo(x + w, y, x + w, y + h, r);
    this.arcTo(x + w, y + h, x, y + h, r);
    this.arcTo(x, y + h, x, y, r);
    this.arcTo(x, y, x + w, y, r);
    this.closePath();
    return this;
}

Then we draw our first airport stroke by stroke. It’s quite some work but that’s the beauty of the Canvas element! You can draw on it just like a real canvas and it’s done in a millisecond.

function drawAirPort(color, x, y) {
    switch (color) {
        case "blue": color = "#9696FF"; break;
        case "red": color = "#FF0000"; break;
        case "green": color = "#33B433"; break;
        case "yellow": color = "#FFCC00"; break;
        case "white": color = "#FFFFFF"; break;
    }

    ctx.shadowBlur = 0;
    ctx.fillStyle = color;
    ctx.beginPath();
    ctx.arc(x - 1.5 * tileWidth, y + tileWidth * 1.5, tileWidth * 0.5, 2 * Math.PI, 0, true);
    ctx.fill();
    ctx.fillStyle = "lightgrey";
    ctx.strokeStyle = "lightgrey";
    ctx.lineWidth = 1;
    ctx.shadowBlur = 20;
    ctx.shadowColor = "grey";
    ctx.roundRect(x - 1.5 * tileWidth + tileWidth / 2 * 0.8, y - tileWidth * 2, tileWidth * 3, tileWidth * 3, tileWidth / 3).stroke();
    ctx.fill();
    ctx.shadowBlur = 0;
    ctx.moveTo(x - 1.0 * tileWidth, y + 0.5 * tileWidth);
    ctx.lineTo(x - 1.5 * tileWidth, y + 1.1 * tileWidth);
    ctx.arc(x - 1.5 * tileWidth, y + tileWidth * 1.5, tileWidth * 0.4, 1.5 * Math.PI, 0, true);
    ctx.lineTo(x - 0.5 * tileWidth, y + 1.0 * tileWidth);
    ctx.closePath();
    ctx.stroke();
    ctx.fill();
    ctx.fillStyle = color;
    ctx.roundRect(x - 1.0 * tileWidth, y - 1.9 * tileWidth, tileWidth * 1.4, tileWidth * 1.4, tileWidth / 6).stroke();
    ctx.fill();
    ctx.roundRect(x + 0.4 * tileWidth, y - 1.9 * tileWidth, tileWidth * 1.4, tileWidth * 1.4, tileWidth / 6).stroke();
    ctx.fill();
    ctx.roundRect(x - 1.0 * tileWidth, y - 0.5 * tileWidth, tileWidth * 1.4, tileWidth * 1.4, tileWidth / 6).stroke();
    ctx.fill();
    ctx.roundRect(x + 0.4 * tileWidth, y - 0.5 * tileWidth, tileWidth * 1.4, tileWidth * 1.4, tileWidth / 6).stroke();
    ctx.fill();
}

Take a look at the red airport drawn with this line of code:

drawAirPort("red", tileWidth * 2.5, tileWidth * 2.5);

Draw the first airport

The rest is easy, we just draw 3 more airports with different colors and put them in the right place with the help of the built-in Canvas methods translate, rotate, etc.

    drawAirPort("red", tileWidth * 2.5, tileWidth * 2.5);

    ctx.translate(tileWidth * 13.5, tileWidth * 2.5)

    ctx.rotate(90 * Math.PI / 180);

    drawAirPort("yellow", 0, 0);

    ctx.translate(tileWidth * 11, tileWidth * 11)

    ctx.rotate(180 * Math.PI / 180);

    drawAirPort("green", 0, 0);

    ctx.restore();

    ctx.rotate(360 * Math.PI / 180);

    ctx.translate(0, tileWidth * 11)

    ctx.rotate(270 * Math.PI / 180);

    drawAirPort("blue", 0, 0);

    ctx.restore();

Now the board is almost ready:

Draw all airports

The next step is to put the planes onto the board. Drawing the planes can be a lot of fun, but it is not wise choice considering how much time we would have to spend on it, so we just decided to use a ready-made picture. By doing this, we save a lot of time, moreover, we can change how the planes look like easily. This means that you can have custom planes.
Here are the planes:

planes

In order to make these planes available for our canvas, we put them on the page but make them hidden, for now:

   <div style="display:none;">

        <img id="redplane" src="Images/redplane.png" alt="plane" />

        <img id="blueplane" src="Images/blueplane.png" alt="plane" />

        <img id="greenplane" src="Images/greenplane.png" alt="plane" />

        <img id="yellowplane" src="Images/yellowplane.png" alt="plane" />

    </div>

The next step, we’ll put all planes on the airports. The planes are what actually move around on the board, in order to keep it separated from the board itself, we place another transparent canvas over the board.

   <div id="playGround" style="display:none;">

        <div id="main">

            <canvas id="gameboard"></canvas>

            <canvas id="playboard"></canvas>

        </div>

    </div>

To use the new canvas, we added a few lines in the function initPlayGround as shown below:

    upcanvas = document.getElementById("playboard");

    upctx = upcanvas.getContext("2d");

    upcanvas.setStyle = function (styleMap) {

        var styleString = new String();

        for (i in styleMap) {

            styleString += i + ':' + styleMap[i] + '; ';

        }

        upcanvas.setAttribute('style', styleString);

    }

    var canvasStyle = {

        'border': '1px solid grey'

    };

    upcanvas.setStyle(canvasStyle);

Also, we need to set its width & height in the function refreshBoard:

upctx.canvas.width = canvasWidth;
upctx.canvas.height = canvasWidth;

Now we have the canvas for the planes to actually move around. We find out the initial coordinates (based on how wide each tile is) to where we put them. I did this by moving the planes around until I got them in the best location:

function placeDefaultPlanes(color) {

    var redposes = [1.65, 0.75, 3.05, 0.75, 1.65, 2.15, 3.05, 2.15, 0.5, 3.5];

    var yellowposes = [12.75, 1.65, 14.15, 1.65, 12.75, 3.05, 14.15, 3.05, 11.5, 0.5];

    var blueposes = [11.85, 12.75, 13.25, 12.75, 11.85, 14.15, 13.25, 14.15, 14.5, 11.5];

    var greenposes = [0.75, 11.85, 2.15, 11.85, 0.75, 13.25, 2.15, 13.25, 3.5, 14.5];

    var currentpos = null;

    var i_role = null;

    switch (color) {

        case "red": currentpos = redposes; i_role = 0; break;

        case "yellow": currentpos = yellowposes; i_role = 1; break;

        case "blue": currentpos = blueposes; i_role = 2; break;

        case "green": currentpos = greenposes; i_role = 3; break;

        default: break;

    }

    var currentplane = color + "plane";

    var img = document.getElementById(currentplane);

    upctx.shadowBlur = 10;

    upctx.shadowOffsetX = 2;

    upctx.shadowOffsetY = 2;

    upctx.shadowColor = "black";

    for (var i = 0; i < 8; i++) {

        upctx.drawImage(img, tileWidth * currentpos[i], tileWidth * currentpos[++i], tileWidth, tileWidth);

    }

}

Now by simply calling the above method for 4 different colors in initPlayGround, we can place these planes in their starting positions.

    placeDefaultPlanes("red");

    placeDefaultPlanes("yellow");

    placeDefaultPlanes("blue");

    placeDefaultPlanes("green");

Take another look at the board, we are almost ready to play.

Place the planes to their initial positions

The one important thing that we are missing now is the die. For this, we use another canvas, and put use 6 images to represent sides one to six of a die in the markup:

<div id="playGround" style="display:none;">

        <div id="main">

            <canvas id="gameboard"></canvas>

            <canvas id="playboard"></canvas>

            <canvas id="dice"></canvas>

        </div>

    <div style="display:none;">

        <img id="redplane" src="Images/redplane.png" alt="plane" />

        <img id="blueplane" src="Images/blueplane.png" alt="plane" />

        <img id="greenplane" src="Images/greenplane.png" alt="plane" />

        <img id="yellowplane" src="Images/yellowplane.png" alt="plane" />

        <img id="diceone" src="Images/diceone.png" alt="dice" />

        <img id="dicetwo" src="Images/dicetwo.png" alt="dice" />

        <img id="dicethree" src="Images/dicethree.png" alt="dice" />

        <img id="dicefour" src="Images/dicefour.png" alt="dice" />

        <img id="dicefive" src="Images/dicefive.png" alt="dice" />

        <img id="dicesix" src="Images/dicesix.png" alt="dice" />

    </div>

And a button to roll the die:

   <div id="buttondiv" style="visibility:hidden; margin-top:0; padding-top:0;">

        <input type="button" id="rollDice" value="Roll the Dice" style="height:40px; cursor:pointer;" onclick="rolltheDice(this)" />

    </div>

Here are the dice:

dice

As we’ve done before, we initiate the new canvas in the function initPlayGround

     dicecanvas = document.getElementById("dice");

     dicectx = dicecanvas.getContext("2d");

And place it in the left top corner using the function refreshboard

   document.getElementById("buttondiv").style.left = tileWidth * 2 + "px";

   document.getElementById("buttondiv").style.top = tileWidth * 7.5 + "px";

Auto-resize this canvas in refreshBoard

dicectx.canvas.width = tileWidth * 4;

dicectx.canvas.height = tileWidth * 6;

Please note that the code to place the new canvas is written in CSS which we’ll not discuss here.

Now let’s place one die on the screen

var img = document.getElementById("diceone");

dicectx.drawImage(img, 50, 20, tileWidth * 2, tileWidth * 2);

Here is what it looks like:

draw all airports final

Now we’ll make the die roll by using a random number between 1 and 6:

function rolltheDice(btn) {

    dicectx.clearRect(0, 0, tileWidth * 4, tileWidth * 4);

    var diceposi = [0, 1, 1, 0];

    var diceposj = [0, 0, 1, 1];

    var i = -1;

    var rolling = setInterval(function () {

        dicectx.clearRect(tileWidth * 2 * (diceposi[i % 4]), tileWidth * 2 * (diceposj[i % 4]), tileWidth * 2, tileWidth * 2);

        diceValue = Math.floor((Math.random() * 6) + 1);

        var img = returnDiceImg(diceValue);

        i++;

        dicectx.drawImage(img, tileWidth * 2 * (diceposi[i % 4]), tileWidth * 2 * (diceposj[i % 4]), tileWidth * 2, tileWidth * 2);

    }, 180);

    setTimeout(function () {

        clearInterval(rolling);

    }, 2000);

}

With this function, once you click the button “Roll the dice”, the die images will appear one after another for 2 seconds. We’ve got almost all the UI stuff we need for the game now.

Source Code

Makeing a Modern Ludo Game Step TwoMakeing a Modern Ludo Game Step Two