(function() { "use strict"; var Phaser, isFinite, now, ref, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; Phaser = Phaser || this.Phaser || window.Phaser || (typeof require === "function" ? require("phaser") : void 0); if (!Phaser) { throw new Error("Couldn't find `Phaser` or require 'phaser'."); } isFinite = Number.isFinite; now = ((ref = window.performance) != null ? ref.now.bind(window.performance) : void 0) || Date.now.bind(Date); Phaser.Plugin.AdvancedTiming = (function(superClass) { extend(AdvancedTiming, superClass); function AdvancedTiming() { return AdvancedTiming.__super__.constructor.apply(this, arguments); } AdvancedTiming.MODE_GRAPH = "graph"; AdvancedTiming.MODE_METER = "meter"; AdvancedTiming.MODE_TEXT = "text"; AdvancedTiming.MODE_DOM_METER = "domMeter"; AdvancedTiming.MODE_DOM_TEXT = "domText"; AdvancedTiming.MODE_DEFAULT = AdvancedTiming.MODE_TEXT; AdvancedTiming.colors = { AQUA: "#7FDBFF", BLUE: "#0074D9", GRAY: "#666666", GREEN: "#2ECC40", NAVY: "#001F3F", ORANGE: "#FF851B", PURPLE: "#B10DC9", RED: "#FF4136", WHITE: "#FFFFFF", YELLOW: "#FFDC00" }; AdvancedTiming.hexColors = { AQUA: 0x7FDBFF, BLUE: 0x0074D9, GRAY: 0x666666, GREEN: 0x2ECC40, NAVY: 0x001F3F, ORANGE: 0xFF851B, PURPLE: 0xB10DC9, RED: 0xFF4136, WHITE: 0xFFFFFF, YELLOW: 0xFFDC00 }; AdvancedTiming.modes = [AdvancedTiming.MODE_DEFAULT, AdvancedTiming.MODE_GRAPH, AdvancedTiming.MODE_METER, AdvancedTiming.MODE_TEXT, AdvancedTiming.MODE_DOM_METER, AdvancedTiming.MODE_DOM_TEXT]; AdvancedTiming.renderTypes = [null, "Canvas", "WebGL", "Headless"]; AdvancedTiming.prototype.alpha = 0.75; AdvancedTiming.prototype.enableResumeHandler = true; AdvancedTiming.prototype.lastTextContent = null; AdvancedTiming.prototype.name = "Advanced Timing Plugin"; AdvancedTiming.prototype.renderDuration = 0; AdvancedTiming.prototype.showDurations = true; AdvancedTiming.prototype.showElapsed = false; AdvancedTiming.prototype.showSpiraling = true; AdvancedTiming.prototype.styleDomTextLikeDebugFont = false; AdvancedTiming.prototype.updateDuration = 0; AdvancedTiming.prototype._mode = null; Object.defineProperty(AdvancedTiming.prototype, "mode", { get: function() { return this._mode; }, set: function(val) { if (val === this._mode) { return this._mode; } switch (val) { case this.constructor.MODE_GRAPH: case this.constructor.MODE_METER: case this.constructor.MODE_TEXT: case this.constructor.MODE_DOM_TEXT: case this.constructor.MODE_DOM_METER: this._mode = val; this.add(); this.activeDisplay = this.display[this._mode]; break; default: throw new Error("No such mode: '" + val + "'"); } this.refresh(); return this._mode; } }); AdvancedTiming.prototype.init = function(options) { var game, mode; game = this.game; game.time.advancedTiming = true; this._gameUpdateLogic = this.game.updateLogic.bind(this.game); this._gameUpdateRender = this.game.updateRender.bind(this.game); this.game.updateLogic = this.updateLogic.bind(this); this.game.updateRender = this.updateRender.bind(this); this.group = game.make.group(null, "advancedTimingPlugin", true); this.position = new Phaser.Point; this.renderType = this.constructor.renderTypes[game.renderType]; this.reset(); game.onResume.add(this.onResume, this); game.debug.gameInfo = this.debugGameInfo.bind(this); game.debug.gameTimeInfo = this.debugGameTimeInfo.bind(this); this.display = {}; if (options) { mode = options.mode; delete options.mode; Phaser.Utils.extend(this, options); } this.mode = mode || this.constructor.MODE_DEFAULT; }; AdvancedTiming.prototype.update = function() { this.group.visible = this.visible; if (this.visible) { if (this.graphGroup && this.graphGroup.visible) { this.updateGraph(); } if (this.meters && this.meters.visible) { this.updateMeters(); } if (this.text && this.text.visible) { this.updateText(); } if (this.domMeter) { this.updateDomMeter(); } if (this.domText) { this.updateDomText(); } } }; AdvancedTiming.prototype.updateLogic = function(timeStep) { var time; time = now(); this._gameUpdateLogic(timeStep); this.updateDuration = now() - time; }; AdvancedTiming.prototype.updateRender = function(elapsedTime) { var time; time = now(); this._gameUpdateRender(elapsedTime); this.renderDuration = now() - time; }; AdvancedTiming.prototype.destroy = function() { AdvancedTiming.__super__.destroy.apply(this, arguments); this.graph.destroy(); this.group.destroy(); }; AdvancedTiming.prototype.add = function() { switch (this._mode) { case this.constructor.MODE_GRAPH: if (!this.graphGroup) { this.addGraph(); } break; case this.constructor.MODE_METER: if (!this.meters) { this.addMeters(); } break; case this.constructor.MODE_TEXT: if (!this.text) { this.addText(); } break; case this.constructor.MODE_DOM_METER: if (!this.domMeter) { this.addDomMeter(); } break; case this.constructor.MODE_DOM_TEXT: if (!this.domText) { this.addDomText(); } break; default: throw new Error("Nothing to add (bad mode: " + this._mode + ")"); } }; AdvancedTiming.prototype.addDomMeter = function() { this.domMeter = document.createElement("meter"); this.domMeter.setAttribute("class", "ppat-fps ppat-meter"); this.domMeter.setAttribute("min", 0); this.domMeter.setAttribute("max", this.game.time.desiredFps); this.domMeter.setAttribute("optimum", this.game.time.desiredFps); this.game.canvas.parentNode.appendChild(this.domMeter); this.display[this.constructor.MODE_DOM_METER] = this.domMeter; }; AdvancedTiming.prototype.addDomText = function() { this.domText = document.createElement("pre"); this.domText.setAttribute("class", "ppat-text"); if (this.styleDomTextLikeDebugFont) { this.domText.style.font = this.game.debug.font; } this.game.canvas.parentNode.appendChild(this.domText); this.display[this.constructor.MODE_DOM_TEXT] = this.domText; }; AdvancedTiming.prototype.addGraph = function(x, y) { var desiredFps, desiredMs, height, ref1, scaleY, style, width; if (x == null) { x = this.position.x; } if (y == null) { y = this.position.y; } desiredFps = this.game.time.desiredFps; desiredMs = this.desiredMs(); style = { fill: "white", font: "10px monospace" }; this.graphGroup = this.game.add.group(this.group, "advancedTimingPluginGraphGroup"); this.graphGroup.x = x; this.graphGroup.y = y; this.graph = this.game.make.bitmapData(60, 60, "advancedTimingPluginGraph"); this.graph.fill(0, 0, 0); this.graphX = 0; this.graphImage = this.game.add.image(0, 0, this.graph, null, this.graphGroup); this.graphImage.alpha = this.alpha; this.graphImage.scale.set(2); this.graphImage.smoothed = false; ref1 = this.graphImage, width = ref1.width, height = ref1.height; scaleY = this.graphImage.scale.y; this.game.add.text(width, height - scaleY * desiredFps, desiredFps + " fps", style, this.graphGroup); this.game.add.text(width, height - scaleY * desiredMs, desiredMs + " ms", style, this.graphGroup); this.display[this.constructor.MODE_GRAPH] = this.graphGroup; }; AdvancedTiming.prototype.addMeter = function(name, x, y, key, tint, group) { var meter; name = name + "Meter"; meter = group.create(x, y, key); meter.height = 10; meter.tint = tint; return this[name] = meter; }; AdvancedTiming.prototype.addMeters = function(x, y) { var bt, hexColors; if (x == null) { x = this.position.x; } if (y == null) { y = this.position.y; } hexColors = this.constructor.hexColors; bt = this.game.make.bitmapData(1, 1).fill(255, 255, 255); this.meters = this.game.add.group(this.group, "advancedTimingPluginMeters"); this.meters.alpha = this.alpha; this.meters.classType = Phaser.Image; this.meters.x = x; this.meters.y = y; this.fpsMeters = this.game.add.group(this.meters, "advancedTimingPluginFpsMeters"); this.elapsedMeters = this.game.add.group(this.meters, "advancedTimingPluginElapsedMeters"); this.durationMeters = this.game.add.group(this.meters, "advancedTimingPluginDurationMeters"); this.addMeter("desiredFps", 0, 0, bt, hexColors.GRAY, this.fpsMeters); this.addMeter("fps", 0, 0, bt, hexColors.BLUE, this.fpsMeters); this.addMeter("desiredMs", 0, 20, bt, hexColors.GRAY, this.elapsedMeters); this.addMeter("elapsed", 0, 20, bt, hexColors.GREEN, this.elapsedMeters); this.addMeter("ms", 0, 20, bt, hexColors.YELLOW, this.elapsedMeters); this.addMeter("desiredDur", 0, 10, bt, hexColors.GRAY, this.durationMeters); this.addMeter("updateDuration", 0, 10, bt, hexColors.ORANGE, this.durationMeters); this.addMeter("renderDuration", 0, 10, bt, hexColors.PURPLE, this.durationMeters); this.display[this.constructor.MODE_METER] = this.meters; }; AdvancedTiming.prototype.addText = function(x, y) { if (x == null) { x = this.position.x; } if (y == null) { y = this.position.y; } this.text = this.game.add.text(x+100, y, null, { fill: this.constructor.colors.WHITE, font: "20px king_cool_kc" }, this.group); this.text.name = "advancedTimingPluginText"; this.display[this.constructor.MODE_TEXT] = this.text; }; AdvancedTiming.prototype.debugGameInfo = function(x, y, color) { var debug, game; game = this.game; debug = game.debug; debug.start(x, y, color); debug.line("renderType: " + this.renderType); debug.line("lockRender: " + game.lockRender); debug.line("forceSingleUpdate: " + game.forceSingleUpdate); debug.line("updatesThisFrame: " + game.updatesThisFrame); debug.line("lastCount: " + game._lastCount); debug.line("spiraling: " + game._spiraling); debug.stop(); }; AdvancedTiming.prototype.debugGameTimeInfo = function(x, y, color) { var debug, game, time; game = this.game; debug = game.debug, time = game.time; debug.start(x, y, color); debug.line("fps: " + time.fps + " " + (this.fpsRangeStr())); debug.line("desiredFps: " + time.desiredFps); debug.line("suggestedFps: " + time.suggestedFps); debug.line("elapsed: " + time.elapsed + " ms " + (this.elapsedRangeStr())); debug.line("elapsedMS: " + time.elapsedMS + " ms"); debug.line("physicsElapsedMS: " + (time.physicsElapsedMS.toFixed(2)) + " ms"); debug.line("slowMotion: " + time.slowMotion); debug.stop(); }; AdvancedTiming.prototype.desiredMs = function() { return Math.ceil(1000 / this.game.time.desiredFps); }; AdvancedTiming.prototype.elapsedRange = function() { return this.game.time.msMax - this.game.time.msMin; }; AdvancedTiming.prototype.elapsedRangeStr = function() { var msMax, msMin, ref1; ref1 = this.game.time, msMax = ref1.msMax, msMin = ref1.msMin; if (isFinite(msMax) && isFinite(msMin)) { return "(" + msMin + "–" + msMax + ")"; } else { return ""; } }; AdvancedTiming.prototype.fpsColor = function(fps) { var colors, desiredFps; if (fps == null) { fps = this.game.time.fps; } desiredFps = this.game.time.desiredFps; colors = this.constructor.colors; switch (false) { case !(fps < (desiredFps / 2)): return colors.ORANGE; case !(fps < desiredFps): return colors.YELLOW; default: return colors.WHITE; } }; AdvancedTiming.prototype.fpsRange = function() { return this.game.time.fpsMax - this.game.time.fpsMin; }; AdvancedTiming.prototype.fpsRangeStr = function() { var fpsMax, fpsMin, ref1; ref1 = this.game.time, fpsMax = ref1.fpsMax, fpsMin = ref1.fpsMin; if (isFinite(fpsMax) && isFinite(fpsMin)) { return "(" + fpsMin + "–" + fpsMax + ")"; } else { return ""; } }; AdvancedTiming.prototype.onResume = function() { this.reset(); }; AdvancedTiming.prototype.refresh = function() { var name, obj, ref1; ref1 = this.display; for (name in ref1) { obj = ref1[name]; if (obj.setAttribute) { if (name === this._mode) { obj.removeAttribute("hidden"); } else { obj.setAttribute("hidden", ""); } } else { obj.visible = name === this._mode; } } }; AdvancedTiming.prototype.reset = function(fpsMin, fpsMax, msMin, msMax) { var time; if (fpsMin == null) { fpsMin = Infinity; } if (fpsMax == null) { fpsMax = 0; } if (msMin == null) { msMin = Infinity; } if (msMax == null) { msMax = 0; } time = this.game.time; time.fpsMin = fpsMin; time.fpsMax = fpsMax; time.msMin = msMin; time.msMax = msMax; }; AdvancedTiming.prototype.resetElapsed = function() { var time; time = this.game.time; time.elapsed = time.now - time.prevTime; }; AdvancedTiming.prototype.textContent = function() { var drawCount; drawCount = this.game.renderer.renderSession.drawCount; return (this.game.time.fps + " fps " + this.renderType) + (drawCount ? " (" + drawCount + ")" : ""); }; AdvancedTiming.prototype.updateDomMeter = function() { this.domMeter.value = this.game.time.fps; }; AdvancedTiming.prototype.updateDomText = function() { var content; content = this.textContent(); if (content !== this.lastTextContent) { this.domText.textContent = this.lastTextContent = content; this.domText.style.color = this.fpsColor(); } }; AdvancedTiming.prototype.updateGraph = function() { var _spiraling, colors, elapsed, elapsedMS, forceSingleUpdate, fps, graph, graphX, height, ref1, ref2, updatesThisFrame; ref1 = this.game, forceSingleUpdate = ref1.forceSingleUpdate, _spiraling = ref1._spiraling, updatesThisFrame = ref1.updatesThisFrame; ref2 = this.game.time, elapsed = ref2.elapsed, elapsedMS = ref2.elapsedMS, fps = ref2.fps; graph = this.graph, graphX = this.graphX; colors = this.constructor.colors; height = graph.height; graph.dirty = true; graph.rect(graphX, 0, 1, height, "black"); if (fps <= height) { graph.rect(graphX, height - fps, 1, 1, colors.BLUE); } if (this.showElapsed) { if (elapsed <= height) { graph.rect(graphX, height - elapsed, 1, 1, colors.GREEN); } if (elapsed !== elapsedMS && elapsed <= height) { graph.rect(graphX, height - elapsedMS, 1, 1, colors.YELLOW); } if (!forceSingleUpdate) { graph.rect(graphX, height - updatesThisFrame, 1, 1, colors.NAVY); } } if (this.showDurations) { graph.rect(graphX, height - ~~this.updateDuration, 1, 1, colors.ORANGE); graph.rect(graphX, height - ~~this.renderDuration, 1, 1, colors.PURPLE); } if (this.showSpiraling && _spiraling > 0) { graph.rect(graphX, height - _spiraling, 1, 1, colors.RED); } this.graphX += 1; this.graphX %= graph.width; }; AdvancedTiming.prototype.updateMeters = function() { var desiredFps, desiredMs, elapsed, elapsedMS, fps, ref1; ref1 = this.game.time, desiredFps = ref1.desiredFps, elapsed = ref1.elapsed, elapsedMS = ref1.elapsedMS, fps = ref1.fps; desiredMs = this.desiredMs(); this.desiredFpsMeter.scale.x = desiredFps; this.fpsMeter.scale.x = fps; this.elapsedMeters.visible = this.showElapsed; if (this.showElapsed) { this.desiredMsMeter.scale.x = desiredMs; this.msMeter.scale.x = elapsedMS; this.elapsedMeter.scale.x = elapsed; } this.durationMeters.visible = this.showDurations; if (this.showDurations) { this.desiredDurMeter.scale.x = desiredMs; this.updateDurationMeter.scale.x = this.updateDuration; this.renderDurationMeter.scale.x = this.renderDuration; this.renderDurationMeter.x = this.updateDurationMeter.width; } }; AdvancedTiming.prototype.updateText = function() { this.text.text = this.textContent(); this.text.style.fill = this.fpsColor(); }; return AdvancedTiming; })(Phaser.Plugin); if (typeof module !== "undefined" && module !== null) { module.exports = Phaser.Plugin.AdvancedTiming; } }).call(this);