ARGENTO CUORE

 May the code be with you.

--.--.--[--] スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

2010.04.14[水] Scalaでゲーム用ライブラリを作る

言語の習得を兼ねて、ゲーム制作用ライブラリを作っています。

import argento._ だけで使用できるようにJavaのライブラリのラッパークラス的なものを用意することも多く……こういうのはScalaのほうで全部用意してあったらいいのになと思いつつ、量的に大変だよなーでも各自で実装してたらそれはそれでもったいないなーと思ったり。

下のコードは てきとーなプログラム。まだKeyEventはラッピングしてないのでimportしている。
コンシューマー系ゲームで使うボタン数は限られているので、GamePadと関連付けを行う処理をユーザーが書くか、APIで設定ファイルを読み込むようにしておけばボタンコンフィグ機能も一発で作れるような感じにしたい。

はじめてJavaを触ったときに、メインループを書きたいがためにRunnableインターフェースを実装してrunメソッドに書かなきゃいけないのは冗長だなと思ったことがって、もしゲーム用のメインループを書きたいだけなら、

def MainLoop():Unit = {
}

とか関数を用意して、あとはその中に処理を書いていくほうが、とっかかりとしては楽だと思うし直感的だ(と勝手に思っている)。今作っているライブラリでは、GameFrame(ウインドウ)にGamePanel(ゲーム用パネル)をパッキングして、パネルにMainLoopのオブジェクトを登録するとそれを毎回指定されたフレームレートにしたがって呼び出すようにしている。
けど、それは非常に、面倒かもしれない。

今はメインループのためにGameProcessというクラスのdisplay、execというメソッドをオーバーライドしてその中に処理を書いていく形になっている(二つにわけたのはフレームスキップをしたいとき用で、その機能を使わなければdisplayメソッドだけをオーバーライドして使えるという形にもできる)。

setDataFromBufferメソッドを使えばBufferedImageのラスタデータに直に値をセットできるようにしたのだが、ひとつ問題があって、JavaにはUnsigned byteがないので、255という値は-1になってしまう。

解決策として、

value & 0xFF

で255の値が得られるし、scalaの対話形式のインタープリター上で確認すると255という値が得られたのだが、それと同じコードをコンパイルして実行。printlnで値を表示させたら-1になってしまう。これはprintlnが勝手にIntに直しているんだろうか。

フレームレート60、640x480の描画エリアで、一旦全てのピクセルを0x000000に指定(BufferedImageのバイトの並びはBGRなのでライブラリ内部で値の計算時に順序を入れ替えるようにしている)し、32x32の矩形をJavaのfillRectメソッドで200個ランダムに表示する処理で、16.666666667msのうち平均10msを消費していて、時々16.666666667ms以内に処理が完了しないこともある。
CPUはCore2Duo 2GHz。何がまずいんだろうか……。


import argento._

object GameMain{
import java.awt.event.KeyEvent

val f = new GameFrame()
def main(args:Array[String]):Unit={
f.contents = new GamePanel(640,480){
frame_rate = 60
process = new MainLoop()
}
f.title = "ゲームタイトル"
f.visible = true


GameKey.keymap += (KeyEvent.VK_W -> GamePad.UP)
GameKey.keymap += (KeyEvent.VK_S -> GamePad.DOWN)
GameKey.keymap += (KeyEvent.VK_A -> GamePad.LEFT)
GameKey.keymap += (KeyEvent.VK_D -> GamePad.RIGHT)
GameKey.keymap += (KeyEvent.VK_J -> GamePad.A)
GameKey.keymap += (KeyEvent.VK_K -> GamePad.B)
GameKey.keymap += (KeyEvent.VK_L -> GamePad.C)
GameKey.keymap += (KeyEvent.VK_SEMICOLON -> GamePad.D)
GameKey.keymap += (KeyEvent.VK_ESCAPE -> GamePad.ESC)
}
}

class MainLoop extends GameProcess{
var randx = new GameRandom(608)
var randy = new GameRandom(448)
var rand2 = new GameRandom(255)

var buffer = new Array[Int](640*480)
override def display(g:GameGraphics):Unit={
//描画
g.setDataFromBuffer(buffer)

for(i <- 0 until 200){
val col:Array[Int] = rand2.generate(3)
g.setColo(new GameColor(col(0),col(1),col(2)))

val x:Array[Int] = randx.generate(1)
val y:Array[Int] = randy.generate(1)
g.fillRect(x(0,y(0),32,32)
}
}

override def exec():Unit={
for(i <- 0 to 640*480-1){
buffer(i)=0x000000
}
//キー入力
if (GameKey.getCode == GamePad.ESC){
System.exit(1)
}
}
}

object GamePad{
val UP = 0x01 << 0
val DOWN = 0x01 << 1
val LEFT = 0x01 << 2
val RIGHT = 0x01 << 3
val A = 0x01 << 4
val B = 0x01 << 5
val C = 0x01 << 6
val D = 0x01 << 7
val ESC = 0x01 << 8
}


gamelib01
スポンサーサイト

Comment






(編集・削除用)


管理者にだけ表示を許可

Trackback

http://ronor.blog81.fc2.com/tb.php/68-ffcf8005

この記事にトラックバック(FC2Blog User)

Scala Feed

scala feed

FC2カウンター

プロフィール

RoNor

Author:RoNor
得意呪文はScalaですって言えるようになるのが夢です。
デスマーチ中、パーティメンバーの防御力を向上させたりさせなかったり。

検索フォーム

QRコード

QRコード

Copyright © 2009-2010 ARGENTO CUORE and RoNor All rights reserved.

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。