From e5859f7296bb1af8de66d66c8565f54545ba0dba Mon Sep 17 00:00:00 2001 From: Tristan Rhodes Date: Sun, 30 Jul 2023 10:02:06 -0600 Subject: [PATCH] [FPS] Update: Provide more accurate values for frames per second (#939) * Improved FPS accuracy by using a sliding window (thanks @arthuro555) --- extensions/reviewed/FPS.json | 369 ++++++++++++++++++++++++++++++----- 1 file changed, 318 insertions(+), 51 deletions(-) diff --git a/extensions/reviewed/FPS.json b/extensions/reviewed/FPS.json index fc541b2b4..925be459e 100644 --- a/extensions/reviewed/FPS.json +++ b/extensions/reviewed/FPS.json @@ -1,15 +1,26 @@ { "author": "Ahnaf30e", "category": "Advanced", - "description": "Adds expressions to get the current FPS and a behavior to display the current FPS easily.\n\nThe FPS, Frames Per Second, describes how many times in the last second your game got updated. An update consists in running all the behaviors, objects, and events sheet code, before rendering the new game state into the game window. The higher the FPS, the more it manages to update in a second, influencing how fluid and performant your game looks.", "extensionNamespace": "", - "fullName": "FPS", + "fullName": "Frames per second (FPS)", "helpPath": "", "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8cGF0aCBkPSJNMzAsM2gtMkg0SDJDMS40LDMsMSwzLjQsMSw0czAuNCwxLDEsMWgxdjE2YzAsMC42LDAuNCwxLDEsMWg5LjhsLTUuNSw2LjNjLTAuNCwwLjQtMC4zLDEsMC4xLDEuNEM4LjUsMjkuOSw4LjgsMzAsOSwzMA0KCWMwLjMsMCwwLjYtMC4xLDAuOC0wLjNsNS4yLTZWMjhjMCwwLjYsMC40LDEsMSwxczEtMC40LDEtMXYtNC4zbDUuMiw2YzAuMiwwLjIsMC41LDAuMywwLjgsMC4zYzAuMiwwLDAuNS0wLjEsMC43LTAuMg0KCWMwLjQtMC40LDAuNS0xLDAuMS0xLjRMMTguMiwyMkgyOGMwLjYsMCwxLTAuNCwxLTFWNWgxYzAuNiwwLDEtMC40LDEtMVMzMC42LDMsMzAsM3ogTTI0LjgsOC42bC00LDZjLTAuMywwLjQtMC44LDAuNi0xLjMsMC4zDQoJTDE1LjgsMTNoLTMuNGwtMy43LDMuN0M4LjUsMTYuOSw4LjMsMTcsOCwxN3MtMC41LTAuMS0wLjctMC4zYy0wLjQtMC40LTAuNC0xLDAtMS40bDQtNGMwLjItMC4yLDAuNC0wLjMsMC43LTAuM2g0DQoJYzAuMiwwLDAuMywwLDAuNCwwLjFsMy4yLDEuNmwzLjUtNS4zYzAuMy0wLjUsMC45LTAuNiwxLjQtMC4zQzI1LDcuNSwyNS4xLDguMSwyNC44LDguNnoiLz4NCjwvc3ZnPg0K", "name": "FPS", "previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/Glyphster Pack/Master/SVG/SEO/SEO_board_performance_profit.svg", - "shortDescription": "Adds expressions and a behavior to get and display the game FPS.", - "version": "1.0.0", + "shortDescription": "Calculate and display the frames per second (FPS) of the game.", + "version": "1.1.0", + "description": [ + "Provides an expression to get the current FPS and a text object behavior to display the current FPS.", + "", + "Frames Per Second (FPS) describes how many times in the last second your game logic was executed. ", + "This includes running behaviors and events, and then rendering the new game state into the game window. The higher the FPS, the more fluid and performant your game looks.", + "", + "Note: Use the Performance Profiler (inside in the Debugger) for detailed performance information about your game." + ], + "origin": { + "identifier": "FPS", + "name": "gdevelop-extension-store" + }, "tags": [ "fps", "frames", @@ -19,78 +30,222 @@ "speed" ], "authorIds": [ - "onPsboRtDkUHNOsx7OPr8R8G1oj2" + "onPsboRtDkUHNOsx7OPr8R8G1oj2", + "gqDaZjCfevOOxBYkK6zlhtZnXCg1" ], "dependencies": [], "eventsFunctions": [ { - "description": "Return your game's current FPS count.", - "fullName": "FPS (Frames per second)", + "fullName": "", + "functionType": "Action", + "name": "onSceneLoaded", + "sentence": "", + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SceneVariablePushNumber" + }, + "parameters": [ + "__FPS.FrameTimestamps", + "Time(\"timestamp\")" + ] + } + ] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "fullName": "", + "functionType": "Action", + "name": "onScenePostEvents", + "sentence": "", + "events": [ + { + "colorB": 228, + "colorG": 176, + "colorR": 74, + "creationTime": 0, + "name": "Keep timestamps for every frame inside the lookback period", + "source": "", + "type": "BuiltinCommonInstructions::Group", + "events": [ + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Record how much time has elapsed" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ModVarScene" + }, + "parameters": [ + "__FPS.TimeElapsed", + "=", + "Time(\"timestamp\") - Variable(__FPS.FrameTimestamps[0])" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Remove any data before the last second from the beginning of the array" + }, + { + "infiniteLoopWarning": true, + "type": "BuiltinCommonInstructions::While", + "whileConditions": [ + { + "type": { + "value": "SceneVariableChildCount" + }, + "parameters": [ + "__FPS.FrameTimestamps", + ">", + "0" + ] + }, + { + "type": { + "value": "VarScene" + }, + "parameters": [ + "__FPS.FrameTimestamps[0]", + "<", + "Time(\"timestamp\") - 1000" + ] + } + ], + "conditions": [], + "actions": [ + { + "type": { + "value": "SceneVariableRemoveAt" + }, + "parameters": [ + "__FPS.FrameTimestamps", + "0" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Add the current timestamp to the end of the array" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "SceneVariablePushNumber" + }, + "parameters": [ + "__FPS.FrameTimestamps", + "Time(\"timestamp\")" + ] + } + ] + } + ], + "parameters": [] + } + ], + "parameters": [], + "objectGroups": [] + }, + { + "description": "Frames per second (FPS) during the last second.", + "fullName": "Frames Per Second (FPS)", "functionType": "Expression", "name": "FPS", - "private": false, "sentence": "", "events": [ { - "disabled": false, - "folded": false, "type": "BuiltinCommonInstructions::Standard", "conditions": [], "actions": [ { "type": { - "inverted": false, "value": "SetReturnNumber" }, "parameters": [ - "ceil(1/TimeDelta())" - ], - "subInstructions": [] + "VariableChildCount(__FPS.FrameTimestamps) / (Variable(__FPS.TimeElapsed) / 1000)" + ] } - ], - "events": [] + ] } ], + "expressionType": { + "type": "expression" + }, "parameters": [], "objectGroups": [] }, { - "description": "Return your game's current FPS count, with more control over rounding.", - "fullName": "Precise FPS (Frames per second)", + "description": "Frames per second (FPS) during the last second. [Deprecated]", + "fullName": "Frames Per Second (FPS) [Deprecated]", "functionType": "Expression", "name": "PreciseFPS", - "private": false, + "private": true, "sentence": "", "events": [ { - "disabled": false, - "folded": false, "type": "BuiltinCommonInstructions::Standard", "conditions": [], "actions": [ { "type": { - "inverted": false, "value": "SetReturnNumber" }, "parameters": [ - "(ceil(1/TimeDelta()*(GetArgumentAsNumber(\"accuracy\") * 10))) / (GetArgumentAsNumber(\"accuracy\") * 10)" - ], - "subInstructions": [] + "FPS::FPS()" + ] } - ], - "events": [] + ] } ], + "expressionType": { + "type": "expression" + }, "parameters": [ { - "codeOnly": false, - "defaultValue": "", "description": "The accuracy of the FPS", "longDescription": "This tells how many numbers after the period should be shown.", "name": "accuracy", - "optional": false, - "supplementaryInformation": "", "type": "expression" } ], @@ -105,53 +260,151 @@ "objectType": "TextObject::Text", "eventsFunctions": [ { - "description": "", "fullName": "", "functionType": "Action", "name": "doStepPreEvents", - "private": false, "sentence": "", "events": [ { - "disabled": false, - "folded": false, + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Generate the raw FPS text" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ModVarSceneTxt" + }, + "parameters": [ + "__FPS.UnformattedFPS", + "=", + "ToString(roundTo(FPS::FPS(), Object.Behavior::PropertyDecimalDigits()))" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Add trailing zeroes, if needed" + }, + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [ + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "Object.Behavior::PropertyDecimalDigits()", + ">", + "0" + ] + }, + { + "type": { + "value": "BuiltinCommonInstructions::CompareNumbers" + }, + "parameters": [ + "StrFind(VariableString(__FPS.UnformattedFPS),\".\")", + "=", + "-1" + ] + } + ], + "actions": [], + "events": [ + { + "type": "BuiltinCommonInstructions::Standard", + "conditions": [], + "actions": [ + { + "type": { + "value": "ModVarSceneTxt" + }, + "parameters": [ + "__FPS.UnformattedFPS", + "+", + "\".\"" + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Repeat", + "repeatExpression": "Object.Behavior::PropertyDecimalDigits()", + "conditions": [], + "actions": [ + { + "type": { + "value": "ModVarSceneTxt" + }, + "parameters": [ + "__FPS.UnformattedFPS", + "+", + "\"0\"" + ] + } + ] + } + ] + }, + { + "type": "BuiltinCommonInstructions::Comment", + "color": { + "b": 109, + "g": 230, + "r": 255, + "textB": 0, + "textG": 0, + "textR": 0 + }, + "comment": "Show the formatted FPS text including the prefix" + }, + { "type": "BuiltinCommonInstructions::Standard", "conditions": [], "actions": [ { "type": { - "inverted": false, "value": "TextObject::String" }, "parameters": [ "Object", "=", - "Object.Behavior::Propertyprefix() + ToString(FPS::FPS())" - ], - "subInstructions": [] + "Object.Behavior::Propertyprefix() + VariableString(__FPS.UnformattedFPS)" + ] } - ], - "events": [] + ] } ], "parameters": [ { - "codeOnly": false, - "defaultValue": "", "description": "Object", - "longDescription": "", "name": "Object", - "optional": false, "supplementaryInformation": "TextObject::Text", "type": "object" }, { - "codeOnly": false, - "defaultValue": "", "description": "Behavior", - "longDescription": "", "name": "Behavior", - "optional": false, "supplementaryInformation": "FPS::FPSDisplayer", "type": "behavior" } @@ -165,11 +418,25 @@ "type": "String", "label": "The prefix before the FPS count", "description": "", + "group": "", "extraInformation": [], "hidden": false, "name": "prefix" + }, + { + "value": "0", + "type": "Number", + "unit": "Dimensionless", + "label": "Number of decimal digits to display", + "description": "", + "group": "", + "extraInformation": [], + "hidden": false, + "name": "DecimalDigits" } - ] + ], + "sharedPropertyDescriptors": [] } - ] + ], + "eventsBasedObjects": [] } \ No newline at end of file