自學程序加工作好幾年了,是時候來練個手了(不算用引擎開發遊戲)。之前Google學習資料的時候,找到一個彈幕射擊遊戲的教程,稍微瞄了眼,還挺不錯的,但用的是封裝的DxLib庫,這就不開心了,後面就沒看了。學習DirectX也有年頭了,覺得是時候可以練習下,但不打算用DirectX來開發,打算用最近剛學習的SDL或者SFML來開發。
爲了加大難度,就打算採用C++加Lua的方式來開發,不用第3方庫,全部自己手寫導出到Lua這邊,加深一下自己對C++和Lua的通信原理。
PS:之前有人聯繫我說,說看不懂,還說只有寫的人能看懂,還有讓我幫你來做功能的。我就奇了怪了,你自己基礎不到位,怪作者,爲啥不怨一下你自己不努力呢?
準備工作
IDE用的是Visual Stuido 2019,這個下載就不介紹了,版本很新,一直在推薦更新╮(╯▽╰)╭。接下來準備lua源碼和SDL庫。
Lua準備工作
去lua官網(https://www.lua.org/download.html)下載源代碼。
新建一個Visual Stuido空工程,空工程名爲Lua,將剛纔下的lua源碼解壓,解壓得到lua-5.3.5文件夾,將lua-5.3.5文件夾中的子文件夾src文件夾整個拷貝到剛建Lua空工程目錄下。在Solution Explorer(解決方案管理器)窗口選擇Lua工程,然後在Solution Explorer窗口的工具欄上點擊Show All Files按鈕。
然後就會看到剛纔拷貝過來的src文件夾。然後選擇src文件夾,右鍵點擊Include In Project(包含到工程中),然後在src文件中找到lua.c和luac.c文件,右鍵點擊Exclude In Project(從工程中排除)。
右鍵Lua工程,點擊屬性按鈕,先將EXE工程改成靜態庫工程。
接着修改Output Directory(輸出目錄)和Intermediate Directory(中間目錄),也可以不改,用默認的也可以,主要是這樣鏈接Lua庫比較方便。
Output Directory(輸出目錄):$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\
Intermediate Directory(中間目錄):$(SolutionDir)bin-int\$(Platform)\$(Configuration)\$(ProjectName)\
然後右鍵Lua工程編譯得到Lua.lib。Lua這邊的準備工作就已經完成了,接下來就是測試。
接着在同一個Solution下新建一個Visual Stuido空工程,空工程名爲Ryuujinn(日語名爲龍(りゅう)(
ryuu)神(じん)(jinn))。右鍵Ryuujinn工程添加新文件夾,命名爲Source,再在Source目錄下添加新文件Main.cpp(這個就不需要列出具體步驟吧)。
現在需要做的事,是鏈接Lua庫來測試。首先右鍵Ryuujinn工程,點擊屬性按鈕,修改Output Directory和Intermediate Directory,改成跟Lua工程一樣的,這個步驟上面有,就不再介紹了。
點擊屬性面板中左側的C/C++按鈕,選擇General(一般),然後在右側的Additional Include Directories(附加的包含目錄)中添加Include;$(SolutionDir)Lua\Src;Include指的是我等下會再建一個Include文件夾目錄,$(SolutionDir)Lua\Src指的是之前創建Lua工程下的拷貝過來的lua源碼目錄。
接着點擊屬性面板中左側的Linker(鏈接器)按鈕,選擇General(一般),然後在右側的Additional Library Directories(附加的庫目錄)中添加$(SolutionDir)bin\$(Platform)\$(Configuration)\Lua\;這個$(SolutionDir)bin\$(Platform)\$(Configuration)\Lua\就是前面Lua工程中Output Directory的目錄。之前說修改Output Directory和Intermediate Directory的方便就在這個地方。如果沒有修改的話,就需要自己去定位到靜態庫的生成目錄。
好了,鏈接Lua庫的大部分工作做完了,開始測試是否可以調用Lua。在之前添加的Main.cpp中添加如下代碼:
// 引入lua需要的頭文件
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
// 鏈接Lua工程生成的靜態庫
#pragma comment(lib, "Lua.lib")
#include <iostream>
int main()
{
// 創建虛擬棧
lua_State* L = luaL_newstate();
// 引入lua的標準庫,不然調用print會報錯,可以註釋掉代碼,查看報錯
luaL_openlibs(L);
// 很簡單的lua代碼,輸出Hello, lua
const char* strLuaScript = R"(
print("Hello, lua")
)";
// 執行lua代碼
int result = luaL_dostring(L, strLuaScript);
if (LUA_OK != result)
std::cout << lua_tostring(L, -1) << std::endl;
else
{
}
// 關閉虛擬棧
lua_close(L);
system("pause");
return 0;
}
代碼中註釋很多,就不一一解釋了,如果想要仔細瞭解C++調用Lua,可以通過百度和Google搜索文章看,也可以通過搜視頻看,國內有一個還可以,但是需要付費,也不貴(60多),但我就不列出具體網址了,國外的我在看,講的很不錯,英文不錯的可以看下,網址在這裏,需要科學上網,最近有個測試的酷鳥瀏覽器是可以科學上網看的(用過,比較差,經常打不開,或者看到一半就掛了,勉強能用)
如果輸出了Hello, lua就說明lua配置沒有問題。lua配置就到此結束了,接下來就是SDL的配置了。
SDL準備工作
去SDL官網(https://www.libsdl.org/download-2.0.php)下載Development Libraries。還需SDL的擴展庫SDL_Image,去該網址下載(https://www.libsdl.org/projects/SDL_image/)Development Libraries。
將下載的2個文件都解壓,放到自己喜歡的硬盤下,接下來配置環境變量,因爲我存放到D盤下,文件名爲_SDL2-2.0.10和_SDL2_image-2.0.5,因此我的環境變量是
SDL_IncludePath: "D:_SDL2-2.0.10\include"
SDL_LibraryPath: "D:_SDL2-2.0.10\lib"
SDL_Image_IncludePath: "D:_SDL2_image-2.0.5\include"
SDL_Image_LibraryPath: "D:_SDL2_image-2.0.5\lib"
win7只能截成這樣了,win10的話就會好一點。環境變量生效的話需要重啓Visual Studio 2019,如果不生效,就關閉explorer.exe,再不行就重啓電腦就OK。
跟之前配置Lua一樣,在Ryuujinn工程的屬性面板上添加剛配置好的環境變量就OK:Additional Include Directories(附加的包含目錄)再添加$(SDL_IncludePath);$(SDL_Image_IncludePath)。
Additional Library Directories(附加的庫目錄)就需要特殊處理下,要根據平臺來處理:
32位(Win32)添加$(SDL_LibraryPath)\x86;$(SDL_Image_LibraryPath)\x86;
64位(x64)添加$(SDL_LibraryPath)\x64;$(SDL_Image_LibraryPath)\x64;
還需要一步處理,也是需要根據平臺來,在Ryuujinn工程的屬性面板點擊左側的Build Events(編譯事件),接着點擊Build Events下方的Pre-Build Evnet(預編譯事件),在屬性面板右側的Command Line(命令行)中點擊,會彈出Edit(編輯)按鈕,點擊後會彈出一個窗口,接下來填入需要處理的命令。
32位(Win32)添加
XCOPY "$(SDL_LibraryPath)\x86\*.dll" "$(TargetDir)" /D /K /Y
XCOPY "$(SDL_Image_LibraryPath)\x86\*.dll" "$(TargetDir)" /D /K /Y
64位(x64)添加
XCOPY "$(SDL_LibraryPath)\x64\*.dll" "$(TargetDir)" /D /K /Y
XCOPY "$(SDL_Image_LibraryPath)\x64\*.dll" "$(TargetDir)" /D /K /Y
這2句命令的主要功能就是將之前下載下來的SDL和SDL_Image目錄中的DLL拷貝到Ryuujinn工程的生成目錄中而已。
SDL配置也已經結束了,接下來在之前Lua測試代碼中添加SDL測試代碼來測試:
新的Main.cpp:
// 引入lua需要的頭文件
extern "C"
{
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
}
// 鏈接Lua工程生成的靜態庫
#pragma comment(lib, "Lua.lib")
#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")
#include <iostream>
int main()
{
// 創建虛擬棧
lua_State* L = luaL_newstate();
// 引入lua的標準庫,不然調用print會報錯,可以註釋掉代碼,查看報錯
luaL_openlibs(L);
// 很簡單的lua代碼,輸出Hello, lua
const char* strLuaScript = R"(
print("Hello, lua")
)";
// 執行lua代碼
int result = luaL_dostring(L, strLuaScript);
if (LUA_OK != result)
std::cout << lua_tostring(L, -1) << std::endl;
else
{
}
// 關閉虛擬棧
lua_close(L);
if (0 != SDL_Init(SDL_INIT_EVERYTHING))
return -1;
int flags = 0;
SDL_Window* pWindow = SDL_CreateWindow("Test", 100, 100, 500, 500, flags);
if (!pWindow)
return -1;
SDL_Renderer* pRenderer = SDL_CreateRenderer(pWindow, -1, 0);
SDL_SetRenderDrawColor(pRenderer, 255, 255, 255, 255);
if (!pRenderer)
return -1;
while (1);
SDL_DestroyWindow(pWindow);
SDL_DestroyRenderer(pRenderer);
SDL_Quit();
system("pause");
return 0;
}
彈出如下窗口,就說明SDL配置成功,但新加的代碼是沒有測試SDL_Image的配置是否成功的,因爲基本差不多,但是要加測試代碼,就不是這麼一點了,還得找資源就有點麻煩了,可以自行上網搜索添加代碼測試。
如果有下圖編譯失敗的,看是不是這個錯誤,這個錯誤的原因是SDL修改了main函數(#define main SDL_main),這個可以在SDL_main.h頭文件中可以查看,解決這個錯誤有多個方法,這邊就採取最簡單的,看是不是沒有添加#define SDL_MAIN_HANDLED,或者這個是否在#include <SDL.h>之前。
好了,Lua和SDL的配置大體完成了,可以舒一口氣了。