Implement the Game Logic | Modern Ludo
Think of the game, we know that we have 4 teams in play. At a given time, all we need to see is where these 16 planes are. For the game engine, all it needs to know is the coordinates of these 16 planes. So we need to create another map which has a different value for each and every position a plane might be placed. So here it is:
function createValueMap() {
var mapxy = new Array();
mapxy.push([00, 00, 00, 00, 01, 02, 03, 04, 05, 06, 07, -4, 00, 00, 00]);
mapxy.push([00, 00, 00, 00, 52, 00, 00, 60, 00, 00, 08, 00, 00, 00, 00]);
mapxy.push([00, 00, 00, 00, 51, 00, 00, 61, 00, 00, 09, 00, 00, 00, 00]);
mapxy.push([-5, 00, 00, 00, 50, 00, 00, 62, 00, 00, 10, 00, 00, 00, 00]);
mapxy.push([46, 47, 48, 49, 00, 00, 00, 63, 00, 00, 00, 11, 12, 13, 14]);
mapxy.push([45, 00, 00, 00, 00, 00, 00, 64, 00, 00, 00, 00, 00, 00, 15]);
mapxy.push([44, 00, 00, 00, 00, 00, 00, 65, 00, 00, 00, 00, 00, 00, 16]);
mapxy.push([43, 90, 91, 92, 93, 94, 95, 99, 75, 74, 73, 72, 71, 70, 17]);
mapxy.push([42, 00, 00, 00, 00, 00, 00, 85, 00, 00, 00, 00, 00, 00, 18]);
mapxy.push([41, 00, 00, 00, 00, 00, 00, 84, 00, 00, 00, 00, 00, 00, 19]);
mapxy.push([40, 39, 38, 37, 00, 00, 00, 83, 00, 00, 00, 23, 22, 21, 20]);
mapxy.push([00, 00, 00, 00, 36, 00, 00, 82, 00, 00, 24, 00, 00, 00, -3]);
mapxy.push([00, 00, 00, 00, 35, 00, 00, 81, 00, 00, 25, 00, 00, 00, 00]);
mapxy.push([00, 00, 00, 00, 34, 00, 00, 80, 00, 00, 26, 00, 00, 00, 00]);
mapxy.push([00, 00, 00, -2, 33, 32, 31, 30, 29, 28, 27, 00, 00, 00, 00]);
return mapxy;
}
Initialize the routes of all planes:
var roles = ["red", "yellow", "blue", "green"];
var routs = []; var specialPos = [];
function initiatePlaneRouts() {
//fly over index -->17 ~ 29 **57 each~~
var redRout = [
46, 47, 48, 49, 50, 51, 52, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 90, 91, 92, 93,
94, 95, 72];
var yellowRout = [
07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 01, 02, 03, 04, 60, 61, 62, 63,
64, 65, 82];
var blueRout = [
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 01, 02, 03,
04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 70, 71, 72, 73,
74, 75, 92];
var greenRout = [
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 80, 81, 82, 83,
84, 85, 62];
routs.push(redRout);
routs.push(yellowRout);
routs.push(blueRout);
routs.push(greenRout);
var redSpecial = [47, 51, 03, 07, 11, 15, 19, 23, 27, 31, 35, 39];
var yellowSpecial = [08, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52];
var blueSpecial = [21, 25, 29, 33, 37, 41, 45, 49, 01, 05, 09, 13];
var greenSpecial = [34, 38, 42, 46, 50, 02, 06, 10, 14, 18, 22, 26];
specialPos.push(redSpecial);
specialPos.push(yellowSpecial);
specialPos.push(blueSpecial);
specialPos.push(greenSpecial);
}
Now it’s time to create a JS object to represent the status of the game. The `playStatus’ basically holds all the positions of the 16 planes and other information like the name of the player, the color of the player, whether it’s allowed to take off, etc. The initial value -1 means it’s in the airport:
var playStatus = (function () {
var s = [];
for (var k = 0; k < roles.length; k++) {
var role = {
self: false,
name: null,
color: roles[k],
index: k,
allowTakeOff: false,
continuePlaying: false,
fly: false,
overLimit: 0,
touchBaseCount: 0,
win: false,
planes: []
};
for (var j = 0; j < 4; j++) {
var plane = {
previousValue: -1,
value: -1,
pos: {
left: -1,
top: -1,
right: -1,
bottom: -1
}
};
role.planes.push(plane);
}
s.push(role);
}
return s;
})();
When we have the positions of all planes, how to place them? Here are basically three scenarios
- The plane is in the airport
- The plane is in the runway preparing to take off
- The plane has taken off
For the first two scenarios, we use one function to handle it. This is a modified version of the function placeDefaultPlanes:
function placeDefaultPlanes(color, planeindex, atTheDoor) {
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";
if (planeindex != undefined) {//not initiation
var tempPosInd = 0;
if (atTheDoor == true) {
tempPosInd = 8;
}
else {
tempPosInd = planeindex * 2
}
upctx.drawImage(img, tileWidth * currentpos[tempPosInd], tileWidth * currentpos[tempPosInd + 1], tileWidth, tileWidth);
playStatus[i_role].planes[planeindex].pos.left = Math.floor(tileWidth * currentpos[tempPosInd]) - 1;
playStatus[i_role].planes[planeindex].pos.top = Math.floor(tileWidth * currentpos[tempPosInd + 1]) - 1;
playStatus[i_role].planes[planeindex].pos.right = Math.floor(tileWidth * currentpos[tempPosInd] + tileWidth) + 1;
playStatus[i_role].planes[planeindex].pos.bottom = Math.floor(tileWidth * currentpos[tempPosInd + 1] + tileWidth) + 1;
}
else {
return;
}
}
Each time a player throws the dice, we get the dice value. When a player clicks on a plane, we add the value to that plane. Below is the function called when a plane is clicked:
function aPlaneClicked(clickedindex, selfclick) {
var tempvar = clickedindex;
if (selfclick) {
var msg = JSON.stringify({ "planeclicked": tempvar });
sendJSONMessage(msg);
}
else {
notMe = true;
}
//////
if (playhand.role.planes[tempvar].value == 56)//clicking on one that has touched base. do nothing
return;
if (diceValue == 0) {
document.getElementById("info").innerText = "Please roll dice";
return;
}
if (diceValue != 6 && playhand.role.planes[tempvar].value == -1) {//There is a plane flying, but he choose to click on one in the airport
return;
}
playhand.role.planes[tempvar].previousValue = playhand.role.planes[tempvar].value;
switch (playhand.role.planes[tempvar].value) {
case -1: if (playhand.role.allowTakeOff) { playhand.role.allowTakeOff = false; playhand.role.planes[tempvar].value = -5 + playhand.value; } diceValue = 0; break;
default:
playhand.role.planes[tempvar].value += diceValue;
if (playhand.role.planes[tempvar].value > 55) {
playhand.role.overLimit = diceValue;
}
if (playhand.role.planes[tempvar].value < 57 && playhand.role.planes[tempvar].value > 0) {
var tempRoutValue = routs[playhand.role.index][playhand.role.planes[tempvar].value - 1];
for (var j = 0; j < specialPos[playhand.role.index].length; j++) {
if (specialPos[playhand.role.index][j] == tempRoutValue) {
switch (j) {
case 3: playhand.role.planes[tempvar].value += 16; playhand.role.fly = true; break;
case 4: playhand.role.planes[tempvar].value += 12; playhand.role.fly = true; break;
default: playhand.role.planes[tempvar].value += 4; playhand.role.fly = true; break;
}
}
}
}
diceValue = 0; break;
}
updatePlayBoard();
if (onmobile) {
dicectx.clearRect(0, 0, tileWidth * 2, tileWidth * 2);
}
else
dicectx.clearRect(0, 0, tileWidth * 4, tileWidth * 4);
}
Every time a plane value is changed, we update all planes:
function updatePlayBoard() {
var ifChangeHands = -1;
if (playhand.role) {
for (var i = 0; i < playhand.role.planes.length; i++) {
if (ifChangeHands < playhand.role.planes[i].value)
ifChangeHands = playhand.role.planes[i].value;
if (playhand.role.planes[i].value != playhand.role.planes[i].previousValue) {//a plane needs to be moved
var coordinates = moveAPlane(playhand.role.planes[i], playhand.role.planes[i].previousValue, playhand.role.planes[i].value);
playhand.role.planes[i].pos.left = Math.floor(coordinates.co_x) - 1;
playhand.role.planes[i].pos.top = Math.floor(coordinates.co_y) - 1;
playhand.role.planes[i].pos.right = Math.floor(coordinates.co_x + tileWidth) + 1;
playhand.role.planes[i].pos.bottom = Math.floor(coordinates.co_y + tileWidth) + 1;
if (playhand.role.planes[i].previousValue == playhand.role.planes[i].value) {
handcount++;
changeHands();
}
break;
}
}
}
if (ifChangeHands == -1 && clickOverflow != true) {
handcount++;
changeHands();
}
}
When a planes is hit, it gets sent home:
function hitAPlane(ind, val) {
for (var j = 0; j < 4; j++) {//role index
for (var k = 0; k < 4; k++) {//plane index in each role
if (j != ind && //Not the same color
playStatus[j].planes[k].value != 0 &&
routs[j][playStatus[j].planes[k].value - 1] == val) { //overlapped
playStatus[j].planes[k].value = -1; //This plane is sent back home, there might be more than 1 plane that get hit at a time
playStatus[j].planes[k].previousValue = -1;
}
}
}
}
Source Code
https://github.com/DynamsoftRD/Modern-Ludo
git clone https://github.com/DynamsoftRD/Modern-Ludo.git