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

    本博客文章版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    react 组件传值
    vue 子组件如何修改父组件data中的值??????????????????
    移动端的一些初始化 css 样式。。。
    centos7命令
    poi导出
    eclipse项目导入工作空间提示已存在问题
    maven jar包冲突问题
    layui下拉框渲染问题,以及回显问题
    两个线程交替运行——使用synchronized+wait+notify实现
    造成索引失效的情况
  • 原文地址:https://www.cnblogs.com/laolieren/p/make_sdl2_game_on_mac_with_csharp.html
Copyright © 2020-2023  润新知