雖然筆者是在Rider下實現的,不過VS下也是可以用的
最近為了折騰這SDL2,可是廢了點時間,嘗試用C/C++/Go/C#進行開發,結果發現:
- C/C++環境好設置,但是cmake配置麻煩(對於沒用過的我來說),而且我受夠了引入文件總要include
- Go最省心,go mod包管理永遠的神!sdl2庫的api封裝也是用起來最舒服的
- C#在windows下很方便,但是切到mac就各種毛病,奈何C#做游戲太香了,寫好了核心類庫,以后port到unity也方便。
C#在mac下用SDL2開發游戲,在油管和各種論壇上有好多帖子,但是沒有一篇能讓我真正運行起來,看到窗口的,着實有點勸退...
幾番探索下,我終於成功了,這里給大家分享下,希望至少能省下下大伙半天時間...
話不多說,開始吧!
創建項目
咱們先不依賴任何編譯器,這樣好多參數也就不用選了,方便大家有統一的環境。
咱們用命令來創建項目
創建項目目錄
項目名稱SDL2_TEST
$ mkdir SDL2_TEST
$ cd SDL2_TEST
用命令創建項目
$ dotnet new console
結果發現報錯,該命令不存在,可是咱們可是安裝了dotnet的,咋回事?
原來這個命令躲在其他地方,我們要鏈接下
$ ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/
再次運行,發現可以了。
$ dotnet new console
利用homebrew安裝sdl2
其實我另一篇文章提到了怎么做,一客不煩二主,直接一篇文章搞定吧!
依次執行下面的命令就好了
- 安裝國內鏡像的Homebrew,一路往下YES就行
$ /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
- 安裝sdl2
$ brew install sdl2 sdl2_image sdl2_mixer sdl2_net sdl2_ttf
- 查看下sdl2庫安裝情況
$ brew info sdl2
根據安裝的版本不同,可能得到不同的信息,下面是我的
sdl2: stable 2.0.16 (bottled), HEAD
Low-level access to audio, keyboard, mouse, joystick, and graphics
https://www.libsdl.org/
/usr/local/Cellar/sdl2/2.0.16 (91 files, 5.4MB) *
Poured from bottle on 2021-08-27 at 05:51:01
From: https://mirrors.ustc.edu.cn/homebrew-core.git/Formula/sdl2.rb
License: Zlib
==> Options
--HEAD
Install HEAD version
==> Analytics
install: 107,393 (30 days), 219,217 (90 days), 957,010 (365 days)
install-on-request: 10,041 (30 days), 19,802 (90 days), 91,778 (365 days)
build-error: 0 (30 days)
下載SDL2-CS庫
上面裝的是sdl2庫本尊,下面我們需要安裝調用其功能的C#庫。
SDL2-CS
是一個c#中SDL2庫的一個封裝,直接用nuget下載這個庫是可行的,不過咱們這里直接引入源文件:
接着上文,我們現在處於項目根目錄中
$ mkdir sdl
$ cd sdl
用wget下載文件
這里你直接把SDL2-CS項目中的
src
目錄下文件下載到我們根目錄也是可以的
$ wget https://github.com/flibitijibibo/SDL2-CS/raw/master/src/SDL2.cs
$ wget https://github.com/flibitijibibo/SDL2-CS/raw/master/src/SDL2_image.cs
$ wget https://github.com/flibitijibibo/SDL2-CS/raw/master/src/SDL2_mixer.cs
$ wget https://github.com/flibitijibibo/SDL2-CS/raw/master/src/SDL2_ttf.cs
$ wget https://github.com/flibitijibibo/SDL2-CS/raw/master/src/LPUtf8StrMarshaler.cs
回到項目根目錄,嘗試着運行一下:
$ cd ../
$ dotnet run
收到報錯不安全代碼只會在使用 /unsafe 編譯的情況下出現
啟用unsafe
上面的報錯,咱們啟用unsafe就好了。
編輯SDL2.csproj
文件,增加下面的文本
SDL2.csproj
這個文件,你用rider默認看不到的,簡單點就用vscode或者任意編譯器打開項目,就能看到這個文件了
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
這樣以來文件內容就變成了
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
項目轉為dotcore
我個人習慣用dotcore開發,所以可以修改上面的SDL2.csproj
文件
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
編輯Program.cs
內容修改為
using System;
using SDL2;
namespace SDL2_TEST
{
class Program
{
static void Main(string[] args)
{
SDL.SDL_Init(SDL.SDL_INIT_VIDEO);
SDL.SDL_Quit();
}
}
}
運行一下
$ dotnet run
看到報錯,說是不存在SDL2.dll
Unhandled exception. System.DllNotFoundException: Unable to load shared library 'SDL2.dll'
下載dll
於是咱們從官網下載了SDL2.dll
,並且放到了根目錄,還把屬性設置為始終復制
,然而,還是沒用。
於是求助了萬能的谷歌,到官網找到了這樣的一個帖子how-to-setup-sdl-with-c-bindings-in-visual-studio-for-mac,
文字內容很多,咱們挑簡要的說,意思就是 :
- 咱們在
mac
下用的netcore 3.1
項目用的dll不應該是SDL2.dll
,應該是SDL2.dylib
那么SDL2.dylib
在哪兒呢?
尋找SDL2.dylib
這個文件是存在的,只不過不叫這個名字。
我們去這里找:
$ cd /usr/local/lib
$ open .
找到libSDL2.dylib
, 右鍵,顯示原身,這文件就是我們要的。
復制到根目錄
我們直接在原位置修改名字不合適,我們可以復制一份到項目根目錄再修改:
- 將上面的文件復制到項目的根目錄,然后設置屬性為
始終復制
再次嘗試運行,發現還是失敗?!
$ dotnet run
同時尋找dll和dylib
這次不賣官子了,直接查看源代碼sdl/SDL2.cs
發現這么一行
private const string nativeLibName = "SDL2.dll";
寫死了尋找dll
文件,我們可以去掉這個dll
后綴,這樣既可以尋找dll
文件,也可以尋找dylib
了。
我們改成
private const string nativeLibName = "SDL2";
再次運行,成了!
$ dotnet run
但是什么窗口都沒看到,不行,必須看到窗口才算結束!
我們要看到窗口!
別說了,把Program.cs內容換成這個,再次運行就看到窗口了
using System;
using SDL2;
namespace SDL2_TEST
{
class Program
{
static void Main(string[] args)
{
SDL.SDL_Init(SDL.SDL_INIT_VIDEO);
IntPtr window = SDL.SDL_CreateWindow("測試窗口",
SDL.SDL_WINDOWPOS_CENTERED,
SDL.SDL_WINDOWPOS_CENTERED,
640,
320,
SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE);
IntPtr renderer = SDL.SDL_CreateRenderer(window, -1, 0);
SDL.SDL_RenderSetScale(renderer, 10.0f, 10.0f); // Render a pixels 10 times bigger than they actually actually are
SDL.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL.SDL_RenderClear(renderer);
SDL.SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
for (int x = 0; x < 64; x++)
{
SDL.SDL_RenderDrawPoint(renderer, x, x / 2);
}
SDL.SDL_RenderPresent(renderer);
// "Game Loop"
SDL.SDL_Event e;
bool quit = false;
while (!quit)
{
while (SDL.SDL_PollEvent(out e) != 0)
{
switch (e.type)
{
case SDL.SDL_EventType.SDL_QUIT:
quit = true;
break;
case SDL.SDL_EventType.SDL_KEYDOWN:
switch (e.key.keysym.sym)
{
case SDL.SDL_Keycode.SDLK_q:
quit = true;
break;
}
break;
}
}
}
SDL.SDL_DestroyRenderer(renderer);
SDL.SDL_DestroyWindow(window);
SDL.SDL_Quit();
}
}
}
這次是真的成了!
最后一點優化
把所有類庫放在根目錄着實有點不雅,我們要做優雅的程序員,要學會目錄管理,於是,我們新建目錄lib
,把相關的dll
和dylib
都放到里面去。
項目一樣可以運行!目錄還合理一些了,何樂而不為?
最后項目目錄在Rider中如下所示:
- 最上面的
SDL
名字可以無視,不影響運行的,如果按照我的步驟做,你可能叫做SDL2_TEST
- 我多了個
README.md
文件,這是我自己建的,因為我凡事喜歡做筆記...
留個尾巴,自我拓展
這個例子只用到了sdl2
核心庫,但是sdl2_img
這些擴展庫還沒用到,到時候再遇到報錯,相信你也可以舉一反三,一一解決吧?