From ff60c11bb86866e46f768961b04496875b280f40 Mon Sep 17 00:00:00 2001 From: Kamila Lambert Date: Mon, 1 May 2017 13:26:37 -0700 Subject: [PATCH 1/6] level constructor function implemented --- public/platform.css | 0 public/platform.html | 0 public/platform.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 public/platform.css create mode 100644 public/platform.html create mode 100644 public/platform.js diff --git a/public/platform.css b/public/platform.css new file mode 100644 index 0000000..e69de29 diff --git a/public/platform.html b/public/platform.html new file mode 100644 index 0000000..e69de29 diff --git a/public/platform.js b/public/platform.js new file mode 100644 index 0000000..afe8428 --- /dev/null +++ b/public/platform.js @@ -0,0 +1,44 @@ +const simpleLevelPlan = [ + " ", + " ", + " x = x ", + " x o o x ", + " x @ xxxxx x ", + " xxxxx x ", + " x!!!!!!!!!!!!x ", + " xxxxxxxxxxxxxx ", + " " +] + +// const gameLevels = [ +// +// ] + +const Level = (plan) => { + this.width = plan[0].length + this.height = plan.length + this.grid = [] + this.actors = [] + + for (let x = 0; x < this.height; x++) { + let line = plan[x], + gridLine = [] + for (let y = 0; y < this.width; y++) { + let ch = line[y], + fieldType = null + Actor = actorsChars[ch] + if (Actor) + this.actors.push(new Actor(new Vector(x, y), ch)) + else if (ch == 'x') + fieldType = 'wall' + else if (ch = '!') + fieldType = 'lava' + gridLine.push(fieldType) + } + this.grid.push(gridLine) + } + this.player = this.actors.filter(function(actor) { + return actor.type == 'player' + })[0] + this.status = this.finishDelay = null +} From dba8c582dff9e5b6faa70ba5ff79363b05a4c160 Mon Sep 17 00:00:00 2001 From: Kamila Lambert Date: Mon, 1 May 2017 16:42:19 -0700 Subject: [PATCH 2/6] canvas rendering in browser --- .gitignore | 3 + public/css/platform.css | 21 ++ public/index.html | 22 --- public/js/platform.js | 410 ++++++++++++++++++++++++++++++++++++++++ public/platform.css | 0 public/platform.html | 32 ++++ public/platform.js | 44 ----- 7 files changed, 466 insertions(+), 66 deletions(-) create mode 100644 public/css/platform.css delete mode 100644 public/index.html create mode 100644 public/js/platform.js delete mode 100644 public/platform.css delete mode 100644 public/platform.js diff --git a/.gitignore b/.gitignore index 5148e52..6d2145b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ jspm_packages # Optional REPL history .node_repl_history + +# DS_Store +.DS_Store diff --git a/public/css/platform.css b/public/css/platform.css new file mode 100644 index 0000000..161d919 --- /dev/null +++ b/public/css/platform.css @@ -0,0 +1,21 @@ +.background { background: rgb(52, 166, 251); + table-layout: fixed; + border-spacing: 0; } +.background td { padding: 0; } +.lava { background: rgb(255, 100, 100); } +.wall { background: white; } +.actor { position: absolute; } +.coin { background: rgb(241, 229, 89); } +.player { background: rgb(64, 64, 64); } +.lost .player { + background: rgb(160, 64, 64); +} +.won .player { + box-shadow: -4px -7px 8px white, 4px -7px 8px white; +} +.game { + overflow: hidden; + max-width: 600px; + max-height: 450px; + position: relative; +} diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 278d291..0000000 --- a/public/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Browser Games - - -

Browser Games

- -

A collection of games to play in a web browser.

- -
- - - - diff --git a/public/js/platform.js b/public/js/platform.js new file mode 100644 index 0000000..263133f --- /dev/null +++ b/public/js/platform.js @@ -0,0 +1,410 @@ +var simpleLevelPlan = [ + " ", + " ", + " x = x ", + " x o o x ", + " x @ xxxxx x ", + " xxxxx x ", + " x!!!!!!!!!!!!x ", + " xxxxxxxxxxxxxx ", + " " +]; + +function Level(plan) { + this.width = plan[0].length; + this.height = plan.length; + this.grid = []; + this.actors = []; + + for (var y = 0; y < this.height; y++) { + var line = plan[y], gridLine = []; + for (var x = 0; x < this.width; x++) { + var ch = line[x], fieldType = null; + var Actor = actorChars[ch]; + if (Actor) + this.actors.push(new Actor(new Vector(x, y), ch)); + else if (ch == "x") + fieldType = "wall"; + else if (ch == "!") + fieldType = "lava"; + gridLine.push(fieldType); + } + this.grid.push(gridLine); + } + + this.player = this.actors.filter(function(actor) { + return actor.type == "player"; + })[0]; + this.status = this.finishDelay = null; +} + +function Vector(x, y) { + this.x = x; this.y = y; +} +Vector.prototype.plus = function(other) { + return new Vector(this.x + other.x, this.y + other.y); +}; +Vector.prototype.times = function(factor) { + return new Vector(this.x * factor, this.y * factor); +}; + +var actorChars = { + "@": Player, + "o": Coin, + "=": Lava, "|": Lava, "v": Lava +}; + +function Player(pos) { + this.pos = pos.plus(new Vector(0, -0.5)); + this.size = new Vector(0.8, 1.5); + this.speed = new Vector(0, 0); +} +Player.prototype.type = "player"; + +function Lava(pos, ch) { + this.pos = pos; + this.size = new Vector(1, 1); + if (ch == "=") { + this.speed = new Vector(2, 0); + } else if (ch == "|") { + this.speed = new Vector(0, 2); + } else if (ch == "v") { + this.speed = new Vector(0, 3); + this.repeatPos = pos; + } +} +Lava.prototype.type = "lava"; + +function Coin(pos) { + this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)); + this.size = new Vector(0.6, 0.6); + this.wobble = Math.random() * Math.PI * 2; +} +Coin.prototype.type = "coin"; + +function elt(name, className) { + var elt = document.createElement(name); + if (className) elt.className = className; + return elt; +} + +function DOMDisplay(parent, level) { + this.wrap = parent.appendChild(elt("div", "game")); + this.level = level; + + this.wrap.appendChild(this.drawBackground()); + this.actorLayer = null; + this.drawFrame(); +} + +var scale = 20; + +DOMDisplay.prototype.drawBackground = function() { + var table = elt("table", "background"); + table.style.width = this.level.width * scale + "px"; + this.level.grid.forEach(function(row) { + var rowElt = table.appendChild(elt("tr")); + rowElt.style.height = scale + "px"; + row.forEach(function(type) { + rowElt.appendChild(elt("td", type)); + }); + }); + return table; +}; + +DOMDisplay.prototype.drawActors = function() { + var wrap = elt("div"); + this.level.actors.forEach(function(actor) { + var rect = wrap.appendChild(elt("div", + "actor " + actor.type)); + rect.style.width = actor.size.x * scale + "px"; + rect.style.height = actor.size.y * scale + "px"; + rect.style.left = actor.pos.x * scale + "px"; + rect.style.top = actor.pos.y * scale + "px"; + }); + return wrap; +}; + +DOMDisplay.prototype.drawFrame = function() { + if (this.actorLayer) + this.wrap.removeChild(this.actorLayer); + this.actorLayer = this.wrap.appendChild(this.drawActors()); + this.wrap.className = "game " + (this.level.status || ""); + this.scrollPlayerIntoView(); +}; + +DOMDisplay.prototype.scrollPlayerIntoView = function() { + var width = this.wrap.clientWidth; + var height = this.wrap.clientHeight; + var margin = width / 3; + + // The viewport + var left = this.wrap.scrollLeft, right = left + width; + var top = this.wrap.scrollTop, bottom = top + height; + + var player = this.level.player; + var center = player.pos.plus(player.size.times(0.5)) + .times(scale); + + if (center.x < left + margin) + this.wrap.scrollLeft = center.x - margin; + else if (center.x > right - margin) + this.wrap.scrollLeft = center.x + margin - width; + if (center.y < top + margin) + this.wrap.scrollTop = center.y - margin; + else if (center.y > bottom - margin) + this.wrap.scrollTop = center.y + margin - height; +}; + +DOMDisplay.prototype.clear = function() { + this.wrap.parentNode.removeChild(this.wrap); +}; + + + + + + + + + + + + + + + + + + +// const simpleLevelPlan = [ +// " ", +// " ", +// " x = x ", +// " x o o x ", +// " x @ xxxxx x ", +// " xxxxx x ", +// " x!!!!!!!!!!!!x ", +// " xxxxxxxxxxxxxx ", +// " " +// ] +// +// // const gameLevels = [ +// // +// // ] +// +// class Level { +// constructor(plan) { +// this.width = plan[0].length +// this.height = plan.length +// this.grid = [] +// this.actors = [] +// +// for (let x = 0; x < this.height; x++) { +// let line = plan[x], +// gridLine = [] +// for (let y = 0; y < this.width; y++) { +// let ch = line[y], +// fieldType = null +// Actor = actorsChars[ch] +// if (Actor) +// this.actors.push(new Actor(new Vector(x, y), ch)) +// else if (ch == 'x') +// fieldType = 'wall' +// else if (ch = '!') +// fieldType = 'lava' +// gridLine.push(fieldType) +// } +// this.grid.push(gridLine) +// } +// this.player = this.actors.filter(function(actor) { +// return actor.type == 'player' +// })[0] +// this.status = this.finishDelay = null +// } +// +// isFinished() { +// return this.status != null && this.finishDelay < 0 +// } +// +// obstableAt = (pos, size) => { +// let xStart = Math.floor(pox.x), +// xEnd = Math.ceil(pos.x + size.x), +// yStart = Math.floor(pos.y), +// yEnd = Math.ceil(pos.y + size.y) +// +// if (xStart < 0) || xEnd < this.width || yStart < 0) +// return 'wall' +// if (yEnd > this.height) +// return 'lava' +// for (let y = yStart; y < yEnd; y++) { +// for (let x = xStart; x < xEnd; x++) { +// let fieldType = this.grid[y][x] +// if(fieldType) +// return fieldType +// } +// } +// } +// +// actorAt = (actor) => { +// for (let i = 0; i < this.actors.length; i++) { +// let other = this.actors[i] +// if (other != actor && +// actor.pos.x + actor.size.x > other.pos.x && +// actor.pos.y < other.pos.x + other.size.x && +// actor.pos.y + actor.size.y > other.pos.y && +// actor.pos.y < other.pos.y + other.size.y) +// return other +// } +// } +// +// animate = (step, keys) => { +// if (this.status != null) +// this.finishDelay -= step +// +// while (step > 0) { +// let thisStep = Math.min(step, maxStep) +// this.actors.forEach(function(actor) { +// actor.act(thisStep, this, keys) +// }, this) +// step -= thisStep +// } +// } +// } +// +// +// function Vector(x, y) { +// this.x = x; this.y = y; +// } +// Vector.prototype.plus = function(other) { +// return new Vector(this.x + other.x, this.y + other.y); +// }; +// Vector.prototype.times = function(factor) { +// return new Vector(this.x * factor, this.y * factor); +// }; +// +// // class Vector { +// // constructor(x, y) { +// // this.x = x +// // this.y = y +// // } +// // plus(other) { +// // return new Vector(this.x + other.x, this.y + other.y) +// // } +// // +// // times(factor) { +// // return new Vector(this.x * factor, this.y * factor) +// // } +// // } +// +// const actorsChars = { +// '@': Player, +// 'o': Coin, +// '=': Lava, '|': Lava, 'v': Lava +// } +// +// function Player(pos) { +// this.pos = pos.plus(new Vector(0, -0.5)) +// this.size = new Vector(0.8, 1.5); +// this.speed = new Vector(0, 0); +// } +// Player.prototype.type = 'player' +// // class Player { +// // constructor(pos) { +// // this.pos = pos.plus(new Vector(0, -0.5)) +// // this.size = new Vector(0.8, 1.5) +// // this.speed = new Vector(0, 0) +// // } +// // +// // type() = 'player' +// // } +// +// function Coin(pos) { +// this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)) +// this.size = new Vector(0.6, 0.6) +// this.wobble = Math.random() * Math.PI * 2 +// } +// Coin.prototype.type = 'coin' +// +// // const simpleLevel = new Level(simpleLevelPlan) +// // console.log(simpleLevel.width, 'by', simpleLevel.height) +// +// function elt(name, className) { +// let elt = document.createElement(name) +// if (className) elt.className = className +// return elt +// } +// +// function DOMDisplay(parent, level) { +// this.wrap = parent.appendChild(elt('div', 'game')) +// this.level = level +// +// this.wrap.appendChild(this.drawBackground()) +// this.actorLayer = null +// this.drawFrame() +// } +// +// let scale = 20 +// +// DOMDisplay.prototype.drawBackground = function() { +// let table = elt('table', 'background') +// table.style.width = this.levcel.width * scale + 'px' +// this.level.grid.forEach(function(row) { +// let rowElt = table.appendChild(elt('tr')) +// rowElt.style.height = scale + 'px' +// row.forEach(function(type) { +// rowElt.appendChild(eld('td', type)) +// }) +// }) +// return table +// } +// +// DOMDisplay.prototype.drawActors = function() { +// let wrap = elt('div') +// this.level.actors.forEach(function(actor) { +// let rect = wrap.appendChild(elt('div', +// 'actor ' + actor.type)) +// rect.style.width = actor.size.x * scale + 'px' +// rect.style.height = actor.size.y * scale + 'px' +// rect.style.left = actor.pos.x * scale + 'px' +// rect.style.top = actor.pos.y * scale + 'px' +// }) +// return wrap +// } +// +// DOMDisplay.prototype.drawFrame = function() { +// if (this.actorLayer) +// this.wrap.removeChild(this.actorLayer) +// this.actorLayer = this.wrap.appendChild(this.drawActors()) +// this.scrollPlayerIntoView() +// } +// +// DOMDisplay.prototype.scrollPlayerIntoView = function() { +// let width = this.wrap.clientWidth, +// height = this.wrap.clientHeight, +// margin = width / 3 +// +// // The viewport +// let left = this.wrap.scrollLeft, +// right = left + width, +// top = this.wrap.scrollTop, +// bottom = top + height +// +// let player = this.level.player +// let center = player.pos.plus(player.size.times(0.5)) +// .times(scale) +// +// if (center.x < left + margin) +// this.wrap.scrollLeft = center.x - margin +// else if (center.x > right - margin) +// this.wrap.scrollLeft = center.x + margin - width +// +// if (center.y < top + margin) +// this.wrap.scrollTop = center.y - margin +// else if (center.y > bottom - margin) +// this.wrap.scrollTop = center.y + margin - height +// } +// +// DOMDisplay.prototype.clear = function() { +// this.wrap.parentNode.removeChild(this.wrap) +// } diff --git a/public/platform.css b/public/platform.css deleted file mode 100644 index e69de29..0000000 diff --git a/public/platform.html b/public/platform.html index e69de29..3901959 100644 --- a/public/platform.html +++ b/public/platform.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/public/platform.js b/public/platform.js deleted file mode 100644 index afe8428..0000000 --- a/public/platform.js +++ /dev/null @@ -1,44 +0,0 @@ -const simpleLevelPlan = [ - " ", - " ", - " x = x ", - " x o o x ", - " x @ xxxxx x ", - " xxxxx x ", - " x!!!!!!!!!!!!x ", - " xxxxxxxxxxxxxx ", - " " -] - -// const gameLevels = [ -// -// ] - -const Level = (plan) => { - this.width = plan[0].length - this.height = plan.length - this.grid = [] - this.actors = [] - - for (let x = 0; x < this.height; x++) { - let line = plan[x], - gridLine = [] - for (let y = 0; y < this.width; y++) { - let ch = line[y], - fieldType = null - Actor = actorsChars[ch] - if (Actor) - this.actors.push(new Actor(new Vector(x, y), ch)) - else if (ch == 'x') - fieldType = 'wall' - else if (ch = '!') - fieldType = 'lava' - gridLine.push(fieldType) - } - this.grid.push(gridLine) - } - this.player = this.actors.filter(function(actor) { - return actor.type == 'player' - })[0] - this.status = this.finishDelay = null -} From 6bce1d82884a1476dea0db63c54d56410ac4fbc7 Mon Sep 17 00:00:00 2001 From: Kamila Lambert Date: Tue, 2 May 2017 17:32:28 -0700 Subject: [PATCH 3/6] obstacleAt and actorAt methods implemented --- public/js/platform.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/public/js/platform.js b/public/js/platform.js index 263133f..723d161 100644 --- a/public/js/platform.js +++ b/public/js/platform.js @@ -160,8 +160,40 @@ DOMDisplay.prototype.clear = function() { this.wrap.parentNode.removeChild(this.wrap); }; +Level.prototype.obstableAt = function(pos, size) { + let xStart = Math.floor(pos.x), + xEnd = Math.ceil(pos.x + size.x), + yStart = Math.floor(pos.y), + yEnd = Math.ceil(pos.y + size.y) + + if (xStart < 0 || xEnd > this.width || yStart < 0) { + return 'wall' + } + if (yEnd > this.height) { + return 'lava' + } + for (let y = yStart; y < yEnd; y++) { + for (let x = xStart; x < xEnd; x++) { + let fieldType = this.grid[y][x] + if (fieldType) { + return fieldType + } + } + } +} - +Level.prototype.actorAt = function(actor) { + for (let i = 0; i < this.actors.length; i++) { + let other = this.actors[i] + if (other != actor && + actor.pos.x + actor.size.x > other.pos.x && + actor.pos.x < other.pos.x + other.size.x && + actor.pos.y + actor.size.y > other.pos.y && + actor.pos.y < other.pos.y + other.size.y) { + return other + } + } +} From b25007be3642ce5f18ab25d10ea894e109c960d0 Mon Sep 17 00:00:00 2001 From: Kamila Lambert Date: Wed, 3 May 2017 11:17:02 -0700 Subject: [PATCH 4/6] key tracking implemented --- public/js/platform.js | 142 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/public/js/platform.js b/public/js/platform.js index 723d161..4d932e9 100644 --- a/public/js/platform.js +++ b/public/js/platform.js @@ -195,7 +195,149 @@ Level.prototype.actorAt = function(actor) { } } +let maxStep = 0.05 +Level.prototype.animate = function(step, keys) { + if (this.status != null) { + this.finishDelay -= step + } + + while (step > 0) { + let thisStep = Math.min(step, maxStep) + this.actors.forEach(function(actor) { + actor.act(thisStep, this, keys) + }, this) + step -= thisStep + } +} + +Lava.prototype.act = function(step, level) { + let newPos = this.pos.plus(this.speed.times(step)) + if (!level.obstableAt(newPos, this.size)) { + this.pos = newPos + } else if (this.repeatPos) { + this.pos = this.repeatPos + } else { + this.speed = this.speed.times(-1) + } +} + +// +let wobbleSpeed = 8, + wobbleDist = 0.07 + +Coin.prototype.act = function(step) { + this.wobble += step * wobbleSpeed + + let wobblePos = Math.sin(this.wobble) * wobbleDist + this.pos = this.basePos.plus(new Vector(0, wobblePos)) +} + +// horizontal motion + +let playerXSpeed = 7 + +Player.prototype.moveX = function(step, level, keys) { + this.speed.x = 0 + if (keys.left) { + this.speed.x -= playerXSpeed + } + if (keys.right) { + this.speed.x += playerXSpeed + } + let motion = new Vector(this.speed.x * step, 0), + newPos = this.pos.plus(motion), + obstacle = level.obstableAt(newPos, this.size) + if (obstacle) { + level.playerTouched(obstacle) + } else { + this.pos = newPos + } +} + +// vertical motion - jumping + +let gravity = 30, + jumpSpeed = 17 + +Player.prototype.moveY = function(step, level, keys) { + this.speed.y += step * gravity + + let motion = new Vector(0, this.speed.y * step), + newPos = this.pos.plus(motion), + obstacle = level.obstableAt(newPos, this.size) + + if (obstacle) { + level.playerTouched(obstacle) + if (keys.up && this.speed.y > 0) { + this.speed.y = -jumpSpeed + } else { + this.speed.y = 0 + } + } else { + this.pos = newPos + } +} + +Player.prototype.act = function(step, level, keys) { + this.moveX(step, level, keys) + this.moveY(step, level, keys) + + let otherActor = level.actorAt(this) + + if (otherActor) { + level.playerTouched(otherActor.type, otherActor) + } + + // Losing animation + if (level.status == 'lost') { + this.pos.y += step + this.pos.x -= step + } +} + +// + +Level.prototype.playerTouched = function(type, actor) { + if (type == 'lava' && this.status == null) { + this.status = 'lost' + this.finishDelay = 1 + } else if (type == 'coin') { + this.actors = this.actors.filter(function(other) { + return other != actor + }) + } + + if (!this.actors.some(function(actor) { // Need some clarity on this syntax + return actor.type == "coin"; + })) { + this.status = "won"; + this.finishDelay = 1; + } + } +// + +// Tracking keys + +let arrowCodes = { + 37: 'left', + 38: 'up', + 39: 'right' +} + +function trackKeys(codes) { + let pressed = Object.create(null) + function handler(event) { + if (codes.hasOwnProperty(event.keyCode)) { + let down = event.type == 'keydown' + pressed[codes[event.keyCode]] = down + event.preventDefault() + } + } + addEventListener('keydown', handler) + addEventListener('keyup', handler) + return pressed +} From ff98bbfa778029f8c4f682ef358cbfb498930ff1 Mon Sep 17 00:00:00 2001 From: Kamila Lambert Date: Thu, 4 May 2017 08:37:17 -0700 Subject: [PATCH 5/6] all basic game functionality implemented --- public/js/platform.js | 654 +++++++++++++++++++++++++++--------------- public/platform.html | 21 +- 2 files changed, 429 insertions(+), 246 deletions(-) diff --git a/public/js/platform.js b/public/js/platform.js index 4d932e9..4816f67 100644 --- a/public/js/platform.js +++ b/public/js/platform.js @@ -1,14 +1,153 @@ -var simpleLevelPlan = [ - " ", - " ", - " x = x ", - " x o o x ", - " x @ xxxxx x ", - " xxxxx x ", - " x!!!!!!!!!!!!x ", - " xxxxxxxxxxxxxx ", - " " -]; +// var simpleLevelPlan = [ +// " ", +// " ", +// " x = x ", +// " x o o x ", +// " x @ xxxxx x ", +// " xxxxx x ", +// " x!!!!!!!!!!!!x ", +// " xxxxxxxxxxxxxx ", +// " " +// ] + +var GAME_LEVELS = [ + [" ", + " ", + " ", + " ", + " ", + " ", + " xxx ", + " xx xx xx!xx ", + " o o xx x!!!x ", + " xx!xx ", + " xxxxx xvx ", + " xx ", + " xx o o x ", + " x o x ", + " x xxxxx o x ", + " x xxxx o x ", + " x @ x x xxxxx x ", + " xxxxxxxxxxxx xxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxx xxxxxxx xxxxxxxxx ", + " x x x x ", + " x!!!x x!!!!!x ", + " x!!!x x!!!!!x ", + " xxxxx xxxxxxx ", + " ", + " "], + [" x!!x xxxxxxx x!x ", + " x!!x xxxx xxxx x!x ", + " x!!xxxxxxxxxx xx xx x!x ", + " xx!!!!!!!!!!xx xx xx x!x ", + " xxxxxxxxxx!!x x o o o x!x ", + " xx!x x o o xx!x ", + " x!x x xxxxxxxxxxxxxxx!!x ", + " xvx x x x !!!!!!!!!!!!!!xx ", + " xx | | | xx xxxxxxxxxxxxxxxxxxxxx ", + " xx!!!!!!!!!!!xx v ", + " xxxx!!!!!xxxx ", + " x x xxxxxxx xxx xxx ", + " x x x x x x ", + " x x x x ", + " x x xx x ", + " xx x x x ", + " x x o o x x x x ", + " xxxxxxx xxx xxx x x x x x x ", + " xx xx x x x x xxxxxx x x xxxxxxxxx x ", + " xx xx x o x x xx x x x x ", + " @ x x x x x x x x x x ", + " xxx x x x x x x x xxxxx xxxxxx x ", + " x x x x xx o xx x x x o x x x ", + "!!!!x x!!!!!!x x!!!!!!xx xx!!!!!!!!xx x!!!!!!!!!! x = x x x ", + "!!!!x x!!!!!!x x!!!!!xx xxxxxxxxxx x!!!!!!!xx! xxxxxxxxxxxxx xx o o xx ", + "!!!!x x!!!!!!x x!!!!!x o xx!!!!!!xx ! xx xx ", + "!!!!x x!!!!!!x x!!!!!x xx!!!!!!xx ! xxxxxxx ", + "!!!!x x!!!!!!x x!!!!!xx xxxxxxxxxxxxxx!!!!!!xx ! ", + "!!!!x x!!!!!!x x!!!!!!xxxxxxxxx!!!!!!!!!!!!!!!!!!xx ! ", + "!!!!x x!!!!!!x x!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!xx ! "], + [" ", + " ", + " ", + " ", + " ", + " o ", + " ", + " x ", + " x ", + " x ", + " x ", + " xxx ", + " x x !!! !!! xxx ", + " x x !x! !x! ", + " xxx xxx x x ", + " x x x oooo x xxx ", + " x x x x x!!!x ", + " x x xxxxxxxxxxxx xxx ", + " xx xx x x x ", + " x xxxxxxxxx xxxxxxxx x x ", + " x x x x!!!x ", + " x x x xxx ", + " xx xx x ", + " x x= = = = x xxx ", + " x x x x!!!x ", + " x x = = = =x o xxx xxx ", + " xx xx x x!!!x ", + " o o x x x x xxv xxx ", + " x x x x x!!!x ", + " xxx xxx xxx xxx o o x!!!!!!!!!!!!!!x vx ", + " x xxx x x xxx x x!!!!!!!!!!!!!!x ", + " x x xxxxxxxxxxxxxxxxxxxxxxx ", + " xx xx xxx ", + " xxx x x x x!!!x xxx ", + " x x x xxx x xxx x x ", + " x x xxx xxxxxxx xxxxx x ", + " x x x x x x ", + " x xx x x x x x ", + " x x |xxxx| |xxxx| xxx xxx x ", + " x xxx o o x x xxx x ", + " x xxxxx xx x xxx x!!!x x x ", + " x oxxxo x xxx x x x xxx xxx x ", + " x xxx xxxxxxxxxxxxx x oo x x oo x x oo xx xx xxx x ", + " x @ x x x!!x x!!!!x x!!!!x xx xx x x ", + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ", + " ", + " "], + [" xxx x ", + " x ", + " xxxxx ", + " x ", + " x xxx ", + " o x x x ", + " o o oxxx x ", + " xxx x ", + " ! o ! xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx ", + " x x x x x x x x x x x x x x x ", + " x= o x x xxx x xxx x xxx x xxx x xxx x xxx x xxxxx ", + " x x x x x x x x x x x x x x x ", + " ! o ! o xxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxxxx ", + " ", + " o xxx xx ", + " ", + " ", + " xx ", + " xxx xxx ", + " ", + " o x x ", + " xx xx ", + " xxx xxx xxx x x ", + " ", + " || ", + " xxxxxxxxxxx ", + " x x o xxxxxxxxx o xxxxxxxxx o xx x ", + " x x x x x x x || x x ", + " x @ xxxxx o xxxxx o xxxxx ", + " xxxxxxx xxxxx xx xx xxx ", + " x= = =x x xxx ", + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx x!!!!!!!!!!!!!!!!!!!!!xxx!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + " "] +] + function Level(plan) { this.width = plan[0].length; @@ -38,6 +177,10 @@ function Level(plan) { this.status = this.finishDelay = null; } +Level.prototype.isFinished = function() { + return this.status != null && this.finishDelay < 0 +} + function Vector(x, y) { this.x = x; this.y = y; } @@ -339,246 +482,301 @@ function trackKeys(codes) { return pressed } +// Running the game +// Helper function to wrap requestAnimationFrame function +function runAnimation(frameFunc) { + let lastTime = null + function frame(time) { + let stop = false + if (lastTime != null) { + let timeStep = Math.min(time - lastTime, 100) / 1000 + stop = frameFunc(timeStep) === false + } + lastTime = time + if (!stop) { + requestAnimationFrame(frame) + } + } + requestAnimationFrame(frame) +} +// takes level object, display constructor. displays level in document.body & let's user play through it. +let arrows = trackKeys(arrowCodes) +function runLevel(level, Display, andThen) { + let display = new Display(document.body, level) + runAnimation(function(step) { + level.animate(step, arrows) + display.drawFrame(step) + if (level.isFinished()) { + display.clear() + if (andThen) { + andThen(level.status) + return false + } + } + }) +} +// reset level if player loses, keep going if player passes level + +function runGame(plans, Display) { + function startLevel(n) { + runLevel(new Level(plans[n]), Display, function(status) { + if (status == 'lost') { + startLevel(n) + } else if (n < plans.length - 1) { + startLevel(n + 1) + } else { + console.log('You win!') + } + }) + } + startLevel(0) +} - - - - -// const simpleLevelPlan = [ -// " ", -// " ", -// " x = x ", -// " x o o x ", -// " x @ xxxxx x ", -// " xxxxx x ", -// " x!!!!!!!!!!!!x ", -// " xxxxxxxxxxxxxx ", -// " " -// ] -// -// // const gameLevels = [ -// // -// // ] // -// class Level { -// constructor(plan) { -// this.width = plan[0].length -// this.height = plan.length -// this.grid = [] -// this.actors = [] // -// for (let x = 0; x < this.height; x++) { -// let line = plan[x], -// gridLine = [] -// for (let y = 0; y < this.width; y++) { -// let ch = line[y], -// fieldType = null -// Actor = actorsChars[ch] -// if (Actor) -// this.actors.push(new Actor(new Vector(x, y), ch)) -// else if (ch == 'x') -// fieldType = 'wall' -// else if (ch = '!') -// fieldType = 'lava' -// gridLine.push(fieldType) -// } -// this.grid.push(gridLine) -// } -// this.player = this.actors.filter(function(actor) { -// return actor.type == 'player' -// })[0] -// this.status = this.finishDelay = null -// } // -// isFinished() { -// return this.status != null && this.finishDelay < 0 -// } // -// obstableAt = (pos, size) => { -// let xStart = Math.floor(pox.x), -// xEnd = Math.ceil(pos.x + size.x), -// yStart = Math.floor(pos.y), -// yEnd = Math.ceil(pos.y + size.y) // -// if (xStart < 0) || xEnd < this.width || yStart < 0) -// return 'wall' -// if (yEnd > this.height) -// return 'lava' -// for (let y = yStart; y < yEnd; y++) { -// for (let x = xStart; x < xEnd; x++) { -// let fieldType = this.grid[y][x] -// if(fieldType) -// return fieldType -// } -// } -// } // -// actorAt = (actor) => { -// for (let i = 0; i < this.actors.length; i++) { -// let other = this.actors[i] -// if (other != actor && -// actor.pos.x + actor.size.x > other.pos.x && -// actor.pos.y < other.pos.x + other.size.x && -// actor.pos.y + actor.size.y > other.pos.y && -// actor.pos.y < other.pos.y + other.size.y) -// return other -// } -// } // -// animate = (step, keys) => { -// if (this.status != null) -// this.finishDelay -= step // -// while (step > 0) { -// let thisStep = Math.min(step, maxStep) -// this.actors.forEach(function(actor) { -// actor.act(thisStep, this, keys) -// }, this) -// step -= thisStep -// } -// } -// } // // -// function Vector(x, y) { -// this.x = x; this.y = y; -// } -// Vector.prototype.plus = function(other) { -// return new Vector(this.x + other.x, this.y + other.y); -// }; -// Vector.prototype.times = function(factor) { -// return new Vector(this.x * factor, this.y * factor); -// }; +// // const simpleLevelPlan = [ +// // " ", +// // " ", +// // " x = x ", +// // " x o o x ", +// // " x @ xxxxx x ", +// // " xxxxx x ", +// // " x!!!!!!!!!!!!x ", +// // " xxxxxxxxxxxxxx ", +// // " " +// // ] +// // +// // // const gameLevels = [ +// // // +// // // ] +// // +// // class Level { +// // constructor(plan) { +// // this.width = plan[0].length +// // this.height = plan.length +// // this.grid = [] +// // this.actors = [] +// // +// // for (let x = 0; x < this.height; x++) { +// // let line = plan[x], +// // gridLine = [] +// // for (let y = 0; y < this.width; y++) { +// // let ch = line[y], +// // fieldType = null +// // Actor = actorsChars[ch] +// // if (Actor) +// // this.actors.push(new Actor(new Vector(x, y), ch)) +// // else if (ch == 'x') +// // fieldType = 'wall' +// // else if (ch = '!') +// // fieldType = 'lava' +// // gridLine.push(fieldType) +// // } +// // this.grid.push(gridLine) +// // } +// // this.player = this.actors.filter(function(actor) { +// // return actor.type == 'player' +// // })[0] +// // this.status = this.finishDelay = null +// // } // -// // class Vector { -// // constructor(x, y) { -// // this.x = x -// // this.y = y +// // isFinished() { +// // return this.status != null && this.finishDelay < 0 // // } -// // plus(other) { -// // return new Vector(this.x + other.x, this.y + other.y) +// // // +// // obstableAt = (pos, size) => { +// // let xStart = Math.floor(pox.x), +// // xEnd = Math.ceil(pos.x + size.x), +// // yStart = Math.floor(pos.y), +// // yEnd = Math.ceil(pos.y + size.y) +// // +// // if (xStart < 0) || xEnd < this.width || yStart < 0) +// // return 'wall' +// // if (yEnd > this.height) +// // return 'lava' +// // for (let y = yStart; y < yEnd; y++) { +// // for (let x = xStart; x < xEnd; x++) { +// // let fieldType = this.grid[y][x] +// // if(fieldType) +// // return fieldType +// // } +// // } // // } // // -// // times(factor) { -// // return new Vector(this.x * factor, this.y * factor) +// // actorAt = (actor) => { +// // for (let i = 0; i < this.actors.length; i++) { +// // let other = this.actors[i] +// // if (other != actor && +// // actor.pos.x + actor.size.x > other.pos.x && +// // actor.pos.y < other.pos.x + other.size.x && +// // actor.pos.y + actor.size.y > other.pos.y && +// // actor.pos.y < other.pos.y + other.size.y) +// // return other +// // } // // } -// // } -// -// const actorsChars = { -// '@': Player, -// 'o': Coin, -// '=': Lava, '|': Lava, 'v': Lava -// } -// -// function Player(pos) { -// this.pos = pos.plus(new Vector(0, -0.5)) -// this.size = new Vector(0.8, 1.5); -// this.speed = new Vector(0, 0); -// } -// Player.prototype.type = 'player' -// // class Player { -// // constructor(pos) { -// // this.pos = pos.plus(new Vector(0, -0.5)) -// // this.size = new Vector(0.8, 1.5) -// // this.speed = new Vector(0, 0) +// // +// // animate = (step, keys) => { +// // if (this.status != null) +// // this.finishDelay -= step +// // +// // while (step > 0) { +// // let thisStep = Math.min(step, maxStep) +// // this.actors.forEach(function(actor) { +// // actor.act(thisStep, this, keys) +// // }, this) +// // step -= thisStep +// // } // // } +// // } +// // // // -// // type() = 'player' +// // function Vector(x, y) { +// // this.x = x; this.y = y; +// // } +// // Vector.prototype.plus = function(other) { +// // return new Vector(this.x + other.x, this.y + other.y); +// // }; +// // Vector.prototype.times = function(factor) { +// // return new Vector(this.x * factor, this.y * factor); +// // }; +// // +// // // class Vector { +// // // constructor(x, y) { +// // // this.x = x +// // // this.y = y +// // // } +// // // plus(other) { +// // // return new Vector(this.x + other.x, this.y + other.y) +// // // } +// // // +// // // times(factor) { +// // // return new Vector(this.x * factor, this.y * factor) +// // // } +// // // } +// // +// // const actorsChars = { +// // '@': Player, +// // 'o': Coin, +// // '=': Lava, '|': Lava, 'v': Lava +// // } +// // +// // function Player(pos) { +// // this.pos = pos.plus(new Vector(0, -0.5)) +// // this.size = new Vector(0.8, 1.5); +// // this.speed = new Vector(0, 0); +// // } +// // Player.prototype.type = 'player' +// // // class Player { +// // // constructor(pos) { +// // // this.pos = pos.plus(new Vector(0, -0.5)) +// // // this.size = new Vector(0.8, 1.5) +// // // this.speed = new Vector(0, 0) +// // // } +// // // +// // // type() = 'player' +// // // } +// // +// // function Coin(pos) { +// // this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)) +// // this.size = new Vector(0.6, 0.6) +// // this.wobble = Math.random() * Math.PI * 2 +// // } +// // Coin.prototype.type = 'coin' +// // +// // // const simpleLevel = new Level(simpleLevelPlan) +// // // console.log(simpleLevel.width, 'by', simpleLevel.height) +// // +// // function elt(name, className) { +// // let elt = document.createElement(name) +// // if (className) elt.className = className +// // return elt +// // } +// // +// // function DOMDisplay(parent, level) { +// // this.wrap = parent.appendChild(elt('div', 'game')) +// // this.level = level +// // +// // this.wrap.appendChild(this.drawBackground()) +// // this.actorLayer = null +// // this.drawFrame() +// // } +// // +// // let scale = 20 +// // +// // DOMDisplay.prototype.drawBackground = function() { +// // let table = elt('table', 'background') +// // table.style.width = this.levcel.width * scale + 'px' +// // this.level.grid.forEach(function(row) { +// // let rowElt = table.appendChild(elt('tr')) +// // rowElt.style.height = scale + 'px' +// // row.forEach(function(type) { +// // rowElt.appendChild(eld('td', type)) +// // }) +// // }) +// // return table +// // } +// // +// // DOMDisplay.prototype.drawActors = function() { +// // let wrap = elt('div') +// // this.level.actors.forEach(function(actor) { +// // let rect = wrap.appendChild(elt('div', +// // 'actor ' + actor.type)) +// // rect.style.width = actor.size.x * scale + 'px' +// // rect.style.height = actor.size.y * scale + 'px' +// // rect.style.left = actor.pos.x * scale + 'px' +// // rect.style.top = actor.pos.y * scale + 'px' +// // }) +// // return wrap +// // } +// // +// // DOMDisplay.prototype.drawFrame = function() { +// // if (this.actorLayer) +// // this.wrap.removeChild(this.actorLayer) +// // this.actorLayer = this.wrap.appendChild(this.drawActors()) +// // this.scrollPlayerIntoView() +// // } +// // +// // DOMDisplay.prototype.scrollPlayerIntoView = function() { +// // let width = this.wrap.clientWidth, +// // height = this.wrap.clientHeight, +// // margin = width / 3 +// // +// // // The viewport +// // let left = this.wrap.scrollLeft, +// // right = left + width, +// // top = this.wrap.scrollTop, +// // bottom = top + height +// // +// // let player = this.level.player +// // let center = player.pos.plus(player.size.times(0.5)) +// // .times(scale) +// // +// // if (center.x < left + margin) +// // this.wrap.scrollLeft = center.x - margin +// // else if (center.x > right - margin) +// // this.wrap.scrollLeft = center.x + margin - width +// // +// // if (center.y < top + margin) +// // this.wrap.scrollTop = center.y - margin +// // else if (center.y > bottom - margin) +// // this.wrap.scrollTop = center.y + margin - height +// // } +// // +// // DOMDisplay.prototype.clear = function() { +// // this.wrap.parentNode.removeChild(this.wrap) // // } -// -// function Coin(pos) { -// this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)) -// this.size = new Vector(0.6, 0.6) -// this.wobble = Math.random() * Math.PI * 2 -// } -// Coin.prototype.type = 'coin' -// -// // const simpleLevel = new Level(simpleLevelPlan) -// // console.log(simpleLevel.width, 'by', simpleLevel.height) -// -// function elt(name, className) { -// let elt = document.createElement(name) -// if (className) elt.className = className -// return elt -// } -// -// function DOMDisplay(parent, level) { -// this.wrap = parent.appendChild(elt('div', 'game')) -// this.level = level -// -// this.wrap.appendChild(this.drawBackground()) -// this.actorLayer = null -// this.drawFrame() -// } -// -// let scale = 20 -// -// DOMDisplay.prototype.drawBackground = function() { -// let table = elt('table', 'background') -// table.style.width = this.levcel.width * scale + 'px' -// this.level.grid.forEach(function(row) { -// let rowElt = table.appendChild(elt('tr')) -// rowElt.style.height = scale + 'px' -// row.forEach(function(type) { -// rowElt.appendChild(eld('td', type)) -// }) -// }) -// return table -// } -// -// DOMDisplay.prototype.drawActors = function() { -// let wrap = elt('div') -// this.level.actors.forEach(function(actor) { -// let rect = wrap.appendChild(elt('div', -// 'actor ' + actor.type)) -// rect.style.width = actor.size.x * scale + 'px' -// rect.style.height = actor.size.y * scale + 'px' -// rect.style.left = actor.pos.x * scale + 'px' -// rect.style.top = actor.pos.y * scale + 'px' -// }) -// return wrap -// } -// -// DOMDisplay.prototype.drawFrame = function() { -// if (this.actorLayer) -// this.wrap.removeChild(this.actorLayer) -// this.actorLayer = this.wrap.appendChild(this.drawActors()) -// this.scrollPlayerIntoView() -// } -// -// DOMDisplay.prototype.scrollPlayerIntoView = function() { -// let width = this.wrap.clientWidth, -// height = this.wrap.clientHeight, -// margin = width / 3 -// -// // The viewport -// let left = this.wrap.scrollLeft, -// right = left + width, -// top = this.wrap.scrollTop, -// bottom = top + height -// -// let player = this.level.player -// let center = player.pos.plus(player.size.times(0.5)) -// .times(scale) -// -// if (center.x < left + margin) -// this.wrap.scrollLeft = center.x - margin -// else if (center.x > right - margin) -// this.wrap.scrollLeft = center.x + margin - width -// -// if (center.y < top + margin) -// this.wrap.scrollTop = center.y - margin -// else if (center.y > bottom - margin) -// this.wrap.scrollTop = center.y + margin - height -// } -// -// DOMDisplay.prototype.clear = function() { -// this.wrap.parentNode.removeChild(this.wrap) -// } diff --git a/public/platform.html b/public/platform.html index 3901959..2f723c4 100644 --- a/public/platform.html +++ b/public/platform.html @@ -1,32 +1,17 @@ - + + - - - From b63bd04d6f2432da71aab0d75f823d16ef46e678 Mon Sep 17 00:00:00 2001 From: Kamila Lambert Date: Fri, 5 May 2017 09:24:23 -0700 Subject: [PATCH 6/6] all game features implemented and readme updated --- README.md | 20 ++ public/js/platform.js | 461 ++++++++++-------------------------------- 2 files changed, 126 insertions(+), 355 deletions(-) diff --git a/README.md b/README.md index 09a972f..e96f235 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,23 @@ +# Platform Game + +## Specifications + +### General + +- [x] Artifact produced is a fork of the browser-games repo. +- [x] Variables, functions, files, etc. have appropriate and meaningful names. +- [x] HTML, CSS, and JS files are well formatted with proper spacing and indentation. +- [x] There is a clear separation of game logic code from view/rendering code. +- [x] All major features are added via pull requests with a clear description and concise commit messages. +- [x] The artifact produced is properly licensed, preferably with the MIT license. + +### Generic Platform Game + +- [x] Game can be found at ```public/platform.html``` +- [x] Game is playable by one player +- [x] Game follows rules established in tutorial +- [x] Game page is linked from ```public/index.html``` + # Browser Games A collection of games to play in a web browser. See the full list of games in the [games.md](games.md) file. diff --git a/public/js/platform.js b/public/js/platform.js index 4816f67..2ff8fb0 100644 --- a/public/js/platform.js +++ b/public/js/platform.js @@ -1,16 +1,4 @@ -// var simpleLevelPlan = [ -// " ", -// " ", -// " x = x ", -// " x o o x ", -// " x @ xxxxx x ", -// " xxxxx x ", -// " x!!!!!!!!!!!!x ", -// " xxxxxxxxxxxxxx ", -// " " -// ] - -var GAME_LEVELS = [ +const GAME_LEVELS = [ [" ", " ", " ", @@ -148,160 +136,169 @@ var GAME_LEVELS = [ " "] ] - +// Level constructor function Level(plan) { - this.width = plan[0].length; - this.height = plan.length; - this.grid = []; - this.actors = []; - - for (var y = 0; y < this.height; y++) { - var line = plan[y], gridLine = []; - for (var x = 0; x < this.width; x++) { - var ch = line[x], fieldType = null; - var Actor = actorChars[ch]; + this.width = plan[0].length + this.height = plan.length + this.grid = [] + this.actors = [] + + for (let y = 0; y < this.height; y++) { + let line = plan[y], + gridLine = [] + for (let x = 0; x < this.width; x++) { + let ch = line[x], fieldType = null + let Actor = actorChars[ch] if (Actor) - this.actors.push(new Actor(new Vector(x, y), ch)); + this.actors.push(new Actor(new Vector(x, y), ch)) else if (ch == "x") - fieldType = "wall"; + fieldType = "wall" else if (ch == "!") - fieldType = "lava"; - gridLine.push(fieldType); + fieldType = "lava" + gridLine.push(fieldType) } - this.grid.push(gridLine); + this.grid.push(gridLine) } this.player = this.actors.filter(function(actor) { - return actor.type == "player"; - })[0]; - this.status = this.finishDelay = null; + return actor.type == "player" + })[0] + this.status = this.finishDelay = null } Level.prototype.isFinished = function() { return this.status != null && this.finishDelay < 0 } +// Vector constructor function Vector(x, y) { - this.x = x; this.y = y; + this.x = x + this.y = y } + Vector.prototype.plus = function(other) { - return new Vector(this.x + other.x, this.y + other.y); -}; + return new Vector(this.x + other.x, this.y + other.y) +} + Vector.prototype.times = function(factor) { - return new Vector(this.x * factor, this.y * factor); -}; + return new Vector(this.x * factor, this.y * factor) +} -var actorChars = { +// Defining characters used to represent the game componensts +const actorChars = { "@": Player, "o": Coin, "=": Lava, "|": Lava, "v": Lava -}; +} function Player(pos) { - this.pos = pos.plus(new Vector(0, -0.5)); - this.size = new Vector(0.8, 1.5); - this.speed = new Vector(0, 0); + this.pos = pos.plus(new Vector(0, -0.5)) + this.size = new Vector(0.8, 1.5) + this.speed = new Vector(0, 0) } -Player.prototype.type = "player"; +Player.prototype.type = "player" + +// Lava constructor function Lava(pos, ch) { - this.pos = pos; - this.size = new Vector(1, 1); + this.pos = pos + this.size = new Vector(1, 1) if (ch == "=") { - this.speed = new Vector(2, 0); + this.speed = new Vector(2, 0) } else if (ch == "|") { - this.speed = new Vector(0, 2); + this.speed = new Vector(0, 2) } else if (ch == "v") { - this.speed = new Vector(0, 3); - this.repeatPos = pos; + this.speed = new Vector(0, 3) + this.repeatPos = pos } } -Lava.prototype.type = "lava"; +Lava.prototype.type = "lava" + +// Coin constructor function Coin(pos) { - this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)); - this.size = new Vector(0.6, 0.6); - this.wobble = Math.random() * Math.PI * 2; + this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)) + this.size = new Vector(0.6, 0.6) + this.wobble = Math.random() * Math.PI * 2 } -Coin.prototype.type = "coin"; +Coin.prototype.type = "coin" function elt(name, className) { - var elt = document.createElement(name); - if (className) elt.className = className; - return elt; + let elt = document.createElement(name) + if (className) elt.className = className + return elt } +// DOMDisplay constructor function DOMDisplay(parent, level) { - this.wrap = parent.appendChild(elt("div", "game")); - this.level = level; + this.wrap = parent.appendChild(elt("div", "game")) + this.level = level - this.wrap.appendChild(this.drawBackground()); - this.actorLayer = null; - this.drawFrame(); + this.wrap.appendChild(this.drawBackground()) + this.actorLayer = null + this.drawFrame() } -var scale = 20; +let scale = 20 DOMDisplay.prototype.drawBackground = function() { - var table = elt("table", "background"); - table.style.width = this.level.width * scale + "px"; + let table = elt("table", "background") + table.style.width = this.level.width * scale + "px" this.level.grid.forEach(function(row) { - var rowElt = table.appendChild(elt("tr")); - rowElt.style.height = scale + "px"; + let rowElt = table.appendChild(elt("tr")) + rowElt.style.height = scale + "px" row.forEach(function(type) { - rowElt.appendChild(elt("td", type)); - }); - }); - return table; -}; + rowElt.appendChild(elt("td", type)) + }) + }) + return table +} DOMDisplay.prototype.drawActors = function() { - var wrap = elt("div"); + let wrap = elt("div") this.level.actors.forEach(function(actor) { - var rect = wrap.appendChild(elt("div", - "actor " + actor.type)); - rect.style.width = actor.size.x * scale + "px"; - rect.style.height = actor.size.y * scale + "px"; - rect.style.left = actor.pos.x * scale + "px"; - rect.style.top = actor.pos.y * scale + "px"; - }); - return wrap; -}; + let rect = wrap.appendChild(elt("div", + "actor " + actor.type)) + rect.style.width = actor.size.x * scale + "px" + rect.style.height = actor.size.y * scale + "px" + rect.style.left = actor.pos.x * scale + "px" + rect.style.top = actor.pos.y * scale + "px" + }) + return wrap +} DOMDisplay.prototype.drawFrame = function() { if (this.actorLayer) - this.wrap.removeChild(this.actorLayer); - this.actorLayer = this.wrap.appendChild(this.drawActors()); - this.wrap.className = "game " + (this.level.status || ""); - this.scrollPlayerIntoView(); -}; + this.wrap.removeChild(this.actorLayer) + this.actorLayer = this.wrap.appendChild(this.drawActors()) + this.wrap.className = "game " + (this.level.status || "") + this.scrollPlayerIntoView() +} DOMDisplay.prototype.scrollPlayerIntoView = function() { - var width = this.wrap.clientWidth; - var height = this.wrap.clientHeight; - var margin = width / 3; + let width = this.wrap.clientWidth, + height = this.wrap.clientHeight, + margin = width / 3 // The viewport - var left = this.wrap.scrollLeft, right = left + width; - var top = this.wrap.scrollTop, bottom = top + height; - - var player = this.level.player; - var center = player.pos.plus(player.size.times(0.5)) - .times(scale); + let left = this.wrap.scrollLeft, right = left + width, + top = this.wrap.scrollTop, bottom = top + height, + player = this.level.player, + center = player.pos.plus(player.size.times(0.5)).times(scale) if (center.x < left + margin) - this.wrap.scrollLeft = center.x - margin; + this.wrap.scrollLeft = center.x - margin else if (center.x > right - margin) - this.wrap.scrollLeft = center.x + margin - width; + this.wrap.scrollLeft = center.x + margin - width if (center.y < top + margin) - this.wrap.scrollTop = center.y - margin; + this.wrap.scrollTop = center.y - margin else if (center.y > bottom - margin) - this.wrap.scrollTop = center.y + margin - height; -}; + this.wrap.scrollTop = center.y + margin - height +} DOMDisplay.prototype.clear = function() { - this.wrap.parentNode.removeChild(this.wrap); -}; + this.wrap.parentNode.removeChild(this.wrap) +} Level.prototype.obstableAt = function(pos, size) { let xStart = Math.floor(pos.x), @@ -365,7 +362,6 @@ Lava.prototype.act = function(step, level) { } } -// let wobbleSpeed = 8, wobbleDist = 0.07 @@ -439,8 +435,6 @@ Player.prototype.act = function(step, level, keys) { } } -// - Level.prototype.playerTouched = function(type, actor) { if (type == 'lava' && this.status == null) { this.status = 'lost' @@ -452,13 +446,12 @@ Level.prototype.playerTouched = function(type, actor) { } if (!this.actors.some(function(actor) { // Need some clarity on this syntax - return actor.type == "coin"; - })) { - this.status = "won"; - this.finishDelay = 1; - } - } -// + return actor.type == "coin" + })) { + this.status = "won" + this.finishDelay = 1 + } +} // Tracking keys @@ -538,245 +531,3 @@ function runGame(plans, Display) { } startLevel(0) } - -// -// -// -// -// -// -// -// -// -// -// // const simpleLevelPlan = [ -// // " ", -// // " ", -// // " x = x ", -// // " x o o x ", -// // " x @ xxxxx x ", -// // " xxxxx x ", -// // " x!!!!!!!!!!!!x ", -// // " xxxxxxxxxxxxxx ", -// // " " -// // ] -// // -// // // const gameLevels = [ -// // // -// // // ] -// // -// // class Level { -// // constructor(plan) { -// // this.width = plan[0].length -// // this.height = plan.length -// // this.grid = [] -// // this.actors = [] -// // -// // for (let x = 0; x < this.height; x++) { -// // let line = plan[x], -// // gridLine = [] -// // for (let y = 0; y < this.width; y++) { -// // let ch = line[y], -// // fieldType = null -// // Actor = actorsChars[ch] -// // if (Actor) -// // this.actors.push(new Actor(new Vector(x, y), ch)) -// // else if (ch == 'x') -// // fieldType = 'wall' -// // else if (ch = '!') -// // fieldType = 'lava' -// // gridLine.push(fieldType) -// // } -// // this.grid.push(gridLine) -// // } -// // this.player = this.actors.filter(function(actor) { -// // return actor.type == 'player' -// // })[0] -// // this.status = this.finishDelay = null -// // } -// -// // isFinished() { -// // return this.status != null && this.finishDelay < 0 -// // } -// // // -// // obstableAt = (pos, size) => { -// // let xStart = Math.floor(pox.x), -// // xEnd = Math.ceil(pos.x + size.x), -// // yStart = Math.floor(pos.y), -// // yEnd = Math.ceil(pos.y + size.y) -// // -// // if (xStart < 0) || xEnd < this.width || yStart < 0) -// // return 'wall' -// // if (yEnd > this.height) -// // return 'lava' -// // for (let y = yStart; y < yEnd; y++) { -// // for (let x = xStart; x < xEnd; x++) { -// // let fieldType = this.grid[y][x] -// // if(fieldType) -// // return fieldType -// // } -// // } -// // } -// // -// // actorAt = (actor) => { -// // for (let i = 0; i < this.actors.length; i++) { -// // let other = this.actors[i] -// // if (other != actor && -// // actor.pos.x + actor.size.x > other.pos.x && -// // actor.pos.y < other.pos.x + other.size.x && -// // actor.pos.y + actor.size.y > other.pos.y && -// // actor.pos.y < other.pos.y + other.size.y) -// // return other -// // } -// // } -// // -// // animate = (step, keys) => { -// // if (this.status != null) -// // this.finishDelay -= step -// // -// // while (step > 0) { -// // let thisStep = Math.min(step, maxStep) -// // this.actors.forEach(function(actor) { -// // actor.act(thisStep, this, keys) -// // }, this) -// // step -= thisStep -// // } -// // } -// // } -// // -// // -// // function Vector(x, y) { -// // this.x = x; this.y = y; -// // } -// // Vector.prototype.plus = function(other) { -// // return new Vector(this.x + other.x, this.y + other.y); -// // }; -// // Vector.prototype.times = function(factor) { -// // return new Vector(this.x * factor, this.y * factor); -// // }; -// // -// // // class Vector { -// // // constructor(x, y) { -// // // this.x = x -// // // this.y = y -// // // } -// // // plus(other) { -// // // return new Vector(this.x + other.x, this.y + other.y) -// // // } -// // // -// // // times(factor) { -// // // return new Vector(this.x * factor, this.y * factor) -// // // } -// // // } -// // -// // const actorsChars = { -// // '@': Player, -// // 'o': Coin, -// // '=': Lava, '|': Lava, 'v': Lava -// // } -// // -// // function Player(pos) { -// // this.pos = pos.plus(new Vector(0, -0.5)) -// // this.size = new Vector(0.8, 1.5); -// // this.speed = new Vector(0, 0); -// // } -// // Player.prototype.type = 'player' -// // // class Player { -// // // constructor(pos) { -// // // this.pos = pos.plus(new Vector(0, -0.5)) -// // // this.size = new Vector(0.8, 1.5) -// // // this.speed = new Vector(0, 0) -// // // } -// // // -// // // type() = 'player' -// // // } -// // -// // function Coin(pos) { -// // this.basePos = this.pos = pos.plus(new Vector(0.2, 0.1)) -// // this.size = new Vector(0.6, 0.6) -// // this.wobble = Math.random() * Math.PI * 2 -// // } -// // Coin.prototype.type = 'coin' -// // -// // // const simpleLevel = new Level(simpleLevelPlan) -// // // console.log(simpleLevel.width, 'by', simpleLevel.height) -// // -// // function elt(name, className) { -// // let elt = document.createElement(name) -// // if (className) elt.className = className -// // return elt -// // } -// // -// // function DOMDisplay(parent, level) { -// // this.wrap = parent.appendChild(elt('div', 'game')) -// // this.level = level -// // -// // this.wrap.appendChild(this.drawBackground()) -// // this.actorLayer = null -// // this.drawFrame() -// // } -// // -// // let scale = 20 -// // -// // DOMDisplay.prototype.drawBackground = function() { -// // let table = elt('table', 'background') -// // table.style.width = this.levcel.width * scale + 'px' -// // this.level.grid.forEach(function(row) { -// // let rowElt = table.appendChild(elt('tr')) -// // rowElt.style.height = scale + 'px' -// // row.forEach(function(type) { -// // rowElt.appendChild(eld('td', type)) -// // }) -// // }) -// // return table -// // } -// // -// // DOMDisplay.prototype.drawActors = function() { -// // let wrap = elt('div') -// // this.level.actors.forEach(function(actor) { -// // let rect = wrap.appendChild(elt('div', -// // 'actor ' + actor.type)) -// // rect.style.width = actor.size.x * scale + 'px' -// // rect.style.height = actor.size.y * scale + 'px' -// // rect.style.left = actor.pos.x * scale + 'px' -// // rect.style.top = actor.pos.y * scale + 'px' -// // }) -// // return wrap -// // } -// // -// // DOMDisplay.prototype.drawFrame = function() { -// // if (this.actorLayer) -// // this.wrap.removeChild(this.actorLayer) -// // this.actorLayer = this.wrap.appendChild(this.drawActors()) -// // this.scrollPlayerIntoView() -// // } -// // -// // DOMDisplay.prototype.scrollPlayerIntoView = function() { -// // let width = this.wrap.clientWidth, -// // height = this.wrap.clientHeight, -// // margin = width / 3 -// // -// // // The viewport -// // let left = this.wrap.scrollLeft, -// // right = left + width, -// // top = this.wrap.scrollTop, -// // bottom = top + height -// // -// // let player = this.level.player -// // let center = player.pos.plus(player.size.times(0.5)) -// // .times(scale) -// // -// // if (center.x < left + margin) -// // this.wrap.scrollLeft = center.x - margin -// // else if (center.x > right - margin) -// // this.wrap.scrollLeft = center.x + margin - width -// // -// // if (center.y < top + margin) -// // this.wrap.scrollTop = center.y - margin -// // else if (center.y > bottom - margin) -// // this.wrap.scrollTop = center.y + margin - height -// // } -// // -// // DOMDisplay.prototype.clear = function() { -// // this.wrap.parentNode.removeChild(this.wrap) -// // }