diff options
author | Mark Powers <markppowers0@gmail.com> | 2020-05-13 10:53:44 -0500 |
---|---|---|
committer | Mark Powers <markppowers0@gmail.com> | 2020-05-13 10:53:44 -0500 |
commit | 1855e0c673b06399ca89aa0c705d30b1a9ea3b97 (patch) | |
tree | 2c78eceab67bc2f377449a25df7f87181876070b | |
parent | a5706caa9cd91e357085d77c62aff7107ac76fc1 (diff) |
Add sim and paperflight games
-rw-r--r-- | src/index.html | 6 | ||||
-rw-r--r-- | src/index.js | 2 | ||||
-rw-r--r-- | src/paperflight/index.html | 123 | ||||
-rw-r--r-- | src/paperflight/server.js | 11 | ||||
-rw-r--r-- | src/paperflight/static/draw.js | 74 | ||||
-rw-r--r-- | src/paperflight/static/levels.js | 94 | ||||
-rw-r--r-- | src/paperflight/static/styles.css | 4 | ||||
-rw-r--r-- | src/paperflight/static/update.js | 48 | ||||
-rw-r--r-- | src/sim/index.html | 183 | ||||
-rw-r--r-- | src/sim/server.js | 10 | ||||
-rw-r--r-- | src/sim/static/items.js | 21 | ||||
-rw-r--r-- | src/sim/static/styles.css | 4 | ||||
-rw-r--r-- | src/sim/static/tiles.js | 73 |
13 files changed, 651 insertions, 2 deletions
diff --git a/src/index.html b/src/index.html index f210089..75d8c00 100644 --- a/src/index.html +++ b/src/index.html @@ -41,8 +41,10 @@ <li><a href="/snake">Snake</a><span class="score"></span></li> <li><a href="/stacker">Stacker</a><span class="score"></span><span class="mobile"></span></li> <li><a href="/math">Math mini games</a></li> - <!-- <li><a href="/pp/index.html">Picture pieces</a></li> --> - <li><a href="/cosmic-cargo">Cosmic Cargo (itch.io)</a><span class="score"></span></li> + <li><a href="/pp/index.html">Picture pieces</a></li> + <li><a href="/cosmic-cargo">Cosmic Cargo</a><span class="score"></span></li> + <li><a href="/sim">Sim</a><span class="score"></span></li> + <li><a href="/paperflight">Paper Flight</a><span class="score"></span></li> </ul> </div> <div> diff --git a/src/index.js b/src/index.js index 0b1e6fe..9e50928 100644 --- a/src/index.js +++ b/src/index.js @@ -82,6 +82,8 @@ server.load("./math/server", models, jwtFunctions, database) server.load("./cosmic-cargo/server", models, jwtFunctions, database) server.load("./quiz-bunny/server", models, jwtFunctions, database) server.load("./pp/server", models, jwtFunctions, database) +server.load("./sim/server", models, jwtFunctions, database) +server.load("./paperflight/server", models, jwtFunctions, database) // Start the server server.listen(config.port); diff --git a/src/paperflight/index.html b/src/paperflight/index.html new file mode 100644 index 0000000..731b92e --- /dev/null +++ b/src/paperflight/index.html @@ -0,0 +1,123 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Paper Flight</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <link rel="stylesheet" type="text/css" href="/paperflight/styles.css"> +</head> + +<body style="padding:0; margin:0; overflow:hidden;"> + <canvas id="canvas"></canvas> + <script src="/highscore.js"></script> + <script> + var width = 800 + var height = 600 + var fps = 60 + </script> + <script src="/paperflight/update.js"></script> + <script src="/paperflight/draw.js"></script> + <script src="/paperflight/levels.js"></script> + <script> + var username = undefined + + var score, plane, gameInterval, currLevelIndex, currLevel, t, collected, startLevel + + var DEFAULT_VX = 3 + var DEFAULT_VY = 0.5 + var UP_VX = 1 + var UP_VY = 0.1 + var DOWN_VX = 5 + var DOWN_VY = 2 + + window.onload = function () { + canvas = document.getElementById("canvas"); + canvas.width = width + canvas.height = height + ctx = canvas.getContext("2d"); + document.addEventListener("keydown", keyDown); + document.addEventListener("keyup", keyUp); + document.addEventListener("click", mouseClick); + init(); + draw() + } + function init() { + if (gameInterval) { + clearInterval(gameInterval) + } + score = 0 + t = 0 + plane = { + x: 30, + y: height / 4, + vx: DEFAULT_VX, + vy: DEFAULT_VY, + width: 30, + height: 10, + dir: 1 + } + setLevel(1) + gameInterval = window.setInterval(function () { + update(); + draw() + }, 1000 / fps) + } + function setLevel(to) { + currLevelIndex = to + currLevel = levels[currLevelIndex] + currLevel.items = currLevel.items.slice() + collected = 0 + startLevel = false + } + function atExit() { + return (Math.sqrt(Math.pow(plane.x - currLevel.exit.x, 2) + Math.pow(plane.y - currLevel.exit.y, 2)) < 20 + || Math.sqrt(Math.pow(plane.x + plane.width - currLevel.exit.x, 2) + Math.pow(plane.y - currLevel.exit.y, 2)) < 20) + && collected >= currLevel.coinsNeeded + } + function gameOver() { + ctx.font = "20px Courier" + ctx.fillStyle = "black" + ctx.fillText("Game Over!", 200, 200); + window.clearInterval(gameInterval) + } + function keyDown(e) { + startLevel = true + switch (e.key) { + case "ArrowLeft": // LEFT + plane.dir = -1 + break; + case "ArrowRight": // RIGHT + plane.dir = 1 + break; + case "ArrowUp": + plane.vx = UP_VX + plane.vy = UP_VY + break; + case "ArrowDown": + plane.vx = DOWN_VX + plane.vy = DOWN_VY + break; + case "R": + case "r": + init() + break; + + } + } + function keyUp(e) { + switch (e.key) { + case "ArrowUp": + case "ArrowDown": + plane.vx = DEFAULT_VX + plane.vy = DEFAULT_VY + break; + } + } + function mouseClick(e) { + console.log(e.x, e.y) + } + </script> +</body> + +</html>
\ No newline at end of file diff --git a/src/paperflight/server.js b/src/paperflight/server.js new file mode 100644 index 0000000..1f05de2 --- /dev/null +++ b/src/paperflight/server.js @@ -0,0 +1,11 @@ +function setUpRoutes(server, models, jwtFunctions, database) { + server.get('/paperflight', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/paperflight/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) + server.get('/paperflight/levels.js', (req, res) => res.sendFile(__dirname + "/static/levels.js")) + server.get('/paperflight/update.js', (req, res) => res.sendFile(__dirname + "/static/update.js")) + server.get('/paperflight/draw.js', (req, res) => res.sendFile(__dirname + "/static/draw.js")) +} + +module.exports = { + setUpRoutes +}; diff --git a/src/paperflight/static/draw.js b/src/paperflight/static/draw.js new file mode 100644 index 0000000..fe0cad5 --- /dev/null +++ b/src/paperflight/static/draw.js @@ -0,0 +1,74 @@ +function draw() { + ctx.fillStyle = "#4444ff" + ctx.fillRect(0, 0, width, height) + + drawPlane() + currLevel.items.forEach(item => { + item.draw() + }) + drawExit(currLevel.exit) + + ctx.fillStyle = "#222" + ctx.font = "20px Courier" + ctx.fillText(`Level ${currLevelIndex} (${collected}/${currLevel.coinsNeeded}) - Time ${Math.round(t / fps / 60)}:${Math.round(t / fps) % 60}`, 20, 20) + +} +function drawPlane() { + ctx.fillStyle = "#fff" + ctx.strokeStyle = "#111" + ctx.lineWidth = 3 + ctx.beginPath(); + if (plane.dir < 0) { + ctx.moveTo(plane.x + plane.width, plane.y); + ctx.lineTo(plane.x, plane.y); + ctx.lineTo(plane.x + plane.width + 4, plane.y + plane.height); + ctx.lineTo(plane.x + plane.width, plane.y); + } else { + ctx.moveTo(plane.x, plane.y); + ctx.lineTo(plane.x + plane.width, plane.y); + ctx.lineTo(plane.x + 4, plane.y + plane.height); + ctx.lineTo(plane.x, plane.y); + } + ctx.stroke(); + ctx.fill(); +} +function drawVent() { + ctx.fillStyle = "#ccc" + ctx.fillRect(this.x, this.y, this.width, 10) + ctx.fillStyle = "white" + var yDelta = Math.sin(t / 30) * 40 + for (var i = this.y; i > 30; i -= 60) { + ctx.fillRect(this.x, this.y - i + yDelta, 1, 8) + ctx.fillRect(this.x+this.width/2-2, this.y - i + yDelta/2, 1, 12) + ctx.fillRect(this.x+this.width-2, this.y - i + yDelta, 1, 8) + } +} +function drawBlock() { + ctx.fillStyle = "#0d0" + ctx.fillRect(this.x, this.y, this.width, this.height) +} +function drawRamp() { + ctx.fillStyle = "#0d0" + var delta = this.width * this.slope + ctx.beginPath() + ctx.moveTo(this.x, this.y) + // Note we subtract beause y=0 is top + ctx.lineTo(this.x + this.width, this.y - delta) + ctx.lineTo(this.x + this.width, this.y + this.height - delta) + ctx.lineTo(this.x, this.y + this.height) + ctx.lineTo(this.x, this.y) + ctx.stroke() + ctx.fill() +} +function drawCoin() { + ctx.fillStyle = "yellow" + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2) + ctx.fill() +} +function drawExit(exit) { + ctx.fillStyle = "green" + ctx.beginPath() + ctx.arc(exit.x, exit.y, 20, 0, Math.PI * 2) + ctx.fill() +}
\ No newline at end of file diff --git a/src/paperflight/static/levels.js b/src/paperflight/static/levels.js new file mode 100644 index 0000000..d826095 --- /dev/null +++ b/src/paperflight/static/levels.js @@ -0,0 +1,94 @@ +var levels = { + 1: { + coinsNeeded: 5, + exit: { + x: 40, + y: 460 + }, + items: [{ + draw: drawVent, + update: updateVent, + x: 420, + y: 580, + width: 60 + }, + { + draw: drawRamp, + update: updateRamp, + x: 0, + y: 0, + slope: 0, + width: 800, + height: 40 + }, + { + draw: drawCoin, + update: updateCoin, + x: 40, + y: 80, + radius: 10 + }, + { + draw: drawVent, + update: updateVent, + x: 120, + y: 100, + width: 280 + }, + { + draw: drawBlock, + update: updateBlock, + x: 580, + y: 200, + width: 10, + height: 250 + }, + { + draw: drawCoin, + update: updateCoin, + x: 700, + y: 240, + radius: 10 + }, + { + draw: drawCoin, + update: updateCoin, + x: 700, + y: 320, + radius: 10 + }, + { + draw: drawCoin, + update: updateCoin, + x: 700, + y: 400, + radius: 10 + }, + { + draw: drawRamp, + update: updateRamp, + x: 70, + y: 410, + slope: 2/5, + width: 200, + height: 10 + }, + { + draw: drawRamp, + update: updateRamp, + x: 70, + y: 470, + slope: 2/5, + width: 200, + height: 10 + }, + { + draw: drawCoin, + update: updateCoin, + x: 170, + y: 405, + radius: 10 + }, + ] + } +}
\ No newline at end of file diff --git a/src/paperflight/static/styles.css b/src/paperflight/static/styles.css new file mode 100644 index 0000000..febe7a0 --- /dev/null +++ b/src/paperflight/static/styles.css @@ -0,0 +1,4 @@ +button { + background-color: lavender; + padding: 10px 20px; +}
\ No newline at end of file diff --git a/src/paperflight/static/update.js b/src/paperflight/static/update.js new file mode 100644 index 0000000..296308f --- /dev/null +++ b/src/paperflight/static/update.js @@ -0,0 +1,48 @@ +function update() { + t++ + score++ + if(startLevel){ + plane.x += plane.vx * plane.dir + plane.y += plane.vy + } + if (plane.x < 0 || plane.x > width - plane.width || plane.y < 0 || plane.y + plane.height > height) { + gameOver() + } + currLevel.items.forEach(item => { + item.update() + }) + currLevel.items = currLevel.items.filter(item => !item.collected ) + if (atExit()) { + console.log("exit!") + } +} +function updateVent() { + if (plane.x >= this.x - plane.width && plane.x <= this.x + this.width && plane.y < this.y) { + plane.y -= 2 + } +} +function updateBlock() { + if (plane.x >= this.x - plane.width && plane.x <= this.x + this.width + && plane.y >= this.y - plane.height && plane.y <= this.y + this.height) { + gameOver() + } +} +function isPointInRamp(x, y, ramp) { + var yDelta = (x - ramp.x) * ramp.slope + return ramp.x < x && x < ramp.x + ramp.width && ramp.y < y + yDelta && y + yDelta < ramp.y + ramp.height +} +function updateRamp() { + if (isPointInRamp(plane.x, plane.y, this) || + isPointInRamp(plane.x + plane.width, plane.y, this) || + isPointInRamp(plane.x + plane.width, plane.y + plane.height, this) || + isPointInRamp(plane.x, plane.y + plane.height, this)) { + gameOver() + } +} +function updateCoin(){ + if( Math.sqrt(Math.pow(plane.x - this.x, 2) + Math.pow(plane.y - this.y, 2)) < this.radius + || Math.sqrt(Math.pow(plane.x + plane.width - this.x, 2) + Math.pow(plane.y - this.y, 2)) < this.radius){ + this.collected = true + collected++ + } +}
\ No newline at end of file diff --git a/src/sim/index.html b/src/sim/index.html new file mode 100644 index 0000000..b9330e0 --- /dev/null +++ b/src/sim/index.html @@ -0,0 +1,183 @@ +<!doctype html> +<html lang="en"> + +<head> + <title>Sim</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <link rel="stylesheet" type="text/css" href="/sim/styles.css"> +</head> + +<body style="padding:0; margin:0; overflow:hidden;"> + <div> + <div>Population: <span id="population"></span></div> + <div>Gold: <span id="gold"></span></div> + <div>Resources: <span id="resources"></span></div> + <button onclick="status = ''; update()">Update</button> + </div> + <canvas id="canvas"></canvas> + <div id="status"></div> + <div id="shopDiv"></div> + <script src="/highscore.js"></script> + <script src="/sim/tiles.js"></script> + <script src="/sim/items.js"></script> + <script> + var score; + var username = undefined + + var populationEl = document.getElementById("population") + var goldEl = document.getElementById("gold") + var shopEl = document.getElementById("shopDiv") + var statusEl = document.getElementById("status") + var resourceEl = document.getElementById("resources") + + var population, gold, resources; + var shopItems = []; + var queuedTile + + var width = 10 + var height = 10 + var tileSize = 40; + var status = "" + + var t + var eventQueue + + var level + window.onload = function () { + canvas = document.getElementById("canvas"); + canvas.width = width * tileSize + canvas.height = height * tileSize + ctx = canvas.getContext("2d"); + document.addEventListener("keydown", keyPush); + document.addEventListener("click", mouseClick); + init(); + draw() + } + function init() { + score = 0 + level = [] + + for (var i = 0; i < width; i++) { + var row = [] + for (var j = 0; j < height; j++) { + row.push(undefined) + } + level.push(row) + } + level[Math.floor(width / 2)][Math.floor(height / 2)] = new Town() + + population = 10 + gold = 5 + resources = 0 + + t = 0 + eventQueue = { + 5: getScout(), + 15: getScout(), + 20: getScout(), + 30: getScout(), + } + addShopItem(getScout()) + } + function draw() { + ctx.fillStyle = "#009900" + ctx.fillRect(0, 0, width * tileSize, height * tileSize) + for (var i = 0; i < width; i++) { + var row = level[i] + for (var j = 0; j < height; j++) { + if (row[j]) { + row[j].draw(i, j, tileSize) + } + } + } + for (var i = 0; i <= height; i++) { + ctx.strokeStyle = "#aaa" + ctx.moveTo(0, i * tileSize) + ctx.lineTo(tileSize * width, i * tileSize) + ctx.stroke() + } + for (var i = 0; i <= width; i++) { + ctx.strokeStyle = "#aaa" + ctx.moveTo(i * tileSize, 0) + ctx.lineTo(i * tileSize, tileSize * height) + ctx.stroke() + } + + populationEl.innerText = population + goldEl.innerText = gold + statusEl.innerText = status + resourceEl.innerText = resources + } + function update() { + t++ + for (var i = 0; i < width; i++) { + var row = level[i] + for (var j = 0; j < height; j++) { + if (row[j]) { + processUpdate(row[j].update()) + } + } + } + if(eventQueue[t]){ + addShopItem(eventQueue[t]) + } + + draw() + } + function keyPush(e) { + status = "" + update() + } + function mouseClick(e) { + if(queuedTile){ + var x = Math.floor((e.x - canvas.offsetLeft) / tileSize) + var y = Math.floor((e.y - canvas.offsetTop) / tileSize) + if(x < 0 || width <= x || y < 0 || height <= y){ + return + } + if(level[x][y] == undefined){ + level[x][y] = queuedTile + status = `You placed the ${queuedTile.name}` + queuedTile = undefined + } else { + status = `You cannot place a tile there.` + } + update() + } + } + function addShopItem(item){ + shopItems.push(item) + + var newButton = document.createElement("button") + newButton.innerText = item.text + ": " + item.cost + newButton.id = item.id + newButton.onclick = function(){ + if(item.cost <= gold){ + shopItems = shopItems.filter(it => it.id != item.id) + shopDiv.removeChild(newButton) + gold -= item.cost + processUpdate(item.callback()) + } else { + status = "not enough gold" + } + update() + } + shopDiv.appendChild(newButton) + update() + } + function processUpdate(response){ + if(response.tile){ + queuedTile = response.tile + } else if(response.gold){ + gold += response.gold + } else if(response.population){ + population += response.population + } else if(response.resources){ + resources += response.resources + } + } + </script> +</body> + +</html>
\ No newline at end of file diff --git a/src/sim/server.js b/src/sim/server.js new file mode 100644 index 0000000..5328b03 --- /dev/null +++ b/src/sim/server.js @@ -0,0 +1,10 @@ +function setUpRoutes(server, models, jwtFunctions, database) { + server.get('/sim', (req, res) => res.sendFile(__dirname + "/index.html")) + server.get('/sim/styles.css', (req, res) => res.sendFile(__dirname + "/static/styles.css")) + server.get('/sim/tiles.js', (req, res) => res.sendFile(__dirname + "/static/tiles.js")) + server.get('/sim/items.js', (req, res) => res.sendFile(__dirname + "/static/items.js")) +} + +module.exports = { + setUpRoutes +}; diff --git a/src/sim/static/items.js b/src/sim/static/items.js new file mode 100644 index 0000000..40f73f1 --- /dev/null +++ b/src/sim/static/items.js @@ -0,0 +1,21 @@ +tileMap = { + 0: Mountain, + 1: Forest, + 2: Town, +} + +function getScout() { + return { + id: 1, + text: "scout", + cost: 2, + callback: function () { + var type = tileMap[Math.floor(Math.random() * 3)] + var tile = new type() + status = `Your scout found a ${tile.name}. Click to place it.` + return { + tile: tile + } + } + } +}
\ No newline at end of file diff --git a/src/sim/static/styles.css b/src/sim/static/styles.css new file mode 100644 index 0000000..febe7a0 --- /dev/null +++ b/src/sim/static/styles.css @@ -0,0 +1,4 @@ +button { + background-color: lavender; + padding: 10px 20px; +}
\ No newline at end of file diff --git a/src/sim/static/tiles.js b/src/sim/static/tiles.js new file mode 100644 index 0000000..5b31d19 --- /dev/null +++ b/src/sim/static/tiles.js @@ -0,0 +1,73 @@ +function Mountain() { + this.name = "mountain" +} +Mountain.prototype.draw = function (x, y, size) { + ctx.fillStyle = "gray" + ctx.beginPath(); + ctx.moveTo(x * size + size / 2, y * size); + ctx.lineTo(x * size, (1 + y) * (size)); + ctx.lineTo((1 + x) * (size), (1 + y) * (size)); + ctx.stroke(); + ctx.fill(); +} +Mountain.prototype.update = function () { + var event = undefined + if(Math.random() < 0.1){ + event = function(){ + + } + } + return { + gold: 1, + event: event + } +} + +function Forest() { + this.name = "forest" +} +Forest.prototype.draw = function (x, y, size) { + ctx.fillStyle = "green" + ctx.beginPath(); + ctx.moveTo(x * size + size / 2, y * size); + ctx.lineTo(x * size, (1 + y) * (size)); + ctx.lineTo((1 + x) * (size), (1 + y) * (size)); + ctx.stroke(); + ctx.fill(); +} +Forest.prototype.update = function () { + var event = {} + if(Math.random() < 0.1){ + event.status = "A tree monster taks half of your" + } + return { + resources: Math.floor(Math.random() * 5), + event: event + } +} + +function Town() { + this.name = "town" +} +Town.prototype.draw = function (x, y, size) { + ctx.fillStyle = "brown" + ctx.stokeStyle = "brown" + ctx.beginPath(); + ctx.moveTo(x * size + size / 2, y * size); + ctx.lineTo(x * size, (1 + y) * (size)); + ctx.lineTo((1 + x) * (size), (1 + y) * (size)); + ctx.stroke(); + ctx.fill(); +} +Town.prototype.update = function () { + var event = undefined + if(Math.random() < 0.1){ + event = function(){ + + } + } + return { + population: Math.floor(Math.random() * 4) - 1, + event: event + } +} |