キーの押下状態を取得する命令を使って押した瞬間・離した瞬間を検出する命令を作ることに関するメモ

細かすぎてどうでもよさそうなことなのですが、個人的に感心したのでメモ。長ったらしい見出しですみません。

HSPでは、キーボードのあるキーが押されているかを判定する機能はある(getkey命令)けど、押された瞬間・離された瞬間のみ検出する機能が不十分です(stick命令で限定的にサポートされているのみ)。でも、ゲームを作るなら後者の機能はよく使いますよね。

というわけで、前者の機能を使って後者の機能を作ることになります。僕は今まで「押された瞬間というのは、前のフレームで押されていなくてこのフレームで押されているということだから……」とかごちゃごちゃと考えつつ、次のように書いていました。関係ないですが、はてなダイアリーソースコード色付け機能はHSP未対応なのがちょっと悲しいです。

	;Zキーが押された瞬間・離された瞬間を検出するサンプル
*main
	wait 20

	;Zキーが押されているかどうかを取得
	getkey key, 'Z'
	keypress_z = key

	;★ここから★
	;Zキーが押された瞬間・離された瞬間を検出
	keydown_z  = 0
	keyup_z    = 0
	if key {                      ;今回押されていて
		if key_prev = 0 {     ;前回押されていなければ
			keydown_z = 1 ;押された瞬間である
		}
	} else {                      ;今回押されていなくて
		if key_prev {         ;前回押されていれば
			keyup_z = 1   ;離された瞬間である
		}
	}
	;★ここまで★

	key_prev = key

	;取得した値を表示
	if keydown_z  : mes "Zキーが押されました。"
	if keypress_z : mes "Zキーが押されています……"
	if keyup_z    : mes "Zキーが離されました。"

	;HSPでは、gotoさんはまだまだ現役です
	goto *main

ifのネストが深くて長ったらしいです。もちろん、実際にはサブルーチンか関数として実装しますよ。

いままで上記スクリプトの方法が当然だと思っていたのですが、HSP3掲示板で以下のような方法が紹介されていました。問題の箇所は★マークで目立たせているところです。さっきのスクリプトよりいい感じだと思うのですがいかがでしょうか。

	;Zキーが押された瞬間・離された瞬間を検出するサンプル その2
*main
	wait 20

	;Zキーが押されているかどうかを取得
	getkey key, 'Z'
	keypress_z = key

	;★ここから★
	;Zキーが押された瞬間・離された瞬間を検出
	;キーの押下状態が変わって、かつ現在押されていれば、押された瞬間
	keydown_z = key ^ key_prev & key

	;キーの押下状態が変わって、かつ現在押されていなければ、離された瞬間
	keyup_z   = key ^ key_prev & key_prev
	;★ここまで★

	key_prev = key

	;取得した値を表示
	if keydown_z  : mes "Zキーが押されました。"
	if keypress_z : mes "Zキーが押されています……"
	if keyup_z    : mes "Zキーが離されました。"

	;もちろんHSPにもループ文はあるのですが、gotoのほうがHSPらしいかなと
	goto *main

やっていることは全く同じなのですが、スクリプトが短くなった上に、やりたいことが1行で簡潔に表現されていてとても読みやすいです。ビット演算は難しそうだしスクリプトの意味が分かりにくくなりがちなのでめったに使わないのですが、このようなエレガントな使い方はいいですね。

今回のは1回書いてしまえば終わりなのでどっちでもいいのですが、こういう短いけど可読性の高いコードを自然に書ければかっこよさそうです。