[實戰]C++加Lua加SDL來重寫龍神錄彈幕遊戲(4):完善Game類

       大部分前期工作都已經完成了,可以正式開始敲遊戲代碼了。之前顯示的都是死循環的窗口,這次終於可以來解決這個問題了,先看看今天的結果。


       這次C++中有部分修改的代碼,但有了之前的基礎,就不花費很多精力在這上面,代碼會放到最後面。首先將之前的Game.lua修改下名字,改成GameBase.lua。

GameBase.lua

require "Module.Enum.SDL"

local GameBase = 
{
	m_bIsRunning = false,	--是否在運行
	m_pSDLWindow = nil,		--SDL_Window指針
	m_pSDLRenderer = nil,	--SDL_Renderer指針

	m_title = "Game",		--窗口標題
	m_width = 0,			--窗口寬度
	m_height = 0,			--窗口高度
	m_bFullscreen = false,	--是否是全屏運行

	m_lastTime = 0,			--上次運行時間
}

--初始化
function GameBase:Init()
	self.m_bIsRunning = false

	--SDL初始化
	local flags = SDL_INIT_TYPE.SDL_INIT_VIDEO
	local bResult = Renderer.SDLInit(flags)
	if not bResult then
		Logger.LogError("Renderer.SDLInit(%d) failed, %s", flags, Renderer.GetError())
		return false
	end

	--讀取Window.ini配置
	local filePath = "Config/Window.ini"
	local windowConfig = io.open(filePath, "r")
	if not windowConfig then
		Logger.LogError("Error: Can't find %s", filePath)
		return false
	end
	self.m_title = windowConfig:read()
	self.m_width = tonumber(windowConfig:read())
	self.m_height = tonumber(windowConfig:read())
	self.m_bFullscreen = tonumber(windowConfig:read()) ~= 0
	windowConfig:close()

	--根據Window.ini配置創建SDL窗口
	flags = 0
	if self.m_bFullscreen then
		flags = flags | SDL_WINDOW_TYPE.SDL_WINDOW_FULLSCREEN
	end
	self.m_pSDLWindow = Renderer.CreateWindow(self.m_title, 100, 100, self.m_width, self.m_height, flags)

	--創建SDLRenderer
	flags = SDL_RENDERER_TYPE.SDL_RENDERER_ACCELERATED | SDL_RENDERER_TYPE.SDL_RENDERER_PRESENTVSYNC
	self.m_pSDLRenderer = Renderer.CreateRenderer(self.m_pSDLWindow, -1, flags)

	--SDL_Image初始化
	flags = SDL_IMAGE_INIT_TYPE.IMG_INIT_PNG
	bResult = Renderer.SDLImageInit(flags)
	if not bResult then
		Logger.LogError("Renderer.SDLImageInit(%d) failed, %s", flags, Renderer.GetError())
		return false
	end

	if self.OnInit then
		bResult = self:OnInit()
		if not bResult then
			return false
		end
	end

	self.m_bIsRunning = true

	return true
end

--運行
function GameBase:Run()
	while self:IsRunning() do
		self:HandleEvents()
		self:Update()
		self:Render()
	end
end

--釋放
function GameBase:Release()
	if self.OnRelease then
		self:OnRelease()
	end

	if self.m_pSDLRenderer then
		Renderer.DestroyRenderer(self.m_pSDLRenderer)
	end
	if self.m_pSDLWindow then
		Renderer.DestroyWindow(self.m_pSDLWindow)
	end
	Renderer.Quit()
end

--是否在運行中
function GameBase:IsRunning()
	return self.m_bIsRunning
end

--退出遊戲
function GameBase:QuitGame()
	self.m_bIsRunning = false
end

--事件處理
function GameBase:HandleEvents()
	local bResult, eventType = Renderer.PollEvent()
	while bResult do
		if eventType == SDL_EVENT_TYPE.SDL_QUIT then
			self:QuitGame()
		else--other event

		end

		bResult, eventType = Renderer.PollEvent()
	end

	--按下Escape鍵退出遊戲
	bResult = Renderer.GetKeyboardState(SDL_KEYCODE.SDL_SCANCODE_ESCAPE)
	if bResult then
		self:QuitGame()
	end

	if self.OnHandleInput then
		self:OnHandleInput()
	end
end

--更新
function GameBase:Update()
	--限制一幀至少16ms
	while not Renderer.TICKS_PASSED(Renderer.GetTicks(), self.m_lastTime + 16) do
	end
	
	local currentTime = Renderer.GetTicks()
	local deltaTime = (currentTime - self.m_lastTime) / 1000
	self.m_lastTime = currentTime

	--調試會導致deltaTime變大,限制一下
	if deltaTime > 0.05 then
		deltaTime = 0.05
	end

	if self.OnUpdate then
		self:OnUpdate(deltaTime)
	end
end

--渲染
function GameBase:Render()
	Renderer.SetRenderDrawColor(self.m_pSDLRenderer, 0, 0, 255, 255)
	Renderer.RenderClear(self.m_pSDLRenderer)

	if self.OnRender then
		self:OnRender()
	end

	Renderer.RenderPresent(self.m_pSDLRenderer)
end

return GameBase

       可以看出來GameBase是作爲元表的,我把很多框架上的函數都寫在GameBase上,是不想被人重載掉這些接口。按順序逐個說下API:GameBase:Init()應該是最簡單的,只是將之前的代碼完善而已。
       SDL初始化應該沒有多少問題,跳過。在創建SDL窗口之前,添加了一堆讀取Window.ini的代碼,實際上只是把創建窗口需要的參數提取出來,放到Window.ini中,利用IO操作來獲取數據,減少在代碼中頻繁修改窗口名,窗口寬度等數據的次數。可以來看下Window.ini的配置:


       創建SDLRenderer也沒有多少變化,跳過。新增加的SDLImageInit其實跟SDL_Init一樣(我避免歧義,重命名了Renderer.Init函數名)。接下來代碼就比較核心了,過會還會看到很多OnXXX的函數,這些纔是我們真正關心的函數。
       沒有用過lua的估計會有點懵逼,這是啥意思,這裏簡單解釋下,因爲GameBase本身是沒有OnInit字段(key),所以會跳過這段代碼,但是不要忘記GameBase是作爲元表的,也就是父類,而我們後面將使用的也是子類(也就是後面的RyuujinnGame)來創建遊戲的。因此如果是子類(RyuujinnGame表)在調用Init函數的時候,執行到同樣的地方時候,self.OnInit就會從子類(RyuujinnGame表)查找這個OnInit字段(key),找到後,就調用OnInit函數,這樣就使得子類(RyuujinnGame表)只關心遊戲的邏輯,不去關係SDL窗口的創建,SDL事件的處理等。
       接下來的GameBase:Run()就是之前的死循環修改後的版本,主要負責3個工作,處理事件,更新遊戲,渲染遊戲。再接着的GameBase:Release()也是之前提取出來的代碼,只是加了OnRelease調用而已,這個跟之前的OnInit是一致的,這邊不再重複。GameBase:IsRunning()和GameBase:QuitGame()的代碼就一句,沒啥可說的。
       GameBase:HandleEvents()主要功能就是事件處理,比如處理點擊關閉按鈕事件,按下Escape按鍵等。lua這邊代碼也很簡單,但這裏有一個特殊的地方就是,C++函數只能有一個返回值(不算把結果按地址傳遞,類似c#的out),lua這邊直接返回了2個值,來看C++這邊的代碼,int PollEvent(lua_State* L)就實現了lua這邊可以接受2個返回值的功能,因爲事件處理只關心類型,也做一步處理,不傳SDL_Event,而是傳SDL_Event的type字段。


       接下來的GameBase:Update()和GameBase:Render()代碼很簡單,可以修改Renderer.SetRenderDrawColor函數後面4個參數來修改SDL窗口的顏色。SDL一些枚舉值,也有部分提取到lua中,在Script文件夾中,創建Module文件夾,再在Module文件夾下創建Enum文件夾,再在Enum文件夾下創建SDL.lua文件,工作也很簡單,就是把大部分ctrl+c,ctrl+v就ok了。需要注意的就是16進制要轉成10進制。

SDL.lua

--SDL初始化類型
SDL_INIT_TYPE = 
{
	SDL_INIT_VIDEO = tonumber("00000020", 16),--將16進制字符串轉換成10進制數字
}

--SDL窗口類型
SDL_WINDOW_TYPE = 
{
	SDL_WINDOW_FULLSCREEN = tonumber("00000001", 16),
}

SDL_RENDERER_TYPE = 
{
	SDL_RENDERER_ACCELERATED = tonumber("00000002", 16),
	SDL_RENDERER_PRESENTVSYNC = tonumber("00000004", 16),
}

--SDL_Image初始化類型
SDL_IMAGE_INIT_TYPE = 
{
	IMG_INIT_PNG = tonumber("00000002", 16),
}

--事件類型
SDL_EVENT_TYPE = 
{
	SDL_QUIT = tonumber("100", 16),
}

--按鍵
SDL_KEYCODE = 
{
	SDL_SCANCODE_A = 4,
    SDL_SCANCODE_B = 5,
    SDL_SCANCODE_C = 6,
    SDL_SCANCODE_D = 7,
    SDL_SCANCODE_E = 8,
    SDL_SCANCODE_F = 9,
    SDL_SCANCODE_G = 10,
    SDL_SCANCODE_H = 11,
    SDL_SCANCODE_I = 12,
    SDL_SCANCODE_J = 13,
    SDL_SCANCODE_K = 14,
    SDL_SCANCODE_L = 15,
    SDL_SCANCODE_M = 16,
    SDL_SCANCODE_N = 17,
    SDL_SCANCODE_O = 18,
    SDL_SCANCODE_P = 19,
    SDL_SCANCODE_Q = 20,
    SDL_SCANCODE_R = 21,
    SDL_SCANCODE_S = 22,
    SDL_SCANCODE_T = 23,
    SDL_SCANCODE_U = 24,
    SDL_SCANCODE_V = 25,
    SDL_SCANCODE_W = 26,
    SDL_SCANCODE_X = 27,
    SDL_SCANCODE_Y = 28,
    SDL_SCANCODE_Z = 29,

    SDL_SCANCODE_1 = 30,
    SDL_SCANCODE_2 = 31,
    SDL_SCANCODE_3 = 32,
    SDL_SCANCODE_4 = 33,
    SDL_SCANCODE_5 = 34,
    SDL_SCANCODE_6 = 35,
    SDL_SCANCODE_7 = 36,
    SDL_SCANCODE_8 = 37,
    SDL_SCANCODE_9 = 38,
    SDL_SCANCODE_0 = 39,

    SDL_SCANCODE_RETURN = 40,
    SDL_SCANCODE_ESCAPE = 41,
    SDL_SCANCODE_BACKSPACE = 42,
    SDL_SCANCODE_TAB = 43,
    SDL_SCANCODE_SPACE = 44,
}

       大部分工作已經在GameBase上完成了,接下來就是來實現子類,添加RyuujinnGame.lua,代碼也很簡單,關鍵就是通過__newindex元方法來進制重載GameBase上的函數。
RyuujinnGame.lua

RyuujinnGame = setmetatable({}, 
{ 
	__index = require "GameBase",
	__newindex = function(t, key, newValue)--禁止重載GameBase函數
		local oldValue = t[key]
		if oldValue == nil or type(oldValue) ~= "function" then
			rawset(t, key, newValue)
		else
			Logger.LogError("This action overrides GameBase's function is not allowed\n"..debug.traceback())
		end
	end
})

function RyuujinnGame:OnInit()
	return true
end

function RyuujinnGame:OnRelease()
	
end

function RyuujinnGame:OnHandleInput()

end

function RyuujinnGame:OnUpdate(deltaTime)
	
end

function RyuujinnGame:OnRender()

end

       Main.lua腳本估計後面也不會用太大的改動,這應該算是最終版吧。
Main.lua

require "Logger"

require "RyuujinnGame"

function Main()
	Logger.Log("Main")
	local bResult = RyuujinnGame:Init()
	if bResult then
		RyuujinnGame:Run()
	end

	RyuujinnGame:Release()
end

       運行後就會得到一個藍色的窗口,點擊關閉按鈕和按下Escape按鍵都能關閉掉SDL窗口。

       是時候在窗口上顯示一張圖片啥的,接下來就只要修改RyuujinnGame.lua的腳本,就會在窗口上顯示一張圖片,並且可以通過WSAD按鍵控制圖片的移動。Renderer.Test只是測試代碼,後面會刪除的。

RyuujinnGame.lua

RyuujinnGame = setmetatable({}, 
{ 
	__index = require "GameBase",
	__newindex = function(t, key, newValue)--禁止重載GameBase函數
		local oldValue = t[key]
		if oldValue == nil or type(oldValue) ~= "function" then
			rawset(t, key, newValue)
		else
			Logger.LogError("This action overrides GameBase's function is not allowed\n"..debug.traceback())
		end
	end
})

function RyuujinnGame:OnInit()
	self.texture = Renderer.GetTexture(self.m_pSDLRenderer, "Resource/body.png")
	self.posX = 0
	self.posY = 0
	return true
end

function RyuujinnGame:OnRelease()
	
end

function RyuujinnGame:OnHandleInput()
	if Renderer.GetKeyboardState(SDL_KEYCODE.SDL_SCANCODE_W) then
		self.posY = self.posY - 10
	end
	if Renderer.GetKeyboardState(SDL_KEYCODE.SDL_SCANCODE_S) then
		self.posY = self.posY + 10
	end
	if Renderer.GetKeyboardState(SDL_KEYCODE.SDL_SCANCODE_A) then
		self.posX = self.posX - 10
	end
	if Renderer.GetKeyboardState(SDL_KEYCODE.SDL_SCANCODE_D) then
		self.posX = self.posX + 10
	end
end

function RyuujinnGame:OnUpdate(deltaTime)
	
end

function RyuujinnGame:OnRender()
	local destWidth = 100
	local destHeight = 100
	Renderer.Test(self.m_pSDLRenderer, self.texture, 100, 100, self.posX, self.posY)
end

Renderer.h

#pragma once

#define SDL_MAIN_HANDLED

// 引入SDL需要的頭文件
#include <SDL.h>
#include <SDL_image.h>

// 鏈接SDL靜態庫
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib, "SDL2_image.lib")

class Renderer
{
public:
#pragma region 初始化
	static bool SDLInit(Uint32 flags);
	static bool SDLImageInit(int flags);
	static SDL_Window* CreateWindow(const char* title, int posX, int posY, int width, int hegiht, Uint32 flags);
	static SDL_Renderer* CreateRenderer(SDL_Window* pWindow, int index, Uint32 flags);
#pragma endregion

#pragma region 釋放
	static void DestroyWindow(SDL_Window* pWindow);
	static void DestroyRenderer(SDL_Renderer* pRenderer);
	static void Quit();
#pragma endregion

#pragma region 報錯
	static const char* GetError();
#pragma endregion

#pragma region 事件
	static bool PollEvent(SDL_Event& event);
#pragma endregion

#pragma region 時間
	static Uint32 GetTicks();
	static bool TICKS_PASSED(Uint32 currentTime, Uint32 targetTime);
#pragma endregion

#pragma region 渲染
	static void SetRenderDrawColor(SDL_Renderer* pRenderer, Uint8 r, Uint8 g, Uint8 b,
		Uint8 a);
	static void RenderClear(SDL_Renderer* pRenderer);
	static void RenderPresent(SDL_Renderer* pRenderer);

	static SDL_Texture* GetTexture(SDL_Renderer* pRenderer, const char* fileName);
	static void Test(SDL_Renderer* pRenderer, SDL_Texture* pTexture, int width, int height, int x, int y);
#pragma endregion

#pragma region 按鈕
	static bool GetKeyboardState(int keycode);
#pragma endregion
};

struct lua_State;
namespace LuaWrap
{
	void RegisterRenderer(lua_State* L);
}

Renderer.cpp

#include "Renderer.h"
#include "Logger.h"

bool Renderer::SDLInit(Uint32 flags)
{
	return 0 == SDL_Init(flags);
}

bool Renderer::SDLImageInit(int flags)
{
	return 0 != IMG_Init(IMG_INIT_PNG);
}

SDL_Window* Renderer::CreateWindow(const char* title, int posX, int posY, int width, int hegiht, Uint32 flags)
{
	return SDL_CreateWindow(title, posX, posY, width, hegiht, flags);
}

SDL_Renderer* Renderer::CreateRenderer(SDL_Window* pWindow, int index, Uint32 flags)
{
	return SDL_CreateRenderer(pWindow, index, flags);
}

void Renderer::DestroyWindow(SDL_Window* pWindow)
{
	if (pWindow)
		SDL_DestroyWindow(pWindow);
}

void Renderer::DestroyRenderer(SDL_Renderer* pRenderer)
{
	if (pRenderer)
		SDL_DestroyRenderer(pRenderer);
}

void Renderer::Quit()
{
	SDL_Quit();
}

const char* Renderer::GetError()
{
	return SDL_GetError();
}

bool Renderer::PollEvent(SDL_Event& event)
{
	return SDL_PollEvent(&event);
}

Uint32 Renderer::GetTicks()
{
	return SDL_GetTicks();
}

bool Renderer::TICKS_PASSED(Uint32 currentTime, Uint32 targetTime)
{
	return SDL_TICKS_PASSED(currentTime, targetTime);
}

void Renderer::SetRenderDrawColor(SDL_Renderer* pRenderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
	SDL_SetRenderDrawColor(pRenderer, r, g, b, a);
}

void Renderer::RenderClear(SDL_Renderer* pRenderer)
{
	SDL_RenderClear(pRenderer);
}

void Renderer::RenderPresent(SDL_Renderer* pRenderer)
{
	SDL_RenderPresent(pRenderer);
}

SDL_Texture* Renderer::GetTexture(SDL_Renderer* pRenderer, const char* fileName)
{
	SDL_Texture* pTexture = nullptr;
	SDL_Surface* pSurface = IMG_Load(fileName);
	if (!pSurface)
	{
		Logger::LogError("IMG_Load() failed in Renderer::GetTexture(): %s", fileName);
		return nullptr;
	}

	pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
	SDL_FreeSurface(pSurface);
	if (!pTexture)
	{
		SDL_Log("SDL_CreateTextureFromSurface() failed in GetTexture(): %s", SDL_GetError());
		return nullptr;
	}

	return pTexture;
}

void Renderer::Test(SDL_Renderer* pRenderer, SDL_Texture* pTexture, int width, int height, int x, int y)
{
	SDL_Rect rect;
	rect.w = width;
	rect.h = height;
	rect.x = x;
	rect.y = y;

	SDL_RenderCopy(pRenderer, pTexture, nullptr, &rect);
}

bool Renderer::GetKeyboardState(int keycode)
{
	bool bResult = false;
	const Uint8* pState = SDL_GetKeyboardState(nullptr);
	if (pState)
		bResult = pState[keycode];

	return bResult;
}

RendererWrap.cpp

#include "Renderer.h"
#include <LuaClient.h>
#include "Logger.h"

int SDLInit(lua_State* L)
{
	Uint32 flag = (Uint32)lua_tointeger(L, 1);
	lua_pushboolean(L, Renderer::SDLInit(flag));

	return 1;
}

int SDLImageInit(lua_State* L)
{
	Uint32 flag = (Uint32)lua_tointeger(L, 1);
	lua_pushboolean(L, Renderer::SDLImageInit(flag));

	return 1;
}

int CreateWindow(lua_State* L)
{
	const char* title = lua_tostring(L, 1);
	int posX = (int)lua_tointeger(L, 2);
	int posY = (int)lua_tointeger(L, 3);
	int width = (int)lua_tointeger(L, 4);
	int hegiht = (int)lua_tointeger(L, 5);
	Uint32 flag = (Uint32)lua_tointeger(L, 6);
	lua_pushlightuserdata(L, Renderer::CreateWindow(title, posX, posY, width, hegiht, flag));

	return 1;
}

int CreateRenderer(lua_State* L)
{
	SDL_Window* pWindow = (SDL_Window*)lua_touserdata(L, 1);
	int index = (int)lua_tointeger(L, 2);
	Uint32 flag = (Uint32)lua_tointeger(L, 3);
	lua_pushlightuserdata(L, Renderer::CreateRenderer(pWindow, index, flag));

	return 1;
}

int DestroyWindow(lua_State* L)
{
	SDL_Window* pWindow = (SDL_Window*)lua_touserdata(L, 1);
	Renderer::DestroyWindow(pWindow);

	return 0;
}

int DestroyRenderer(lua_State* L)
{
	SDL_Renderer* pRenderer = (SDL_Renderer*)lua_touserdata(L, 1);
	Renderer::DestroyRenderer(pRenderer);

	return 0;
}

int Quit(lua_State* L)
{
	Renderer::Quit();

	return 0;
}

int GetError(lua_State* L)
{
	auto ss = Renderer::GetError();
	lua_pushstring(L, Renderer::GetError());

	return 1;
}

int PollEvent(lua_State* L)
{
	SDL_Event event;
	bool bResult = 1 == SDL_PollEvent(&event);
	long type = -1;
	if (bResult)
		type = event.type;

	lua_pushboolean(L, bResult);
	lua_pushnumber(L, type);

	return 2;
}

int GetTicks(lua_State* L)
{
	lua_pushnumber(L, Renderer::GetTicks());

	return 1;
}

int TICKS_PASSED(lua_State* L)
{
	Uint32 currentTime = (Uint32)lua_tonumber(L, 1);
	Uint32 targetTime = (Uint32)lua_tonumber(L, 2);
	lua_pushboolean(L, Renderer::TICKS_PASSED(currentTime, targetTime));

	return 1;
}

int SetRenderDrawColor(lua_State* L)
{
	SDL_Renderer* pRenderer = (SDL_Renderer*)lua_touserdata(L, 1);
	Uint8 r = (Uint8)lua_tonumber(L, 2);
	Uint8 g = (Uint8)lua_tonumber(L, 3);
	Uint8 b = (Uint8)lua_tonumber(L, 4);
	Uint8 a = (Uint8)lua_tonumber(L, 5);
	Renderer::SetRenderDrawColor(pRenderer, r, g, b, a);

	return 0;
}

int RenderClear(lua_State* L)
{
	SDL_Renderer* pRenderer = (SDL_Renderer*)lua_touserdata(L, 1);
	Renderer::RenderClear(pRenderer);

	return 0;
}

int RenderPresent(lua_State* L)
{
	SDL_Renderer* pRenderer = (SDL_Renderer*)lua_touserdata(L, 1);
	Renderer::RenderPresent(pRenderer);

	return 0;
}

int GetTexture(lua_State* L)
{
	SDL_Renderer* pRenderer = (SDL_Renderer*)lua_touserdata(L, 1);
	const char* fileName = lua_tostring(L, 2);

	lua_pushlightuserdata(L, Renderer::GetTexture(pRenderer, fileName));

	return 1;
}

int Test(lua_State* L)
{
	SDL_Renderer* pRenderer = (SDL_Renderer*)lua_touserdata(L, 1);
	SDL_Texture* pTexture = (SDL_Texture*)lua_touserdata(L, 2);
	int width = (int)lua_tonumber(L, 3);
	int height = (int)lua_tonumber(L, 4);
	int x = (int)lua_tonumber(L, 5);
	int y = (int)lua_tonumber(L, 6);
	Renderer::Test(pRenderer, pTexture, width, height, x, y);

	return 0;
}

int GetKeyboardState(lua_State* L)
{
	int keycode = (int)lua_tonumber(L, 1);
	lua_pushboolean(L, Renderer::GetKeyboardState(keycode));

	return 1;
}

int RendererGet(lua_State* L)
{
	const char* strKey = lua_tostring(L, 2);

	luaL_getmetatable(L, "RendererMetaTable");
	lua_pushvalue(L, 2);
	lua_rawget(L, -2);
	if (lua_isnil(L, -1))
		Logger::LogError("Renderer don't have the field: %s.\n%s:%d: in function '%s'", strKey, __FILE__, __LINE__, __FUNCTION__);

	return 1;
}

int RendererSet(lua_State* L)
{
	luaL_getmetatable(L, "RendererMetaTable");
	lua_pushvalue(L, 2);
	lua_rawget(L, -2);
	if (lua_isnil(L, -1))
	{
		lua_pop(L, 1);
		lua_pushvalue(L, 2);
		lua_pushvalue(L, 3);
		lua_rawset(L, -3);
	}
	else
	{
		if(LUA_TFUNCTION == lua_type(L, -1))
			Logger::LogError("The action is not allowed.\n%s:%d: in function '%s'", __FILE__, __LINE__, __FUNCTION__);
		else
		{
			lua_pop(L, 1);
			lua_pushvalue(L, 2);
			lua_pushvalue(L, 3);
			lua_rawset(L, -3);
		}
	}

	return 0;
}

void LuaWrap::RegisterRenderer(lua_State* L)
{
	if (!L) return;

	lua_newtable(L);

	luaL_newmetatable(L, "RendererMetaTable");
	lua_pushstring(L, "__index");
	lua_pushcfunction(L, RendererGet);
	lua_rawset(L, -3);

	lua_pushstring(L, "__newindex");
	lua_pushcfunction(L, RendererSet);
	lua_rawset(L, -3);

	lua_pushstring(L, "SDLInit");
	lua_pushcfunction(L, SDLInit);
	lua_rawset(L, -3);

	lua_pushstring(L, "SDLImageInit");
	lua_pushcfunction(L, SDLImageInit);
	lua_rawset(L, -3);

	lua_pushstring(L, "CreateWindow");
	lua_pushcfunction(L, CreateWindow);
	lua_rawset(L, -3);

	lua_pushstring(L, "CreateRenderer");
	lua_pushcfunction(L, CreateRenderer);
	lua_rawset(L, -3);

	lua_pushstring(L, "GetTexture");
	lua_pushcfunction(L, GetTexture);
	lua_rawset(L, -3);

	lua_pushstring(L, "Test");
	lua_pushcfunction(L, Test);
	lua_rawset(L, -3);
	
	lua_pushstring(L, "DestroyWindow");
	lua_pushcfunction(L, DestroyWindow);
	lua_rawset(L, -3);

	lua_pushstring(L, "DestroyRenderer");
	lua_pushcfunction(L, DestroyRenderer);
	lua_rawset(L, -3);

	lua_pushstring(L, "Quit");
	lua_pushcfunction(L, Quit);
	lua_rawset(L, -3);

	lua_pushstring(L, "GetError");
	lua_pushcfunction(L, GetError);
	lua_rawset(L, -3);

	lua_pushstring(L, "PollEvent");
	lua_pushcfunction(L, PollEvent);
	lua_rawset(L, -3);

	lua_pushstring(L, "SetRenderDrawColor");
	lua_pushcfunction(L, SetRenderDrawColor);
	lua_rawset(L, -3);

	lua_pushstring(L, "RenderClear");
	lua_pushcfunction(L, RenderClear);
	lua_rawset(L, -3);

	lua_pushstring(L, "RenderPresent");
	lua_pushcfunction(L, RenderPresent);
	lua_rawset(L, -3);

	lua_pushstring(L, "GetTicks");
	lua_pushcfunction(L, GetTicks);
	lua_rawset(L, -3);

	lua_pushstring(L, "TICKS_PASSED");
	lua_pushcfunction(L, TICKS_PASSED);
	lua_rawset(L, -3);

	lua_pushstring(L, "GetKeyboardState");
	lua_pushcfunction(L, GetKeyboardState);
	lua_rawset(L, -3);

	lua_setmetatable(L, -2);
	lua_setglobal(L, "Renderer");
}

源碼下載地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章