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