次に swing を書く。Scala 逆引きレシピだと、「165: GUIアプリケーションを作りたい」が一応参考になるけど、ある程度 Java Swing を一緒に勉強する必要があると思う。
package com.tetrix.swing
import swing._
import event._
object Main extends SimpleSwingApplication {
import event.Key._
import java.awt.{Dimension, Graphics2D, Graphics, Image, Rectangle}
import java.awt.{Color => AWTColor}
val bluishGray = new AWTColor(48, 99, 99)
val bluishSilver = new AWTColor(210, 255, 255)
def onKeyPress(keyCode: Value) = keyCode match {
case _ => // do something
}
def onPaint(g: Graphics2D) {
// paint something
}
def top = new MainFrame {
title = "tetrix"
contents = mainPanel
}
def mainPanel = new Panel {
preferredSize = new Dimension(700, 400)
focusable = true
listenTo(keys)
reactions += {
case KeyPressed(_, key, _, _) =>
onKeyPress(key)
repaint
}
override def paint(g: Graphics2D) {
g setColor bluishGray
g fillRect (0, 0, size.width, size.height)
onPaint(g)
}
}
}
The scala.swing package もちらっと見たけど、上はだいたい前に書いた Tetrix の実装からもらってきた。
scala swing はセッターメソッド (x_=
) をいくつも定義しているため、クラスの本体に直接 x = "foo"
のように書くことができる。すがすがしいぐらいに可変 (mutable) なフレームワークだ。UI は全部副作用なので、これはうまくいっていると思う。
あまり swing に縛られたくないが、特にプラットフォーム間で違いがあるわけでもない。だいたい画面があって、ブロックを動かすインプットがある。プレーヤーかタイマーがゲームがアクションを実行し、ゲームの状態が変わり、結果が画面に表示される。今のところは、ゲームの状態を String
の var で代用しよう。
package com.eed3si9n.tetrix
class AbstractUI {
private[this] var lastKey: String = ""
def left() {
lastKey = "left"
}
def right() {
lastKey = "right"
}
def up() {
lastKey = "up"
}
def down() {
lastKey = "down"
}
def space() {
lastKey = "space"
}
def last: String = lastKey
}
以下のようにして swing UI につなぐ:
import com.eed3si9n.tetrix._
val ui = new AbstractUI
def onKeyPress(keyCode: Value) = keyCode match {
case Left => ui.left()
case Right => ui.right()
case Up => ui.up()
case Down => ui.down()
case Space => ui.space()
case _ =>
}
def onPaint(g: Graphics2D) {
g setColor bluishSilver
g drawString (ui.last, 20, 20)
}
これで、左矢印を押すと "left"
と表示される面白いゲームができた。
初日はこんなものでいいんじゃないかな。
自分のマシンで試してみる手順:
$ git clone https://github.com/eed3si9n/tetrix.scala.git
$ cd tetrix.scala
$ git co day0v2 -b try/day0
$ sbt swing/run