Scalaでゲームプログラミング - 番外編 デバッグの方法を見つけ出す -


エラーが起こったり、きちんと動いているか確認するためにもデバッグは必要です。
デバッグをするにあたり、データをどこかに出力しなければなりません。


そこでDebuggerというオブジェクトをつくりどこからでもアクセスできるようにしておきます。

標準入出力


printlnしてください


ファイルに出力する


pushでメッセージを追加し、releaseでファイルに書き出します。
プログラムが終了するときにreleaseするとよいと思います。

import java.io._
//---------------------------------------------------------
// DEBUG MESSAGE
//---------------------------------------------------------
object Debugger
{
    private var mMessages = List[String]()
    private var mMode = true

    val FILE_NAME = "debug.txt"
    val FILE_PATH = "./" 
    
    def setEnable(flg:Boolean) = mMode = flg
    def push(in:Any) = if(mMode){ in_push(in); true } else false
    def release()    = if(mMode){ in_release(); true } else false

    private def in_push(in:Any)  =
    {
        //
    }

    private def in_release() =
    {
        //
    }
}

mModeは、メッセージを受け付けるかどうかのフラグです。


さて、簡単なpushの機能から見てみましょう。

Debuger.push
private def in_push(in:Any)  =
{
    in match
    {
        case e : String => mMessages = mMessages ::: List(e)
        case e          => mMessages = mMessages ::: List(e.toString)
    }
}


文字列の場合はそのまま追加、そうでない場合は変換してから追加。
Scalaのパターンマッチは強力でオブジェクトの型も判別できます。


さて、次はreleaseの機能を見てみます。

Debuger.release
private def in_release() =
{
    try
    {
        val file = new File(FILE_PATH+FILE_NAME)
        if( !file.exists() ) new Exception(FILE_NAME+" is not exist")
        if( !file.isFile() ) new Exception(FILE_NAME+" is not file")
        if( !file.canWrite() ) new Exception(FILE_NAME+" can't write")

        val writer = new FileWriter(file)
        val buffer = new BufferedWriter(writer)
        val printer = new PrintWriter(buffer)

        mMessages.foreach(printer.println)

        printer.close
    }
    catch
    {
        case e => println(e)
    }
}


エラーがでたら標準入出力で対応します。
この辺はさらにthrowした方がいいのかもしれませんね。


FileWriterやBufferedWriterやPrintWriterはJavaのものです。
ただ生成して使えるようにしているだけなので特に問題ありませんね。


便利なのがforeachです。println関数を渡してあげる書き方もできるのです。

mMessages.foreach(printer.println)

タイトルバー出力

タイトルバーに出力するデバッグは簡単にできるので便利です。
第三回システムの骨格を考えるにてRenderのクラスを利用します。

Render.setTitleを呼び出すだけ
def printTitle(str:String) = Render.setTitle(str)


Render側に直接値を渡しても良かったのですが
Debuger特有の加工がのちのちあるかもしれないので間接的に呼び出します。