diff --git a/Makefile b/Makefile index 88fcf00..dd4c680 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,12 @@ www/js/escalator.js: $(shell find src -name "*.js") mkdir -p www/js cat \ src/open.js \ + src/screen.js \ src/scene.js \ src/box.js \ src/platform.js \ + src/menu.js \ + src/game.js \ src/main.js \ src/close.js \ > www/js/escalator.js diff --git a/src/game.js b/src/game.js new file mode 100644 index 0000000..81e0ccf --- /dev/null +++ b/src/game.js @@ -0,0 +1,39 @@ +class Game { + + constructor(canvas) { + // Create menu + let menu = new Menu(canvas); + + // Create game scene + let box = new Box(); + this.scene = new Scene(document.getElementById('canvas'), box); + + this.changeScreen(menu); + } + + changeScreen(screen) { + if (this.mainSCreen !== undefined) { + this.mainScreen.removeListeners(); + } + + this.mainScreen = screen; + screen.status = Status.Running; + screen.addListeners(); + } + + update(time = 0.002) { + this.mainScreen.update(time); + + if (this.mainScreen.status === Status.Finished) { + if (this.mainScreen.after === AfterMenu.Start) { + this.changeScreen(this.scene); + } else if (this.mainScreen.after === AfterMenu.Exit) { + alert("I don't know how to exit"); + } + } + } + + render() { + this.mainScreen.render(); + } +} diff --git a/src/main.js b/src/main.js index 751c764..519cfe3 100644 --- a/src/main.js +++ b/src/main.js @@ -1,34 +1,22 @@ -let scene; +let game; init(); loop(); function init() { - // Initialize scene - let box = new Box(); - scene = new Scene(document.getElementById('canvas'), box); - - // Initialize listeners - window.addEventListener('resize', () => { - scene.autoResize() - }); - - document.addEventListener('touchstart', (event) => { - scene.start(); - let e = event.changedTouches[0]; - box.jump(e.clientX / window.innerWidth, e.clientY / window.innerHeight); - }); + let canvas = document.getElementById('canvas'); + game = new Game(canvas); } function loop() { // Manage physics - scene.update(); + game.update(); // Do rendering - scene.render(); + game.render(); requestAnimationFrame(loop); } diff --git a/src/menu.js b/src/menu.js new file mode 100644 index 0000000..aebcc67 --- /dev/null +++ b/src/menu.js @@ -0,0 +1,122 @@ +const AfterMenu = { + Exit: 0, + Start: 1, +}; + +class Menu extends Screen { + constructor(canvas) { + super(canvas); + + this.addEventListener('touchstart', (event) => { + this.onTouchStart(event); + }); + } + + render() { + this.clear(); + this.drawBackground(); + this.drawTitle(); + this.drawMenu(); + } + + drawTitle() { + this.context.font = "50px Arial"; + this.context.stokeStyle = 'rgb(0, 0, 0)'; + this.context.fillStyle = 'rgb(255, 255, 255)'; + + let text = "Escalator"; + let size = this.context.measureText(text).width; + let offset = (this.width() - size) / 2; + + this.context.fillText(text, offset, 0.1 * this.width() + 50); + this.context.strokeText(text, offset, 0.1 * this.width() + 50); + } + + drawMenu() { + this.context.font = "30px Arial"; + this.context.fillStyle = 'rgb(255, 255, 255)'; + + let text = "New Game"; + let box = this.newGameBox(); + this.context.fillText(text, box.x, box.y + 30); + + // this.context.beginPath(); + // box = this.enlargeBox(box); + // this.context.rect(box.x, box.y, box.width, box.height); + // this.context.stroke(); + + text = "Exit"; + box = this.exitBox(); + this.context.fillText(text, box.x, box.y + 30); + + // this.context.beginPath(); + // box = this.enlargeBox(box); + // this.context.rect(box.x, box.y, box.width, box.height); + // this.context.stroke(); + } + + drawBackground() { + this.context.fillStyle = 'rgb(255, 0, 0)'; + this.context.beginPath(); + this.context.rect(0, 0, this.width(), this.height()); + this.context.fill(); + } + + newGameBox() { + this.context.font = "30px Arial"; + let text = "New Game"; + let size = this.context.measureText(text); + let offset = (this.width() - size.width) / 2; + + return { + x: offset, + y: 0.5 * this.height(), + width: size.width, + height: 30, + }; + } + + exitBox() { + this.context.font = "30px Arial"; + let text = "Exit"; + let size = this.context.measureText(text); + let offset = (this.width() - size.width) / 2; + + return { + x: offset, + y: 0.7 * this.height(), + width: size.width, + height: 30, + }; + + } + + onTouchStart(event) { + let e = event.changedTouches[0]; + + let box = this.enlargeBox(this.newGameBox()); + if (e.clientX > box.x && e.clientX < box.x + box.width) { + if (e.clientY > box.y && e.clientY < box.y + box.height) { + this.status = Status.Finished; + this.after = AfterMenu.Start; + } + } + + box = this.enlargeBox(this.exitBox()); + if (e.clientX > box.x && e.clientX < box.x + box.width) { + if (e.clientY > box.y && e.clientY < box.y + box.height) { + this.status = Status.Finished; + this.after = AfterMenu.Exit; + } + } + } + + enlargeBox(box) { + return { + x: box.x - box.width * 0.1, + y: box.y - box.height * 0.1, + width: box.width * 1.2, + height: box.height * 1.4, + } + } +} diff --git a/src/scene.js b/src/scene.js index 09aba6d..83c4425 100644 --- a/src/scene.js +++ b/src/scene.js @@ -1,18 +1,23 @@ -class Scene { +class Scene extends Screen { constructor(canvas, player) { - this.canvas = canvas; - this.context = canvas.getContext('2d'); + super(canvas); this.player = player; + this.currentHeight = 0; this.maxHeight = 0; this.initialize(); + + this.addEventListener('touchstart', (event) => { + this.onTouchStart(event); + }); } initialize() { - this.autoResize(); + super.initialize(); this.player.reset(); this.platforms = []; this.cameraHeight = 0; this.cameraSpeed = 0; + this.currentHeight = 0; this.started = false; // Generate random initial platforms @@ -30,32 +35,10 @@ class Scene { } } - width() { - return this.canvas.width; - } - - height() { - return this.canvas.height; - } - - resize(width, height) { - this.canvas.width = width; - this.canvas.height = height; - } - - autoResize() { - this.canvas.width = window.innerWidth; - this.canvas.height = window.innerHeight; - } - - clear() { - this.context.clearRect(0, 0, this.width(), this.height()); - } - drawBackground() { this.context.fillStyle = 'rgb(255, 0, 0)'; this.context.beginPath(); - this.context.rect(0, 0, this.canvas.width, this.canvas.height); + this.context.rect(0, 0, this.width(), this.height()); this.context.fill(); } @@ -82,6 +65,7 @@ class Scene { // Update high score this.maxHeight = Math.max(this.player.y, this.maxHeight); + this.currentHeight = Math.max(this.player.y, this.currentHeight); let previous = { x: this.player.x, @@ -177,7 +161,18 @@ class Scene { drawHud() { this.context.font = "20px Arial"; this.context.fillStyle = 'rgb(255, 255, 255)'; - this.context.fillText("High score: " + Math.floor(100 * this.maxHeight), 0, 20); + this.context.fillText("Current score: " + Math.floor(100 * this.currentHeight), 0, 20); + this.context.fillText("High score: " + Math.floor(100 * this.maxHeight), 0, 50); + } + + onTouchStart(event) { + + let e = event.changedTouches[0]; + this.start(); + if (e !== undefined) { + this.player.jump(e.clientX / window.innerWidth, e.clientY / window.innerHeight); + } + } } diff --git a/src/screen.js b/src/screen.js new file mode 100644 index 0000000..8225517 --- /dev/null +++ b/src/screen.js @@ -0,0 +1,69 @@ +const Status = { + Idle: 0, + Running: 1, + Finished: 2, +}; + +class Screen { + + constructor(canvas) { + this.status = Status.Idle; + this.canvas = canvas; + this.context = canvas.getContext('2d'); + this.listeners = []; + this.autoResize(); + } + + addEventListener(type, callback) { + this.listeners.push({ + type: type, + callback: callback, + }); + } + + addListeners() { + for (let listener of this.listeners) { + document.addEventListener(listener.type, listener.callback); + } + } + + removeListeners() { + for (let listener of this.listeners) { + document.removeElementListener(listener.type, listener.callback); + } + } + + initialize() { + this.autoResize(); + } + + autoResize() { + this.resize(window.innerWidth, window.innerHeight); + } + + resize(width, height) { + this.canvas.width = width; + this.canvas.height = height; + } + + clear() { + this.context.clearRect(0, 0, this.width(), this.height()); + } + + render() { + + } + + update(time = 0.002) { + + } + + width() { + return this.canvas.width; + } + + height() { + return this.canvas.height; + } + +}