はじめてのYaneSDK.NETその4

今回はフレームレートについてです。フレームレートは1秒間に何回画面を書き換えるかの指標で30fpsとか60fpsとか言ったりします(アドベンチャー系ならあまり関係ないかも)。YaneSDKは基本的にメインループを回して・・・というアクションゲームスタイルなコーディングをするので、fpsを指定するのに便利なFpsTimerクラスが用意されています。
以下は、画面上で指定したfpsで画面の書き換えを行うテストアプリです。また、実際のfpsの測定も行っています。WinFormsの場合、タイマーイベントが定期的に起こりますので、FpsTimerは不要に思うかも知れませんが、タイマーイベントの間隔をギリギリにしておくとどうしても遅延が発生するので、タイマーは若干余裕のある間隔にしておいて、FpsTimerで調整するのが良いかも知れません。ちなみにサンプルではタイマーの間隔を30msにしましたので、論理的には33fpsになるはずですが、画像にあるように33fpsを指定すると遅延が発生しました。(若干落とした30fpsを指定すると安定します)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using YT = Yanesdk.Timer;
using YD = Yanesdk.Draw;

namespace Sample4
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        int x = 0;
        int y = 0;
        int dx = 1;
        int dy = 1;
        YD.Win32Window window;
        YD.GlTexture texture;
        YD.FpsLayer fpsLayer;

        private void Form1_Load(object sender, EventArgs e)
        {
            // 初期処理

            // 描画サイズは320x240
            ClientSize = new Size(320, 240);
            // PictureBoxをDockStyle.Fillで貼り付けている
            // PictureBox上に描画
            window = new YD.Win32Window(pictureBox1.Handle);
            // Texture作成時はScreen.Selectを呼ぶ
            window.Screen.Select();
            // ゴシック(0がゴシック、明朝は1)、32ポイントのフォントを読み込み
            YD.Font font = new YD.Font();
            font.Load(0, 32);
            // フォント色は赤
            font.SetColor(255, 0, 0);
            // 描画用のテクスチャを用意
            texture = new YD.GlTexture();
            // カラーキーは座標(0, 0)の色とする
            texture.SetColorKeyPos(0, 0);
            // Hello, Worldの文字をテクスチャに貼り付ける
            texture.SetSurface(font.DrawBlended("Hello, World"));

            // FPSの表示
            YT.FpsTimer fpsTimer = new YT.FpsTimer();
            fpsTimer.Fps = (float)numericUpDown1.Value;
            fpsLayer = new YD.FpsLayer(fpsTimer);
        }

        private void OnTick(object sender, EventArgs e)
        {
            // TimerクラスのTickイベント
            // 定期的に呼ばれる

            // ウィンドウの端で反射
            x += dx;
            y += dy;

            if (x < 0 || x > pictureBox1.Width - texture.Width)
                dx = -dx;
            if (y < 0 || y > pictureBox1.Height - texture.Height)
                dy = -dy;

            // 指定したフレームレートになるように待つ
            fpsLayer.FpsTimer.WaitFrame();
            if (fpsLayer.FpsTimer.ToBeSkip)
            {
                // 指定したFPSを満たせないので(重い)描画をスキップ
                return;
            }

            if ((int)fpsLayer.FpsTimer.Fps != (int)numericUpDown1.Value)
                fpsLayer.FpsTimer.Fps = (float)numericUpDown1.Value;

            YD.Screen scr = window.Screen;

            // 描画はScreen.Select〜Updateで挟む
            scr.Select();

            // 画面を白でクリア
            scr.SetClearColor(255, 255, 255);
            scr.Clear();

            // アルファ転送ON
            scr.BlendSrcAlpha();
            // テクスチャを描画(Hello, World)
            scr.Blt(texture, x, y);

            fpsLayer.OnDraw(scr, 10, 10);

            // 描画終了
            scr.Update();
        }
    }
}