initial commit
This commit is contained in:
commit
ba20bac6b8
|
@ -0,0 +1,131 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Vier gewinnt</title>
|
||||
|
||||
<style>
|
||||
|
||||
div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.board {
|
||||
width: 84vw;
|
||||
margin: auto;
|
||||
outline: 1px solid black;
|
||||
}
|
||||
|
||||
.board .field {
|
||||
border: 1px solid black;
|
||||
width: 12vw;
|
||||
height: 12vw;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.board .field:first-child {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.board .field .piece {
|
||||
width: 10vw;
|
||||
height: 10vw;
|
||||
border-radius: 50%;
|
||||
margin: 1vw;
|
||||
}
|
||||
.board .field .blue {
|
||||
background-color: blue;
|
||||
}
|
||||
.board .field .red {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const elt = function (type, attrs, ...children) {
|
||||
let node = document.createElement(type)
|
||||
for (a in attrs) {
|
||||
node.setAttribute(a, attrs[a])
|
||||
}
|
||||
for (let child of children) {
|
||||
if (typeof child != "string") node.appendChild(child)
|
||||
else node.appendChild(document.createTextNode(child))
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
const columns = 7
|
||||
const rows = 6
|
||||
let nextColor = "red"
|
||||
|
||||
let state = Array(rows).fill('').map(el => Array(columns).fill(''))
|
||||
|
||||
const showBoard = function() {
|
||||
document.querySelector(".board").innerHTML = ''
|
||||
for(row = 0; row < rows; row++) {
|
||||
for(column = 0; column < columns; column++) {
|
||||
let attributes = {"class": "field", "onclick": "setColumn(" + column + ")"}
|
||||
let children = elt("div", {"class": state[row][column] + " piece"})
|
||||
document.querySelector(".board").append(elt("div", attributes, children))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="board"></div>
|
||||
|
||||
<script>
|
||||
showBoard()
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
<script>
|
||||
const switchNextColor = function() {
|
||||
if(nextColor === "red") {
|
||||
nextColor = "blue"
|
||||
} else if(nextColor === "blue") {
|
||||
nextColor = "red"
|
||||
}
|
||||
}
|
||||
|
||||
const setField = function(row, column) {
|
||||
state[row][column] = nextColor
|
||||
console.log(state)
|
||||
switchNextColor()
|
||||
showBoard()
|
||||
}
|
||||
|
||||
const setColumn = function(column) {
|
||||
let row = rows - 1
|
||||
const column_number = column
|
||||
while(row >= 0){
|
||||
if(state[row][column_number] !== ''){
|
||||
row--
|
||||
} else {
|
||||
console.log("setting", row, column)
|
||||
setField(row, column_number)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// const interval = setInterval(function() {
|
||||
// let color = ""
|
||||
// let action = Math.floor(Math.random() * 3)
|
||||
// if(action == 1) {
|
||||
// color = "red"
|
||||
// } else if(action == 2) {
|
||||
// color = "blue"
|
||||
// }
|
||||
// setField(Math.floor(Math.random() * rows), Math.floor(Math.random() * columns), color)
|
||||
// }, 1000);
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,359 @@
|
|||
var simpleLevelPlan = `
|
||||
......................
|
||||
..#................#..
|
||||
..#..............=.#..
|
||||
..#.........o.o....#..
|
||||
..#.@......#####...#..
|
||||
..#####............#..
|
||||
......#++++++++++++#..
|
||||
......##############..
|
||||
......................`;
|
||||
|
||||
var Level = class Level {
|
||||
constructor(plan) {
|
||||
let rows = plan.trim().split("\n").map(l => [...l]);
|
||||
this.height = rows.length;
|
||||
this.width = rows[0].length;
|
||||
this.startActors = [];
|
||||
|
||||
this.rows = rows.map((row, y) => {
|
||||
return row.map((ch, x) => {
|
||||
let type = levelChars[ch];
|
||||
if (typeof type == "string") return type;
|
||||
this.startActors.push(
|
||||
type.create(new Vec(x, y), ch));
|
||||
return "empty";
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var State = class State {
|
||||
constructor(level, actors, status) {
|
||||
this.level = level;
|
||||
this.actors = actors;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
static start(level) {
|
||||
return new State(level, level.startActors, "playing");
|
||||
}
|
||||
|
||||
get player() {
|
||||
return this.actors.find(a => a.type == "player");
|
||||
}
|
||||
}
|
||||
|
||||
var Vec = class Vec {
|
||||
constructor(x, y) {
|
||||
this.x = x; this.y = y;
|
||||
}
|
||||
plus(other) {
|
||||
return new Vec(this.x + other.x, this.y + other.y);
|
||||
}
|
||||
times(factor) {
|
||||
return new Vec(this.x * factor, this.y * factor);
|
||||
}
|
||||
}
|
||||
|
||||
var Player = class Player {
|
||||
constructor(pos, speed) {
|
||||
this.pos = pos;
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
get type() { return "player"; }
|
||||
|
||||
static create(pos) {
|
||||
return new Player(pos.plus(new Vec(0, -0.5)),
|
||||
new Vec(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
Player.prototype.size = new Vec(0.8, 1.5);
|
||||
|
||||
var Lava = class Lava {
|
||||
constructor(pos, speed, reset) {
|
||||
this.pos = pos;
|
||||
this.speed = speed;
|
||||
this.reset = reset;
|
||||
}
|
||||
|
||||
get type() { return "lava"; }
|
||||
|
||||
static create(pos, ch) {
|
||||
if (ch == "=") {
|
||||
return new Lava(pos, new Vec(2, 0));
|
||||
} else if (ch == "|") {
|
||||
return new Lava(pos, new Vec(0, 2));
|
||||
} else if (ch == "v") {
|
||||
return new Lava(pos, new Vec(0, 3), pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Lava.prototype.size = new Vec(1, 1);
|
||||
|
||||
var Coin = class Coin {
|
||||
constructor(pos, basePos, wobble) {
|
||||
this.pos = pos;
|
||||
this.basePos = basePos;
|
||||
this.wobble = wobble;
|
||||
}
|
||||
|
||||
get type() { return "coin"; }
|
||||
|
||||
static create(pos) {
|
||||
let basePos = pos.plus(new Vec(0.2, 0.1));
|
||||
return new Coin(basePos, basePos,
|
||||
Math.random() * Math.PI * 2);
|
||||
}
|
||||
}
|
||||
|
||||
Coin.prototype.size = new Vec(0.6, 0.6);
|
||||
|
||||
var levelChars = {
|
||||
".": "empty", "#": "wall", "+": "lava",
|
||||
"@": Player, "o": Coin,
|
||||
"=": Lava, "|": Lava, "v": Lava
|
||||
};
|
||||
|
||||
var simpleLevel = new Level(simpleLevelPlan);
|
||||
|
||||
function elt(name, attrs, ...children) {
|
||||
let dom = document.createElement(name);
|
||||
for (let attr of Object.keys(attrs)) {
|
||||
dom.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
for (let child of children) {
|
||||
dom.appendChild(child);
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
|
||||
var DOMDisplay = class DOMDisplay {
|
||||
constructor(parent, level) {
|
||||
this.dom = elt("div", {class: "game"}, drawGrid(level));
|
||||
this.actorLayer = null;
|
||||
parent.appendChild(this.dom);
|
||||
}
|
||||
|
||||
clear() { this.dom.remove(); }
|
||||
}
|
||||
|
||||
var scale = 20;
|
||||
|
||||
function drawGrid(level) {
|
||||
return elt("table", {
|
||||
class: "background",
|
||||
style: `width: ${level.width * scale}px`
|
||||
}, ...level.rows.map(row =>
|
||||
elt("tr", {style: `height: ${scale}px`},
|
||||
...row.map(type => elt("td", {class: type})))
|
||||
));
|
||||
}
|
||||
|
||||
function drawActors(actors) {
|
||||
return elt("div", {}, ...actors.map(actor => {
|
||||
let rect = elt("div", {class: `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 rect;
|
||||
}));
|
||||
}
|
||||
|
||||
DOMDisplay.prototype.syncState = function(state) {
|
||||
if (this.actorLayer) this.actorLayer.remove();
|
||||
this.actorLayer = drawActors(state.actors);
|
||||
this.dom.appendChild(this.actorLayer);
|
||||
this.dom.className = `game ${state.status}`;
|
||||
this.scrollPlayerIntoView(state);
|
||||
};
|
||||
|
||||
DOMDisplay.prototype.scrollPlayerIntoView = function(state) {
|
||||
let width = this.dom.clientWidth;
|
||||
let height = this.dom.clientHeight;
|
||||
let margin = width / 3;
|
||||
|
||||
// The viewport
|
||||
let left = this.dom.scrollLeft, right = left + width;
|
||||
let top = this.dom.scrollTop, bottom = top + height;
|
||||
|
||||
let player = state.player;
|
||||
let center = player.pos.plus(player.size.times(0.5))
|
||||
.times(scale);
|
||||
|
||||
if (center.x < left + margin) {
|
||||
this.dom.scrollLeft = center.x - margin;
|
||||
} else if (center.x > right - margin) {
|
||||
this.dom.scrollLeft = center.x + margin - width;
|
||||
}
|
||||
if (center.y < top + margin) {
|
||||
this.dom.scrollTop = center.y - margin;
|
||||
} else if (center.y > bottom - margin) {
|
||||
this.dom.scrollTop = center.y + margin - height;
|
||||
}
|
||||
};
|
||||
|
||||
Level.prototype.touches = function(pos, size, type) {
|
||||
var xStart = Math.floor(pos.x);
|
||||
var xEnd = Math.ceil(pos.x + size.x);
|
||||
var yStart = Math.floor(pos.y);
|
||||
var yEnd = Math.ceil(pos.y + size.y);
|
||||
|
||||
for (var y = yStart; y < yEnd; y++) {
|
||||
for (var x = xStart; x < xEnd; x++) {
|
||||
let isOutside = x < 0 || x >= this.width ||
|
||||
y < 0 || y >= this.height;
|
||||
let here = isOutside ? "wall" : this.rows[y][x];
|
||||
if (here == type) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
State.prototype.update = function(time, keys) {
|
||||
let actors = this.actors
|
||||
.map(actor => actor.update(time, this, keys));
|
||||
let newState = new State(this.level, actors, this.status);
|
||||
|
||||
if (newState.status != "playing") return newState;
|
||||
|
||||
let player = newState.player;
|
||||
if (this.level.touches(player.pos, player.size, "lava")) {
|
||||
return new State(this.level, actors, "lost");
|
||||
}
|
||||
|
||||
for (let actor of actors) {
|
||||
if (actor != player && overlap(actor, player)) {
|
||||
newState = actor.collide(newState);
|
||||
}
|
||||
}
|
||||
return newState;
|
||||
};
|
||||
|
||||
function overlap(actor1, actor2) {
|
||||
return actor1.pos.x + actor1.size.x > actor2.pos.x &&
|
||||
actor1.pos.x < actor2.pos.x + actor2.size.x &&
|
||||
actor1.pos.y + actor1.size.y > actor2.pos.y &&
|
||||
actor1.pos.y < actor2.pos.y + actor2.size.y;
|
||||
}
|
||||
|
||||
Lava.prototype.collide = function(state) {
|
||||
return new State(state.level, state.actors, "lost");
|
||||
};
|
||||
|
||||
Coin.prototype.collide = function(state) {
|
||||
let filtered = state.actors.filter(a => a != this);
|
||||
let status = state.status;
|
||||
if (!filtered.some(a => a.type == "coin")) status = "won";
|
||||
return new State(state.level, filtered, status);
|
||||
};
|
||||
|
||||
Lava.prototype.update = function(time, state) {
|
||||
let newPos = this.pos.plus(this.speed.times(time));
|
||||
if (!state.level.touches(newPos, this.size, "wall")) {
|
||||
return new Lava(newPos, this.speed, this.reset);
|
||||
} else if (this.reset) {
|
||||
return new Lava(this.reset, this.speed, this.reset);
|
||||
} else {
|
||||
return new Lava(this.pos, this.speed.times(-1));
|
||||
}
|
||||
};
|
||||
|
||||
var wobbleSpeed = 8, wobbleDist = 0.07;
|
||||
|
||||
Coin.prototype.update = function(time) {
|
||||
let wobble = this.wobble + time * wobbleSpeed;
|
||||
let wobblePos = Math.sin(wobble) * wobbleDist;
|
||||
return new Coin(this.basePos.plus(new Vec(0, wobblePos)),
|
||||
this.basePos, wobble);
|
||||
};
|
||||
|
||||
var playerXSpeed = 7;
|
||||
var gravity = 30;
|
||||
var jumpSpeed = 17;
|
||||
|
||||
Player.prototype.update = function(time, state, keys) {
|
||||
let xSpeed = 0;
|
||||
if (keys.ArrowLeft) xSpeed -= playerXSpeed;
|
||||
if (keys.ArrowRight) xSpeed += playerXSpeed;
|
||||
let pos = this.pos;
|
||||
let movedX = pos.plus(new Vec(xSpeed * time, 0));
|
||||
if (!state.level.touches(movedX, this.size, "wall")) {
|
||||
pos = movedX;
|
||||
}
|
||||
|
||||
let ySpeed = this.speed.y + time * gravity;
|
||||
let movedY = pos.plus(new Vec(0, ySpeed * time));
|
||||
if (!state.level.touches(movedY, this.size, "wall")) {
|
||||
pos = movedY;
|
||||
} else if (keys.ArrowUp && ySpeed > 0) {
|
||||
ySpeed = -jumpSpeed;
|
||||
} else {
|
||||
ySpeed = 0;
|
||||
}
|
||||
return new Player(pos, new Vec(xSpeed, ySpeed));
|
||||
};
|
||||
|
||||
function trackKeys(keys) {
|
||||
let down = Object.create(null);
|
||||
function track(event) {
|
||||
if (keys.includes(event.key)) {
|
||||
down[event.key] = event.type == "keydown";
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
window.addEventListener("keydown", track);
|
||||
window.addEventListener("keyup", track);
|
||||
return down;
|
||||
}
|
||||
|
||||
var arrowKeys =
|
||||
trackKeys(["ArrowLeft", "ArrowRight", "ArrowUp"]);
|
||||
|
||||
function runAnimation(frameFunc) {
|
||||
let lastTime = null;
|
||||
function frame(time) {
|
||||
if (lastTime != null) {
|
||||
let timeStep = Math.min(time - lastTime, 100) / 1000;
|
||||
if (frameFunc(timeStep) === false) return;
|
||||
}
|
||||
lastTime = time;
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
function runLevel(level, Display) {
|
||||
let display = new Display(document.body, level);
|
||||
let state = State.start(level);
|
||||
let ending = 1;
|
||||
return new Promise(resolve => {
|
||||
runAnimation(time => {
|
||||
state = state.update(time, arrowKeys);
|
||||
display.syncState(state);
|
||||
if (state.status == "playing") {
|
||||
return true;
|
||||
} else if (ending > 0) {
|
||||
ending -= time;
|
||||
return true;
|
||||
} else {
|
||||
display.clear();
|
||||
resolve(state.status);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function runGame(plans, Display) {
|
||||
for (let level = 0; level < plans.length;) {
|
||||
let status = await runLevel(new Level(plans[level]),
|
||||
Display);
|
||||
if (status == "won") level++;
|
||||
}
|
||||
console.log("You've won!");
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
var results = [
|
||||
{name: "Satisfied", count: 1043, color: "lightblue"},
|
||||
{name: "Neutral", count: 563, color: "lightgreen"},
|
||||
{name: "Unsatisfied", count: 510, color: "pink"},
|
||||
{name: "No comment", count: 175, color: "silver"}
|
||||
];
|
||||
|
||||
function flipHorizontally(context, around) {
|
||||
context.translate(around, 0);
|
||||
context.scale(-1, 1);
|
||||
context.translate(-around, 0);
|
||||
}
|
||||
|
||||
var CanvasDisplay = class CanvasDisplay {
|
||||
constructor(parent, level) {
|
||||
this.canvas = document.createElement("canvas");
|
||||
this.canvas.width = Math.min(600, level.width * scale);
|
||||
this.canvas.height = Math.min(450, level.height * scale);
|
||||
parent.appendChild(this.canvas);
|
||||
this.cx = this.canvas.getContext("2d");
|
||||
|
||||
this.flipPlayer = false;
|
||||
|
||||
this.viewport = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: this.canvas.width / scale,
|
||||
height: this.canvas.height / scale
|
||||
};
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.canvas.remove();
|
||||
}
|
||||
}
|
||||
|
||||
CanvasDisplay.prototype.syncState = function(state) {
|
||||
this.updateViewport(state);
|
||||
this.clearDisplay(state.status);
|
||||
this.drawBackground(state.level);
|
||||
this.drawActors(state.actors);
|
||||
};
|
||||
|
||||
CanvasDisplay.prototype.updateViewport = function(state) {
|
||||
let view = this.viewport, margin = view.width / 3;
|
||||
let player = state.player;
|
||||
let center = player.pos.plus(player.size.times(0.5));
|
||||
|
||||
if (center.x < view.left + margin) {
|
||||
view.left = Math.max(center.x - margin, 0);
|
||||
} else if (center.x > view.left + view.width - margin) {
|
||||
view.left = Math.min(center.x + margin - view.width,
|
||||
state.level.width - view.width);
|
||||
}
|
||||
if (center.y < view.top + margin) {
|
||||
view.top = Math.max(center.y - margin, 0);
|
||||
} else if (center.y > view.top + view.height - margin) {
|
||||
view.top = Math.min(center.y + margin - view.height,
|
||||
state.level.height - view.height);
|
||||
}
|
||||
};
|
||||
|
||||
CanvasDisplay.prototype.clearDisplay = function(status) {
|
||||
if (status == "won") {
|
||||
this.cx.fillStyle = "rgb(68, 191, 255)";
|
||||
} else if (status == "lost") {
|
||||
this.cx.fillStyle = "rgb(44, 136, 214)";
|
||||
} else {
|
||||
this.cx.fillStyle = "rgb(52, 166, 251)";
|
||||
}
|
||||
this.cx.fillRect(0, 0,
|
||||
this.canvas.width, this.canvas.height);
|
||||
};
|
||||
|
||||
var otherSprites = document.createElement("img");
|
||||
otherSprites.src = "img/sprites.png";
|
||||
|
||||
CanvasDisplay.prototype.drawBackground = function(level) {
|
||||
let {left, top, width, height} = this.viewport;
|
||||
let xStart = Math.floor(left);
|
||||
let xEnd = Math.ceil(left + width);
|
||||
let yStart = Math.floor(top);
|
||||
let yEnd = Math.ceil(top + height);
|
||||
|
||||
for (let y = yStart; y < yEnd; y++) {
|
||||
for (let x = xStart; x < xEnd; x++) {
|
||||
let tile = level.rows[y][x];
|
||||
if (tile == "empty") continue;
|
||||
let screenX = (x - left) * scale;
|
||||
let screenY = (y - top) * scale;
|
||||
let tileX = tile == "lava" ? scale : 0;
|
||||
this.cx.drawImage(otherSprites,
|
||||
tileX, 0, scale, scale,
|
||||
screenX, screenY, scale, scale);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var playerSprites = document.createElement("img");
|
||||
playerSprites.src = "img/player.png";
|
||||
var playerXOverlap = 4;
|
||||
|
||||
CanvasDisplay.prototype.drawPlayer = function(player, x, y,
|
||||
width, height){
|
||||
width += playerXOverlap * 2;
|
||||
x -= playerXOverlap;
|
||||
if (player.speed.x != 0) {
|
||||
this.flipPlayer = player.speed.x < 0;
|
||||
}
|
||||
|
||||
let tile = 8;
|
||||
if (player.speed.y != 0) {
|
||||
tile = 9;
|
||||
} else if (player.speed.x != 0) {
|
||||
tile = Math.floor(Date.now() / 60) % 8;
|
||||
}
|
||||
|
||||
this.cx.save();
|
||||
if (this.flipPlayer) {
|
||||
flipHorizontally(this.cx, x + width / 2);
|
||||
}
|
||||
let tileX = tile * width;
|
||||
this.cx.drawImage(playerSprites, tileX, 0, width, height,
|
||||
x, y, width, height);
|
||||
this.cx.restore();
|
||||
};
|
||||
|
||||
CanvasDisplay.prototype.drawActors = function(actors) {
|
||||
for (let actor of actors) {
|
||||
let width = actor.size.x * scale;
|
||||
let height = actor.size.y * scale;
|
||||
let x = (actor.pos.x - this.viewport.left) * scale;
|
||||
let y = (actor.pos.y - this.viewport.top) * scale;
|
||||
if (actor.type == "player") {
|
||||
this.drawPlayer(actor, x, y, width, height);
|
||||
} else {
|
||||
let tileX = (actor.type == "coin" ? 2 : 1) * scale;
|
||||
this.cx.drawImage(otherSprites,
|
||||
tileX, 0, width, height,
|
||||
x, y, width, height);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -0,0 +1,178 @@
|
|||
var GAME_LEVELS = [`
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
..................................................................###...........
|
||||
...................................................##......##....##+##..........
|
||||
....................................o.o......##..................#+++#..........
|
||||
.................................................................##+##..........
|
||||
...................................#####..........................#v#...........
|
||||
............................................................................##..
|
||||
..##......................................o.o................................#..
|
||||
..#.....................o....................................................#..
|
||||
..#......................................#####.............................o.#..
|
||||
..#..........####.......o....................................................#..
|
||||
..#..@.......#..#................................................#####.......#..
|
||||
..############..###############...####################.....#######...#########..
|
||||
..............................#...#..................#.....#....................
|
||||
..............................#+++#..................#+++++#....................
|
||||
..............................#+++#..................#+++++#....................
|
||||
..............................#####..................#######....................
|
||||
................................................................................
|
||||
................................................................................
|
||||
`,`
|
||||
................................................................................
|
||||
................................................................................
|
||||
....###############################.............................................
|
||||
...##.............................##########################################....
|
||||
...#.......................................................................##...
|
||||
...#....o...................................................................#...
|
||||
...#................................................=.......................#...
|
||||
...#.o........################...................o..o...........|........o..#...
|
||||
...#.........................#..............................................#...
|
||||
...#....o....................##########.....###################....##########...
|
||||
...#..................................#+++++#.................#....#............
|
||||
...###############....oo......=o.o.o..#######.###############.#....#............
|
||||
.....#...............o..o.............#.......#......#........#....#............
|
||||
.....#....................#############..######.####.#.########....########.....
|
||||
.....#.............########..............#...........#.#..................#.....
|
||||
.....#..........####......####...#####################.#..................#.....
|
||||
.....#........###............###.......................########....########.....
|
||||
.....#.......##................#########################......#....#............
|
||||
.....#.......#................................................#....#............
|
||||
.....###......................................................#....#............
|
||||
.......#...............o...........................................#............
|
||||
.......#...............................................o...........#............
|
||||
.......#########......###.....############.........................##...........
|
||||
.............#..................#........#####....#######.o.........########....
|
||||
.............#++++++++++++++++++#............#....#.....#..................#....
|
||||
.............#++++++++++++++++++#..........###....###...####.o.............#....
|
||||
.............####################..........#........#......#.....|.........#....
|
||||
...........................................#++++++++#......####............#....
|
||||
...........................................#++++++++#.........#........@...#....
|
||||
...........................................#++++++++#.........##############....
|
||||
...........................................##########...........................
|
||||
................................................................................
|
||||
`,`
|
||||
......................................#++#........................#######....................................#+#..
|
||||
......................................#++#.....................####.....####.................................#+#..
|
||||
......................................#++##########...........##...........##................................#+#..
|
||||
......................................##++++++++++##.........##.............##...............................#+#..
|
||||
.......................................##########++#.........#....................................o...o...o..#+#..
|
||||
................................................##+#.........#.....o...o....................................##+#..
|
||||
.................................................#+#.........#................................###############++#..
|
||||
.................................................#v#.........#.....#...#........................++++++++++++++##..
|
||||
.............................................................##..|...|...|..##............#####################...
|
||||
..............................................................##+++++++++++##............v........................
|
||||
...............................................................####+++++####......................................
|
||||
...............................................#.....#............#######........###.........###..................
|
||||
...............................................#.....#...........................#.#.........#.#..................
|
||||
...............................................#.....#.............................#.........#....................
|
||||
...............................................#.....#.............................##........#....................
|
||||
...............................................##....#.............................#.........#....................
|
||||
...............................................#.....#......o..o.....#...#.........#.........#....................
|
||||
...............#######........###...###........#.....#...............#...#.........#.........#....................
|
||||
..............##.....##.........#...#..........#.....#.....######....#...#...#########.......#....................
|
||||
.............##.......##........#.o.#..........#....##...............#...#...#...............#....................
|
||||
.....@.......#.........#........#...#..........#.....#...............#...#...#...............#....................
|
||||
....###......#.........#........#...#..........#.....#...............#...#####...######......#....................
|
||||
....#.#......#.........#.......##.o.##.........#.....#...............#.....o.....#.#.........#....................
|
||||
++++#.#++++++#.........#++++++##.....##++++++++##....#++++++++++.....#.....=.....#.#.........#....................
|
||||
++++#.#++++++#.........#+++++##.......##########.....#+++++++##+.....#############.##..o.o..##....................
|
||||
++++#.#++++++#.........#+++++#....o.................##++++++##.+....................##.....##.....................
|
||||
++++#.#++++++#.........#+++++#.....................##++++++##..+.....................#######......................
|
||||
++++#.#++++++#.........#+++++##.......##############++++++##...+..................................................
|
||||
++++#.#++++++#.........#++++++#########++++++++++++++++++##....+..................................................
|
||||
++++#.#++++++#.........#++++++++++++++++++++++++++++++++##.....+..................................................
|
||||
`,`
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
........................................o.....................................................................
|
||||
..............................................................................................................
|
||||
........................................#.....................................................................
|
||||
........................................#.....................................................................
|
||||
........................................#.....................................................................
|
||||
........................................#.....................................................................
|
||||
.......................................###....................................................................
|
||||
.......................................#.#.................+++........+++..###................................
|
||||
.......................................#.#.................+#+........+#+.....................................
|
||||
.....................................###.###................#..........#......................................
|
||||
......................................#...#.................#...oooo...#.......###............................
|
||||
......................................#...#.................#..........#......#+++#...........................
|
||||
......................................#...#.................############.......###............................
|
||||
.....................................##...##......#...#......#................................................
|
||||
......................................#...#########...########..............#.#...............................
|
||||
......................................#...#...........#....................#+++#..............................
|
||||
......................................#...#...........#.....................###...............................
|
||||
.....................................##...##..........#.......................................................
|
||||
......................................#...#=.=.=.=....#............###........................................
|
||||
......................................#...#...........#...........#+++#.......................................
|
||||
......................................#...#....=.=.=.=#.....o......###.......###..............................
|
||||
.....................................##...##..........#.....................#+++#.............................
|
||||
..............................o...o...#...#...........#.....#................##v........###...................
|
||||
......................................#...#...........#..............#.................#+++#..................
|
||||
.............................###.###.###.###.....o.o..#++++++++++++++#...................v#...................
|
||||
.............................#.###.#.#.###.#..........#++++++++++++++#........................................
|
||||
.............................#.............#...#######################........................................
|
||||
.............................##...........##.........................................###......................
|
||||
..###.........................#.....#.....#.........................................#+++#................###..
|
||||
..#.#.........................#....###....#..........................................###.................#.#..
|
||||
..#...........................#....###....#######........................#####.............................#..
|
||||
..#...........................#...........#..............................#...#.............................#..
|
||||
..#...........................##..........#..............................#.#.#.............................#..
|
||||
..#.......................................#.......|####|....|####|.....###.###.............................#..
|
||||
..#................###.............o.o....#..............................#.........###.....................#..
|
||||
..#...............#####.......##..........#.............................###.......#+++#..........#.........#..
|
||||
..#...............o###o.......#....###....#.............................#.#........###..........###........#..
|
||||
..#................###........#############..#.oo.#....#.oo.#....#.oo..##.##....................###........#..
|
||||
..#......@..........#.........#...........#++#....#++++#....#++++#....##...##....................#.........#..
|
||||
..#############################...........#############################.....################################..
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
`,`
|
||||
..................................................................................................###.#.......
|
||||
......................................................................................................#.......
|
||||
..................................................................................................#####.......
|
||||
..................................................................................................#...........
|
||||
..................................................................................................#.###.......
|
||||
..........................o.......................................................................#.#.#.......
|
||||
.............................................................................................o.o.o###.#.......
|
||||
...................###................................................................................#.......
|
||||
.......+..o..+................................................#####.#####.#####.#####.#####.#####.#####.......
|
||||
.......#.....#................................................#...#.#...#.#...#.#...#.#...#.#...#.#...........
|
||||
.......#=.o..#............#...................................###.#.###.#.###.#.###.#.###.#.###.#.#####.......
|
||||
.......#.....#..................................................#.#...#.#...#.#...#.#...#.#...#.#.....#.......
|
||||
.......+..o..+............o..................................####.#####.#####.#####.#####.#####.#######.......
|
||||
..............................................................................................................
|
||||
..........o..............###..............................##..................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
......................................................##......................................................
|
||||
...................###.........###............................................................................
|
||||
..............................................................................................................
|
||||
..........................o.....................................................#......#......................
|
||||
..........................................................##.....##...........................................
|
||||
.............###.........###.........###.................................#..................#.................
|
||||
..............................................................................................................
|
||||
.................................................................||...........................................
|
||||
..###########.................................................................................................
|
||||
..#.........#.o.#########.o.#########.o.##................................................#...................
|
||||
..#.........#...#.......#...#.......#...#.................||..................#.....#.........................
|
||||
..#..@......#####...o...#####...o...#####.....................................................................
|
||||
..#######.....................................#####.......##.....##.....###...................................
|
||||
........#=..................=................=#...#.....................###...................................
|
||||
........#######################################...#+++++++++++++++++++++###+++++++++++++++++++++++++++++++++++
|
||||
..................................................############################################################
|
||||
..............................................................................................................
|
||||
`];
|
||||
|
||||
if (typeof module != "undefined" && module.exports && (typeof window == "undefined" || window.exports != exports))
|
||||
module.exports = GAME_LEVELS;
|
||||
if (typeof global != "undefined" && !global.GAME_LEVELS)
|
||||
global.GAME_LEVELS = GAME_LEVELS;
|
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,10 @@
|
|||
<!doctype html>
|
||||
<script src="code/chapter/16_game.js"></script>
|
||||
<script src="code/levels.js"></script>
|
||||
<script src="code/chapter/17_canvas.js"></script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
runGame(GAME_LEVELS, CanvasDisplay);
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,15 @@
|
|||
This example is part of:
|
||||
|
||||
Marijn Haverbeke
|
||||
Eloquent JavaScript
|
||||
3rd edition (2018)
|
||||
|
||||
https://eloquentjavascript.net
|
||||
|
||||
|
||||
Chapter 16: Project: A Platform Game
|
||||
https://eloquentjavascript.net/16_game.html
|
||||
|
||||
Chapter 17: Drawing on Canvas
|
||||
https://eloquentjavascript.net/17_canvas.html
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
var simpleLevelPlan = `
|
||||
......................
|
||||
..#................#..
|
||||
..#..............=.#..
|
||||
..#.........o.o....#..
|
||||
..#.@......#####...#..
|
||||
..#####............#..
|
||||
......#++++++++++++#..
|
||||
......##############..
|
||||
......................`;
|
||||
|
||||
var Level = class Level {
|
||||
constructor(plan) {
|
||||
let rows = plan.trim().split("\n").map(l => [...l]);
|
||||
this.height = rows.length;
|
||||
this.width = rows[0].length;
|
||||
this.startActors = [];
|
||||
|
||||
this.rows = rows.map((row, y) => {
|
||||
return row.map((ch, x) => {
|
||||
let type = levelChars[ch];
|
||||
if (typeof type == "string") return type;
|
||||
this.startActors.push(
|
||||
type.create(new Vec(x, y), ch));
|
||||
return "empty";
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var State = class State {
|
||||
constructor(level, actors, status) {
|
||||
this.level = level;
|
||||
this.actors = actors;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
static start(level) {
|
||||
return new State(level, level.startActors, "playing");
|
||||
}
|
||||
|
||||
get player() {
|
||||
return this.actors.find(a => a.type == "player");
|
||||
}
|
||||
}
|
||||
|
||||
var Vec = class Vec {
|
||||
constructor(x, y) {
|
||||
this.x = x; this.y = y;
|
||||
}
|
||||
plus(other) {
|
||||
return new Vec(this.x + other.x, this.y + other.y);
|
||||
}
|
||||
times(factor) {
|
||||
return new Vec(this.x * factor, this.y * factor);
|
||||
}
|
||||
}
|
||||
|
||||
var Player = class Player {
|
||||
constructor(pos, speed) {
|
||||
this.pos = pos;
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
get type() { return "player"; }
|
||||
|
||||
static create(pos) {
|
||||
return new Player(pos.plus(new Vec(0, -0.5)),
|
||||
new Vec(0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
Player.prototype.size = new Vec(0.8, 1.5);
|
||||
|
||||
var Lava = class Lava {
|
||||
constructor(pos, speed, reset) {
|
||||
this.pos = pos;
|
||||
this.speed = speed;
|
||||
this.reset = reset;
|
||||
}
|
||||
|
||||
get type() { return "lava"; }
|
||||
|
||||
static create(pos, ch) {
|
||||
if (ch == "=") {
|
||||
return new Lava(pos, new Vec(2, 0));
|
||||
} else if (ch == "|") {
|
||||
return new Lava(pos, new Vec(0, 2));
|
||||
} else if (ch == "v") {
|
||||
return new Lava(pos, new Vec(0, 3), pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Lava.prototype.size = new Vec(1, 1);
|
||||
|
||||
var Coin = class Coin {
|
||||
constructor(pos, basePos, wobble) {
|
||||
this.pos = pos;
|
||||
this.basePos = basePos;
|
||||
this.wobble = wobble;
|
||||
}
|
||||
|
||||
get type() { return "coin"; }
|
||||
|
||||
static create(pos) {
|
||||
let basePos = pos.plus(new Vec(0.2, 0.1));
|
||||
return new Coin(basePos, basePos,
|
||||
Math.random() * Math.PI * 2);
|
||||
}
|
||||
}
|
||||
|
||||
Coin.prototype.size = new Vec(0.6, 0.6);
|
||||
|
||||
var levelChars = {
|
||||
".": "empty", "#": "wall", "+": "lava",
|
||||
"@": Player, "o": Coin,
|
||||
"=": Lava, "|": Lava, "v": Lava
|
||||
};
|
||||
|
||||
var simpleLevel = new Level(simpleLevelPlan);
|
||||
|
||||
function elt(name, attrs, ...children) {
|
||||
let dom = document.createElement(name);
|
||||
for (let attr of Object.keys(attrs)) {
|
||||
dom.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
for (let child of children) {
|
||||
dom.appendChild(child);
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
|
||||
var DOMDisplay = class DOMDisplay {
|
||||
constructor(parent, level) {
|
||||
this.dom = elt("div", {class: "game"}, drawGrid(level));
|
||||
this.actorLayer = null;
|
||||
parent.appendChild(this.dom);
|
||||
}
|
||||
|
||||
clear() { this.dom.remove(); }
|
||||
}
|
||||
|
||||
var scale = 20;
|
||||
|
||||
function drawGrid(level) {
|
||||
return elt("table", {
|
||||
class: "background",
|
||||
style: `width: ${level.width * scale}px`
|
||||
}, ...level.rows.map(row =>
|
||||
elt("tr", {style: `height: ${scale}px`},
|
||||
...row.map(type => elt("td", {class: type})))
|
||||
));
|
||||
}
|
||||
|
||||
function drawActors(actors) {
|
||||
return elt("div", {}, ...actors.map(actor => {
|
||||
let rect = elt("div", {class: `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 rect;
|
||||
}));
|
||||
}
|
||||
|
||||
DOMDisplay.prototype.syncState = function(state) {
|
||||
if (this.actorLayer) this.actorLayer.remove();
|
||||
this.actorLayer = drawActors(state.actors);
|
||||
this.dom.appendChild(this.actorLayer);
|
||||
this.dom.className = `game ${state.status}`;
|
||||
this.scrollPlayerIntoView(state);
|
||||
};
|
||||
|
||||
DOMDisplay.prototype.scrollPlayerIntoView = function(state) {
|
||||
let width = this.dom.clientWidth;
|
||||
let height = this.dom.clientHeight;
|
||||
let margin = width / 3;
|
||||
|
||||
// The viewport
|
||||
let left = this.dom.scrollLeft, right = left + width;
|
||||
let top = this.dom.scrollTop, bottom = top + height;
|
||||
|
||||
let player = state.player;
|
||||
let center = player.pos.plus(player.size.times(0.5))
|
||||
.times(scale);
|
||||
|
||||
if (center.x < left + margin) {
|
||||
this.dom.scrollLeft = center.x - margin;
|
||||
} else if (center.x > right - margin) {
|
||||
this.dom.scrollLeft = center.x + margin - width;
|
||||
}
|
||||
if (center.y < top + margin) {
|
||||
this.dom.scrollTop = center.y - margin;
|
||||
} else if (center.y > bottom - margin) {
|
||||
this.dom.scrollTop = center.y + margin - height;
|
||||
}
|
||||
};
|
||||
|
||||
Level.prototype.touches = function(pos, size, type) {
|
||||
var xStart = Math.floor(pos.x);
|
||||
var xEnd = Math.ceil(pos.x + size.x);
|
||||
var yStart = Math.floor(pos.y);
|
||||
var yEnd = Math.ceil(pos.y + size.y);
|
||||
|
||||
for (var y = yStart; y < yEnd; y++) {
|
||||
for (var x = xStart; x < xEnd; x++) {
|
||||
let isOutside = x < 0 || x >= this.width ||
|
||||
y < 0 || y >= this.height;
|
||||
let here = isOutside ? "wall" : this.rows[y][x];
|
||||
if (here == type) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
State.prototype.update = function(time, keys) {
|
||||
let actors = this.actors
|
||||
.map(actor => actor.update(time, this, keys));
|
||||
let newState = new State(this.level, actors, this.status);
|
||||
|
||||
if (newState.status != "playing") return newState;
|
||||
|
||||
let player = newState.player;
|
||||
if (this.level.touches(player.pos, player.size, "lava")) {
|
||||
return new State(this.level, actors, "lost");
|
||||
}
|
||||
|
||||
for (let actor of actors) {
|
||||
if (actor != player && overlap(actor, player)) {
|
||||
newState = actor.collide(newState);
|
||||
}
|
||||
}
|
||||
return newState;
|
||||
};
|
||||
|
||||
function overlap(actor1, actor2) {
|
||||
return actor1.pos.x + actor1.size.x > actor2.pos.x &&
|
||||
actor1.pos.x < actor2.pos.x + actor2.size.x &&
|
||||
actor1.pos.y + actor1.size.y > actor2.pos.y &&
|
||||
actor1.pos.y < actor2.pos.y + actor2.size.y;
|
||||
}
|
||||
|
||||
Lava.prototype.collide = function(state) {
|
||||
return new State(state.level, state.actors, "lost");
|
||||
};
|
||||
|
||||
Coin.prototype.collide = function(state) {
|
||||
let filtered = state.actors.filter(a => a != this);
|
||||
let status = state.status;
|
||||
if (!filtered.some(a => a.type == "coin")) status = "won";
|
||||
return new State(state.level, filtered, status);
|
||||
};
|
||||
|
||||
Lava.prototype.update = function(time, state) {
|
||||
let newPos = this.pos.plus(this.speed.times(time));
|
||||
if (!state.level.touches(newPos, this.size, "wall")) {
|
||||
return new Lava(newPos, this.speed, this.reset);
|
||||
} else if (this.reset) {
|
||||
return new Lava(this.reset, this.speed, this.reset);
|
||||
} else {
|
||||
return new Lava(this.pos, this.speed.times(-1));
|
||||
}
|
||||
};
|
||||
|
||||
var wobbleSpeed = 8, wobbleDist = 0.07;
|
||||
|
||||
Coin.prototype.update = function(time) {
|
||||
let wobble = this.wobble + time * wobbleSpeed;
|
||||
let wobblePos = Math.sin(wobble) * wobbleDist;
|
||||
return new Coin(this.basePos.plus(new Vec(0, wobblePos)),
|
||||
this.basePos, wobble);
|
||||
};
|
||||
|
||||
var playerXSpeed = 7;
|
||||
var gravity = 30;
|
||||
var jumpSpeed = 17;
|
||||
|
||||
Player.prototype.update = function(time, state, keys) {
|
||||
let xSpeed = 0;
|
||||
if (keys.ArrowLeft) xSpeed -= playerXSpeed;
|
||||
if (keys.ArrowRight) xSpeed += playerXSpeed;
|
||||
let pos = this.pos;
|
||||
let movedX = pos.plus(new Vec(xSpeed * time, 0));
|
||||
if (!state.level.touches(movedX, this.size, "wall")) {
|
||||
pos = movedX;
|
||||
}
|
||||
|
||||
let ySpeed = this.speed.y + time * gravity;
|
||||
let movedY = pos.plus(new Vec(0, ySpeed * time));
|
||||
if (!state.level.touches(movedY, this.size, "wall")) {
|
||||
pos = movedY;
|
||||
} else if (keys.ArrowUp && ySpeed > 0) {
|
||||
ySpeed = -jumpSpeed;
|
||||
} else {
|
||||
ySpeed = 0;
|
||||
}
|
||||
return new Player(pos, new Vec(xSpeed, ySpeed));
|
||||
};
|
||||
|
||||
function trackKeys(keys) {
|
||||
let down = Object.create(null);
|
||||
function track(event) {
|
||||
if (keys.includes(event.key)) {
|
||||
down[event.key] = event.type == "keydown";
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
window.addEventListener("keydown", track);
|
||||
window.addEventListener("keyup", track);
|
||||
return down;
|
||||
}
|
||||
|
||||
var arrowKeys =
|
||||
trackKeys(["ArrowLeft", "ArrowRight", "ArrowUp"]);
|
||||
|
||||
function runAnimation(frameFunc) {
|
||||
let lastTime = null;
|
||||
function frame(time) {
|
||||
if (lastTime != null) {
|
||||
let timeStep = Math.min(time - lastTime, 100) / 1000;
|
||||
if (frameFunc(timeStep) === false) return;
|
||||
}
|
||||
lastTime = time;
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
function runLevel(level, Display) {
|
||||
let display = new Display(document.body, level);
|
||||
let state = State.start(level);
|
||||
let ending = 1;
|
||||
return new Promise(resolve => {
|
||||
runAnimation(time => {
|
||||
state = state.update(time, arrowKeys);
|
||||
display.syncState(state);
|
||||
if (state.status == "playing") {
|
||||
return true;
|
||||
} else if (ending > 0) {
|
||||
ending -= time;
|
||||
return true;
|
||||
} else {
|
||||
display.clear();
|
||||
resolve(state.status);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function runGame(plans, Display) {
|
||||
for (let level = 0; level < plans.length;) {
|
||||
let status = await runLevel(new Level(plans[level]),
|
||||
Display);
|
||||
if (status == "won") level++;
|
||||
}
|
||||
console.log("You've won!");
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
var GAME_LEVELS = [`
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
................................................................................
|
||||
..................................................................###...........
|
||||
...................................................##......##....##+##..........
|
||||
....................................o.o......##..................#+++#..........
|
||||
.................................................................##+##..........
|
||||
...................................#####..........................#v#...........
|
||||
............................................................................##..
|
||||
..##......................................o.o................................#..
|
||||
..#.....................o....................................................#..
|
||||
..#......................................#####.............................o.#..
|
||||
..#..........####.......o....................................................#..
|
||||
..#..@.......#..#................................................#####.......#..
|
||||
..############..###############...####################.....#######...#########..
|
||||
..............................#...#..................#.....#....................
|
||||
..............................#+++#..................#+++++#....................
|
||||
..............................#+++#..................#+++++#....................
|
||||
..............................#####..................#######....................
|
||||
................................................................................
|
||||
................................................................................
|
||||
`,`
|
||||
................................................................................
|
||||
................................................................................
|
||||
....###############################.............................................
|
||||
...##.............................##########################################....
|
||||
...#.......................................................................##...
|
||||
...#....o...................................................................#...
|
||||
...#................................................=.......................#...
|
||||
...#.o........################...................o..o...........|........o..#...
|
||||
...#.........................#..............................................#...
|
||||
...#....o....................##########.....###################....##########...
|
||||
...#..................................#+++++#.................#....#............
|
||||
...###############....oo......=o.o.o..#######.###############.#....#............
|
||||
.....#...............o..o.............#.......#......#........#....#............
|
||||
.....#....................#############..######.####.#.########....########.....
|
||||
.....#.............########..............#...........#.#..................#.....
|
||||
.....#..........####......####...#####################.#..................#.....
|
||||
.....#........###............###.......................########....########.....
|
||||
.....#.......##................#########################......#....#............
|
||||
.....#.......#................................................#....#............
|
||||
.....###......................................................#....#............
|
||||
.......#...............o...........................................#............
|
||||
.......#...............................................o...........#............
|
||||
.......#########......###.....############.........................##...........
|
||||
.............#..................#........#####....#######.o.........########....
|
||||
.............#++++++++++++++++++#............#....#.....#..................#....
|
||||
.............#++++++++++++++++++#..........###....###...####.o.............#....
|
||||
.............####################..........#........#......#.....|.........#....
|
||||
...........................................#++++++++#......####............#....
|
||||
...........................................#++++++++#.........#........@...#....
|
||||
...........................................#++++++++#.........##############....
|
||||
...........................................##########...........................
|
||||
................................................................................
|
||||
`,`
|
||||
......................................#++#........................#######....................................#+#..
|
||||
......................................#++#.....................####.....####.................................#+#..
|
||||
......................................#++##########...........##...........##................................#+#..
|
||||
......................................##++++++++++##.........##.............##...............................#+#..
|
||||
.......................................##########++#.........#....................................o...o...o..#+#..
|
||||
................................................##+#.........#.....o...o....................................##+#..
|
||||
.................................................#+#.........#................................###############++#..
|
||||
.................................................#v#.........#.....#...#........................++++++++++++++##..
|
||||
.............................................................##..|...|...|..##............#####################...
|
||||
..............................................................##+++++++++++##............v........................
|
||||
...............................................................####+++++####......................................
|
||||
...............................................#.....#............#######........###.........###..................
|
||||
...............................................#.....#...........................#.#.........#.#..................
|
||||
...............................................#.....#.............................#.........#....................
|
||||
...............................................#.....#.............................##........#....................
|
||||
...............................................##....#.............................#.........#....................
|
||||
...............................................#.....#......o..o.....#...#.........#.........#....................
|
||||
...............#######........###...###........#.....#...............#...#.........#.........#....................
|
||||
..............##.....##.........#...#..........#.....#.....######....#...#...#########.......#....................
|
||||
.............##.......##........#.o.#..........#....##...............#...#...#...............#....................
|
||||
.....@.......#.........#........#...#..........#.....#...............#...#...#...............#....................
|
||||
....###......#.........#........#...#..........#.....#...............#...#####...######......#....................
|
||||
....#.#......#.........#.......##.o.##.........#.....#...............#.....o.....#.#.........#....................
|
||||
++++#.#++++++#.........#++++++##.....##++++++++##....#++++++++++.....#.....=.....#.#.........#....................
|
||||
++++#.#++++++#.........#+++++##.......##########.....#+++++++##+.....#############.##..o.o..##....................
|
||||
++++#.#++++++#.........#+++++#....o.................##++++++##.+....................##.....##.....................
|
||||
++++#.#++++++#.........#+++++#.....................##++++++##..+.....................#######......................
|
||||
++++#.#++++++#.........#+++++##.......##############++++++##...+..................................................
|
||||
++++#.#++++++#.........#++++++#########++++++++++++++++++##....+..................................................
|
||||
++++#.#++++++#.........#++++++++++++++++++++++++++++++++##.....+..................................................
|
||||
`,`
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
........................................o.....................................................................
|
||||
..............................................................................................................
|
||||
........................................#.....................................................................
|
||||
........................................#.....................................................................
|
||||
........................................#.....................................................................
|
||||
........................................#.....................................................................
|
||||
.......................................###....................................................................
|
||||
.......................................#.#.................+++........+++..###................................
|
||||
.......................................#.#.................+#+........+#+.....................................
|
||||
.....................................###.###................#..........#......................................
|
||||
......................................#...#.................#...oooo...#.......###............................
|
||||
......................................#...#.................#..........#......#+++#...........................
|
||||
......................................#...#.................############.......###............................
|
||||
.....................................##...##......#...#......#................................................
|
||||
......................................#...#########...########..............#.#...............................
|
||||
......................................#...#...........#....................#+++#..............................
|
||||
......................................#...#...........#.....................###...............................
|
||||
.....................................##...##..........#.......................................................
|
||||
......................................#...#=.=.=.=....#............###........................................
|
||||
......................................#...#...........#...........#+++#.......................................
|
||||
......................................#...#....=.=.=.=#.....o......###.......###..............................
|
||||
.....................................##...##..........#.....................#+++#.............................
|
||||
..............................o...o...#...#...........#.....#................##v........###...................
|
||||
......................................#...#...........#..............#.................#+++#..................
|
||||
.............................###.###.###.###.....o.o..#++++++++++++++#...................v#...................
|
||||
.............................#.###.#.#.###.#..........#++++++++++++++#........................................
|
||||
.............................#.............#...#######################........................................
|
||||
.............................##...........##.........................................###......................
|
||||
..###.........................#.....#.....#.........................................#+++#................###..
|
||||
..#.#.........................#....###....#..........................................###.................#.#..
|
||||
..#...........................#....###....#######........................#####.............................#..
|
||||
..#...........................#...........#..............................#...#.............................#..
|
||||
..#...........................##..........#..............................#.#.#.............................#..
|
||||
..#.......................................#.......|####|....|####|.....###.###.............................#..
|
||||
..#................###.............o.o....#..............................#.........###.....................#..
|
||||
..#...............#####.......##..........#.............................###.......#+++#..........#.........#..
|
||||
..#...............o###o.......#....###....#.............................#.#........###..........###........#..
|
||||
..#................###........#############..#.oo.#....#.oo.#....#.oo..##.##....................###........#..
|
||||
..#......@..........#.........#...........#++#....#++++#....#++++#....##...##....................#.........#..
|
||||
..#############################...........#############################.....################################..
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
`,`
|
||||
..................................................................................................###.#.......
|
||||
......................................................................................................#.......
|
||||
..................................................................................................#####.......
|
||||
..................................................................................................#...........
|
||||
..................................................................................................#.###.......
|
||||
..........................o.......................................................................#.#.#.......
|
||||
.............................................................................................o.o.o###.#.......
|
||||
...................###................................................................................#.......
|
||||
.......+..o..+................................................#####.#####.#####.#####.#####.#####.#####.......
|
||||
.......#.....#................................................#...#.#...#.#...#.#...#.#...#.#...#.#...........
|
||||
.......#=.o..#............#...................................###.#.###.#.###.#.###.#.###.#.###.#.#####.......
|
||||
.......#.....#..................................................#.#...#.#...#.#...#.#...#.#...#.#.....#.......
|
||||
.......+..o..+............o..................................####.#####.#####.#####.#####.#####.#######.......
|
||||
..............................................................................................................
|
||||
..........o..............###..............................##..................................................
|
||||
..............................................................................................................
|
||||
..............................................................................................................
|
||||
......................................................##......................................................
|
||||
...................###.........###............................................................................
|
||||
..............................................................................................................
|
||||
..........................o.....................................................#......#......................
|
||||
..........................................................##.....##...........................................
|
||||
.............###.........###.........###.................................#..................#.................
|
||||
..............................................................................................................
|
||||
.................................................................||...........................................
|
||||
..###########.................................................................................................
|
||||
..#.........#.o.#########.o.#########.o.##................................................#...................
|
||||
..#.........#...#.......#...#.......#...#.................||..................#.....#.........................
|
||||
..#..@......#####...o...#####...o...#####.....................................................................
|
||||
..#######.....................................#####.......##.....##.....###...................................
|
||||
........#=..................=................=#...#.....................###...................................
|
||||
........#######################################...#+++++++++++++++++++++###+++++++++++++++++++++++++++++++++++
|
||||
..................................................############################################################
|
||||
..............................................................................................................
|
||||
`];
|
||||
|
||||
if (typeof module != "undefined" && module.exports && (typeof window == "undefined" || window.exports != exports))
|
||||
module.exports = GAME_LEVELS;
|
||||
if (typeof global != "undefined" && !global.GAME_LEVELS)
|
||||
global.GAME_LEVELS = GAME_LEVELS;
|
|
@ -0,0 +1,24 @@
|
|||
.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); }
|
||||
|
||||
.game {
|
||||
overflow: hidden;
|
||||
max-width: 600px;
|
||||
max-height: 450px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.lost .player {
|
||||
background: rgb(160, 64, 64);
|
||||
}
|
||||
.won .player {
|
||||
box-shadow: -4px -7px 8px white, 4px -7px 8px white;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<script src="code/chapter/16_game.js"></script>
|
||||
<script src="code/levels.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="css/game.css">
|
||||
|
||||
<body>
|
||||
<script>
|
||||
runGame(GAME_LEVELS, DOMDisplay);
|
||||
</script>
|
||||
</body>
|
|
@ -0,0 +1,12 @@
|
|||
This example is part of:
|
||||
|
||||
Marijn Haverbeke
|
||||
Eloquent JavaScript
|
||||
3rd edition (2018)
|
||||
|
||||
https://eloquentjavascript.net
|
||||
|
||||
|
||||
Chapter 16: Project: A Platform Game
|
||||
https://eloquentjavascript.net/16_game.html
|
||||
|
Loading…
Reference in New Issue