Kuina-chan

くいなちゃん2018年10月19日


プログラミング言語Kuin」の逆引き辞典10、グラフィックスの描画の方法についてです。

目次

ドローコントロールを扱う

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

Kuinにおける2Dや3Dの高度なグラフィックスはすべて、ドローコントロールを使用して描画します。
ドローコントロールを作成するには「wnd@makeDraw(親ウインドウ,X座標,Y座標,,高さ,アンカーX,アンカーY,ドットバイドットにするかどうか)」とします(ドローコントロールの作成)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  while(wnd@act())
    do draw@render(60)
  end while
end func
ドローコントロールの作成
第6、7引数のアンカーは、親ウインドウのサイズが変わったときに、サイズを固定したままにするには「%fix」、一緒に拡縮するには「%scale」、右下にくっつくように移動するには「%move」とします。
第8引数は、コントロールのサイズが変わったときに描画内容を、ドットバイドット(等倍を維持)にするには「true」、コントロールのサイズに合わせて拡縮するには「false」とします。
ドローコントロールは、描画途中の結果が見えないように、一度バックバッファと呼ばれる見えないバッファに描画しておいてから最終的な画面に転送します。 9行目の「draw@render」は、バックバッファから最終的な画面に転送する関数で、いろいろな図形を描画した後にdraw@renderで転送する流れにします。
draw@renderの引数に0以外の値を渡すと、1秒間に指定回数だけ画面が更新(FPS)されるように、待機して時間を調整します。 例えば引数に60を渡すと、1秒間に60回画面が更新されるようになります。 ゲームを作る場合は60か30を指定することが多いです。 0を渡すと待機せずに描画結果の転送だけを行います。
実行するとドローコントロールのようになります。
ドローコントロール
ドローコントロール

背景色を変える

draw@render関数で画面を転送したときに、バックバッファは自動でクリアされます。 このクリア時の背景色は変更でき、またクリアを自動ではせずに手動で行うようにもできます。
クリア時の背景色はデフォルトでは黒ですが、これを変更するには「draw@clearColor()」とします(クリアカラーの設定)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  do draw@clearColor(0xFFCC6666)
  
  while(wnd@act())
    do draw@render(60)
  end while
end func
クリアカラーの設定
色は16進数で2桁ずつ「0x不透明度」と指定します。 例えば青は「0xFF0000FF」になります。 また白と黒は定数が定義されており、白(0xFFFFFFFF)は「draw@white」と書け、黒(0xFF000000)は「draw@black」と書けます。
実行するとクリアカラーのようになります。
クリアカラー
クリアカラー
draw@render関数の呼び出し時に自動でクリアをしないようにするには、事前に「autoClear(false)」を呼び出しておきます。 この場合「draw@clear()」を呼び出すことで手動でクリアできます。

描画先のドローコントロールを切り替える

「draw@」ライブラリでの描画や操作はすべて、最後に作成したドローコントロールに対して行われます。 この操作対象のドローコントロールを切り替えるには「draw@target(ドローコントロール)」とします(操作対象の切り替え)。
var wndMain: wnd@Wnd
var draw1: wnd@Draw
var draw2: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @draw1 :: wnd@makeDraw(@wndMain, 0, 0, 797, 900, %fix, %fix, false)
  do @draw2 :: wnd@makeDraw(@wndMain, 803, 0, 797, 900, %fix, %fix, false)
  
  while(wnd@act())
    do draw@target(@draw1) {操作対象を@draw1に切り替え}
    do draw@clearColor(0xFFCC6666) {背景色を赤にする}
    do draw@render(0) {@draw1のバックバッファを転送してクリア}
    do draw@target(@draw2) {操作対象を@draw2に切り替え}
    do draw@clearColor(0xFF6666CC) {背景色を青にする}
    do draw@render(60) {@draw2のバックバッファを転送してクリア}
  end while
end func
操作対象の切り替え
実行すると操作対象の切り替えのようになります。
操作対象の切り替え
操作対象の切り替え

単純な図形を描画する

線分を描画する

線分を描画するには「draw@line(始点X,始点Y,終点X,終点Y,)」とします(線分の描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  while(wnd@act())
    do draw@line(100.0, 100.0, 1500.0, 800.0, 0xFFFFFF00)
    do draw@render(60)
  end while
end func
線分の描画
実行すると線分のようになります。
線分
線分

四角形を描画する

塗りつぶしの四角形を描画するには「draw@rect(始点X,始点Y,,高さ,)」とし、塗りつぶさない四角形を描画するには「draw@rectLine(始点X,始点Y,,高さ,)」とします(四角形の描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  while(wnd@act())
    do draw@rect(100.0, 100.0, 100.0, 200.0, 0xFF00FFFF)
    do draw@rectLine(300.0, 100.0, 100.0, 200.0, 0xFF00FF00)
    do draw@render(60)
  end while
end func
四角形の描画
実行すると四角形のようになります。
四角形
四角形

円を描画する

塗りつぶしの円を描画するには「draw@circle(中心X,中心Y,半径X,半径Y,)」とし、塗りつぶさない円を描画するには「draw@circleLine(中心X,中心Y,半径X,半径Y,)」とします(円の描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  while(wnd@act())
    do draw@circle(200.0, 200.0, 100.0, 100.0, 0xFFFF00FF)
    do draw@circleLine(500.0, 200.0, 100.0, 100.0, 0xFFFF00FF)
    do draw@render(60)
  end while
end func
円の描画
実行するとのようになります。
円

画像を描画する

画像ファイルを描画する

画像ファイルを描画するには「draw@makeTex(ファイルパス)」で読み込んでから、「draw@Tex.draw(転送先X,転送先Y,転送元X,転送元Y,転送元幅,転送元高さ,)」で描画します(画像の描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  var tex: draw@Tex :: draw@makeTex("res/dot_back_side.png")
  
  while(wnd@act())
    do tex.draw(0.0, 0.0, 0.0, 0.0, 800.0, 450.0, draw@white)
    do draw@render(60)
  end while
end func
画像の描画
読み込める画像ファイルの形式は、「.png」「.jpg」「.dds」です。
「res/dot_back_side.png」に画像ファイルを用意して実行すると画像のようになります。
画像
画像

画像を拡縮して描画する

画像を拡縮して描画するには「draw@Tex.drawScale(転送先X,転送先Y,転送先幅,転送先高さ,転送元X,転送元Y,転送元幅,転送元高さ,)」とします(画像の拡縮描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  var tex: draw@Tex :: draw@makeTex("res/dot_back_side.png")
  
  while(wnd@act())
    do tex.drawScale(0.0, 0.0, 1600.0, 900.0, 0.0, 0.0, 800.0, 450.0, draw@white)
    do draw@render(60)
  end while
end func
画像の拡縮描画
実行すると画像の拡縮のようになります。
画像の拡縮
画像の拡縮

画像を回転して描画する

画像を回転して描画するには「draw@Tex.drawRot(転送先X,転送先Y,転送先幅,転送先高さ,転送元X,転送元Y,転送元幅,転送元高さ,回転中心座標X,回転中心座標Y,回転角度(ラジアン),)」とします(画像の回転描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  var tex: draw@Tex :: draw@makeTex("res/dot_back_side.png")
  
  while(wnd@act())
    do tex.drawRot(0.0, 0.0, 800.0, 450.0, 0.0, 0.0, 800.0, 450.0, 0.0, 0.0, lib@pi / 4.0, draw@white)
    do draw@render(60)
  end while
end func
画像の回転描画
実行すると画像の回転のようになります。
画像の回転
画像の回転

テキストを描画する

テキストを描画する

テキストを描画するには「draw@makeFont(フォント名,サイズ,太字かどうか,斜体かどうか,プロポーショナルかどうか,文字の間隔)」でフォントを読み込んでから、「draw@Font.draw(描画先X,描画先Y,テキスト,)」で描画します(テキストの描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  var font1: draw@Font :: draw@makeFont(null, 60, false, false, false, 60.0)
  var font2: draw@Font :: draw@makeFont(null, 60, false, false, true, 0.0)
  
  while(wnd@act())
    do font1.draw(0.0, 0.0, "Hello, world!", 0xFFFF9999)
    do font2.draw(0.0, 120.0, "Hello, world!", 0xFF9999FF)
    do draw@render(60)
  end while
end func
テキストの描画
draw@makeFontの第1引数のフォント名を「null」にすると、Windowsに標準でインストールされている「"Meiryo UI"」になります。
draw@makeFontの第5引数を「false(等幅)」にしたときは、文字間隔は第6引数で指定した幅になります。 「true(プロポーショナル)」にしたときは、文字間隔は自然になるように自動調整されますが、さらに第6引数で指定した幅が加算されるため幅を増減させることができます。
実行するとテキストのようになります。
テキスト
テキスト

テキストを中央揃えや右揃えで描画する

テキストを中央揃えや右揃えで描画するには「draw@Font.calcWidth(テキスト)」で幅を取得してから描画します(テキストの文字揃え描画)。
var wndMain: wnd@Wnd
var drawMain: wnd@Draw
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Title")
  do @drawMain :: wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  
  var font: draw@Font :: draw@makeFont(null, 60, false, false, true, 0.0)
  
  while(wnd@act())
    const text: []char :: "Hello, world!"
    var width: float :: font.calcWidth(text)
    do draw@line(800.0, 0.0, 800.0, 900.0, 0xFFFFFF99)
    do font.draw(800.0, 0.0, text, 0xFF9999FF)
    do font.draw(800.0 - width / 2.0, 120.0, text, 0xFF9999FF)
    do font.draw(800.0 - width, 240.0, text, 0xFF9999FF)
    do draw@render(60)
  end while
end func
テキストの文字揃え描画
実行するとテキストの文字揃えのようになります。
テキストの文字揃え
テキスト

3Dオブジェクトを描画する

(この記事は執筆中です!)
1539958475jaf