[實戰]C++加Lua加SDL來重寫龍神錄彈幕遊戲(3):添加Logger類

       上一篇已經完成了Lua調用SDL創建窗口的功能了,めでたしめでたし。但在開始敲遊戲代碼之前,繼續做一個準備工作,添加C++類logger。
       在之前的測試中,控制檯上全是白色的輸出字,一眼望過去,全是一樣,調試的時候很難找到自己想要查看的輸出。繼續在Ryuujinn工程中添加頭文件Logger.h和Logger.cpp文件,在Source文件夾下的Wrap文件中添加LoggerWrap.cpp,沒錯,Logger也要導出到Lua中。
Logger.h

#pragma once

class Logger
{
public:
	/**
	 * 在控制檯上輸出紅色的信息
	 */
	static void LogError(const char* fmt, ...);
	/**
	 * 在控制檯上輸出黃色的信息
	 */
	static void LogWarning(const char* fmt, ...);
	/**
	 * 在控制檯上輸出白色的信息
	 */
	static void Log(const char* fmt, ...);

	/**
	 * 修改控制檯上輸出信息的顏色爲紅色
	 */
	static void SwtichColorToRed();
	/**
	 * 修改控制檯上輸出信息的顏色爲黃色
	 */
	static void SwitchColorToYellow();
	/**
	 * 修改控制檯上輸出信息的顏色爲白色
	 */
	static void SwitchColorToWhite();
};

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

Logger.cpp

#include "Logger.h"
#include <stdarg.h>
#include <string>
#include <iostream>
#include <Windows.h>

void Logger::LogError(const char* fmt, ...)
{
	va_list arg;
	va_start(arg, fmt);
	char msg[1024] = { 0 };
	vsprintf_s(msg, 1024, fmt, arg);
	va_end(arg);

	SwtichColorToRed();
	std::cout << msg << std::endl;
	SwitchColorToWhite();
}

void Logger::LogWarning(const char* fmt, ...)
{
	va_list arg;
	va_start(arg, fmt);
	char msg[1024] = { 0 };
	vsprintf_s(msg, 1024, fmt, arg);
	va_end(arg);

	SwitchColorToYellow();
	std::cout << msg << std::endl;
	SwitchColorToWhite();
}

void Logger::Log(const char* fmt, ...)
{
	va_list arg;
	va_start(arg, fmt);
	char msg[1024] = { 0 };
	vsprintf_s(msg, 1024, fmt, arg);
	va_end(arg);

	std::cout << msg << std::endl;
}

void Logger::SwtichColorToRed()
{
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(hConsole, FOREGROUND_RED);
}

void Logger::SwitchColorToYellow()
{
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN);
}

void Logger::SwitchColorToWhite()
{
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}

       代碼實現很簡單,就是修改控制檯顏色而已,3個輸出函數,3個修改顏色函數,也沒啥好說的。剛好把之前的輸出信息全部替換成Logger中的方法,之前LuaClient中打印堆棧的函數,調用std::cout太多次,不做任何改動,只是在函數執行最開始調用修改顏色函數,將堆棧信息改成黃色。
LoggerWrap.cpp

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

int SwtichColorToRed(lua_State* L)
{
	Logger::SwtichColorToRed();

	return 0;
}

int SwitchColorToYellow(lua_State* L)
{
	Logger::SwitchColorToYellow();

	return 0;
}

int SwitchColorToWhite(lua_State* L)
{
	Logger::SwitchColorToWhite();

	return 0;
}

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

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

	return 1;
}

int LoggerSet(lua_State* L)
{
	luaL_getmetatable(L, "LoggerMetaTable");
	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::RegisterLogger(lua_State* L)
{
	if (!L) return;

	lua_newtable(L);

	luaL_newmetatable(L, "LoggerMetaTable");
	lua_pushstring(L, "__index");
	lua_pushcfunction(L, LoggerGet);
	lua_rawset(L, -3);

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

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

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

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

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

       這次並沒有把所有函數全部導出到lua中,因爲可變參數不太好實現,google也沒搜到比較好的解決方案,所以3個輸出函數就沒有導出。但還是想要這個輸出功能,只好在lua稍作改動,在Script文件夾中添加Logger.lua腳本。
Logger.lua

Logger.LogError = function(fmt, ...)
	Logger.SwtichColorToRed()
	print(string.format(fmt, ...))
	Logger.SwitchColorToWhite()
end

Logger.LogWarning = function(fmt, ...)
	Logger.SwitchColorToYellow()
	print(string.format(fmt, ...))
	Logger.SwitchColorToWhite()
end

Logger.Log = function(fmt, ...)
	print(string.format(fmt, ...))
end

       代碼實現還是很簡單,利用lua的print函數來實現,而且因爲C++那邊設置過lua表只會給函數賦值一次的功能,也就表示不能重載Logger.LogError,Logger.LogWarning及Logger.Log函數等。
修改Main.lua測試:

require "Logger"

function Main()
	Logger.Log("Main")
	--將16進制字符串轉換成10進制數字
	local flag = "00000020"
	flag = tonumber(flag, 16)

	Renderer.Init(flag)
	--這裏需要設置lua查找路徑
	gGame = require("Game")
	gGame.pSDLWindow = Renderer.CreateWindow("Test", 100, 100, 500, 500, 0)
	gGame.pSDLRenderer = Renderer.CreateRenderer(gGame.pSDLWindow, -1, 0)
	
	--while循環中添加print函數是爲了避免執行太快,窗口一閃而過
	local count = 1
	while count < 10000 do
		count = count + 1
		--Logger.LogError(count)
	end
	
	Renderer.DestroyRenderer(gGame.pSDLRenderer)
	Renderer.DestroyWindow(gGame.pSDLWindow)
	Renderer.Quit()

	Logger.LogError("%s is %d, have %f", "jack", 18, 990.0011)
	Logger.LogWarning("%s is %d, have %f", "jack", 18, 990.0011)
	Logger.Log("%s is %d, have %f", "jack", 18, 990.0011)
end

       得到如下結果,說明添加logger類成功。

源碼下載地址

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