From 72589544bd3861bc104aab8e06ca26a081567ca8 Mon Sep 17 00:00:00 2001 From: Mal Date: Wed, 12 Feb 2020 23:30:04 +0100 Subject: [PATCH] Performance optimizations and refacturing. --- js/Camera.js | 17 ++++++ js/FrameRateMeasurer.js | 86 +++++++++++++++++++++++++++++ js/Movable.js | 6 +- js/events/FrameRateMeasuredEvent.js | 9 +++ js/events/InterfaceEvent.js | 11 ++-- js/module.js | 35 ++++++------ 6 files changed, 138 insertions(+), 26 deletions(-) create mode 100644 js/FrameRateMeasurer.js create mode 100644 js/events/FrameRateMeasuredEvent.js diff --git a/js/Camera.js b/js/Camera.js index a1ab763..b0df01c 100644 --- a/js/Camera.js +++ b/js/Camera.js @@ -1,4 +1,5 @@ import GeometryPoint from "./geometry/GeometryPoint.js"; +import GeometryRect from "./geometry/GeometryRect.js"; export default class Camera { @@ -114,4 +115,20 @@ export default class Camera } } } + + getViewAsRect() + { + return new GeometryRect(this.position.x, this.position.y, this.width, this.height); + } + + isMovableInsideView(movable) + { + let viewRect = this.getViewAsRect(); + let distanceMovable = movable.getRect().getDiagonal().getLength() * 0.5; + let distanceCamera = viewRect.getDiagonal().getLength() * 0.5; + + let distanceMin = distanceMovable + distanceCamera; + + return movable.getCenter().getDistanceToPoint(viewRect.getCenter()) < distanceMin; + } } \ No newline at end of file diff --git a/js/FrameRateMeasurer.js b/js/FrameRateMeasurer.js new file mode 100644 index 0000000..76328c8 --- /dev/null +++ b/js/FrameRateMeasurer.js @@ -0,0 +1,86 @@ +import FrameRateMeasuredEvent from "./events/FrameRateMeasuredEvent.js"; + +export default class FrameRateMeasurer +{ + constructor(rounds = 100) + { + this.rounds = rounds; + this.round = 0; + this.lastTimestamp = undefined; + this.frameDurations = []; + + window.requestAnimationFrame( + (timestamp) => { + this.measureFrameRate(timestamp); + } + ); + } + + measureFrameRate(timestamp) + { + if (this.lastTimestamp !== undefined) { + this.round++; + this.frameDurations.push(timestamp - this.lastTimestamp); + + this.lastTimestamp = timestamp; + + if (this.round < this.rounds) { + window.requestAnimationFrame( + (timestamp) => { + this.measureFrameRate(timestamp); + } + ); + } else { + window.dispatchEvent(new FrameRateMeasuredEvent(this.getAverageFrameRate())); + } + } else { + this.round = 0; + this.lastTimestamp = timestamp; + window.requestAnimationFrame( + (timestamp) => { + this.measureFrameRate(timestamp); + } + ); + } + + this.lastTimestamp = timestamp + } + + getAverageFrameRate() + { + let frameDurationSum = 0; + + this.frameDurations.forEach( + (duration) => { + frameDurationSum += duration; + } + ); + + let durationAverage = frameDurationSum / this.frameDurations.length; + + return 1000 / durationAverage; + } + + getFrameRate() + { + const DEFAULT_FRAME_RATES = [30, 60, 120]; + + let averageFrameRate = this.getAverageFrameRate(); + let closestDistance = {frameRate: 0, distance: 99999}; + + DEFAULT_FRAME_RATES.forEach( + (frameRate) => { + let distance = Math.abs(frameRate - averageFrameRate); + + if (closestDistance.distance > distance) { + closestDistance.frameRate = frameRate; + closestDistance.distance = distance; + } + } + ); + + console.log(this.frameDurations); + + return closestDistance.frameRate; + } +} \ No newline at end of file diff --git a/js/Movable.js b/js/Movable.js index f8cb198..544e8e8 100644 --- a/js/Movable.js +++ b/js/Movable.js @@ -109,7 +109,9 @@ export default class Movable draw(context, camera) { - this.animations[this.currentAnimation].setFootPosition(this.position.x, this.position.y); - this.animations[this.currentAnimation].draw(context, camera); + if (camera.isMovableInsideView(this)) { + this.animations[this.currentAnimation].setFootPosition(this.position.x, this.position.y); + this.animations[this.currentAnimation].draw(context, camera); + } } } \ No newline at end of file diff --git a/js/events/FrameRateMeasuredEvent.js b/js/events/FrameRateMeasuredEvent.js new file mode 100644 index 0000000..73ad6d6 --- /dev/null +++ b/js/events/FrameRateMeasuredEvent.js @@ -0,0 +1,9 @@ +import InterfaceEvent from "./InterfaceEvent.js"; + +export default class FrameRateMeasuredEvent extends Event +{ + constructor(frameRate) { + super(InterfaceEvent.FRAME_RATE_MEASURED); + this.frameRate = frameRate; + } +} \ No newline at end of file diff --git a/js/events/InterfaceEvent.js b/js/events/InterfaceEvent.js index cbe1d37..a6e9ed5 100644 --- a/js/events/InterfaceEvent.js +++ b/js/events/InterfaceEvent.js @@ -1,6 +1,7 @@ -export default InterfaceEvent; - const InterfaceEvent = { - IMAGE_LOADED: 'imgloaded', - MEDIA_COLLECTION_LOADED: 'mediacollectionloaded', -}; \ No newline at end of file + IMAGE_LOADED: 'imageLoaded', + MEDIA_COLLECTION_LOADED: 'mediaCollectionLoaded', + FRAME_RATE_MEASURED: 'frameRateMeasured', +}; + +export default InterfaceEvent; \ No newline at end of file diff --git a/js/module.js b/js/module.js index 3c19053..6fcfced 100644 --- a/js/module.js +++ b/js/module.js @@ -7,6 +7,8 @@ import FileLoader from "./FileLoader.js"; import Camera from "./Camera.js"; import Gisela from "./Gisela.js"; import Setting from "./Setting.js"; +import InterfaceEvent from "./events/InterfaceEvent.js"; +import FrameRateMeasurer from "./FrameRateMeasurer.js"; class ImageLoader { @@ -27,8 +29,10 @@ class ImageLoader return this.numberImagesLoaded / this.images.length; } - addImage(image) + addImage(imagePath) { + let image = new Image(); + image.src = imagePath; image.addEventListener( 'load', () => { this.update(); @@ -125,7 +129,7 @@ function MainLoop(timestamp) camera.lockCameraIntoBorders(); /* Drawing */ - if (timestamp - lastRendered >= FRAME_DURATION) { + if (timestamp - lastRendered >= frameDuration) { context.clearRect(0, 0, window.innerWidth, window.innerHeight); architecture.draw(context, camera); @@ -151,10 +155,10 @@ function MainLoop(timestamp) window.requestAnimationFrame(MainLoop); } -const FPS = 120; -const FRAME_DURATION = 1000 / FPS; const GAME_SPEED = 1; const GRAVITY = 2; +let fps; +let frameDuration; let levelJson = new FileLoader('levels/level01.json'); @@ -174,21 +178,12 @@ let KeyJump = new Key('Space'); let loader = new ImageLoader(); -let imgAnimation = new Image(); -imgAnimation.src = Setting.GRAPHICS_LOCATION + 'mr-croc-walk-right.png'; -loader.addImage(imgAnimation); +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 + 'landscape01.jpg'); +loader.addImage(Setting.GRAPHICS_LOCATION + 'gisela-right.png'); -let imgAnimationB = new Image(); -imgAnimationB.src = Setting.GRAPHICS_LOCATION + 'mr-croc-walk-left.png'; -loader.addImage(imgAnimationB); - -let imgArch = new Image(); -imgArch.src = Setting.TILESET_LOCATION + 'landscape01.jpg'; -loader.addImage(imgArch); - -let imgGisela = new Image(); -imgGisela.src = Setting.GRAPHICS_LOCATION + 'gisela-right.png'; -loader.addImage(imgGisela); +new FrameRateMeasurer(); window.addEventListener( 'imagesloaded', @@ -217,6 +212,8 @@ window.addEventListener( gisela = new Gisela(); architecture.setMovableToTargetPosition(gisela); + fps = 120; //event.frameRate; + frameDuration = 1000 / fps; window.requestAnimationFrame(MainLoop); } -); +); \ No newline at end of file