'use strict'; import Key from "./Key.js"; import MrCroc from "./MrCroc.js"; import RetroArchitecture from "./retro/RetroArchitecture.js"; import FileLoader from "./FileLoader.js"; import Camera from "./Camera.js"; import Gisela from "./Gisela.js"; class ImageLoader { images = []; numberImagesLoaded = 0; update() { this.numberImagesLoaded++; if (this.numberImagesLoaded === this.images.length) { window.dispatchEvent(new Event('imagesloaded')); } } getCurrentProgress() { return this.numberImagesLoaded / this.images.length; } addImage(image) { image.addEventListener( 'load', () => { this.update(); } ); this.images.push(image); } } function MainLoop(timestamp) { if (lastRendered === undefined && lastTimestamp === undefined) { lastRendered = timestamp; lastTimestamp = timestamp; } let delta = (timestamp - lastTimestamp) / (10 / GAME_SPEED); let ceilingHeight = Math.max( architecture.getCeilingHeight(mrCroc.getPositionHeadLeft()), architecture.getCeilingHeight(mrCroc.getPositionHeadRight()), ); let groundHeight = Math.min( architecture.getGroundHeight(mrCroc.getPositionFootLeft()), architecture.getGroundHeight(mrCroc.getPositionFootRight()) ); /* Handle falling */ mrCroc.position.y += mrCroc.fallSpeed; mrCroc.fallSpeed += GRAVITY * delta; /* Handle ground collision */ if (mrCroc.position.y > groundHeight && mrCroc.fallSpeed > 0) { mrCroc.position.y = groundHeight; mrCroc.fallSpeed = 0; } /* Handle ceiling collision */ if (mrCroc.position.y - mrCroc.getHeight() <= ceilingHeight) { mrCroc.fallSpeed = 0; mrCroc.position.y = ceilingHeight + mrCroc.getHeight() + 1; } /* Handle jumping */ if (!mrCroc.isJumping && mrCroc.fallSpeed === 0 && mrCroc.position.y === groundHeight && KeyJump.isPressed()) { mrCroc.jump(); } else if (!KeyJump.isPressed()) { mrCroc.isJumping = false; } /* Movement left and right */ if (!hasPlayerLeftArchitecture && KeyLeft.isPressed()) { let lastWallLeft = Math.min( architecture.getWallLeft(mrCroc.getPositionHeadLeft()), architecture.getWallLeft(mrCroc.getPositionFootLeft()) ); mrCroc.moveLeft(timestamp, delta); if (mrCroc.position.x <= lastWallLeft + mrCroc.getWidth() * 0.5) { mrCroc.position.x = lastWallLeft + mrCroc.getWidth() * 0.5 + 1; } } else if (!hasPlayerLeftArchitecture && KeyRight.isPressed()) { let lastWallRight = Math.max( architecture.getWallRight(mrCroc.getPositionHeadRight()), architecture.getWallRight(mrCroc.getPositionFootRight()) ); mrCroc.moveRight(timestamp, delta); if (mrCroc.position.x >= lastWallRight - mrCroc.getWidth() * 0.5) { mrCroc.position.x = lastWallRight - mrCroc.getWidth() * 0.5 - 1; } } if (!hasPlayerLeftArchitecture && !architecture.isInsideArchitecture(mrCroc.position)) { hasPlayerLeftArchitecture = true; setTimeout( function () { architecture.setMovableToStartPosition(mrCroc); hasPlayerLeftArchitecture = false; }, 2000 ); } if (!gameFinished && architecture.isMovableInsideTargetPosition(mrCroc)) { gameFinished = true; setTimeout( function () { alert('Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."'); lastTimestamp = timestamp; lastRendered = timestamp; }, 1000 ) } camera.focusPosition( mrCroc.position.x - mrCroc.getWidth() * 0.5, mrCroc.position.y - mrCroc.getHeight() * 0.5, 20 ); camera.lockCameraIntoBorders(); /* Drawing */ if (timestamp - lastRendered >= FRAME_DURATION) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); // camera.centerCamera(mrCroc.position.x - mrCroc.getWidth() * 0.5, mrCroc.position.y - mrCroc.getHeight() * 0.5); architecture.draw(context, camera); mrCroc.draw(context, camera); gisela.draw(context, camera); lastRendered = timestamp; } lastTimestamp = timestamp; window.requestAnimationFrame(MainLoop); } const FPS = 60; const FRAME_DURATION = 1000 / FPS; const GAME_SPEED = 1; const GRAVITY = 2; let levelJson = new FileLoader('levels/level01.json'); const LEVEL = JSON.parse(levelJson.getContent()); let lastRendered = undefined; let lastTimestamp = undefined; let context; let mrCroc, gisela, architecture; let camera = new Camera(); let gameFinished = false; let hasPlayerLeftArchitecture = false; let KeyLeft = new Key('ArrowLeft'); let KeyRight = new Key('ArrowRight'); let KeyJump = new Key('Space'); let loader = new ImageLoader(); let imgAnimation = new Image(); imgAnimation.src = 'graphics/mr-croc-walk-right.png'; loader.addImage(imgAnimation); let imgAnimationB = new Image(); imgAnimationB.src = 'graphics/mr-croc-walk-left.png'; loader.addImage(imgAnimationB); let imgArch = new Image(); imgArch.src = 'graphics/tileset-landscape01.jpg'; loader.addImage(imgArch); let imgGisela = new Image(); imgGisela.src = 'graphics/gisela-right.png'; loader.addImage(imgGisela); window.addEventListener( 'imagesloaded', () => { let canvas = document.getElementById('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; window.addEventListener( 'resize', function () { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } ); context = canvas.getContext('2d'); architecture = RetroArchitecture.createFromData(LEVEL); camera.borderRight = architecture.columns * architecture.tileWidth; camera.borderBottom = architecture.rows * architecture.tileHeight; mrCroc = new MrCroc(); architecture.setMovableToStartPosition(mrCroc); gisela = new Gisela(); architecture.setMovableToTargetPosition(gisela); window.requestAnimationFrame(MainLoop); } );