• 在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这些扩展库还没用到,到时候再遇到报错,相信你也可以举一反三,一一解决吧?

    本博客文章版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    UVa 116 单向TSP(多段图最短路)
    POJ 1328 Radar Installation(贪心)
    POJ 1260 Pearls
    POJ 1836 Alignment
    POJ 3267 The Cow Lexicon
    UVa 1620 懒惰的苏珊(逆序数)
    POJ 1018 Communication System(DP)
    UVa 1347 旅行
    UVa 437 巴比伦塔
    UVa 1025 城市里的间谍
  • 原文地址:https://www.cnblogs.com/laolieren/p/make_sdl2_game_on_mac_with_csharp.html
Copyright © 2020-2023  润新知