Last active
August 4, 2016 19:16
-
-
Save rBurgett/1f3067005d9dbed92bb91130718ab4af to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Here is another way to do the Game constructor. This uses a constructor function, but makes use of the function closure. | |
* You will notice that all the annoying .bind() calls are gone, because we are no longer using the `this` keyword to reference | |
* properties and methods. Rather than storing those as properties and methods on an object, I use shared variables inside | |
* the closure. The benefits of this design are that anything within the closure is private, so nobody can accidentally | |
* change those functions or values. Then, at the bottom we expose three items which can be accessed outside of the closure. | |
* If we were using ES6, we could also make many of the variable into constants, which would add another layer of protection | |
* and reduce the surface area for bugs. The downside is that this is not as fast as a traditional constructor, but when we | |
* are just talking about a couple milliseconds the speed difference is a non-issue! The only time it would mean anything is | |
* if you are calling these tens of thousands of times at once. In that case, using the prototype and a traditional constructor | |
* is definitely the way to go. | |
* | |
* This is by far my preferred way to build constructors. | |
* | |
* To run the constructor and instantiate the class: | |
* var game = new Game({ | |
* levels: levels, | |
* ctx : canvas.getContext("2d"), | |
* tileSize : 16 | |
* }); | |
**/ | |
var EventEmitter = require("events").EventEmitter; | |
var Game = function(options) { | |
// private variables and functions | |
var defaultGrid = options.levels; | |
var ctx = options.ctx; | |
var tileSize = options.tileSize; | |
var cloneLevels = function(levels) { | |
return levels.map(function(level) { | |
return level.map(function(row) { | |
return row.concat(); | |
}); | |
}); | |
}; | |
var grid = cloneLevels(options.levels); | |
var events = new EventEmitter(); | |
var frozen = false; | |
var currentLevel = 0; | |
var charX = 1; | |
var charY = 1; | |
var moveQueue = []; | |
var tiles = { | |
0: "black", | |
1: "yellow", | |
2: "blue", | |
3: "red" | |
}; | |
var draw = function() { | |
if(!frozen && moveQueue.length > 0) { | |
moveQueue[0](); | |
} | |
moveQueue = []; | |
make(); | |
}; | |
var make = function() { | |
var level = currentLevel; | |
grid[level][charX][charY] = 2; | |
var row, col; | |
for (var i = 0; i < grid[level].length; i++) { | |
row = tileSize * i; | |
for (var j = 0; j < grid[level][0].length; j++) { | |
col = tileSize * j; | |
ctx.beginPath(); | |
ctx.rect(row, col, tileSize, tileSize); | |
ctx.fillStyle = tiles[grid[level][i][j]]; | |
ctx.fill(); | |
ctx.closePath(); | |
} | |
} | |
}; | |
var moveRight = function() { | |
var level = currentLevel; | |
if(charX < 19) { | |
if (grid[level][charX + 1][charY] === 0) { | |
grid[level][charX][charY] = 0; | |
charX += 1; | |
grid[level][charX][charY] = 2; | |
} else if (grid[level][charX + 1][charY] === 3) { | |
levelUp(); | |
} | |
} | |
}; | |
var moveLeft = function() { | |
var level = currentLevel; | |
if(charX > 0) { | |
if (grid[level][charX - 1][charY] === 0) { | |
grid[level][charX][charY] = 0; | |
charX -= 1; | |
grid[level][charX][charY] = 2; | |
} else if (grid[level][charX - 1][charY] === 3) { | |
levelUp(); | |
} | |
} | |
}; | |
var moveUp = function() { | |
var level = currentLevel; | |
if(charY > 0) { | |
if (grid[level][charX][charY -1] === 0) { | |
grid[level][charX][charY] = 0; | |
charY -= 1; | |
grid[level][charX][charY] = 2; | |
} else if (grid[level][charX][charY -1] === 3) { | |
levelUp(); | |
} | |
} | |
}; | |
var moveDown = function() { | |
var level = currentLevel; | |
if(charY < 19) { | |
if (grid[level][charX][charY + 1] === 0) { | |
grid[level][charX][charY] = 0; | |
charY += 1; | |
grid[level][charX][charY] = 2; | |
} else if (grid[level][charX][charY + 1] === 3) { | |
levelUp(); | |
} | |
} | |
}; | |
var levelUp = function() { | |
moveQueue = []; | |
if (currentLevel === grid.length - 1) { | |
frozen = true; | |
events.emit("gameOver"); | |
} else { | |
frozen = true; | |
currentLevel++; | |
events.emit("leveledUp", {currentLevel: currentLevel + 1}); | |
charX = 1; | |
charY = 1; | |
frozen = false; | |
} | |
}; | |
var keyDownHandler = function(e) { | |
switch(e.keyCode) { | |
case 39: | |
moveQueue.push(moveRight); | |
break; | |
case 37: | |
moveQueue.push(moveLeft); | |
break; | |
case 38: | |
moveQueue.push(moveUp); | |
break; | |
case 40: | |
moveQueue.push(moveDown); | |
break; | |
} | |
}; | |
// publicly exposed variables and functions | |
this.restart = function() { | |
events.emit("restart"); | |
grid = cloneLevels(defaultGrid); | |
charX = 1; | |
charY = 1; | |
currentLevel = 0; | |
frozen = false; | |
moveQueue = 0; | |
make(); | |
}; | |
this.start = function() { | |
document.addEventListener("keydown", keyDownHandler); | |
setInterval(function() { | |
draw(); | |
}, 90); | |
}; | |
this.events = events; | |
}; | |
module.exports = Game; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment