Home English

Kuina-chan

くいなちゃんApr 23, 2018


プログラミング言語Kuin」のシューティングゲームを作るチュートリアルです。

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

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

完成予想図

ファイルを作成する

まずは適当なフォルダを作成し、その中に「res」フォルダと「stg.kn」というファイルを作成します(ディレクトリ構造)。
ディレクトリ構造
ディレクトリ構造
そしてペイントソフトを使い、resフォルダ内に画像ファイルのように、「back.png」と「pieces.png」の2つの画像ファイルを作成します。
画像ファイル
画像ファイル
pieces.pngの背景でチェック模様になっている部分は透明色です。
作成する作業を省略したい方はres.zipからダウンロードできます。
このようにソースファイルと同じ場所の「res」フォルダに入れたファイルは、実行時にexeファイルの位置に自動でコピーされ、リリースビルド時にはアーカイブファイル「res.knd」に変換されます。 プログラムから読み込むファイルは「res」フォルダに入れると良いでしょう。

背景と自機の表示

まずは背景と自機を表示します。 「stg.kn」をKuinエディタで開き、背景と自機の表示を入力してください。
var wndMain: wnd@Wnd
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Shooting Game")
  do wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var texBack: draw@Tex :: draw@makeTex("res/back.png")
  var texPieces: draw@Tex :: draw@makeTex("res/pieces.png")
  
  while(wnd@act())
    do texBack.draw(0.0, 0.0, 0.0, 0.0, 1600.0, 900.0, draw@white)
    do texPieces.draw(736.0, 386.0, 0.0, 0.0, 128.0, 128.0, draw@white)
    do draw@render(60)
  end while
end func
背景と自機の表示
実行すると背景と自機の表示の実行結果のようになります。
背景と自機の表示の実行結果
背景と自機の表示の実行結果
プログラムの内容は、ほぼ以前のチュートリアル「はじめてのKuin」と「画像ファイルを描画する」で説明した通りです。 ウインドウを作成し、画像ファイルを読み込んで描画しています。

自機の移動

次に、自機が移動できるようにします。
自機を移動させるということは、自機画像の表示位置を動かせばよいため、表示位置を変数にすることを考えます。
x、yという2つの変数を用意し、その位置に自機画像を表示するようにします。 そして、ゲームパッドやキーボードの入力によりその変数を増減させて移動させます。
プログラムで書くと自機の移動の通りです。
var wndMain: wnd@Wnd
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Shooting Game")
  do wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var texBack: draw@Tex :: draw@makeTex("res/back.png")
  var texPieces: draw@Tex :: draw@makeTex("res/pieces.png")
  var x: float :: 736.0
  var y: float :: 386.0
  
  while(wnd@act())
    do texBack.draw(0.0, 0.0, 0.0, 0.0, 1600.0, 900.0, draw@white)
    if(input@pad(0, %left) > 0)
      do x :- 8.0
    end if
    if(input@pad(0, %right) > 0)
      do x :+ 8.0
    end if
    if(input@pad(0, %up) > 0)
      do y :- 8.0
    end if
    if(input@pad(0, %down) > 0)
      do y :+ 8.0
    end if
    do texPieces.draw(x, y, 0.0, 0.0, 128.0, 128.0, draw@white)
    do draw@render(60)
  end while
end func
自機の移動
texPieces.drawの引数に「x, y」を渡す箇所を見落とさないでください。
実行すると、ゲームパッドもしくはキーボードの上下左右により自機が移動できることが分かります。
ゲームパッドやキーボードの入力を扱う詳しい方法は「ゲームでキーボードやゲームパッドを扱う」をご覧ください。

画面外の処理

さて、現状では自機を移動させていくと画面外に出てしまいますので、画面端でぶつかってそれ以上移動できないようにします。
画面外の処理のプログラムを追加します。 ただし、「while(wnd@act())」以降の部分を掲載しています。
  while(wnd@act())
    do texBack.draw(0.0, 0.0, 0.0, 0.0, 1600.0, 900.0, draw@white)
    if(input@pad(0, %left) > 0)
      do x :- 8.0
    end if
    if(input@pad(0, %right) > 0)
      do x :+ 8.0
    end if
    if(input@pad(0, %up) > 0)
      do y :- 8.0
    end if
    if(input@pad(0, %down) > 0)
      do y :+ 8.0
    end if
    if(x < 0.0)
      do x :: 0.0
    end if
    if(x > 1600.0 - 128.0)
      do x :: 1600.0 - 128.0
    end if
    if(y < 0.0)
      do y :: 0.0
    end if
    if(y > 900.0 - 128.0)
      do y :: 900.0 - 128.0
    end if
    do texPieces.draw(x, y, 0.0, 0.0, 128.0, 128.0, draw@white)
    do draw@render(60)
  end while
end func
画面外の処理
実行すると、自機を移動しても画面端を超えないようになっています。
座標を(x,y)で表すと、画面端の座標は左上が(0,0)、右下が(1600,900)です。 この数値はドローコントロールを作成したときに指定したものです。 そして、自機画像の表示位置は左上が(x,y)、右下が(x+128,y+128)となるため、今回追加したプログラムは、自機画像が画面端を超えたら座標を画面端まで戻すという処理になっています。

自機の弾の発射

それでは、自機の弾を発射させましょう。 まずは弾を扱うクラスと変数を定義するために、自機の弾の定義のプログラムを追加します。 ただし、「while(wnd@act())」より前を掲載しています。
var wndMain: wnd@Wnd
  
class Beam()
  +var x: float
  +var y: float
end class
  
func main()
  do @wndMain :: wnd@makeWnd(null, %aspect, 1600, 900, "Shooting Game")
  do wnd@makeDraw(@wndMain, 0, 0, 1600, 900, %scale, %scale, false)
  var texBack: draw@Tex :: draw@makeTex("res/back.png")
  var texPieces: draw@Tex :: draw@makeTex("res/pieces.png")
  var x: float :: 736.0
  var y: float :: 386.0
  var beams: list<@Beam> :: #list<@Beam>
  
  while(wnd@act())
自機の弾の定義
自機の弾は座標さえ保持していれば十分と考え、「x」「y」の2つのプロパティを持つクラス「@Beam」を定義しました。
また自機の弾は画面上にいくつでも存在しうるため、個数に上限がある配列よりもリストで管理すると便利そうなので、「list<@Beam>」型の変数「beams」を作成し、新規インスタンス「#list<@Beam>」で初期化しました。
実際に発射しましょう。 自機の弾の発射のプログラムを追加します。 ただし、「while(wnd@act())」以降を掲載しています。
  while(wnd@act())
    do texBack.draw(0.0, 0.0, 0.0, 0.0, 1600.0, 900.0, draw@white)
    if(input@pad(0, %left) > 0)
      do x :- 8.0
    end if
    if(input@pad(0, %right) > 0)
      do x :+ 8.0
    end if
    if(input@pad(0, %up) > 0)
      do y :- 8.0
    end if
    if(input@pad(0, %down) > 0)
      do y :+ 8.0
    end if
    if(x < 0.0)
      do x :: 0.0
    end if
    if(x > 1600.0 - 128.0)
      do x :: 1600.0 - 128.0
    end if
    if(y < 0.0)
      do y :: 0.0
    end if
    if(y > 900.0 - 128.0)
      do y :: 900.0 - 128.0
    end if
    do texPieces.draw(x, y, 0.0, 0.0, 128.0, 128.0, draw@white)
  
    if(input@pad(0, %a) = 1)
      var beam: @Beam :: #@Beam
      do beam.x :: x
      do beam.y :: y
      do beams.add(beam)
    end if
    do beams.head()
    while(!beams.term())
      var beam: @Beam :: beams.get()
      do beam.y :- 12.0
      if(beam.y <= -128.0)
        do beams.del()
      else
        do texPieces.draw(beam.x, beam.y, 128.0, 0.0, 128.0, 128.0, draw@white)
        do beams.next()
      end if
    end while
    do draw@render(60)
  end while
end func
自機の弾の発射
実行すると自機の弾の発射の実行結果のようになります。
自機の弾の発射の実行結果
自機の弾の発射の実行結果
ゲームパッドのAボタン、もしくはキーボードのZキーが押されると、@Beamクラスの新しいインスタンスを生成し、リストbeamsに追加しています。
リストbeamsに登録した自機の弾は順番に、上方向に移動させつつ描画します。 画面端を超えた弾はリストから削除しています。
これにより、複数の弾が発射できるようになりました。

敵の出現

敵の弾の発射

衝突判定

敵の破壊

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

1524489624ja