ゲーム実装で身に付くプログラミング 11

ゲームオーバーに遷移する

ゲームオーバーに遷移する

「GameOver.kt」ファイルを新規作成します。次のビルドコマンドを実行し「color.jar」を起動すると、すべての色ブロックがなくなったらゲームオーバーになります。

ただし今回は解説を簡単にするため、ゲームオーバー画面は表示しません。タイトル画面を参考に、ゲームオーバー画像の表示とクリックでタイトル画面に遷移する処理を実装してみてください。

・ビルドコマンド

$ kotlinc main.kt Title.kt MainLoop.kt ColorBlock.kt GameOver.kt -include-runtime -d color.jar

・サンプルコード「MainLoop.kt」ファイル

public class MainLoop extends JPanel {
(中略)

  public MainLoop(JFrame frame) {
(中略)
  }

  override fun paintComponent(g: Graphics) {
    super.paintComponent(g)

    val g2d = g as Graphics2D
    var flg = 0

    for (c in colors) {
      flg += c.update(width, height)
      c.image?.let { img ->
        g2d.drawImage(img, c.pos[0], c.pos[1], this)
      }
    }
    if (flg <= 0) {
      timer.stop()
      frame.contentPane.removeAll()
      frame.add(GameOver(frame))
      frame.revalidate()
      frame.repaint()
    }
  }
}

【サンプルコードの解説】
「ColorBlock」クラスの「update」メソッドで色ブロックを移動した際、色ブロックが画面内にあればflgをインクリメントします。
flgが0ならすべての色ブロックがなくなったということなので、現在のフレームの中身をすべて削除し、新たに「GameOver」クラスを画面フレームに追加します。

・サンプルコード「GameOver.kt」ファイル

import javax.swing.JFrame
import javax.swing.JPanel

class GameOver(frame: JFrame) : JPanel() {
  init {
    frame.contentPane.removeAll()
    frame.add(Title(frame))
    frame.revalidate()
    frame.repaint()
  }
}

【サンプルコードの解説】
ゲームオーバー画面のGameOverクラスでは、何もせずにすぐにTitleクラスのタイトル画面に遷移します。

背景色を表示する

やっと、このゲームの肝である背景色をセットします(図4)。背景色は、赤緑青の色ブロックをクリックするとその色が強くなるように計算します。

図4:背景色の表示

・サンプルコード「MainLoop.kt」ファイル

import java.awt.Color
import java.awt.Graphics
import java.awt.Graphics2D
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.util.Random
import javax.swing.JFrame
import javax.swing.JPanel
import javax.swing.Timer

class MainLoop(private val frame: JFrame) : JPanel() {
  private val colors = ArrayList<ColorBlock>()
  private val rgb = intArrayOf(0, 0, 0)
  private val timer: Timer

  init {
    val rand = Random()
    val stage = frame.title.toInt()
    repeat(3 * stage) {
      colors.add(ColorBlock(it % 3))
    }
    addMouseListener(object : MouseAdapter() {
      override fun mousePressed(e: MouseEvent) {
        for (i in colors.indices) {
          if (colors[i].click(e)) {
            rgb[colors[i].color]++
            colors.removeAt(i)
            break
          }
        }
      }
    })
    while (rgb[0] == rgb[1]) {
      rgb[0] = rand.nextInt(stage)
      rgb[1] = rand.nextInt(stage)
      rgb[2] = rand.nextInt(stage)
    }
    timer = Timer(100) {
      // 毎フレームの処理(更新・再描画)
      frame.repaint()
    }
    timer.start()
  }

  override fun paintComponent(g: Graphics) {
    super.paintComponent(g)
    var flg = 0
    val g2d = g as Graphics2D
    for (c in colors) {
      flg += c.update(width, height)
      c.image?.let { img ->
        g2d.drawImage(img, c.pos[0], c.pos[1], this)
      }
    }
    if (flg <= 0) {
      timer.stop()
      frame.contentPane.removeAll()
      frame.add(GameOver(frame))
      frame.revalidate()
      frame.repaint()
    }
    if (setBgColor()) {
       // 条件成立時の処理
    }
  }

  private fun setBgColor(): Boolean {
    val max = if (rgb[0] > rgb[1]) {
      if (rgb[0] > rgb[2]) 0 else 2
    } else {
      if (rgb[1] > rgb[2]) 1 else 2
    }
    val ratio = 255f / rgb[max]
    val r = (ratio * rgb[0]).toInt()
    val g = (ratio * rgb[1]).toInt()
    val b = (ratio * rgb[2]).toInt()
    background = Color(r, g, b)
    return (rgb[0] == rgb[1] && rgb[1] == rgb[2])
  }
}

【サンプルコードの解説】
配列「rgb」プロパティの{赤,緑,青}の要素にランダムな整数値が代入されます。
マウスがクリックされたら、マウスカーソルの位置に色ブロックがあった場合、その色のrgb配列の要素をインクリメントします。
「setBgColor」メソッドでは、rgb配列の最も大きい要素のインデックス(色)を取得します。255をその要素で除算し「i」変数に代入します。rgb配列の各要素にiを乗算した値を背景色にします。rgb配列の各要素の値が3つとも同じなら背景は真っ白になり、戻り値としてtrueを返します。それ以外はfalseを返します。

ステージクリアに遷移する

これで最後の仕上げです。「StageClear.kt」ファイルを新規作成します。次のビルドコマンドを実行しcolor.jarを起動すると、背景色が真っ白になった時に「StageClear」画面に遷移しますが、何も表示せず次のステージへ進みます。タイトル画面を参考に、ステージクリア画像の表示とクリックでメインループに遷移する処理を実装してみてください。

・ビルドコマンド

$ kotlinc main.kt Title.kt MainLoop.kt ColorBlock.kt GameOver.kt StageClear.kt -include-runtime -d color.jar

・サンプルコード「MainLoop.kt」ファイル

(前略)
public class MainLoop extends JPanel {
(中略)

  public MainLoop(JFrame frame) {
(中略)
  }

  @Override
  protected void paintComponent(Graphics g) {
(中略)
    if (setBgColor()) {
      timer.stop()
      frame.contentPane.removeAll()
      frame.add(StageClear(frame))
      frame.revalidate()
      frame.repaint()
    }
  }

  private boolean setBgColor() {
(中略)
  }
}

【サンプルコードの解説】
背景色が真っ白になったらステージクリアで、画面フレームを空にしてStageClearクラスを画面フレームに追加します。

・サンプルコード「StageClear.kt」ファイル

import javax.swing.JFrame
import javax.swing.JPanel

class StageClear(frame: JFrame) : JPanel() {
  init {
    val title = frame.title.toInt() + 1
    frame.title = title.toString()
    frame.contentPane.removeAll()
    frame.add(MainLoop(frame))
    frame.revalidate()
    frame.repaint()
  }
}

【サンプルコードの解説】
ウィンドウタイトルの"2"などがそのままステージ番号で、これを整数化してインクリメントした値が次のステージの値になります。
それ以外はGameOver.ktのコードとほとんど同じで、MainLoop画面に遷移するところだけが異なります。

【コラム】正しい努力

モーツァルトが「天才」と呼ばれるのは、音楽家の親が3歳から正しく教育し、何時間も正しい努力をしたから。僕も進学校で教師に正しく指導された頃は勉強ができたけど、大学に入ってからは独学で正攻法ではなかったので、成功できませんでした…。

おわりに

今回はプログラミング言語「Kotlin」と「Swing」「Java2D」を使ってColorゲームを作りました。

Javaのライブラリがそのまま使え、ほとんどJava言語と変わらないので、第4回のJavaの解説でゲームを完成できた方は楽に進められたのではないかと思います。

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored