タイマ、タイム、キー
QUICKBIND重要
「QUICKBINDをundefしてはいけません」
速度が段違いでした。メモリ使用量が多少増えるけど、それを 引き替えにしてあまりある効果がでます。よってこれからは QUICKBINDをdefineしておきます。
以上余談。だけど重要。
タイマ、キーのサポート始めました
nmport_b.cのコメントを読むと分かりますが、nmport_b.cには ブートストラップとクラスローダの他に、
を実装する必要があります。こいつらを実装することで、 Control.addTimerメソッドや、Control.onEventメソッドが動作するように なります。
- タイマによる、_onTimerTickメソッド呼び出し
- キー入力、マウス入力による、_postEventメソッド呼び出し
これらの機能はあっても損はない、というかないといろいろと困りそうなので 実装してみます。とりあえず、いままでかなりおざなりだった、 メインルーチンを改良して、こんな感じにする。
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してどこかに軟着陸しないといかんと 思いつつあるこのごろ。軟着陸でなくて胴体着陸になる可能性は高い。
もどる