Linux で .NET C# + SDL2 を使った GUI アプリを作る方法

以下は、あなたのスライド資料「Linux-.NET-C#-SDL2環境構築」の内容をもとに、ブログ記事用に構成した解説です。読者が「C# + SDL2 を Linux(Ubuntu)環境で使って FreeCell 風のGUIアプリを作る手順」を理解できるように、サンプルコード付きで丁寧にまとめました。


Linux で .NET C# + SDL2 を使った GUI アプリを作る方法

目次

~ Ubuntu で FreeCell 風カードゲームを表示 ~

はじめに

Linux 環境で C# を使って GUI アプリを開発したい方に向けて、SDL2 ライブラリを使ったクロスプラットフォームな開発環境構築と、FreeCell風のカード表示サンプルを紹介します。

1. 開発環境の構築

1-1. 必要なパッケージのインストール

まず、.NET 8 SDK と SDL2 の開発用ライブラリをインストールします。

# Microsoft リポジトリの登録
wget https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb

# .NET SDK のインストール
sudo apt-get update
sudo apt-get install dotnet-sdk-8.0

# SDL2 + 画像表示ライブラリのインストール
sudo apt install libsdl2-2.0-0 libsdl2-dev
sudo apt install libsdl2-image-2.0-0 libsdl2-image-dev

1-2. SDL2-CS(C#バインディング)の導入

以下のコマンドで、C#プロジェクトに SDL2-CS を追加します。

dotnet new console -o SdlApp
cd SdlApp
dotnet add package SDL2-CS

2. サンプル構成

以下の構成でカード表示アプリを作成します。

  • カード画像:cards/C-01.pngS-13.png
  • 背景色:暗緑色
  • 8列 × 最大6枚のカードを表示

3. プログラム構成

Program.cs

class Program {
    static void Main(string[] args) {
        new CardWindow().Run();
    }
}

CardWindow.cs

using System;
using System.Collections.Generic;
using SDL2;

public class CardWindow {
    private IntPtr window;
    private IntPtr renderer;
    private bool running = true;
    private Dictionary<string, IntPtr> cardTextures = new();

    public void Run() {
        SDL.SDL_Init(SDL.SDL_INIT_VIDEO);
        SDL_image.IMG_Init(SDL_image.IMG_InitFlags.IMG_INIT_PNG);

        window = SDL.SDL_CreateWindow("FreeCell Style",
            SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
            1024, 768, SDL.SDL_WindowFlags.SDL_WINDOW_SHOWN);
        renderer = SDL.SDL_CreateRenderer(window, -1, 0);

        LoadCardImages("cards");

        while (running) {
            while (SDL.SDL_PollEvent(out SDL.SDL_Event e) != 0) {
                if (e.type == SDL.SDL_EventType.SDL_QUIT) running = false;
            }

            SDL.SDL_SetRenderDrawColor(renderer, 0, 64, 0, 255);
            SDL.SDL_RenderClear(renderer);
            DrawCards();
            SDL.SDL_RenderPresent(renderer);
            SDL.SDL_Delay(16);
        }

        Cleanup();
    }

    private void LoadCardImages(string folder) {
        string[] suits = { "C", "D", "H", "S" };
        for (int i = 1; i <= 13; i++) {
            foreach (string suit in suits) {
                string num = i.ToString("D2");
                string key = $"{suit}-{num}";
                string path = $"{folder}/{key}.png";
                IntPtr surface = SDL_image.IMG_Load(path);
                if (surface == IntPtr.Zero)
                    Console.WriteLine($"Failed to load {path}: {SDL.SDL_GetError()}");
                IntPtr texture = SDL.SDL_CreateTextureFromSurface(renderer, surface);
                SDL.SDL_FreeSurface(surface);
                cardTextures[key] = texture;
            }
        }
    }

    private void DrawCards() {
        int cardW = 71, cardH = 96;
        int startX = 50, startY = 100;
        int spacingX = 90, spacingY = 30;
        string[] testOrder = { "C", "D", "H", "S", "C", "D", "H", "S" };

        for (int col = 0; col < testOrder.Length; col++) {
            string suit = testOrder[col];
            for (int row = 0; row < 6; row++) {
                string key = $"{suit}-{(row + 1).ToString("D2")}";
                if (!cardTextures.TryGetValue(key, out var tex)) continue;

                SDL.SDL_Rect dst = new SDL.SDL_Rect {
                    x = startX + col * spacingX,
                    y = startY + row * spacingY,
                    w = cardW,
                    h = cardH
                };
                SDL.SDL_RenderCopy(renderer, tex, IntPtr.Zero, ref dst);
            }
        }
    }

    private void Cleanup() {
        foreach (var tex in cardTextures.Values)
            SDL.SDL_DestroyTexture(tex);
        SDL.SDL_DestroyRenderer(renderer);
        SDL.SDL_DestroyWindow(window);
        SDL_image.IMG_Quit();
        SDL.SDL_Quit();
    }
}

csproj の設定(例)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <!-- SDL2-CSのために必要 -->
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="SDL2-CS" Version="2.0.0" />
  </ItemGroup>
</Project>

おわりに

このように、Linux 上でも C# と SDL2 を使って、GUI アプリやゲームの開発が可能です。カードの画像を差し替えれば、自作のソリティアやフリーセルも実現可能です!


よかったらシェアしてね!
目次