From df60e5870640fe22597ae942cc95a4b68cfed92c Mon Sep 17 00:00:00 2001 From: Daniel Hug Date: Wed, 12 Apr 2017 23:22:29 -0700 Subject: [PATCH] split into two files --- index.html | 1 + js/app.js | 187 ++++++---------------------------------------- js/maze-engine.js | 134 +++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 164 deletions(-) create mode 100644 js/maze-engine.js diff --git a/index.html b/index.html index e988665..de861ed 100644 --- a/index.html +++ b/index.html @@ -35,6 +35,7 @@ + diff --git a/js/app.js b/js/app.js index 4f304f0..954145d 100644 --- a/js/app.js +++ b/js/app.js @@ -1,157 +1,3 @@ -// Get element position: -function getOffset(el) { - return { - top: el.offsetTop, - left: el.offsetLeft, - bottom: el.offsetTop + el.offsetHeight, - right: el.offsetLeft + el.offsetWidth - }; -} - - -// Game constructor: -var Game = function(options) { - // options will override the following defaults if set - var offset = extend(options, extend({ - // Initial game state defaults - score: 0, - finished: false, - player: {}, - step: 2 - }, this)); - - // Setup interval. Delay controlls tickrate: - this.frameRefresher = createInterval(function() { - this.movTick(); - }, 10, this); - - this.frameRefresher.start(); -}; - - -// Checks if an element is inside its viewport: -Game.prototype.insideGameArea = function(offset) { - return !( - offset.left < 0 || - offset.top < 0 || - offset.right > this.viewport.width || - offset.bottom > this.viewport.height - ); -}; - -// Checks if rectangle a overlaps rectangle b -Game.prototype.overlaps = function(a, b) { - // no horizontal overlap - if (a.left >= b.right || b.left >= a.right) return false; - - // no vertical overlap - if (a.top >= b.bottom || b.top >= a.bottom) return false; - - return true; -}; - -// Checks if rectangle a touches rectangle b -Game.prototype.touches = function(a, b) { - // has horizontal gap - if (a.left > b.right || b.left > a.right) return false; - - // has vertical gap - if (a.top > b.bottom || b.top > a.bottom) return false; - - return true; -}; - -Game.prototype.getNewPlayerPosition = (function() { - // Which keys are pressed: - var keys = { - left: false, - right: false, - up: false, - down: false - }; - - var keyCodeMap = { - 37: 'left', - 38: 'up', - 39: 'right', - 40: 'down' - }; - - // Keydown listener - document.body.addEventListener('keydown', function(event) { - Object.keys(keyCodeMap).forEach(function(keyCode) { - if (event.keyCode === +keyCode) keys[keyCodeMap[keyCode]] = true; - }); - }); - - // Keyup listener - document.body.addEventListener('keyup', function(e) { - Object.keys(keyCodeMap).forEach(function(keyCode) { - if (event.keyCode === +keyCode) keys[keyCodeMap[keyCode]] = false; - }); - }); - - return function() { - var moved = false; - var offset = extend(this.player.pos, {}); - - if (!(keys.up && keys.down)) { - if (keys.up) { offset.top -= this.step; offset.bottom -= this.step; moved = true; } - else if (keys.down) { offset.top += this.step; offset.bottom += this.step; moved = true; } - } - if (!(keys.left && keys.right)) { - if (keys.left) { offset.left -= this.step; offset.right -= this.step; moved = true; } - else if (keys.right) { offset.left += this.step; offset.right += this.step; moved = true; } - } - return moved ? offset : null; - }; -})(); - -Game.prototype.isValidPlayerPosition = function(sidePositions) { - // Ensure move is inside the game area: - if (!this.insideGameArea(sidePositions)) return false; - - // Ensure we're not entering a solid: - if ([].some.call(this.solids, function(solidPos, i) { - return this.overlaps(sidePositions, solidPos); - }, this)) return false; - - return true; -}; - -Game.prototype.movePlayer = function(sidePositions) { - var ps = this.player.el.style; - ps.left = sidePositions.left + 'px'; - ps.top = sidePositions.top + 'px'; - this.player.pos = sidePositions; -}; - -// Move one pixel for each direction and check if move is valid. -Game.prototype.movTick = function() { - var t = this; - - // ensure player position changed - var newPos = this.getNewPlayerPosition(); - if (!newPos) return; - - // ensure valid player position - if (!this.isValidPlayerPosition(newPos)) return; - - // Touchable collisions: - Object.keys(this.touchables).forEach(function(name) { - var touchable = this.touchables[name]; - var positions = touchable.positions; - for (var i = 0; i < positions.length; i++) { - if (this.touches(newPos, positions[i])) { - touchable.onTouch.call(this, positions[i], i); - } - } - }, t); - - this.movePlayer(newPos); -}; - - // Create a game: var game = (function() { // Viewport element & style: @@ -159,16 +5,24 @@ var game = (function() { var cs = getComputedStyle(viewportEl); // Grab necessary game elements: - var solidEls = qsa('.solid', viewportEl); - var scoreEls = qsa('.score', viewportEl); var playerEl = qs(".player", viewportEl); - - // Use array to enable easy removal with splice + var solidEls = [].slice.call(qsa('.solid', viewportEl)); + var scoreEls = [].slice.call(qsa('.score', viewportEl)); var coinEls = [].slice.call(qsa('.coin', viewportEl)); - var solids = [].map.call(solidEls, getOffset); + var finishI = [].indexOf.call(solidEls, qs(".finish", viewportEl)); + // Get element position: + function getOffset(el) { + return { + top: el.offsetTop, + left: el.offsetLeft, + bottom: el.offsetTop + el.offsetHeight, + right: el.offsetLeft + el.offsetWidth + }; + } + // Create game passing initial state return new Game({ viewport: { @@ -176,10 +30,15 @@ var game = (function() { height: parseInt(cs.height, 10) }, - // Player and their position: + // Player position and move function: player: { - el: playerEl, - pos: getOffset(playerEl) + pos: getOffset(playerEl), + move: function(sidePositions) { + var ps = playerEl.style; + ps.left = sidePositions.left + 'px'; + ps.top = sidePositions.top + 'px'; + this.player.pos = sidePositions; + } }, // Positions of solids: @@ -187,7 +46,7 @@ var game = (function() { touchables: { coin: { - positions: [].map.call(coinEls, getOffset), + positions: coinEls.map(getOffset), onTouch: function(pos, i) { this.setScore('add', 50); this.touchables.coin.positions.splice(i, 1); @@ -209,7 +68,7 @@ var game = (function() { if (method === 'add') this.score += amount; else this.score -= amount; - [].forEach.call(scoreEls, function(scoreEl) { + scoreEls.forEach(function(scoreEl) { scoreEl.textContent = this.score; }, this); } diff --git a/js/maze-engine.js b/js/maze-engine.js new file mode 100644 index 0000000..427c2ec --- /dev/null +++ b/js/maze-engine.js @@ -0,0 +1,134 @@ +// Game constructor: +var Game = function(options) { + // options will override the following defaults if set + var offset = extend(options, extend({ + // Initial game state defaults + score: 0, + finished: false, + player: {}, + step: 2 + }, this)); + + // Setup interval. Delay controlls tickrate: + this.frameRefresher = createInterval(function() { + this.movTick(); + }, 10, this); + + this.frameRefresher.start(); +}; + + +// Checks if an element is inside its viewport: +Game.prototype.insideGameArea = function(offset) { + return !( + offset.left < 0 || + offset.top < 0 || + offset.right > this.viewport.width || + offset.bottom > this.viewport.height + ); +}; + +// Checks if rectangle a overlaps rectangle b +Game.prototype.overlaps = function(a, b) { + // no horizontal overlap + if (a.left >= b.right || b.left >= a.right) return false; + + // no vertical overlap + if (a.top >= b.bottom || b.top >= a.bottom) return false; + + return true; +}; + +// Checks if rectangle a touches rectangle b +Game.prototype.touches = function(a, b) { + // has horizontal gap + if (a.left > b.right || b.left > a.right) return false; + + // has vertical gap + if (a.top > b.bottom || b.top > a.bottom) return false; + + return true; +}; + +Game.prototype.getNewPlayerPosition = (function() { + // Which keys are pressed: + var keys = { + left: false, + right: false, + up: false, + down: false + }; + + var keyCodeMap = { + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down' + }; + + // Keydown listener + document.body.addEventListener('keydown', function(event) { + Object.keys(keyCodeMap).forEach(function(keyCode) { + if (event.keyCode === +keyCode) keys[keyCodeMap[keyCode]] = true; + }); + }); + + // Keyup listener + document.body.addEventListener('keyup', function(e) { + Object.keys(keyCodeMap).forEach(function(keyCode) { + if (event.keyCode === +keyCode) keys[keyCodeMap[keyCode]] = false; + }); + }); + + return function() { + var moved = false; + var offset = extend(this.player.pos, {}); + + if (!(keys.up && keys.down)) { + if (keys.up) { offset.top -= this.step; offset.bottom -= this.step; moved = true; } + else if (keys.down) { offset.top += this.step; offset.bottom += this.step; moved = true; } + } + if (!(keys.left && keys.right)) { + if (keys.left) { offset.left -= this.step; offset.right -= this.step; moved = true; } + else if (keys.right) { offset.left += this.step; offset.right += this.step; moved = true; } + } + return moved ? offset : null; + }; +})(); + +Game.prototype.isValidPlayerPosition = function(sidePositions) { + // Ensure move is inside the game area: + if (!this.insideGameArea(sidePositions)) return false; + + // Ensure we're not entering a solid: + if ([].some.call(this.solids, function(solidPos, i) { + return this.overlaps(sidePositions, solidPos); + }, this)) return false; + + return true; +}; + +// Move one pixel for each direction and check if move is valid. +Game.prototype.movTick = function() { + var t = this; + + // ensure player position changed + var newPos = this.getNewPlayerPosition(); + if (!newPos) return; + + // ensure valid player position + if (!this.isValidPlayerPosition(newPos)) return; + + // Touchable collisions: + Object.keys(this.touchables).forEach(function(name) { + var touchable = this.touchables[name]; + var positions = touchable.positions; + for (var i = 0; i < positions.length; i++) { + if (this.touches(newPos, positions[i])) { + touchable.onTouch.call(this, positions[i], i); + } + } + }, t); + + this.player.move.call(this, newPos); +}; \ No newline at end of file