The User Player
This particular object is the person that plays. It’s a child of our Player object.
function User(i, base, limit) {
'use strict';
this.setName();
// Call the parent constructor
Player.call(this, i, base, limit);
}
// Inherit Player
User.prototype = Object.create(Player.prototype);
Events Handlers
Our player is using his mouse to play. Right. So we need events handlers. We’re going to use jQuery here as well.
For a click, we attempt to execute the action. When the mouse moves, we attempt to preview it. If the mouse is out, we simply refresh the rendering.
User.prototype.play = function () {
'use strict';
// We won't be able to access "this" in the coming event-handlers
var user = this;
// Reset the action
user.action = false;
jQuery(game.canvas).click(function (event) {
// If the user clicked, we get the action corresponding to the current mouse position
user.setAction(event);
if (!user.action) {
// Wrong action : let's display the concerned rule
user.alert(game.rule);
} else {
// Good action : Let's unbind those handlers and execute it !
jQuery(game.canvas).unbind();
if (user.action instanceof Square) { user.move(user.action); } else { user.putUp(user.action); }
}
});
jQuery(game.canvas).mousemove(function (event) {
// Every time the mouse is moving over the canvas, we get the action that its position would trigger on a click
if (user.setAction(event)) {
// We render and preview that action
game.render(user.action);
// And we update the cursor
jQuery(game.canvas).css('cursor', (user.action !== false) ? 'default' : 'not-allowed');
}
});
// If the mouse is exiting the board, we reset and redraw
jQuery(game.canvas).mouseout(function () {
user.action = false;
game.render();
});
};
Action Detection
For a given event (an object containing our mouse position), we can guess which object to return.
If the pointer is over a span (a gap between two squares), we guess a fence. Otherwise (and as long as it is over a pattern unit) we guess a Square. Then if we have a valid Object, we return it. We return false in any other situation.
User.prototype.setAction = function (event) {
'use strict';
// Get the mouse position from the event object
var offset = jQuery(game.canvas).offset(),
pointer = {x: (event.pageX - offset.left) / game.pattern, y: (event.pageY - offset.top) / game.pattern},
// From this position we deduce the action implied
action = this.getSpan(pointer) || this.getSquare(pointer);
// Was this action already requested ? Are we actually talking about an action currently showed as a preview ?
if ((action.a === this.action.a) && (action.b === this.action.b) && ((action instanceof Square && this.action instanceof Square) || (action.horizontal === this.action.horizontal))) {
// If yes, then our job here is done.
return false;
}
// Is this a valid action ?
if (((action instanceof Square) && this.validSquare(action)) || (!(action instanceof Square) && game.validFence(action, this.limit))) {
// If yes, let's set it up and return true
this.action = action;
return true;
}
// Was the last action invalid as well ?
action = !!this.action;
this.action = false;
// And we return the answer to the question : was a new action set ?
return action;
};
Action Getters
Those methods attempt to catch a particular action (a fence or a square).
User.prototype.getSpan = function (pointer) {
'use strict';
// "a" and "b" here are the pattern coordinates, and "x" and "y" the coordinates of the pointer within this pattern unit.
var shift = game.units.square / 2,
a = Math.floor(pointer.x),
b = Math.floor(pointer.y),
x = pointer.x - a,
y = pointer.y - b,
horizontal;
// If we don't have any fences left, no need to continue
if (this.left === 0) { return false; }
// Is our pointer over a span (a gap between two squares) ?
if ((x > game.units.square) || (y > game.units.square)) {
horizontal = (x < y);
a = (horizontal && (x < shift)) ? a - 1 : a;
b = (!horizontal && (y < shift)) ? b - 1 : b;
// Avoid the fence to be defined out of the board
if (a < 0) { a = 0; } else if (a >= game.size) { a = game.size - 1; }
if (b < 0) { b = 0; } else if (b >= game.size) { b = game.size - 1; }
// Yep, let's return the corresponding fence
return {a: a, b: b, horizontal: horizontal};
}
// Nope, no fence to return
return false;
};
User.prototype.getSquare = function (pointer) {
'use strict';
// Returning the closest Square.
return game.board[Math.floor(pointer.x)][Math.floor(pointer.y)];
};
Alert Messages
Displays a given rule in the game’s caption.
User.prototype.alert = function (rule) {
'use strict';
// Remind the user of a rule
jQuery('#caption').html(jQuery('#rule-' + rule).html());
};