私はプログラムでお絵描きしたくなるタイプなので、 Crystal でももちろんお絵描きしたくなります。
というわけで SDL-Crystal-Bindings をちょっと触ってみました。
ちなみに awesome-crystal の「Game Development」のセクションには他にもいくつかのライブラリが並んでいます。今回は定番感のある SDL を選んでみましたが、他のも触ってみたいですね(誰かやりませんか? Raylib-cr とか)。
何か手頃なお題はないか……としばし考え 、DXOpalのトップページ用のデモ を動かす(ために DXRuby/DXOpal のサブセットを作る)ことにしました。
できたもの:
冒頭で require している行を書き換えた以外は Ruby 向けに書かれたコードをそのまま動かすことができました。さすがですね(Crystal が)。
# main.cr
# オリジナルでは
# require 'dxopal'; include DXOpal
require "./dxcrystal"; include DXCrystal
Window.width = 300
Window.height = 300
Window.bgcolor = C_WHITE
Window.load_resources do
x = rand(Window.width)
y = rand(Window.height)
dx = dy = 2
Window.loop do
Window.draw_circle_fill(x, y, 10, C_RED)
dx = -dx if x < 0 || x > Window.width
dy = -dy if y < 0 || y > Window.height
x += dx
y += dy
end
end
SDL を使っている処理は require 先の dxcrystal.cr
の方に書いていて、200行ちょっとあります。全体は GitHub の方で見てください。
SDL-Crystal-Bindings には円を描く API がないので適当なものを自作しました。LibSDL.render_geometry
を使って三角形を並べる方式です。
def self._draw_triangle(
x1, y1,
x2, y2,
x3, y3,
color : LibSDL::Color
)
vertices = [
_sdl_vertex(_sdl_fpoint(x1, y1), color),
_sdl_vertex(_sdl_fpoint(x2, y2), color),
_sdl_vertex(_sdl_fpoint(x3, y3), color)
]
LibSDL.render_geometry(
@@sdl_renderer.not_nil!,
nil, # texture
vertices, vertices.size,
nil, 0 # indices
)
end
def self.draw_circle_fill(
x, y, r,
color : ArgbColor,
z = 0
)
c = Color.from_argb(color).to_sdl_color
n = 16
pi2 = Math::PI * 2
(0..n)
.map { |i|
rad = pi2 * (i.to_f / n)
x2 = x + Math.cos(rad) * r
y2 = y + Math.sin(rad) * r
{ x2, y2 }
}
.each_cons(2) { |pt_pair|
pt1, pt2 = pt_pair
_draw_triangle(x, y, *pt1, *pt2, c)
}
end
メモ
- 今回はちゃんと
crystal init
でプロジェクトを作って shard を使う実績を解除できた -
Hadeweka/SDL-Crystal-Bindings 内のコードと、examples/ に置かれているサンプル(git submodule になっていて、実態は Hadeweka/sdl-crystal-bindings-examples にある)を見る程度でなんとかなった。まあ今回はちょっとしたものなので……。
- と書いている間に sdl-crystal-bindings-examples のリポジトリが消えていました。整理中なのかもしれません。
この記事を読んだ人は(ひょっとしたら)こちらも読んでいます
以下は去年のアドベントカレンダー向けに書いたもの: