ABA Games

タイマ、タイム、キー


QUICKBIND重要

「QUICKBINDをundefしてはいけません」

速度が段違いでした。メモリ使用量が多少増えるけど、それを 引き替えにしてあまりある効果がでます。よってこれからは QUICKBINDをdefineしておきます。

以上余談。だけど重要。

タイマ、キーのサポート始めました

nmport_b.cのコメントを読むと分かりますが、nmport_b.cには ブートストラップとクラスローダの他に、

を実装する必要があります。こいつらを実装することで、 Control.addTimerメソッドや、Control.onEventメソッドが動作するように なります。

これらの機能はあっても損はない、というかないといろいろと困りそうなので 実装してみます。とりあえず、いままでかなりおざなりだった、 メインルーチンを改良して、こんな感じにする。

static void startEventLoop() {
	int key;
	int *timerID;
	timerID = bi_tmset(2, 255, 1, timer64Func);	// タイマの設定
	do {
		int pushd;
		pushd = bi_sensbtn(&key);		// キーのチェック
		if ( pushd ) {
			handleKeyPress(key);		// キーイベント処理
			bi_clrbtn();			// キーバッファクリア
		}
		if ( globalTimerInterval >= 0 ) {
			timerCheck();			// タイマチェック
		}
	} while (
	 (key&KEY_FILER) != KEY_FILER
	  && vmStatus.errNum == 0
	  && !mainWinExit );
	bi_tmdel(timerID);				// タイマ後片付け
}
おお、なんかちゃんとしたラピュータアプリのメインルーチンみたいだ。 かっくいー。

ポイントはwbios関数であらせられるところのbi_tmsetとbi_sensbtnですかね。 前者はタイマを使って定期的に(この場合は1/64秒ごと)に 特定関数(この場合はtimer64Func)を呼び出させる関数、 後者はキーバッファからキー入力状態を取得する関数です。 これらを使うことで、タイマのカウントや、キー入力の取得ができます。

_onTimerTickを叩く、ぺちぺちと

ここまでできればあとは簡単。timer64Funcでタイマをカウントして、 nmruputer_c.cのMainWinSetTimerInterval関数から取得できる タイマ間隔と照らし合わせて、一定時間ごとに_onTimerTickメソッドを 呼び出してやればいい。

詳しいことはnmruputer_b.cのtimerCheck関数参照。 ちなみにクラスのメソッドを呼び出すには、

	vclass = WOBJ_class(mainWinObj);
	method = getMethod(vclass, createUtfString("_onTimerTick"),
		createUtfString("()V"), &vclass);
	if (method != NULL) {
		params[0].obj = mainWinObj;
		executeMethod(vclass, method, params, 1);
	}
みたいに、クラスとメソッドを取得してから、executeMethod関数を 呼べばいいみたい。QUICKBIND使用時は、メソッドを高速に取得する方法が あるので、そっちを使った方がいいけど、その辺のことはソースをみてくれい。

あ、あとTimerクラスが、Vm.getTimeStampメソッドを使っているので、 nmruputer_c.cでVmGetTimeStamp関数を実装することを忘れないように。

キー、というかスティック

そろそろラピュータスティック(仮称)を受け付けるようにしましょう。 前述のstartEventLoop関数内でキー状態は取得しているので、 あとはキー状態に応じて、KeyEventを_postEventメソッドを通じて 送ってやればよし。

現時点ではオートリピートには対応してません。 rupsysライブラリのKeyIn関数はオートリピートをちゃんと 実現してくれるらしいのだが、この関数は一度呼ぶと何か 押されるまで帰ってこなくなるので使えないし、困ったもんだ。 ま、対応するかどうかは後で考えるということで、ひとつ。

今何時?

日時を取れるようにしましょう。突然こんなのを実装することにしたのは、 以下のクラスを動作させたかったから。

import waba.sys.*;

public class Rnd {
  private final static int multiplier = 8513;
  private final static int addend = 179;

  static private int v;

  static public int nextInt() {
    v = v * multiplier + addend;
    return v;
  }

  static {
    Time t = new Time();
    v = t.year + t.month + t.day + t.hour + t.minute + t.second;
  }
}
用は乱数のシード(種)として時間が欲しかっただけです。 あんまり本質的な使い方ではないような気もしますが、 それはそれとします。

時刻が取れるようにするのは簡単で、nmruputer_c.cの TimeCreateっていう関数を実装すればいいだけ。

static Var TimeCreate(Var stack[])
	{
	Var v;
	WObject time;
	char year, month, day, hour, minute, second;

	time = stack[0].obj;
	bi_dtread(&year, &month, &day);
	bi_tmread(&hour, &minute, &second);
	WOBJ_TimeYear(time) = year;
	WOBJ_TimeMonth(time) = month;
	WOBJ_TimeDay(time) = day;
	WOBJ_TimeHour(time) = hour;
	WOBJ_TimeMinute(time) = minute;
	WOBJ_TimeSecond(time) = second;
	WOBJ_TimeMillis(time) = getTimeStamp() % 1000;
	v.obj = 0;
	return v;
	}
bi_dtread関数とbi_tmread関数の使い方さえ分かれば どうってことない。あ、でもまだ乱数シードとしてしか 使ってないから、ちゃんと日時が取れてるか確認してないや。

今回のサンプル

ver.0.02の時のラインうねうねサンプルの改良版。 やっと真っ当なWabaアプリっぽくなってきた。 前バージョンと同じところは略します。

import waba.fx.*;
import waba.ui.*;

public class MainClass extends MainWindow {
(略)
  private Graphics grp;

  public void onPaint(Graphics g) {
    if ( grp == null ) {
      grp = createGraphics();
      addTimer(250);
    }
  }

  private void moveLines() {
    if ( fl[flIdx] != null ) {
      fl[flIdx].clear(grp);
    } else {
      fl[flIdx] = new FlowLine();
    }
    fl[flIdx].setPos(x1/256, y1/256, x2/256, y2/256);
    fl[flIdx].draw(grp);
    x1 += mx1; y1 += my1;
    if ( x1 < 0 || x1 >= WIDTH ) {
      mx1 = -mx1; x1 += mx1*2;
    }
    if ( y1 < 0 || y1 >= HEIGHT ) {
      my1 = -my1; y1 += my1*2;
    }
    x2 += mx2; y2 += my2;
    if ( x2 < 0 || x2 >= WIDTH ) {
      mx2 = -mx2; x2 += mx2*2;
    }
    if ( y2 < 0 || y2 >= HEIGHT ) {
      my2 = -my2; y2 += my2*2;
    }
    flIdx++; if ( flIdx >= FLOW_LINE_NMB ) flIdx = 0;
  }

  public void onEvent(Event e) {
    if ( e.type == ControlEvent.TIMER ) {
      moveLines();
    } else if ( e.type == KeyEvent.KEY_PRESS ) {
      exit(0);
    }
  }
}

今回のバージョンは、何かキーを押すまで動きつづけます。 ver.0.03のVMは、FILERボタンを押せばいつでも終了できるようにも なってます。

今後

そろそろ実装する機能をfixしてどこかに軟着陸しないといかんと 思いつつあるこのごろ。軟着陸でなくて胴体着陸になる可能性は高い。


Rerurn もどる