'use strict'; import Key from "./Key.js"; import MrCroc from "./MrCroc.js"; import RetroArchitecture from "./retro/RetroArchitecture.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"; import ImageLoader from "./ImageLoader.js"; import Level from "./Level.js"; import InterfaceEvent from "./events/InterfaceEvent.js"; import UrlParam from "./UrlParam.js"; import UserInterface from "./ui/UserInterface.js"; import TextMessageGisela from "./ui/TextMessageGisela.js"; import TextMessageMrCroc from "./ui/TextMessageMrCroc.js"; 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) { if (gisela.currentAnimation !== 'LOOK_LEFT' && mrCroc.position.x < gisela.position.x) { gisela.currentAnimation = 'LOOK_LEFT'; } else if (gisela.currentAnimation !== 'LOOK_RIGHT' && mrCroc.position.x >= gisela.position.x) { gisela.currentAnimation = 'LOOK_RIGHT'; } context.clearRect(0, 0, window.innerWidth, window.innerHeight); architecture.draw(context, camera); mrCroc.draw(context, camera); gisela.draw(context, camera); userInterface.draw(context); 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; textBoxGameFinished.updateLines(window.innerWidth - 40, context); textBoxGameFinished.animate(75); userInterface.addTextBox(textBoxGameFinished); } window.requestAnimationFrame(MainLoop); } const LEVEL = [ 'level01.json', 'moon.json', 'moonbase.json', 'terrain8.json', ]; let urlGetter = new UrlParam(); let levelIndex = urlGetter.getInt('level'); if (levelIndex === undefined || levelIndex < 0 || levelIndex >= LEVEL.length) { levelIndex = 0; } let level = Level.createFromFile(Setting.LEVELS_LOCATION + LEVEL[levelIndex]); const GAME_SPEED = 1; const GRAVITY = level.gravity; let fps; let frameDuration; let lastRendered = undefined; let lastTimestamp = undefined; let context; let mrCroc, gisela, architecture; let camera = new Camera(); let gameFinished = false; let hasPlayerLeftArchitecture = false; let textBoxGameStart; let textBoxGameFinished; let userInterface = new UserInterface(); 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.getTilesetId()].tileset); loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-right.png'); loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-left.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.getTilesetId()].backgroundImage !== null) { canvas.style.backgroundImage = 'url("' + Setting.GRAPHICS_LOCATION + GraphicSet[level.getTilesetId()].backgroundImage +'")'; } canvas.style.backgroundColor = level.getBackgroundColor(); window.addEventListener( 'resize', function () { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } ); context = canvas.getContext('2d'); textBoxGameFinished = new TextMessageGisela( 'Gisela: "Thanks for showing up, Mr. Croc, but I\'m not in danger."', context ); textBoxGameStart = new TextMessageMrCroc('Mr. Croc: "Where is Gisela? I have to find her!"', context); textBoxGameStart.animate(75, 1000); textBoxGameStart.show(1000); textBoxGameStart.hide(10000); userInterface.addTextBox(textBoxGameStart); 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.addEventListener( InterfaceEvent.FRAME_RATE_MEASURED, (event) => { fps = event.frameRate; frameDuration = 1000 / fps; window.requestAnimationFrame(MainLoop); } ); } );