/*Downloaded from https://www.codeseek.co/benlorantfy/dots-and-boxes-vWPbGy */
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
/**
* A class that abstracts the firebase api so we can specify our
* own api, using the adapter design pattern.
*
* Minimze this if you don't care
*/
var FireQuery = function () {
function FireQuery(ref) {
_classCallCheck(this, FireQuery);
this.ref = ref;
this.cancelled = false;
this.numCalls = 0;
}
_createClass(FireQuery, [{
key: 'orderByChild',
value: function orderByChild(child) {
this.ref = this.ref.orderByChild(child);
return this; // Return this so we can chain them
}
}, {
key: 'limitToFirst',
value: function limitToFirst(n) {
this.ref = this.ref.limitToFirst(n);
return this;
}
}, {
key: 'off',
value: function off() {
this.cancelled = true;
this.ref.off('child_added');
}
}, {
key: 'twice',
value: function twice(callback) {
var _this = this;
this.ref.on('child_added', function () {
if (_this.numCalls < 2 && !_this.cancelled) {
_this.numCalls++;
callback.apply(undefined, arguments);
} else if (!_this.cancelled) {
_this.ref.off('child_added');
}
});
return this;
}
}]);
return FireQuery;
}();
var Server = function () {
function Server() {
_classCallCheck(this, Server);
this.joined = false;
}
_createClass(Server, [{
key: 'setup',
value: function setup() {
var _this2 = this;
var config = {
apiKey: "AIzaSyARzEfIvAiWvjGv2khFL0koGbLpcZE0U2k",
authDomain: "ben-codepen.firebaseapp.com",
databaseURL: "https://ben-codepen.firebaseio.com",
projectId: "ben-codepen",
storageBucket: "ben-codepen.appspot.com",
messagingSenderId: "141282204522"
};
firebase.initializeApp(config);
this.db = firebase.database();
firebase.auth().signInAnonymously().then(function (user) {
_this2.user = user;
_this2.db.ref('/dots-and-boxes/lobby/' + _this2.user.uid).update({
timestamp: firebase.database.ServerValue.TIMESTAMP
}).then(function () {
_this2.joinGame();
});
});
}
}, {
key: 'joinGame',
value: function joinGame() {
var _this3 = this;
// 1. find player who has been waiting the longest
// 2. try to create a game with that player
// - firebase should only allow one game
// 3. if failure, try again later
// note: at any point, we want to cancel this process if another player
// adds this player to their game
// Get's a ref to the dots and boxes lobby, which is
// where all the unmatched players sit
var ref = this.db.ref('/dots-and-boxes/lobby');
// Look for the oldest two players in the lobby. We
// need two players because one of them might be the
// current player
var qry = new FireQuery(ref).orderByChild('timestamp').limitToFirst(2).twice(function (player) {
// We don't care if the player is the current player,
// we're trying to find the oldest player that isn't the current player
if (player.key === _this3.user.uid) return;
// As soon as we find a player that isn't the current player,
// we can cancel the qry. This is for the case that the two oldest
// players aren't this player, in which case we only want one of them
if (player.key !== _this3.user.uid) {
qry.off();
}
// The following code should only execute once with the oldest
// player that isn't the current player
var foeId = player.key;
_this3.db.ref('/dots-and-boxes/games/' + _this3.user.uid + '-' + foeId).set({
lines: []
}).then(function () {
console.log('wazzup'); // a
}).catch(function () {
console.log('damn son'); // b
});
});
// let qry = ref
// // We want to get the players waiting the longest
// .orderByChild('timestamp')
// // We need to look for the first 2 people in the lobby, because the person waiting the longest
// // could be the current player
// .limitToFirst(2)
// .once('child_added', (player) => {
// console.log(player.key);
// // ref.off('child_added');//////
// // if (player.key === this.user.uid) return;
// ////
// // console.log(player.key )
// // const playerId = player.key;
// // this.db.ref(`/dots-and-boxes/games/${this.user.uid}-${playerId}`).set({
// // lines: []
// // }).then(() => {
// // console.log('wazzup'); //
// // })
// });
}
}]);
return Server;
}();
var Game = function Game() {
_classCallCheck(this, Game);
this.currentLine = [];
this.width = 4;
this.height = 4;
this.lines = [{ player: 1, x1: 0, y1: 0, x2: 1, y2: 0 }, { player: 2, x1: 1, y1: 1, x2: 1, y2: 2 }];
};
var GameController = function () {
function GameController(_ref) {
var _this4 = this;
var game = _ref.game,
window = _ref.window,
server = _ref.server;
_classCallCheck(this, GameController);
var canvas = window.document.getElementsByTagName('canvas')[0];
var width = window.innerWidth;
var height = window.innerHeight;
this.game = game;
this.window = window;
// Start the drawer
this.drawer = new Drawer({ game: game, canvas: canvas, width: width, height: height });
// Setup the events
this.watchMouseDown();
this.watchMouseMove();
// Resize game on window resize
window.addEventListener("resize", function () {
_this4.drawer.resize(window.innerWidth, window.innerHeight);
});
// Start the game loop
raf(function () {
return _this4.gameLoop();
});
// Setup the server
server.setup();
}
_createClass(GameController, [{
key: 'gameLoop',
value: function gameLoop() {
var _this5 = this;
var mouseWasPressedDown = this.mousedown && !this.oldMouseDown;
var mouseWasLetGo = !this.mousedown && this.oldMouseDown;
var mouseWasMoved = this.oldMouseX !== this.mouseX || this.oldMouseY !== this.mouseY;
var mouseWasMovedWhilePressedDown = mouseWasMoved && this.mousedown && this.oldMouseDown;
if (mouseWasMovedWhilePressedDown) {
this.game.currentLine.push({ x: this.drawer.toGridX(this.mouseX), y: this.drawer.toGridY(this.mouseY) });
}
if (mouseWasPressedDown) {
this.dragStartX = this.mouseX;
this.dragStartY = this.mouseY;
}
if (mouseWasLetGo) {
this.game.currentLine = [];
this.dragEndX = this.mouseX;
this.dragEndY = this.mouseY;
this.createLine();
}
this.oldMouseDown = this.mousedown;
this.oldMouseX = this.mouseX;
this.oldMouseY = this.mouseY;
raf(function () {
return _this5.gameLoop();
});
}
}, {
key: 'createLine',
value: function createLine() {
var x1 = this.drawer.toRoundedGridX(this.dragStartX);
var y1 = this.drawer.toRoundedGridY(this.dragStartY);
var x2 = this.drawer.toRoundedGridX(this.dragEndX);
var y2 = this.drawer.toRoundedGridY(this.dragEndY);
// Validate the line
var isHorizontal = x1 === x2;
var isVertical = y1 === y2;
var isNotDiagonal = isHorizontal || isVertical;
var verticalNeighbours = x2 === x1 + 1 || x2 === x1 - 1;
var horizontalNeighbours = y2 === y1 + 1 || y2 === y1 - 1;
var areNeighbours = verticalNeighbours || horizontalNeighbours;
var withinHorizontalBounds = x1 >= 0 && x2 >= 0 && x1 < this.game.width && x2 < this.game.width;
var withinVerticalBounds = y1 >= 0 && y2 >= 0 && y1 < this.game.height && y2 < this.game.height;
var isValid = isNotDiagonal && areNeighbours && withinHorizontalBounds && withinVerticalBounds;
if (isValid) {
var line = {
player: 1,
x1: x1,
x2: x2,
y1: y1,
y2: y2
};
this.game.lines.push(line);
}
}
}, {
key: 'watchMouseDown',
value: function watchMouseDown() {
var _this6 = this;
this.oldMouseDown = this.mousedown = false;
this.window.addEventListener("mousedown", function () {
return _this6.mousedown = true;
});
this.window.addEventListener("mouseup", function () {
return _this6.mousedown = false;
});
this.window.addEventListener("mouseout", function () {
return _this6.mousedown = false;
});
}
}, {
key: 'watchMouseMove',
value: function watchMouseMove() {
var _this7 = this;
this.window.addEventListener("mousemove", function (e) {
_this7.mouseX = e.pageX;
_this7.mouseY = e.pageY;
});
}
}]);
return GameController;
}();
var Drawer = function () {
function Drawer(_ref2) {
var _this8 = this;
var game = _ref2.game,
canvas = _ref2.canvas,
width = _ref2.width,
height = _ref2.height;
_classCallCheck(this, Drawer);
var context = canvas.getContext('2d');
this.canvas = canvas;
this.game = game;
this.ctx = context;
this.dotColor = "black";
this.dotSize = 4;
this.dotSpacing = 50;
this.p1Color = "red";
this.p2Color = "blue";
this.resize(width, height);
raf(function () {
return _this8.draw();
});
}
_createClass(Drawer, [{
key: 'clear',
value: function clear() {
this.ctx.fillStyle = "white";
this.ctx.beginPath();
this.ctx.rect(0, 0, this.width, this.height);
this.ctx.closePath();
this.ctx.fill();
}
}, {
key: 'draw',
value: function draw() {
var _this9 = this;
this.clear();
this.drawLines();
this.drawDots();
this.drawCurrentLine();
raf(function () {
return _this9.draw();
});
}
}, {
key: 'drawDots',
value: function drawDots() {
var padding = this.dotSpacing;
var gridLeft = this.gridLeft;
var gridTop = this.gridTop;
for (var i = 0; i < this.game.width; i++) {
for (var j = 0; j < this.game.height; j++) {
this.ctx.beginPath();
this.ctx.arc(gridLeft + i * padding, gridTop + j * padding, this.dotSize, 0, 2 * Math.PI, false);
this.ctx.fillStyle = this.dotColor;
this.ctx.fill();
}
}
}
}, {
key: 'drawLines',
value: function drawLines() {
var padding = this.dotSpacing;
var gridLeft = this.gridLeft;
var gridTop = this.gridTop;
for (var i = 0; i < this.game.lines.length; i++) {
var line = this.game.lines[i];
this.ctx.beginPath();
this.ctx.moveTo(this.toGlobalX(line.x1), this.toGlobalY(line.y1));
this.ctx.lineTo(this.toGlobalX(line.x2), this.toGlobalY(line.y2));
if (line.player === 1) this.ctx.strokeStyle = this.p1Color;
if (line.player === 2) this.ctx.strokeStyle = this.p2Color;
this.ctx.stroke();
}
}
}, {
key: 'drawCurrentLine',
value: function drawCurrentLine() {
var _this10 = this;
this.ctx.beginPath();
this.game.currentLine.forEach(function (p, i) {
if (i === 0) {
_this10.ctx.moveTo(_this10.toGlobalX(p.x), _this10.toGlobalY(p.y));
} else {
_this10.ctx.lineTo(_this10.toGlobalX(p.x), _this10.toGlobalY(p.y));
}
});
this.ctx.strokeStyle = this.p1Color;
this.ctx.stroke();
}
}, {
key: 'toRoundedGridX',
value: function toRoundedGridX(x) {
return Math.round(this.toGridX(x));
}
}, {
key: 'toRoundedGridY',
value: function toRoundedGridY(y) {
return Math.round(this.toGridY(y));
}
}, {
key: 'toGridX',
value: function toGridX(x) {
return (x - this.gridLeft) / this.dotSpacing;
}
}, {
key: 'toGridY',
value: function toGridY(y) {
return (y - this.gridTop) / this.dotSpacing;
}
}, {
key: 'toGlobalX',
value: function toGlobalX(x) {
return this.gridLeft + this.dotSpacing * x;
}
}, {
key: 'toGlobalY',
value: function toGlobalY(y) {
return this.gridTop + this.dotSpacing * y;
}
}, {
key: 'resize',
value: function resize(newWidth, newHeight) {
this.width = newWidth;
this.height = newHeight;
this.gridLeft = this.width / 2 - this.dotSpacing * this.game.width / 2;
this.gridTop = this.height / 2 - this.dotSpacing * this.game.height / 2;
this.canvas.setAttribute("width", newWidth);
this.canvas.setAttribute("height", newHeight);
}
}]);
return Drawer;
}();
var Main = function Main(window) {
_classCallCheck(this, Main);
var game = new Game();
var server = new Server();
var controller = new GameController({ game: game, window: window, server: server });
};
new Main(window);