Home English

Kuina-chan

くいなちゃんNov 18, 2017


プログラミング言語Kuin」の2Dグラフィックスのチュートリアルです。

Kuinドキュメント」の内容を組み合わせた、実践的な使い方を示します。
目次

ドローコントロールを作成する

2Dグラフィックスの基本的な使い方について説明していきます。

ドローコントロールを作成する

Kuinでグラフィックスを表示するには、グラフィックスを描画するためのドローコントロールをウインドウに配置して実現します。 ドローコントロールの表示のように書きます。
func main()
  var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, 1600, 900, "Test")
  do wnd@makeDraw(wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  while(wnd@act())
    do draw@render(60)
  end while
end func
ドローコントロールの表示
「wnd@makeWnd」関数に「%aspect」を指定すると、ウインドウがサイズの比率(この例では「幅:高さ=1600:900」)を維持するように拡大・縮小します。
「wnd@makeDraw」関数に指定した「%scale」とは、親ウインドウのサイズが変わったときに、ドローコントロールも追従して拡大・縮小させることを意味します。
ドローコントロールを作成すると、drawライブラリの描画先が自動的にそのコントロールに設定されます。 「draw@render」関数で、1秒間に60回画面を更新しています。
実行すると、ドローコントロールの作成の実行結果のようになります。
ドローコントロールの作成の実行結果
ドローコントロールの作成の実行結果

円を描画する

ドローコントロールに円を描画するには、円の描画のようにプログラムを追加します。
func main()
  var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, 1600, 900, "Test")
  do wnd@makeDraw(wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var theta: float :: 0.0
  while(wnd@act())
    do theta :+ lib@pi / 60.0
    do draw@circle(800.0 + lib@cos(theta) * 300.0, 450.0 + lib@sin(theta) * 300.0, 80.0, 80.0, 16#FFFFFF00)
    do draw@render(60)
  end while
end func
円の描画
実行すると、円がウインドウの中央を中心にぐるぐる回り続けます(円の描画の実行結果)。
円の描画の実行結果
円の描画の実行結果
「draw@circle」関数で円を描画していますが、この関数を呼んだ時点ではバックバッファと呼ばれる領域に描画されていて、画面には何も映りません。 一通りバックバッファに描画し終わったら「draw@render」関数を呼ぶことで、バックバッファの内容が画面に転送され、見えるようになります。 このような仕組みにすることで、描画途中の状態が画面に現れず、ちらつきを防いでいます。

いろいろな図形を描画する

drawライブラリには様々な図形を描画する関数が用意されています。 例えば、いろいろな図形の描画のように書きます。
func main()
  var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, 1600, 900, "Test")
  do wnd@makeDraw(wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  while(wnd@act())
    do draw@circle(50.0, 150.0, 50.0, 50.0, 16#FFFFFF00)
    do draw@rect(100.0, 100.0, 100.0, 100.0, 16#FFFF0000)
    do draw@line(200.0, 100.0, 300.0, 200.0, 16#FF0000FF)
    do draw@rectLine(300.0, 100.0, 100.0, 100.0, 16#FF00FF00)
    do draw@tri(450.0, 100.0, 400.0, 200.0, 500.0, 200.0, 16#FFFF00FF)
    do draw@render(60)
  end while
end func
いろいろな図形の描画
実行すると、いろいろな図形の描画の実行結果のようになります。
いろいろな図形の描画の実行結果
いろいろな図形の描画の実行結果

文字列を描画する

文字列を描画するには、「draw@makeFont」関数を使って文字列の描画のように書きます。
func main()
  var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, 1600, 900, "Test")
  do wnd@makeDraw(wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var font: draw@Font :: draw@makeFont(null, 32, false, false, true, 0.0)
  while(wnd@act())
    do font.draw(50.0, 50.0, "Hello, world!", 16#FFFFFF00)
    do draw@render(60)
  end while
end func
文字列の描画
「draw@makeFont」関数でフォントクラス「draw@Font」のインスタンスを生成し、その「draw」メソッドで文字列を描画します。
実行すると、文字列の描画の実行結果のようになります。
文字列の描画の実行結果
文字列の描画の実行結果

画像ファイルを描画する

画像の作成

Kuinでは、「.png」「.jpg」「.dds」形式の画像ファイルを読み込んで描画することができます。
例えば、画像の作成のような2枚の画像「back.jpg」と「block.png」を作成しておきます。 block.pngの背景は白ではなく透明です。
画像の作成
画像の作成
作成する作業を省略したい方はres.zipからダウンロードできます。
画像ファイルが非対応の形式の場合、実行時に「E9170008」のエラーが発生しますので保存し直してください。 特に、jpgファイルの形式は「プログレッシブ」ではなく「ベースライン」で保存してください。
これらの画像ファイルをプログラムで読み込むためには、メインのソースコードと同じフォルダに「res」というフォルダを作成してその中に入れます(resフォルダ)。
resフォルダ
resフォルダ
resフォルダはコンパイル時に自動でexeファイルの位置にコピーしてくれます。 プログラムから読み込むファイルはすべてresフォルダに入れると良いでしょう。

背景の表示

さて、背景画像「back.jpg」を表示させます。 背景の表示のように書きます。
func main()
  var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, 1600, 900, "Test")
  do wnd@makeDraw(wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var texBack: draw@Tex :: draw@makeTex("res/back.jpg")
  while(wnd@act())
    do texBack.draw(0.0, 0.0, 0.0, 0.0, 1600.0, 900.0, draw@white)
    do draw@render(60)
  end while
end func
背景の表示
実行すると、背景の表示の実行結果のようになります。
背景の表示の実行結果
背景の表示の実行結果

ブロックの表示

最後に、ブロックをマップチップとして描画します。 効率的な手法として、1次元の配列を2次元のマップとして使う方法がよく行われます(ブロックの表示)。
func main()
  var wndMain: wnd@Wnd :: wnd@makeWnd(null, %aspect, 1600, 900, "Test")
  do wnd@makeDraw(wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var texBack: draw@Tex :: draw@makeTex("res/back.jpg")
  var texBlock: draw@Tex :: draw@makeTex("res/block.png")
  var map: []int ::
  | [
  |   0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  |   0, 1, 2, 1, 1, 0, 0, 0, 0, 2, 0, 0,
  |   0, 0, 2, 0, 0, 0, 1, 1, 1, 2, 1, 1,
  |   0, 0, 2, 0, 0, 0, 0, 1, 0, 2, 0, 1,
  |   0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0, 0,
  |   1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1
  | ]
  while(wnd@act())
    do texBack.draw(0.0, 0.0, 0.0, 0.0, 1600.0, 900.0, draw@white)
    for y(0, 5)
      for x(0, 11)
        var n: int :: map[y * 12 + x] {描画するブロックの種類}
        if(n <> 0)
          do texBlock.draw((112 + x * 112) $ float, (112 + y * 112) $ float, ((n - 1) * 112) $ float, 0.0, 112.0, 112.0, draw@white)
        end if
      end for
    end for
    do draw@render(60)
  end while
end func
ブロックの表示
実行すると、ブロックの表示の実行結果のようになります。
ブロックの表示の実行結果
ブロックの表示の実行結果
1511006959ja