Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

空前のシダブームということで、私も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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした