একটি গেমের প্রতি সেকেন্ড ফ্রেম গণনা করা


110

গেমের প্রতি সেকেন্ডে ফ্রেম গণনা করার জন্য একটি ভাল অ্যালগরিদম কী? আমি এটি স্ক্রিনের কোণায় একটি সংখ্যা হিসাবে দেখাতে চাই। আমি যদি দেখি যে শেষ ফ্রেমটি রেন্ডার করতে কতক্ষণ সময় লেগেছিল তখন সংখ্যাটি খুব দ্রুত পরিবর্তিত হয়।

বোনাস পয়েন্ট যদি আপনার উত্তর প্রতিটি ফ্রেম আপডেট করে এবং ফ্রেমের হার হ্রাস ক্রমহ্রাসমান বাড়তে থাকে তখন আলাদাভাবে রূপান্তর না করে।

উত্তর:


100

আপনার একটি ধীরে ধীরে গড়ের দরকার, সহজতম উপায় হ'ল বর্তমান উত্তরটি (শেষ ফ্রেম আঁকার সময়) নেওয়া এবং এটি পূর্ববর্তী উত্তরের সাথে একত্রিত করা।

// eg.
float smoothing = 0.9; // larger=more smoothing
measurement = (measurement * smoothing) + (current * (1.0-smoothing))

০.৯ / ০.০ অনুপাত সমন্বয় করে আপনি 'সময় ধ্রুবক' পরিবর্তন করতে পারেন - সংখ্যাটি কত দ্রুত পরিবর্তনের প্রতিক্রিয়া জানায়। পুরানো উত্তরের পক্ষে বৃহত্তর ভগ্নাংশটি ধীরে ধীরে মসৃণ পরিবর্তন দেয়, নতুন উত্তরের পক্ষে একটি বৃহত ভগ্নাংশ দ্রুত পরিবর্তিত মান দেয়। স্পষ্টতই দুটি কারণ অবশ্যই যুক্ত করতে হবে!


14
তারপরে নির্বোধ-প্রমাণ এবং পরিষ্কার-পরিচ্ছন্নতার জন্য, আপনি সম্ভবত ভাসমান ওজনের মতো কিছু চান: রেটিও = 0.1; এবং সময় = সময় * (1.0 - ওজনরেশি) + শেষ_ফ্রেম * ওজনরতিও
কোরোনা

2
নীতিগতভাবে ভাল এবং সহজ বলে মনে হচ্ছে, তবে বাস্তবে এই পদ্ধতির মসৃণতা সবে লক্ষণীয়। ভাল না.
পেট্রুসিও

1
@ পেত্রুসিও যদি স্মুথিং খুব কম হয় তবে কেবল সময় ধ্রুবকটি ক্র্যাঙ্ক করুন (ওজনরেশিও = 0.05, 0.02, 0.01 ...)
জন ডিভোরাক

8
@ পেত্রুসিও: পূর্ববর্তী ফ্রেমের সময়কাল last_frame(বা কমপক্ষে অর্থ হওয়া উচিত নয় ); এটির timeঅর্থটি আপনার শেষ ফ্রেমের জন্য গণনা করা উচিত । এইভাবে, পূর্ববর্তী সমস্ত ফ্রেমগুলি অন্তর্ভুক্ত করা হবে, অতি সাম্প্রতিক ফ্রেমগুলি সবচেয়ে বেশি ভারী করে।
j_random_hacker

1
ভেরিয়েবলের নাম "সর্বশেষ_ ফ্রেম" বিভ্রান্তিকর। "কারেন্ট_ফ্রেম" আরও বর্ণনামূলক হবে। এটি জানাও গুরুত্বপূর্ণ যে উদাহরণে পরিবর্তনশীল "সময়" অবশ্যই বিশ্বব্যাপী হতে হবে (যেমন এর মানটি সমস্ত ফ্রেমের মধ্যে রাখতে হবে) এবং আদর্শভাবে একটি ভাসমান পয়েন্ট সংখ্যা। এটিতে গড় / সমষ্টিগত মান থাকে এবং প্রতিটি ফ্রেমে আপডেট হয়। অনুপাত যত বেশি হবে, একটি মানের দিকে "সময়" পরিবর্তনশীল স্থির করতে তত বেশি সময় লাগবে (অথবা এটি থেকে দূরে সরে যেতে হবে)।
jox

52

এটি আমি অনেক গেমগুলিতে ব্যবহার করেছি।

#define MAXSAMPLES 100
int tickindex=0;
int ticksum=0;
int ticklist[MAXSAMPLES];

/* need to zero out the ticklist array before starting */
/* average will ramp up until the buffer is full */
/* returns average ticks per frame over the MAXSAMPLES last frames */

double CalcAverageTick(int newtick)
{
    ticksum-=ticklist[tickindex];  /* subtract value falling off */
    ticksum+=newtick;              /* add new value */
    ticklist[tickindex]=newtick;   /* save new value so it can be subtracted later */
    if(++tickindex==MAXSAMPLES)    /* inc buffer index */
        tickindex=0;

    /* return average */
    return((double)ticksum/MAXSAMPLES);
}

আমি এই পদ্ধতির অনেক পছন্দ। আপনি ম্যাক্সসম্পলগুলি 100 এ সেট করার কোনও নির্দিষ্ট কারণ?
জোলোমন

1
এখানে ম্যাক্সসম্প্লেসগুলি এইচপিএসের জন্য একটি মান নিয়ে আসার জন্য গড় মানগুলির সংখ্যা।
কোরি গ্রস

8
এটি সাধারণ চলমান গড় (এসএমএ)
KindDragon

পারফেক্ট, ধন্যবাদ! আমি আমার গেমটিতে এটি টুইট করেছি যাতে টিক ফানকটি শূন্য হয় এবং অন্য একটি ফাংশন এফপিএস দেয়, তবে আমি রেন্ডার কোডটিতে এফপিএস প্রদর্শিত না থাকলেও আমি প্রতিটি টিকটি চালাতে পারি।
TheJosh

2
দয়া করে মডুলো ব্যবহার করুন এবং একটি নয় if tickindex = (tickindex + 1) % MAXSAMPLES;
ফেলিক্স কে।

25

ঠিক আছে, অবশ্যই

frames / sec = 1 / (sec / frame)

তবে, যেমন আপনি উল্লেখ করেছেন, একক ফ্রেম রেন্ডার করতে যে সময় লাগে তার মধ্যে অনেক তফাত রয়েছে এবং কোনও ইউআই দৃষ্টিকোণ থেকে ফ্রেম হারে fps মান আপডেট করা মোটেও ব্যবহারযোগ্য নয় (যদি সংখ্যাটি খুব স্থিতিশীল না হয়)।

আপনি যা চান তা সম্ভবত চলন্ত গড় বা কোনও ধরণের বিনিং / রিসেট কাউন্টার।

উদাহরণস্বরূপ, আপনি একটি সারি ডেটা কাঠামো বজায় রাখতে পারেন যা গত 30, 60, 100 এর প্রত্যেকের জন্য রেন্ডারিং সময়গুলি ধারণ করে বা আপনার কী ফ্রেম থাকে (আপনি এমনকি এটি ডিজাইন করতে পারেন যাতে রান-টাইমে সীমাটি সামঞ্জস্যযোগ্য ছিল)। একটি শালীন fps আনুমানিকতা নির্ধারণ করতে আপনি সারিতে সমস্ত রেন্ডারিং সময় থেকে গড় fps নির্ধারণ করতে পারেন:

fps = # of rendering times in queue / total rendering time

আপনি যখন একটি নতুন ফ্রেম রেন্ডারিং শেষ করেন আপনি একটি নতুন রেন্ডারিং সময় সজ্জিত করেন এবং একটি পুরানো রেন্ডারিং সময় সন্ধান করেন। পর্যায়ক্রমে, আপনি যখন কেবলমাত্র রেন্ডারিং সময়গুলি কিছু প্রিসেট মান (যেমন 1 সেকেন্ড) ছাড়িয়েছিলেন তখনই আপনি শনাক্ত করতে পারেন। আপনি "শেষ এফপিএস মান" এবং একটি সর্বশেষ আপডেট হওয়া টাইমস্ট্যাম্প বজায় রাখতে পারেন যাতে আপনি যদি ইচ্ছা করেন তবে fps চিত্রটি আপডেট করার সময় ট্রিগার করতে পারেন। যদিও আপনার চলমান গড়ের সাথে যদি ধারাবাহিক বিন্যাস থাকে তবে প্রতিটি ফ্রেমে "তাত্ক্ষণিক গড়" fps ছাপানো সম্ভবত ঠিক আছে।

আরেকটি পদ্ধতিতে রিসেট কাউন্টার থাকা উচিত। একটি সুনির্দিষ্ট (মিলিসেকেন্ড) টাইমস্ট্যাম্প, একটি ফ্রেম কাউন্টার এবং একটি fps মান বজায় রাখুন। আপনি যখন কোনও ফ্রেমের রেন্ডারিং শেষ করেন, তখন কাউন্টারটি বাড়ান। যখন কাউন্টারটি একটি প্রাক-সেট সীমাটি (যেমন 100 ফ্রেম) হিট করে বা টাইমস্ট্যাম্পের পরে কিছু প্রাক-সেট মান (যেমন 1 সেকেন্ড) পেরিয়ে যায়, তখন fps গণনা করুন:

fps = # frames / (current time - start time)

তারপরে কাউন্টারটিকে 0 এ রিসেট করুন এবং বর্তমান সময়ের জন্য টাইমস্ট্যাম্প সেট করুন।


12

প্রতিবার আপনি কোনও স্ক্রিন রেন্ডার করুন এবং একটি ফ্রেম-হার পরিমাপ করতে চান এমন কিছু সময়ের ব্যবধানের জন্য সেই কাউন্টারটি সাফ করুন a

অর্থাৎ। প্রতি 3 সেকেন্ডে, কাউন্টার / 3 পান এবং তারপরে কাউন্টারটি সাফ করুন।


+1 যদিও এটি আপনাকে অন্তরগুলিতে কেবল একটি নতুন মান দেয়, তবে এটি বোঝা সহজ এবং অ্যারে বা অনুমানের মানগুলির প্রয়োজন নেই এবং এটি বৈজ্ঞানিকভাবে সঠিক।
opatut

10

এটি করার জন্য কমপক্ষে দুটি উপায় রয়েছে:


প্রথমটি অন্যটি আমার আগে এখানে উল্লেখ করেছেন। আমি মনে করি এটি সবচেয়ে সহজ এবং পছন্দসই উপায়। আপনি শুধু ট্র্যাক রাখা

  • সিএন: আপনি যে কতগুলি ফ্রেম রেন্ডার করেছেন তার কাউন্টার
  • সময়_শক্তি: আপনি গণনা শুরু করার সময় থেকে
  • সময়_ এখন: বর্তমান সময়

এই ক্ষেত্রে fps গণনা করা এই সূত্রটি মূল্যায়ন করার মতোই সহজ:

  • এফপিএস = সিএন / (সময়_ এখন - সময়_স্টার্ট)।

তারপরে আপনি কিছু দিন ব্যবহার করতে পছন্দ করতে পারেন এমন দুর্দান্ত উপায় রয়েছে:

ধরা যাক আপনার বিবেচনার জন্য 'আমি' ফ্রেম রয়েছে। আমি এই স্বরলিপিটি ব্যবহার করব: চ [0], চ [1], ..., চ [i-1] ফ্রেম 0, ফ্রেম 1, ..., ফ্রেম রেন্ডার করতে কত সময় লেগেছে তা বর্ণনা করতে (i-1) ) যথাক্রমে।

Example where i = 3

|f[0]      |f[1]         |f[2]   |
+----------+-------------+-------+------> time

তারপরে, আমি ফ্রেমের পরে fps এর গাণিতিক সংজ্ঞা হবে

(1) fps[i]   = i     / (f[0] + ... + f[i-1])

এবং একই সূত্র কিন্তু কেবল আই -1 ফ্রেম বিবেচনা করে।

(2) fps[i-1] = (i-1) / (f[0] + ... + f[i-2]) 

এখন এখানে কৌশলটি হ'ল সূত্রের ডান দিকটি (1) এমনভাবে সংশোধন করা যাতে এতে সূত্রের ডান দিকটি থাকে (2) এবং এটির বাম পাশের জন্য এটি বিকল্পযুক্ত করে।

ভালো লেগেছে (আপনি যদি এটি কাগজে লিখে থাকেন তবে আপনাকে আরও স্পষ্ট দেখতে হবে):

fps[i] = i / (f[0] + ... + f[i-1])
       = i / ((f[0] + ... + f[i-2]) + f[i-1])
       = (i/(i-1)) / ((f[0] + ... + f[i-2])/(i-1) + f[i-1]/(i-1))
       = (i/(i-1)) / (1/fps[i-1] + f[i-1]/(i-1))
       = ...
       = (i*fps[i-1]) / (f[i-1] * fps[i-1] + i - 1)

সুতরাং এই সূত্র অনুসারে (আমার গণিত থেকে প্রাপ্ত দক্ষতা কিছুটা মরিচা হয়ে উঠেছে), নতুন fps গণনা করার জন্য আপনাকে আগের ফ্রেম থেকে fps জানতে হবে, শেষ ফ্রেমটি রেন্ডার করতে আপনি যে সময়কালে নিয়েছিলেন এবং আপনার ফ্রেমের সংখ্যাটি অনুষ্ঠিত.


1
দ্বিতীয় পদ্ধতির জন্য +1। আমি ধারণা করি যে এটি উবার সুনির্দিষ্ট গণনার জন্য ভাল হবে: 3
জেবোইডলুন্ড

5

এটি বেশিরভাগ লোকের জন্য অতিমাত্রার চাপ হতে পারে, এ কারণেই আমি যখন এটি প্রয়োগ করি তখন এটি পোস্ট করি নি। তবে এটি খুব মজবুত এবং নমনীয়।

এটি সর্বশেষ ফ্রেমের সময়গুলির সাথে একটি সারি সঞ্চয় করে, তাই এটি সর্বশেষ ফ্রেমটিকে বিবেচনায় না নেওয়ার চেয়ে যথাযথভাবে গড়ে গড়ে গড়ে নেওয়া এফপিএস মান গণনা করতে পারে।

এটি আপনাকে একটি ফ্রেম উপেক্ষা করার অনুমতি দেয়, আপনি যদি এমন কিছু করেন যা আপনি জানেন যে কৃত্রিমভাবে সেই ফ্রেমের সময়টুকু স্ক্রু আপ করে দেবে।

এটি কুইউতে চলার সাথে সাথে ফ্রেমের সংরক্ষণের সংখ্যা পরিবর্তন করার অনুমতি দেয়, তাই এটি আপনার জন্য সবচেয়ে ভাল মান কী তা উড়ে তা পরীক্ষা করে দেখতে পারেন।

// Number of past frames to use for FPS smooth calculation - because 
// Unity's smoothedDeltaTime, well - it kinda sucks
private int frameTimesSize = 60;
// A Queue is the perfect data structure for the smoothed FPS task;
// new values in, old values out
private Queue<float> frameTimes;
// Not really needed, but used for faster updating then processing 
// the entire queue every frame
private float __frameTimesSum = 0;
// Flag to ignore the next frame when performing a heavy one-time operation 
// (like changing resolution)
private bool _fpsIgnoreNextFrame = false;

//=============================================================================
// Call this after doing a heavy operation that will screw up with FPS calculation
void FPSIgnoreNextFrame() {
    this._fpsIgnoreNextFrame = true;
}

//=============================================================================
// Smoothed FPS counter updating
void Update()
{
    if (this._fpsIgnoreNextFrame) {
        this._fpsIgnoreNextFrame = false;
        return;
    }

    // While looping here allows the frameTimesSize member to be changed dinamically
    while (this.frameTimes.Count >= this.frameTimesSize) {
        this.__frameTimesSum -= this.frameTimes.Dequeue();
    }
    while (this.frameTimes.Count < this.frameTimesSize) {
        this.__frameTimesSum += Time.deltaTime;
        this.frameTimes.Enqueue(Time.deltaTime);
    }
}

//=============================================================================
// Public function to get smoothed FPS values
public int GetSmoothedFPS() {
    return (int)(this.frameTimesSize / this.__frameTimesSum * Time.timeScale);
}

2

এখানে ভাল উত্তর। আপনি কীভাবে এটি প্রয়োগ করেন তা নির্ভর করে আপনার এটির জন্য যা প্রয়োজন on আমি উপরের লোকটির দ্বারা নিজেকে রানিং গড়কে "সময় = সময় * 0.9 + শেষ_ ফ্রেম * 0.1" পছন্দ করি।

তবে আমি ব্যক্তিগতভাবে নতুন ডেটার দিকে আমার গড়কে আরও ভারী করে তুলতে পছন্দ করি কারণ একটি গেমের মধ্যে এমন স্পাইক হয় যা স্কোয়াশ হওয়া আমার পক্ষে সবচেয়ে কঠিন এবং এইভাবে আমার পক্ষে সবচেয়ে আগ্রহ interest সুতরাং আমি .7 \ .3 বিভাজনের মতো আরও কিছু ব্যবহার করব যা স্পাইকে আরও দ্রুত প্রদর্শিত হবে (যদিও এর প্রভাবটি দ্রুত স্ক্রিনটিকেও ছাড়বে .. নীচে দেখুন)

যদি আপনার ফোকাস রেন্ডারিংয়ের সময় হয়, তবে .9.1 বিভাজনটি খুব সুন্দরভাবে কাজ করে বি / সি এটি আরও মসৃণ হওয়ার ঝোঁক। গেমপ্লে / এআই / পদার্থবিজ্ঞানের স্পাইসের জন্য এটি একটি উদ্বেগের বিষয় কারণ সাধারণত আপনার গেমটি চপ্পল দেখা দেয় (যা প্রায়শই নিম্ন ফ্রেমের হারের চেয়ে খারাপ যে ধরে নেওয়া যায় যে আমরা ২০ এফপিএসের নিচে নামছি না)

সুতরাং, আমি যা করব তা হ'ল এটির মতো কিছু যুক্ত করুন:

#define ONE_OVER_FPS (1.0f/60.0f)
static float g_SpikeGuardBreakpoint = 3.0f * ONE_OVER_FPS;
if(time > g_SpikeGuardBreakpoint)
    DoInternalBreakpoint()

(আপনি যদি কোনও গ্রহণযোগ্যতা না বলে মনে করেন তবেই আপনার বিশাল আকারের সাথে 3.0f পূরণ করুন) এটি আপনাকে এফপিএস ইস্যুগুলির ফ্রেমটির শেষের দিকে সমাধান করতে দেবে।


আমি time = time * 0.9 + last_frame * 0.1গড় গণনা পছন্দ করি যা প্রদর্শনটি মসৃণভাবে পরিবর্তন করে।
ফ্যাবিয়েন কোয়াটারভাক্স

2

পুরানো ফ্রেমরেটগুলির একটি বড় অ্যারে ব্যবহার করার চেয়ে একটি আরও ভাল সিস্টেম হ'ল এই জাতীয় কিছু করা:

new_fps = old_fps * 0.99 + new_fps * 0.01

এই পদ্ধতিতে অনেক কম মেমরি ব্যবহার করা হয়, এর চেয়ে অনেক কম কোডের প্রয়োজন হয় এবং হঠাৎ ফ্রেমরেট পরিবর্তনের প্রভাবগুলি স্মুথ করার সময় পুরানো ফ্রেমেট্রেটের তুলনায় সাম্প্রতিক ফ্রেমারেটের উপর বেশি গুরুত্ব দেয়।


1

আপনি একটি কাউন্টার রাখতে পারেন, প্রতিটি ফ্রেম রেন্ডার হওয়ার পরে এটি বাড়িয়ে তোলেন, তারপরে আপনি যখন নতুন সেকেন্ডে থাকবেন তখন কাউন্টারটি পুনরায় সেট করুন (ফ্রেমের আগের সেকেন্ডের # হিসাবে শেষের মানটি সংরক্ষণ করা)


1

javascript:

// Set the end and start times
var start = (new Date).getTime(), end, FPS;
  /* ...
   * the loop/block your want to watch
   * ...
   */
end = (new Date).getTime();
// since the times are by millisecond, use 1000 (1000ms = 1s)
// then multiply the result by (MaxFPS / 1000)
// FPS = (1000 - (end - start)) * (MaxFPS / 1000)
FPS = Math.round((1000 - (end - start)) * (60 / 1000));

1

পাইথন ব্যবহার করে (তবে সহজে কোনও ভাষার সাথে মানিয়ে নেওয়া) এখানে একটি সম্পূর্ণ উদাহরণ's এটি মার্টিনের উত্তরে স্মুথিং সমীকরণটি ব্যবহার করে, তাই প্রায় কোনও স্মৃতি ওভারহেড নেই এবং আমি এমন মানগুলি বেছে নিয়েছি যা আমার জন্য কাজ করেছে (আপনার ব্যবহারের ক্ষেত্রে খাপ খাইয়ে নিতে ধ্রুবকগুলির সাথে ঘুরে বেড়াতে নির্দ্বিধায়)।

import time

SMOOTHING_FACTOR = 0.99
MAX_FPS = 10000
avg_fps = -1
last_tick = time.time()

while True:
    # <Do your rendering work here...>

    current_tick = time.time()
    # Ensure we don't get crazy large frame rates, by capping to MAX_FPS
    current_fps = 1.0 / max(current_tick - last_tick, 1.0/MAX_FPS)
    last_tick = current_tick
    if avg_fps < 0:
        avg_fps = current_fps
    else:
        avg_fps = (avg_fps * SMOOTHING_FACTOR) + (current_fps * (1-SMOOTHING_FACTOR))
    print(avg_fps)

0

শূন্যের বিপরীতে সেট করুন। প্রতিবার আপনি একটি ফ্রেম বর্ধিত কাউন্টার আঁকেন। প্রতি সেকেন্ডের পরে কাউন্টারটি প্রিন্ট করুন। লাথার, ধুয়ে ফেলা, পুনরাবৃত্তি। আপনি যদি অতিরিক্ত creditণ চান, একটি চলমান কাউন্টার রাখুন এবং চলমান গড়ের জন্য মোট সেকেন্ডের সংখ্যার দ্বারা ভাগ করুন।


0

(সি ++ লাইক) সিউডোকোডে এই দুটি আমি শিল্প ইমেজ প্রসেসিং অ্যাপ্লিকেশনগুলিতে ব্যবহার করেছি যা বাহ্যিকভাবে ট্রিগার হওয়া ক্যামেরার সেট থেকে চিত্রগুলি প্রক্রিয়া করতে হয়েছিল। "ফ্রেম রেট" এর পরিবর্তনের একটি আলাদা উত্স ছিল (বেল্টে ধীর বা দ্রুত উত্পাদন) তবে সমস্যাটি একই। (আমি ধরে নিয়েছি যে আপনার কাছে একটি সহজ টাইম.পিক (কল) রয়েছে যা অ্যাপ্লিকেশন শুরু হওয়ার পরে বা শেষ কল হওয়ার পরে আপনাকে এমআরসি (এনএসসি?) এর মতো কিছু দেয়)

সমাধান 1: দ্রুত তবে প্রতিটি ফ্রেম আপডেট হয় না

do while (1)
{
    ProcessImage(frame)
    if (frame.framenumber%poll_interval==0)
    {
        new_time=timer.peek()
        framerate=poll_interval/(new_time - last_time)
        last_time=new_time
    }
}

সমাধান 2: প্রতিটি ফ্রেম আপডেট হয়েছে, আরও মেমরি এবং সিপিইউ প্রয়োজন

do while (1)
{
   ProcessImage(frame)
   new_time=timer.peek()
   delta=new_time - last_time
   last_time = new_time
   total_time += delta
   delta_history.push(delta)
   framerate= delta_history.length() / total_time
   while (delta_history.length() > avg_interval)
   {
      oldest_delta = delta_history.pop()
      total_time -= oldest_delta
   }
} 

0
qx.Class.define('FpsCounter', {
    extend: qx.core.Object

    ,properties: {
    }

    ,events: {
    }

    ,construct: function(){
        this.base(arguments);
        this.restart();
    }

    ,statics: {
    }

    ,members: {        
        restart: function(){
            this.__frames = [];
        }



        ,addFrame: function(){
            this.__frames.push(new Date());
        }



        ,getFps: function(averageFrames){
            debugger;
            if(!averageFrames){
                averageFrames = 2;
            }
            var time = 0;
            var l = this.__frames.length;
            var i = averageFrames;
            while(i > 0){
                if(l - i - 1 >= 0){
                    time += this.__frames[l - i] - this.__frames[l - i - 1];
                }
                i--;
            }
            var fps = averageFrames / time * 1000;
            return fps;
        }
    }

});

0

আমি কী করে!

boolean run = false;

int ticks = 0;

long tickstart;

int fps;

public void loop()
{
if(this.ticks==0)
{
this.tickstart = System.currentTimeMillis();
}
this.ticks++;
this.fps = (int)this.ticks / (System.currentTimeMillis()-this.tickstart);
}

কথায় আছে, একটি টিক ক্লক টিকগুলি ট্র্যাক করে। যদি এটি প্রথমবার হয় তবে এটি বর্তমান সময় নেয় এবং এটি 'টিকস্টার্ট'-এ রাখে। প্রথম টিকের পরে, এটি পরিবর্তনশীল 'fps' সমান করে তোলে টিক ক্লকের কত টিকটি প্রথম টিকের সময়কে বিয়োগ করে বিভক্ত করে তোলে।

Fps হ'ল একটি পূর্ণসংখ্যা, অতএব "(int)"।


1
কারও জন্য সুপারিশ করবে না। টিকের মোট সংখ্যাটিকে সেকেন্ডের সংখ্যায় বিভক্ত করা এফপিএসের কাছে গাণিতিক সীমাবদ্ধতার মতো কিছু তৈরি করে, যেখানে এটি মূলত দীর্ঘ সময়ের পরে 2-3 মানগুলিতে স্থির হয় এবং ভুল ফলাফল প্রদর্শন করে।
কার্তিক চুগ

0

আমি এটি কীভাবে করব তা এখানে (জাভাতে):

private static long ONE_SECOND = 1000000L * 1000L; //1 second is 1000ms which is 1000000ns

LinkedList<Long> frames = new LinkedList<>(); //List of frames within 1 second

public int calcFPS(){
    long time = System.nanoTime(); //Current time in nano seconds
    frames.add(time); //Add this frame to the list
    while(true){
        long f = frames.getFirst(); //Look at the first element in frames
        if(time - f > ONE_SECOND){ //If it was more than 1 second ago
            frames.remove(); //Remove it from the list of frames
        } else break;
        /*If it was within 1 second we know that all other frames in the list
         * are also within 1 second
        */
    }
    return frames.size(); //Return the size of the list
}

0

টাইপস্ক্রিপ্টে, আমি ফ্রেমরেট এবং ফ্রেমটাইম গড় গণনা করতে এই অ্যালগরিদম ব্যবহার করি:

let getTime = () => {
    return new Date().getTime();
} 

let frames: any[] = [];
let previousTime = getTime();
let framerate:number = 0;
let frametime:number = 0;

let updateStats = (samples:number=60) => {
    samples = Math.max(samples, 1) >> 0;

    if (frames.length === samples) {
        let currentTime: number = getTime() - previousTime;

        frametime = currentTime / samples;
        framerate = 1000 * samples / currentTime;

        previousTime = getTime();

        frames = [];
    }

    frames.push(1);
}

ব্যবহার:

statsUpdate();

// Print
stats.innerHTML = Math.round(framerate) + ' FPS ' + frametime.toFixed(2) + ' ms';

টিপ: নমুনাগুলি যদি 1 হয়, ফলাফলটি রিয়েল-টাইম ফ্রেমরেট এবং ফ্রেমটাইম।


0

এটি কেপিেক্সইএর উত্তরের ভিত্তিতে এবং সরল মুভিং গড়কে দেয়। সহজ অনুলিপি এবং পেস্টের জন্য সজ্জিত এবং টাইপস্ক্রিপ্টে রূপান্তরিত:

পরিবর্তনশীল ঘোষণা:

fpsObject = {
  maxSamples: 100,
  tickIndex: 0,
  tickSum: 0,
  tickList: []
}

ফাংশন:

calculateFps(currentFps: number): number {
  this.fpsObject.tickSum -= this.fpsObject.tickList[this.fpsObject.tickIndex] || 0
  this.fpsObject.tickSum += currentFps
  this.fpsObject.tickList[this.fpsObject.tickIndex] = currentFps
  if (++this.fpsObject.tickIndex === this.fpsObject.maxSamples) this.fpsObject.tickIndex = 0
  const smoothedFps = this.fpsObject.tickSum / this.fpsObject.maxSamples
  return Math.floor(smoothedFps)
}

ব্যবহার (আপনার অ্যাপে ভিন্ন হতে পারে):

this.fps = this.calculateFps(this.ticker.FPS)

-1

একটি শুরুর সময় সঞ্চয় এবং একবার প্রতি লুপ প্রতি আপনার ফ্রেমকাউন্টার বৃদ্ধি? প্রতি কয়েক সেকেন্ডে আপনি কেবল ফ্রেমকাউন্ট / / (এখন - শুরুর সময়) মুদ্রণ করতে পারেন এবং তারপরে এগুলি পুনরায় পুনঃনির্মাণ করতে পারেন।

সম্পাদনা: উফ! দুবার ninja'ed

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.