コラム / テトリスぽいもの / 24



ブロックが落ちてくるようになったので、
それを動かす部分を作りましょう。
動かす部分にはキー入力のチェックが必要です。
具体的な方法は後で説明するとして、
キー入力情報では、
「押しているか、押していないか」しかわかりません。
しかし、ゲームの処理では、
「押した直後」や、「一定時間押し続けたら」
といった判定をしたいことがあります。
例えば移動なら、
右を押していたら毎フレーム右に移動だと、
瞬きする間に瞬間移動してしまいます。
ん?瞬きする間の移動を瞬間移動っていうのか。
頭痛で頭が痛い。馬から落馬して落ちた。
さて、そこで、
俺オススメの手法が、
「押されたらキーカウンタを+1、

  離されたらキーカウンタを0」

という処理を、毎フレームとおすことです。
そうするとこうなります。

key.png

キーカウンタが0なら離している
キーカウンタが1なら押した直後
キーカウンタが2以上なら押し続けていて、カウンタ値が押し続けた長さ
と、必要な情報が扱いやすい数値体系でわかります。
この、キーカウンタ処理を一括して行うクラスがあると、
いっそう整理されるのですが、
今回は単純に実装しましょう。
TPieceに変数を追加します。
   public
       (略)
       death:Boolean;

       k_left,k_right:integer;

       procedure Init(_x,_y,dm:Integer;mb:TMapBlocks);

       (略)
   end;
k_left 左キーのキーカウンタです。
k_ ってのは keyの って意味です。
k_right 右に同じ。つか左に同じ。
で、初期化関数で初期化します。
initの実装部を編集です。
procedure TPiece.Init(_x,_y,dm:Integer;mb:TMapBlocks);
begin
   x:=_x;
   y:=_y;
   d_counter:=0;
   d_max:=dm;
   MapBlocks:=mb;
   death:=False;

   k_left:=0;
   k_right:=0;
end;
そして、mainにキーカウント処理を追加します。
procedure TPiece.Main;
begin

   if GetKeyState(VK_LEFT)<0 then k_left:=k_left+1 else k_left:=0;
   if GetKeyState(VK_RIGHT)<0 then k_right:=k_right+1 else k_right:=0;

   d_counter:=d_counter+1;         //1増える
   if d_counter=d_max then begin
       d_counter:=0;               //maxになったら即リセット
   end;
   (略)
end;
追加されたのは2行です。
   if GetKeyState(VK_LEFT)<0 then k_left:=k_left+1 else k_left:=0;
   if GetKeyState(VK_RIGHT)<0 then k_right:=k_right+1 else k_right:=0;
if else 文ですね。
条件は、GetKeyState(VK_LEFT)<0です。
GetKeyState関数は、与えられた仮想キーコードが、
押されていたら負の数を返し、押されていなければ0以上の数を返します。
この場合は、GKS<0 なので、押されていたら真になる式ですね。
仮想キーコードとはなんでしょうか。
まぁ、キーの番号です。
仮想ってのは、実際のハードウェアではなく、
Windows経由でアクセスするため、仮想キーに抽象化されてる
ってことなんですが、
まぁ、キーの番号です。(2回目
もし、押されていたら、カウンタを1増やし、
( x:=x+1 は 1増える式ってのは大丈夫ですよね。
離されていたら、一気に0です。
では、次回で移動させましょう。