【Game Engine】第三節:Clock幀計時器 && DLL鏈接 && 鍵盤按鍵事件

Clock幀計時器

  • 目的

    • 使用Qtime循環調用myUpdate來刷新幀畫面時,幀數非固定,若每兩幀之間的計算量相差較大,會出現兩幀之間卡頓,使得畫面停滯,需要利用幀計時來優化計算
  • 原理

    • 統計連續兩幀之間的時鐘週期數量,除以當前的每秒時鐘週期數,可獲得相鄰兩幀的差時
  • Clock類

#include <Windows.h>
namespace Time {
	class __declspec(dllexport) Clock {			//生成lib文件
	private:
		LARGE_INTEGER lastFrameCounter;			//上一幀週期數
		LARGE_INTEGER deltaCounter;				//差值週期數
		float deltaTime;						//差值時間
	public:
		LARGE_INTEGER nowPerformanceFrequency;	//每秒週期數
		bool clockInitialize();					//clock初始化
		bool clockGetNewFrame();				//獲取新一幀
		float clockTimeLastFrame();				//獲取幀差值時間
		bool clockShutdown();					//clock關閉
	};
}
  • API

    • LARGE_INTEGER
      • 大整數Union,64位整數,一位符號位
      • LargeInteger.QuadPart:__int64
    • bool QueryPerformanceFrequency(LARGE_INTEGER *frequncy)
      • 查詢當前系統每秒週期數
      • 成功返回1,系統無法查詢返回0,存在於frequncy
    • bool QueryPerformanceCounter(LARGE_INTEGER *performanceCount)
      • 查詢當前指令所在週期數
      • 成功返回1,系統無法查詢返回0,存在於performanceCount
  • 實現

#include "Clock.h"
namespace Time {

	bool Clock::clockInitialize() {
		bool errorCode = QueryPerformanceFrequency(&nowPerformanceFrequency);
		deltaTime = 0;
		lastFrameCounter.QuadPart = 0;
		return errorCode;
	}

	bool Clock::clockGetNewFrame() {
		LARGE_INTEGER nowFrameCounter;
		bool errorCode = QueryPerformanceCounter(&nowFrameCounter);
		if (!errorCode) return false;
		deltaCounter.QuadPart = nowFrameCounter.QuadPart - lastFrameCounter.QuadPart;
		if (lastFrameCounter.QuadPart != 0) 
			deltaTime = ((float)deltaCounter.QuadPart) / nowPerformanceFrequency.QuadPart;
		lastFrameCounter.QuadPart = nowFrameCounter.QuadPart;
		return true;
	}

	float Clock::clockTimeLastFrame() {
		return deltaTime;
	}

	bool Clock::clockShutdown() {
		return true;
	}
}
  • 應用

void MyGlWindow::myUpdate() {
	myClock.clockGetNewFrame();
	float frameTime = myClock.clockTimeLastFrame();
	Velocity = Vector2D(0.1f,0.1f);
	shipPosition = shipPosition + frameTime*Velocity;  
	repaint();
}

//myTimer.start(17);  六十幀每秒

DLL鏈接

  • 目的

    • Vector2D實現使用的是包含inl文件,實質上只有.h,不存在編譯問題
    • Clock中使用了.cpp,需要對engine項目進行編譯生成,需要生成動態鏈接庫給其他項目
  • 實現

    • 解決方案屬性->設置項目依賴
    • engine屬性->配置類型:dll
    • sandbox屬性:配置lib與include目錄
    • sandbox添加生成事件,將engine.dll拷貝到sandbox的debug目錄中

鍵盤按鍵事件

  • QT鍵盤事件

    • 不易處理同時按下兩按鍵
  • Windows鍵盤事件

    • API

      • short GetAsyncKeyState(int vKey)
        • 返回值非空爲按vKey鍵信號
        • vKey爲VK_按鍵名
    • 實現

void MyGlWindow::myCheckKeyState() {
	const float ACCERALATION = 0.08f * myClock.clockTimeLastFrame();
	if (GetAsyncKeyState(VK_UP))
		shipVelocity.y += ACCERALATION;
	if (GetAsyncKeyState(VK_DOWN))
		shipVelocity.y -= ACCERALATION;
	if (GetAsyncKeyState(VK_RIGHT))
		shipVelocity.x += ACCERALATION;
	if (GetAsyncKeyState(VK_LEFT))
		shipVelocity.x -= ACCERALATION;
	if (GetAsyncKeyState(VK_SPACE))
		shipVelocity.x = 0, shipVelocity.y = 0;
}
發佈了34 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章