自機を動かす(1/2)

 キー、ジョイパッドの入力に従って自機を動かします。

 1.キー、ジョイパッドの入力を判断
 2.自機を動かす

2進数と論理演算

 私達が普段使っている数は、10進数です。1の位、10の位、100の位……、からなっています。これは10の0乗の位、10の1乗の位、10の2乗の位……、からなっているとも言えます。  それぞれの位には0から9までの値が書かれます。例えば、4126という数字は、
  4*10^3+1*10^2+2*10^1+6*10^0
 と表されます。("^"はべき乗です。)
 これに対してそれぞれの位が2のべき乗で表される数を2進数と言います。例えば、1011という2進数は、
  1*2^3+0*2^2+1*2^1+1*2^0
 と表されます。10進数でいうところの11です。2進数では、それぞれの位には0か1しか書けません。各々の位は「ビット」と呼ばれます。「第nビット」あるいは「nビット目」といえば、「2のn乗の位」を指します。
  ビットのイメージ
 ビットの値が1の場合、「ビットが立っている」という表現をします。例えば1011の場合、第3ビット、第1ビット、第0ビットが立っています。また「ビットを立てる」といえば、そのビットを1にすることを言います。

 プログラミングではこの2進数の考え方と論理演算をよく使います。論理和や論理積、排他的論理和といった演算です。
  <条件1> and <条件2>
 これは論理積です。<条件1>が真であり、<条件2>も真の場合にのみ、この結果は真になります。HSPではandを記号"&"で表します。(a>3)&(a<12)は、「aは3より大きく、かつaは12よりも小さい」です。
  <条件1> or <条件2>
 は論理和です。<条件1> か<条件2>のどちらか1つでも真であれば結果は真になります。HSPではorを記号"|"で表します。(a>20)|(a<5)は、「aは20より大きいか、または5よりも小さい」です。
 これらはよくif文で使われます。
  if (a>3)&(a<12) {
    ……
  }
 は、「もしaが3より大きく12より小さいならば、命令を実行せよ」という意味になります。
 この論理演算を、数字に対して行うこともできます。
  x & y
 という演算は、「xとyそれぞれを2進数で表した数に対し、各ビットごとに論理積(and)を行なった値」を求めます。この場合1が真、0が偽に対応します。つまり、
  1&1=1
  1&0=0
  0&1=0
  0&0=0
 となります。  xが156、yが87であれば、2進数で書くとxは10011100、yは1010111です。両方とも1のビットだけが1になります。
  10011100 ←x
  01010111 ←y
  --------
  00010100 ←答
 これを10進数で書くと20です。よって156&87=20です。論理和(or)の場合は、どちらか一方でも1の箇所が1になります。

 1.キー、ジョイパッドの入力を判断

「スタートボタン」の所で、digetkeystate k,0という命令を実行した時、Ctrlキーを押していた場合、kには256が代入されると書きました。Ctrlキーを押すと、第8ビットが立つのです。つまり、2^8=256です。Ctrlキー以外のキーも同時に押した場合、違う値になってしまうと書きましたが、他のビットも立ってしまうからです。つまりこの命令は、同時に複数のキーを押した場合もすべて判別できるということです。カーソルキーの上と左、およびCtrlキーを同時に押した場合、第0ビット、第2ビット、第8ビットが立ちます。この時kには2^8+2^2+2^0、つまり261が代入されます。実際、ショットボタンを押したまま自機を左斜め上に動かすなんてことはよくあることです。では、こういう場合でもCtrlキーが押されていることを判別するにはどうしたらよいでしょうか?

 kの値について、第8ビットが立っているかどうかを判別すればいいのです。kと2^8(=256)の論理積を計算し、結果が256であれば第8ビットが立っているといえます。
  0……0100000101 ←k
  0……0100000000 ←256
  ---------------
  0……0100000000 ←k and 256
 あるいは、Ctrlキーを押していなければこの結果は0になるはずですから、計算結果が0でなければCtrlキーが押されているとも言えます。カーソルキー等についても同様の方法で判別できます。

 ゲームをキーボードでやる場合、自機の移動にはカーソルキーが割り当てられているのが一般的ですが、これって押しにくいと思いませんか? 手の形にフィットしていないからです。だったら、手の形にフィットするキーに割り当てればいいですね。ところが、キーによってはビープ音(プーッという音)がしたり、ゲームが一瞬止まってしまったりします。いろいろ検討した結果、y、b、g、uキーがいいのではないかと思います。それぞれ、上下左右に対応します。(ただし、これでも最適ではありません。ノートパソコンを使っている人は、誤ってタッチパッドに触れてしまうことがあります。)
 そこで、カーソルキー、y、b、g、u、ジョイパッドの3通りの操作方法に対応したいと思います。

 スタートボタンとショットボタンには、同じキーを割り当てるのが普通です。また、オプション画面まで作りたいのであれば、上下左右の入力はそこでも使います。多くの場所で使えるように、この処理はサブルーチン化することにします。

 Ctrlキーの入力は
  digetkeystate k,0
 とすることは説明した通りです。第2引数はキーの種類です。ゲームによく使うキーは0です。カーソルキーもこれに含まれます。アルファベットキーの場合は、第2引数に1を指定します。
  digetkeystate k,1
 この場合、何ビット目が立つかはアルファベットの順番によります。aを1番目として何番目かを数え、1を引いた数のビットに対応します。

 ジョイパッドの入力を判別するには、まずパソコンにジョイパッドが何本つながっているか調べます。1本もつながっていなかったら、入力を判別する必要はありません。
    digetjoynum
    njoy=stat
 digetjoynum命令を実行すると、システム変数statに本数が代入されます。また、各パッドに0から順に番号が割り当てられます。本数を変数njoyに入れます。(number of joypadの略です。)
 2本以上つながっている場合、すべてのジョイパッドに対応すべきでしょうか? 2プレイヤー用のゲームならそうですが、1プレイヤー用のゲームなら1本だけ対応すれば十分だと思うのです。ここでは0番のパッドにのみ対応することにします。
    if njoy>0 {
        digetjoystate k,0
    }
 njoyが0より大きい場合、0番のジョイパッドの入力状態を変数kに代入します。第2引数に何番のジョイパッドについて調べるかを指定します。十字キー、ボタンに対応するビットが立つのは、digetkeystateと同様です。

 使用する命令、キーと対応するビットは以下の通りです。なお、Ctrlキーとジョイパッドのボタン1は同じ役割(ショットボタン、スタートボタン)とします。

digetkeystate k,0
0
1
2
3
Ctrl8

digetkeystate k,1
y24
b1
g6
u20

digetjoystate k,0
0
1
2
3
第1ボタン4

 例えばカーソルキーの上、y、ジョイパッドの上の3つのうち、どれか1つでも押されたら上が入力されたと判断するにはどうしたらよいでしょうか?
 ukeyという変数(up keyの略です)に上キーの状態を入れることにします。入力されていたら1を、入力されていなかったら0を代入します。
 1)最初に、0を代入します。
 2)digetkeystate key,0を行い、カーソルキーの上が押されていたら1を代入します。
 3)digetkeystate key,1を行い、yが押されていたら1を代入します。
 4)digetjoystate key,0を行い、十字キーの上が押されていたら1を代入します。

  ukey=0

  digetkeystate key,0
  if key&1!0 { ukey=1 }

  digetkeystate key,1
  if key&16777216!0 { ukey=1 }

  if njoy>0 {
    digetjoystate key,0
    if key&1!0 { ukey=1 }
  }

 key&1は、変数keyと2^0の論理積です。key&16777216は、keyと2^24の論理積です。2),3),4)で、押されていなかったらukeyの値を変更しないことに注意して下さい。これで、どれか1つでも押されたらukeyの値は1に、どれも押されていなかったら0になります。

 他のキーについても同様に書くと、以下のようになります。なお、ckeyはCtrl key、dkeyはdown key、lkeyはleft key、rkeyはright keyの略です。

	; キー、ジョイパッドの入力
*In_Key
	ckey=0
	ukey=0
	dkey=0
	lkey=0
	rkey=0

	digetkeystate key,0
	if key&256!0 { ckey=1 }
	if key&1!0 { ukey=1 }
	if key&2!0 { dkey=1 }
	if key&4!0 { lkey=1 }
	if key&8!0 { rkey=1 }

	digetkeystate key,1
	if key&16777216!0 { ukey=1 }
	if key&2!0 { dkey=1 }
	if key&64!0 { lkey=1 }
	if key&1048576!0 { rkey=1 }

	if njoy>0 {
		digetjoystate key,0
		if key&16!0 { ckey=1 }
		if key&1!0 { ukey=1 }
		if key&2!0 { dkey=1 }
		if key&4!0 { lkey=1 }
		if key&8!0 { rkey=1 }
	}

	return

[目次へ][前へ][次へ] inserted by FC2 system