在mac環境下用c#進行SDL2游戲開發


雖然筆者是在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,把相關的dlldylib都放到里面去。

項目一樣可以運行!目錄還合理一些了,何樂而不為?

最后項目目錄在Rider中如下所示:

  • 最上面的SDL名字可以無視,不影響運行的,如果按照我的步驟做,你可能叫做SDL2_TEST
  • 我多了個README.md文件,這是我自己建的,因為我凡事喜歡做筆記...

留個尾巴,自我拓展

這個例子只用到了sdl2核心庫,但是sdl2_img這些擴展庫還沒用到,到時候再遇到報錯,相信你也可以舉一反三,一一解決吧?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM