'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"; import Setting from "./Setting.js"; import FrameRateMeasurer from "./FrameRateMeasurer.js"; import GraphicSet from "./GraphicSet.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(imagePath) { let image = new Image(); image.src = imagePath; 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 ); } camera.focusPosition( mrCroc.position.x - mrCroc.getWidth() * 0.5, mrCroc.position.y - mrCroc.getHeight() * 0.5, 20 ); camera.lockCameraIntoBorders(); /* Drawing */ if (timestamp - lastRendered >= frameDuration) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); architecture.draw(context, camera); mrCroc.draw(context, camera); gisela.draw(context, camera); lastRendered = timestamp; } lastTimestamp = timestamp; if (!gameFinished && mrCroc.isJumping === false && architecture.isMovableInsideTargetPosition(mrCroc)) { gameFinished = true; KeyLeft.pressed = false; KeyRight.pressed = false; KeyJump.pressed = false; lastTimestamp = undefined; lastRendered = undefined; alert('Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."'); } window.requestAnimationFrame(MainLoop); } const GAME_SPEED = 1; const GRAVITY = 2; let fps; let frameDuration; let levelJson = new FileLoader('levels/moon.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(); loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png'); loader.addImage(Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left.png'); loader.addImage(Setting.TILESET_LOCATION + GraphicSet[LEVEL.tileset].tileset); loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-right.png'); new FrameRateMeasurer(); window.addEventListener( 'imagesloaded', () => { let canvas = document.getElementById('canvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; canvas.style.backgroundAttachment = 'fixed'; canvas.style.backgroundSize = 'cover'; canvas.style.backgroundPosition = 'center center'; if (GraphicSet[LEVEL.tileset].backgroundImage !== null) { canvas.style.backgroundImage = 'url("' + Setting.GRAPHICS_LOCATION + GraphicSet[LEVEL.tileset].backgroundImage +'")'; } canvas.style.backgroundColor = LEVEL.backgroundColor; 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); fps = 120; frameDuration = 1000 / fps; window.requestAnimationFrame(MainLoop); } );