class Scene extends Screen { constructor(canvas, player) { super(canvas); this.player = player; this.currentHeight = 0; this.maxHeight = 0; this.initialize(); this.addEventListener('touchstart', (event) => { this.onTouchStart(event); }); } initialize() { super.initialize(); this.player.reset(); this.platforms = []; this.cameraHeight = 0; this.cameraSpeed = 0; this.currentHeight = 0; this.started = false; // Generate random initial platforms for (let i = 0.25; i <= 2; i += 0.33) { let platform = new Platform(Math.random(), i, 0.2); this.addPlatform(platform); } } start() { if (!this.started) { this.started = true; this.cameraSpeed = 0.005; } } drawBackground() { this.context.fillStyle = 'rgb(255, 0, 0)'; this.context.beginPath(); this.context.rect(0, 0, this.width(), this.height()); this.context.fill(); } update(time = 0.002) { // Check if the game is lost if (this.player.y + this.player.size < this.cameraHeight) { this.initialize(); } // The last platform is the highest. let last = this.platforms[this.platforms.length - 1]; // If the last platform is on screen, we need to create the next platform. if (last.y <= this.cameraHeight + 1) { let diff = 0.1 + Math.random() * 0.4; let platform = new Platform(Math.random(), last.y + diff, 0.2); this.platforms.push(platform); } // Increase position of the camera this.cameraHeight += this.cameraSpeed * time * this.height(); // 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, y: this.player.y + this.player.size / 2, }; this.player.update(time); let next = { x: this.player.x, y: this.player.y + this.player.size / 2, size: this.player.size, }; // Detect collision with platform for (let platform of this.platforms) { let p = { x: platform.x, y: platform.y + platform.height / 2, width: platform.width, height: platform.height, }; if (previous.y >= p.y && next.y < p.y) { if (next.x >= p.x - p.width / 2 - next.size / 2) { if (next.x <= p.x + p.width / 2 + next.size / 2) { // Collision detected this.player.collide(p.y - next.size/2); } } } } // Collision with the ground if (this.player.y <= 0) { this.player.collide(0); } // Collisions with the border of the screen this.player.x = Math.max(this.player.x, this.player.size / 2); this.player.x = Math.min(this.player.x, 1 - this.player.size / 2); } addPlatform(object) { this.platforms.push(object); } render() { this.clear(); this.drawBackground(); for (let platform of this.platforms) { this.drawPlatform(platform); } this.drawObject(this.player); this.drawHud(); } drawObject(object) { let size = object.size * this.width(); this.context.fillStyle = 'rgb(0, 0, 0)'; this.context.beginPath(); this.context.rect( (object.x - object.size / 2) * this.width(), (1 - object.y - object.size / 2 + this.cameraHeight) * this.height(), size, size, ); this.context.fill(); } drawPlatform(object) { let width = object.width * this.width(); let height = object.height * this.height(); this.context.fillStyle = object.color || 'rgb(0, 0, 0)'; this.context.beginPath(); this.context.rect( (object.x - object.width / 2) * this.width(), (1 - object.y - object.height / 2 + this.cameraHeight) * this.height(), width, height, ); this.context.fill(); } drawHud() { this.context.font = "20px Arial"; this.context.fillStyle = 'rgb(255, 255, 255)'; 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); } } }