LoginSignup
11
10

More than 5 years have passed since last update.

「プログラムでシダを描画する」をD言語+SDL2+dubで描画する

Last updated at Posted at 2014-06-05

空前のシダブームということで、私もD言語とSDL2.0でシダを描いてみました。

元ネタ

ソースコード

source/app.d
module dshida.main;

import std.c.string;
import std.exception;
import std.random;
import std.stdio;
import std.string;

import derelict.sdl2.sdl;

/// ウィンドウの幅
enum WIDTH = 640;

/// ウィンドウの高さ
enum HEIGHT = 640;

/// ウィンドウタイトル
immutable TITLE = "D Shida";

/// 再帰レベル
enum N = 20;

/// 背景色
enum BackColor : Uint8 {
    R = Uint8.max,
    G = Uint8.max,
    B = Uint8.max,
    A = Uint8.max,
}

/// 描画色
enum PlotColor : Uint8 {
    R = 0,
    G = Uint8.max,
    B = 0,
    A = Uint8.max,
}

/// 描画用スケール・オフセット
enum {
    SCALE_X = WIDTH,
    SCALE_Y = -HEIGHT,
    OFFSET_X = WIDTH / 2,
    OFFSET_Y = HEIGHT
}

/// 座標変換関数
auto transform(alias A, alias B, alias C)(typeof(A) x, typeof(A) y) {
    return A * x + B * y + C;
}

alias transform!( 0.836,  0.044,    0.0  ) W1x;
alias transform!(-0.044,  0.836,    0.169) W1y;
alias transform!(-0.141,  0.302,    0.0  ) W2x;
alias transform!( 0.302,  0.141,    0.127) W2y;
alias transform!( 0.141, -0.302,    0.0  ) W3x;
alias transform!( 0.302,  0.141,    0.169) W3y;
alias transform!( 0.0,    0.0,      0.0  ) W4x;
alias transform!( 0.0,    0.175337, 0.0  ) W4y;

/// 描画関数
void f(alias plot)(size_t k, double x, double y) {
    if(0 < k) {
        f!plot(k - 1, W1x(x, y), W1y(x, y));
        if(uniform(0, 3) == 0) f!plot(k - 1, W2x(x, y), W2y(x, y));
        if(uniform(0, 3) == 0) f!plot(k - 1, W3x(x, y), W3y(x, y));
        if(uniform(0, 3) == 0) f!plot(k - 1, W4x(x, y), W4y(x, y));
    } else {
        plot(x, y);
    }
}

/// SDLのロード
static this() {
    DerelictSDL2.load();
}

/// メイン関数
void main() {
    // SDL初期化
    enforceSdl(SDL_Init(SDL_INIT_EVERYTHING) == 0);
    scope(exit) SDL_Quit();

    // ウィンドウの生成・表示
    auto window = enforceSdl(SDL_CreateWindow(
            toStringz(TITLE),
            SDL_WINDOWPOS_UNDEFINED,
            SDL_WINDOWPOS_UNDEFINED,
            WIDTH,
            HEIGHT,
            SDL_WINDOW_SHOWN));
    scope(exit) SDL_DestroyWindow(window);

    // レンダラーの生成
    auto renderer = enforceSdl(SDL_CreateRenderer(
            window,
            -1,
            SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC));
    scope(exit) SDL_DestroyRenderer(renderer);

    // 画面クリア
    SDL_SetRenderDrawColor(
            renderer,
            BackColor.R,
            BackColor.G,
            BackColor.B,
            BackColor.A);
    enforceSdl(SDL_RenderClear(renderer) == 0);

    // 点の描画用関数
    void plot(double x, double y) {
        SDL_RenderDrawPoint(renderer, cast(int)(x * SCALE_X + OFFSET_X), cast(int)(y * SCALE_Y + OFFSET_Y));
    }

    // 描画実行
    SDL_SetRenderDrawColor(
            renderer,
            PlotColor.R,
            PlotColor.G,
            PlotColor.B,
            PlotColor.A);
    f!plot(N, 0.0, 0.0);
    SDL_RenderPresent(renderer);

    // イベントループ
    mainLoop: for(SDL_Event event; SDL_WaitEvent(&event);) {
        switch(event.type) {
            // マウスボタンクリックやウィンドウクローズで終了
            case SDL_MOUSEBUTTONDOWN:
            case SDL_QUIT:
                break mainLoop;
            default:
                break;
        }
    }
}

/**
 *  SDLのエラーメッセージの取得
 *
 *  Returns:
 *      SDLのエラーメッセージ。エラーが無ければnull。
 */
@trusted string getSdlMessage() {
    if(auto msg = SDL_GetError()) {
        return msg[0 .. strlen(msg)].idup;
    } else {
        return null;
    }
}

/**
 *  SDL関数のエラーチェック
 *
 *  Params:
 *      value = SDL関数の戻り値か、エラーチェック結果。
 *  Returns:
 *      エラーが発生していなければvalue。
 *  Throws:
 *      Exception エラーが発生していた場合にスローされる。
 */
T enforceSdl(T)(T value, string file = __FILE__, size_t line = __LINE__) {
    return enforce(value, getSdlMessage(), file, line);
}
dub.json
{
    "name": "dshida",
        "targetType": "executable",
    "description": "A fractal shida implementation written by D language.",
    "copyright": "Copyright © 2014, outlandkarasu",
    "authors": ["outlandkarasu"],
    "dependencies": {
                "derelict-sdl2": "~master"
    }
}

実行結果

D Shida

11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10