👾

raylibを試す

2022/08/21に公開

raylib

「ビデオゲームプログラミングを楽しむためのシンプルで使い勝手の良いライブラリ」
のraylibを試してみました!
WebAssemblyにも対応していたりするので、今回はサンプルアプリをデスクトップアプリ(mac)とWebアプリとして動作させ、基本的な図形表示する所まで試して見ました。

試した環境

$ sw_vers
ProductName:	macOS
ProductVersion:	12.4
BuildVersion:	21F79

raylib architecture

raylibは以下の7つのmoduleから構成されているようです。

  1. rcore: Window / Graphic Context / Inputsの管理module
  2. rlgl: OpenGL APIをラップしたIFを提供するmodule
  3. rtextures: テクスチャ/画像の読み込みと管理を行うmodule
  4. rtext: フォントデータの読み込みとテキストの描画を行うmodule
  5. rshapes: 基本的な2D描画を行うmodule
  6. rmodels: 3Dモデルの読み込みと描画を行うmodule
  7. raudio: オーディオデバイスの管理、サウンド/音楽の読み込みと再生を行うmodule

また主要な7つのmoduleの他に以下のサブmoduleも存在します。

  1. raymath: Vector2、Vector3、Matrix、Quaternion等のmath関連module
  2. rcamera: 3D空間でのカメラ関連module
  3. rgestures: タッチジェスチャーの検出と処理を行うmodule
  4. raygui: ツール開発のためのいくつかのコントロールを備えたシンプルなIMGUIシステムmodule
  5. easigns: こちらをベースにしたアニメーションのEasing機能module

テキストの描画や、3D関連、IMGUIなど、とても充実している印象です ✨

環境設定

Homebrewでraylibがインストールできるので、インストールしておきます。

$ brew install raylib

Working on macOS · raysan5/raylib Wiki

サンプルを動かしてみる

raysan5/raylib-game-template: A small template to start your raylib game

早速↑をcloneしてきて、以下を実行します。

$ cd raylib-game-template/src
$ make

warningが出るかもですが、一旦スキップで raylib_game が作成されていればOKです。
実行してみると、↓のような画面が立ち上がるかと思います。

$ ./raylib_game

WebAssemblyコンパイル + 実行してみる

次にraylibをWebAssemblyで出力してWebブラウザで表示してみます。
Working for Web (HTML5) · raysan5/raylib Wiki
↑のチュートリアルに沿って進めて行きたいと思います。

1. Install emscripten toolchain

Web向けにraylibでは Emscripten でWebAssemblyにコンパイルしているようです。
早速Emscriptenをインストールしていきます。
emscripten-core/emsdk: Emscripten SDK

※ macosの場合の条件
Download and install — Emscripten 3.1.19-git (dev) documentation

- macOS 10.14 Mojave以降が必要
- 以下がインストールされている必要がある
    - Xcode Command Line Tools
    - git
    - cmake
インストール手順
$ git clone https://github.com/emscripten-core/emsdk.git
$ cd emsdk
$ ./emsdk install latest
$ ./emsdk activate latest
$ source ./emsdk_env.sh

上記コマンドを実行していくと、自身の環境だとビルド時に以下エラーが発生しました。

Error: Downloading URL 'https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-darwin-x64.tar.gz': <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)>
Warning: Possibly SSL/TLS issue. Update or install Python SSL root certificates (2048-bit or greater) supplied in Python folder or https://pypi.org/project/certifi/ and try again.
error: installation failed!

こちら を参考に emsdk.py に以下を追加し再実行します。

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

再度以下のコマンドで実行してやると、自分の環境ではうまくインストールできました ✨

$ python3 ./emsdk.py install latest
$ python3 ./emsdk.py activate latest
$ source ./emsdk_env.sh

2. Compile raylib library

次にraylibライブラリをHTML5用にコンパイルし、libraylib.aを生成する必要があるので、コンパイルしていきます。
raylibのリポジトリをクローンし、こちらを参考に libraylib.a を作成します。

$ git clone git@github.com:raysan5/raylib.git
$ cd raylib/src
$ emcc -c rcore.c -Os -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2
$ emcc -c rshapes.c -Os -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2
$ emcc -c rtextures.c -Os -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2
$ emcc -c rtext.c -Os -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2
$ emcc -c rmodels.c -Os -Wall -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2
$ emcc -c utils.c -Os -Wall -DPLATFORM_WEB
$ emcc -c raudio.c -Os -Wall -DPLATFORM_WEB

$ emar rcs libraylib.a rcore.o rshapes.o rtextures.o rtext.o rmodels.o utils.o raudio.o

4. Compile raylib game for web

raylib-game-template/src/Makefile をWebアプリとしてコンパイルする際に必要な EMSDK_PATH を設定します
EMSDKsource ./emsdk_env.sh 実行時に設定される環境変数です。

ifeq ($(PLATFORM),PLATFORM_WEB)
    # Emscripten required variables
    EMSDK_PATH         ?= $(EMSDK) # ⇐ ここを修正!!
    EMSCRIPTEN_PATH    ?= $(EMSDK_PATH)/upstream/emscripten
    CLANG_PATH          = $(EMSDK_PATH)/upstream/bin
    PYTHON_PATH         = $(EMSDK_PATH)/python/3.9.2-1_64bit
    NODE_PATH           = $(EMSDK_PATH)/node/14.15.5_64bit/bin
    export PATH         = $(EMSDK_PATH);$(EMSCRIPTEN_PATH);$(CLANG_PATH);$(NODE_PATH);$(PYTHON_PATH):$$(PATH)
endif

準備ができたら、make PLATFORM=PLATFORM_WEB -e でコンパイルしていきます。無事コンパイルができれば以下が作成されていればOKです。

.
├── raylib_game.data
├── raylib_game.html
├── raylib_game.js
├── raylib_game.wasm

5. Test raylib game on web

ここまで出来たらローカルにWebサーバーを立ち上げてブラウザで確認してみます。
raylib-game-template/src で以下コマンドを実行します。

$ python3 -m http.server 8080

ブラウザで http://localhost:8080/raylib_game.html にアクセスし以下のように表示されればOKです ✨


一旦最小限の構成にする

サンプルを動作させる事ができたので、ここで色々試せるように一旦最小限の構成にしてみます。
raylib-game-template/src/raylib_game.c のみしか使わないので、Makefileの PROJECT_SOURCE_FILES を以下に修正します。

PROJECT_SOURCE_FILES ?= \
    raylib_game.c

他のファイル(*.c)をコンパイル対象から削除しています。
次に raylib_game.c を以下に修正します。

#include "raylib.h"
#if defined(PLATFORM_WEB)
    #include <emscripten/emscripten.h>
#endif

void UpdateDrawFrame(void)
{
    BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawText("Hello World!", 190, 200, 20, BLACK);
    EndDrawing();
}

int main(void)
{
    InitWindow(800, 450, "raylib");

#if defined(PLATFORM_WEB)
    emscripten_set_main_loop(UpdateDrawFrame, 60, 1);
#else
    SetTargetFPS(60);
    while (!WindowShouldClose())
    {
        UpdateDrawFrame();
    }
#endif

    CloseWindow();

    return 0;
}

↑をコンパイルして実行してやると↓の様な画面が表示されるはずです。

# デスクトップ用にコンパイル
$ make -e
# Webアプリ用にコンパイル
$ make PLATFORM=PLATFORM_WEB -e

様々な図形を表示させてみる

試しに矩形や円、線、三角形などを表示させてみたいと思います。
関連するmoduleとしては rshapes になります。

矩形表示

DrawRectangle* 関数を使います。定義はこちら

void DrawRectangles(void)
{
    DrawRectangle(100, 50, 120, 60, RED); // 塗りつぶした矩形表示
    DrawRectangleLines(100, 150, 120, 60, BLUE); // 枠線の矩形表示
    DrawRectangleGradientV(100, 250, 120, 60, MAROON, ORANGE); // 縦方向のグラデーション
    Rectangle rec = { 100, 350, 120, 60 };
    DrawRectangleRounded(rec, 0.2f, 0, LIGHTGRAY); // 角丸矩形
}

void UpdateDrawFrame(void)
{
    BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawRectangles(); // 変更!
    EndDrawing();
}

円表示

DrawCircle* 関数を使います。定義はこちら

void DrawCircles(void)
{
    DrawCircle(100, 100, 20.0f, RED); // 塗りつぶした円表示
    Vector2 center = { 200, 100 };
    DrawCircleSector(center, 20.0f, 0.0f, 180.0f, 10, BLUE); // 円の一部を表示
    DrawCircleGradient(300, 100, 20.0f, MAROON, ORANGE); // 円の外側から中心部方向へのグラデーション
    DrawCircleLines(400, 100, 20.0f, LIGHTGRAY); // 円を外側の線で表示
}

void UpdateDrawFrame(void)
{
    BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawCircles(); // 変更!
    EndDrawing();
}

線表示

DrawLine* 関数を使います。定義はこちら

void DrawLines(void)
{
    DrawLine(10, 10, 210, 10, RED); // 線表示
    {
        Vector2 startPos = { 10, 50 };
        Vector2 endPos = { 210, 50 };
        DrawLineEx(startPos, endPos, 20, BLUE); // 太さ指定して線表示
    }
    {
        Vector2 startPos = { 10, 100 };
        Vector2 endPos = { 210, 120 };
        DrawLineBezier(startPos, endPos, 10, MAROON); // ベジェ曲線 ease-in-out
    }
    {
        Vector2 vecs[] = {{ 10, 150 }, {50, 160}, {100, 145}, {210, 150}};
        DrawLineStrip(vecs, 4, ORANGE); // 複数の点を指定
    }
}

void UpdateDrawFrame(void)
{
    BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawLines(); // 変更!
    EndDrawing();
}

三角形表示

DrawTriangle* 関数を使います。定義はこちら

void DrawTriangles(void)
{
    {
        Vector2 v1 = { 60, 10 };
        Vector2 v2 = { 10, 100 };
        Vector2 v3 = { 100, 100 };
        DrawTriangle(v1, v2, v3, RED); // 3点を指定して三角形表示
    }
    {
        Vector2 vecs[] = {{ 60, 110 }, { 10, 200 }, { 100, 200 }, { 120, 150 }};
        DrawTriangleFan(vecs, 4, BLUE); // 3角形の線上以外を指定した場合は多角形として表示される
    }
    {
        Vector2 vecs[] = {{ 60, 210 }, { 10, 300 }, { 100, 300 }, { 120, 250 }};
        DrawTriangleStrip(vecs, 4, ORANGE); // 3角形の線上以外を指定した場合は無視される
    }
}

void UpdateDrawFrame(void)
{
    BeginDrawing();
        ClearBackground(RAYWHITE);
        DrawTriangles(); // 変更!
    EndDrawing();
}

VSCodeの設定を行う (おまけ:必要あれば)

開発をスムーズに行う為に、以下のExtensionをインストールしておきます。

バッドノウハウ

デスクトップアプリをコンパイル中に以下エラーが出る

ld: warning: ignoring file ../../raylib/src/libraylib.a, building for macOS-x86_64
but attempting to link with file built for unknown-unsupported file format

Webアプリで動かす為に作成した raylib/src/libraylib.a を参照している為、Makefileの以下項目をコメントアウトするとwarningは出るが、コンパイルはできるようになります。

# RAYLIB_PATH           ?= ../../raylib

まとめ

個人的な印象ですが、Raspberry Piみたいに、ちょっとした趣味や教育などでも使えそうな印象でした ✨ 有志によって他の言語に移植したものもあるみたいなので、好きな言語でちょっと試してみる事もできそうです。

参考URL

Discussion