見出し画像

「〇〇キーが押されたら…」はとても簡単!- パート❸:keyPressedでキー操作をすべて検知できる - JavaScriptでやる1分間プログラミング

前回パート❷ではジャンプの動きのロジックを考えてみました。ジャンプ量をvelocity(速度)という値で表現し、このvelocityを重力分だけ毎回小さくしていくと飛び上がった後に頂点に達し、その後落ちていくジャンプの動きが表現できました。

ゲームのようにキーを押したらジャンプさせたい

ところが、今のところプログラムを実行したらジャンプはするのですが、たったの一回のみ。それ以降は何も起こりません。もう一度ジャンプが見たい場合はプログラムを実行し直さないといけないわけです。これではダメで、やはりゲームのように何かキーを押すとジャンプを何度もするようにしたいですよね。

それではユーザのキー操作をどうやってチェックできるのでしょうか。例えば「スペースバーを押したらジャンプする」にはどうしたらよいのでしょうか。

まずは現段階のコードをもう一度見てみます。これまでのコメントはわかりやすいように書き直しています。

let unicorn; //ユニコーン変数を作る

function setup() {
createCanvas(400, 400);
//ユニコーンを一つ作る
unicorn = new Unicorn(100, height-25, 50);
}

function draw() {
background(220);
fill(200, 0, 200);
unicorn.move(); //ユニコーンを動かす.
unicorn.show(); //ユニコーンを表示させる
}

//ユニコーンのクラス
class Unicorn {
//コンストラクタ
constructor (x, y, r) {
  this.x = x;
  this.y = y;
  this.r = r;
  this.velocity = 25; //最初のジャンプ量
}
 
//動く
move() {
  this.y -= this.velocity; //ジャンプ距離分をYから引く(上昇)
  this.velocity -= 5; //ジャンプ移動距離から重力分の5を引く
}
//クラスの表示 
 show() {
  this.y = constrain(this.y, 0, height-this.r/2);
  circle (this.x, this.y, this.r);
 }
}

まずは最初にジャンプしないようにする

今のプログラムは実行するとすぐにジャンプします。その理由は分かりますか?velocity(ジャンプ量)が最初に25と設定されているからです。つまりUnicornはその実体が作られるとすぐに「ジャンプする」ようになっているのです。

プログラムがスタートした時点でUnicornがnew Unicorn()で作成されますが、その段階ではジャンプしてもらっては困るのです。キーが押されるまで待ってもらわないといけません。そのためにどうしますか?

そうです、最初のvelocityをゼロにします。

//コンストラクタ
constructor (x, y, r) {
  this.x = x;
  this.y = y;
  this.r = r;
  this.velocity = 0; //1⃣ 最初のジャンプ量はゼロにする
}

これでプログラムを実行した段階ではUnicornは地面に置かれたまま動きません。ジャンプ量がゼロなので何も動かないということ。まずは初期状態はこれでOKです。

キー操作はkeyPressed関数で検知する

p5.jsにはキー操作を検知する簡単な関数が用意されています。それがkeyPressed(キーが押された)です。

function keyPressed() {
 
  ・・・処理を書く・・・
  
}

この関数を加えるだけでキーのどれかが押されたらこの関数が呼び出されます。つまりこの中にキーが押されたときのコードを書けばよいのです。

今回は「スペースバーが押されたらジャンプする」ですから、まずは「もし押されたキーがスペースバーだったら」という条件文を書きます。

function keyPressed() {
  if (key == ' ') {
   ・・・処理を書く・・・
  }
}

キーが押されるとkeyという値に情報が入っています。スペースバーの場合は簡単で、それが空の文字(引用符の間にスペースがあります)であるかどうかを確かめます。これで押されたキーがスペースバーかどうかチェックできます。

スペースが押されたらジャンプする…とうやって?

ではこのIF文の中でなにをすればよいのでしょうか。それはもちろんジャンプなのですが、Unicornクラスにはmoveというメソッドしかありません。これはジャンプの動きを表すコードなので、そもそもジャンプを始めた”後”の話です。そこでジャンプを始動させるためにjump関数をUnicornクラスに追加しましょう

//ジャンプ
 jump () {
   this.velocity = 50;
 }

ここでやっていることはとても単純です。冒頭でUnicornのジャンプ量、つまりvelocityをゼロにして動かないようにしましたよね。逆にこれに値を入れてやるだけでジャンプが始動するのです。ここではちょっと大きめに50としています。

これをキー操作の関数のところで呼び出します。

//3⃣ キー操作の検知
function keyPressed() {
 if (key == "ArrowUp")
   unicorn.jump(); //jump関数を呼び出す
}

最終的なコードは次のようになります。

let unicorn; //ユニコーン変数を作る

function setup() {
createCanvas(400, 400);
//ユニコーンを一つ作る
unicorn = new Unicorn(100, height-25, 50);
}

//3⃣ キー操作の検知
function keyPressed() {
 if (key == ' ')
   unicorn.jump(); //jump関数を呼び出す
}

function draw() {
background(220);
fill(200, 0, 200);
unicorn.move(); //ユニコーンを動かす.
unicorn.show(); //ユニコーンを表示させる
}

//ユニコーンのクラス
class Unicorn {
//コンストラクタ
constructor (x, y, r) {
  this.x = x;
  this.y = y;
  this.r = r;
  this.velocity = 0; //1⃣ 最初のジャンプ量はゼロにする
}

//2⃣ jump関数を追加する
jump() {
 this.velocity = 50; 
}
 
//動く
move() {
  this.y -= this.velocity; //ジャンプ距離分をYから引く(上昇)
  this.velocity -= 5; //ジャンプ移動距離から重力分の5を引く
}
//クラスの表示 
 show() {
  this.y = constrain(this.y, 0, height-this.r/2);
  circle (this.x, this.y, this.r);
}
}

これを実行して、最初にキャンバスのどこかを一度クリックしてからスペースバーを押してください。プログラムをスタートするのに▶ボタンをクリックする瞬間、フォーカスがプログラミングをするところに移るので、それを右サイドのブラウザに戻す必要があるためです。

画像1

いい感じでジャンプしますよね。スペースバーで何度もできます。

画像2

左右にジャンプしたい場合は?

ではもう少し複雑な動きにしてみます。今はジャンプは最初に円が現れた場所でしかできません。左右に動きながらジャンプしたほうがもっとリアルですよね。つまりスペースバーを押してポーンと上に上がったら、左右の矢印キーで横に空中移動するようにしたいです。

ではどうするか考えてみてください。何だかわかった気がしませんか?そうです、あの「キーが押されたら」のところで左右の矢印キーを加えればよいのではないでしょうか。そう考えた方はすばらしい!考え方は大正解なのですが、残念ながらここではちょっとも問題があるのです。

//3⃣ キー操作の検知
function keyPressed() {
 if (key == ' ')
   unicorn.jump(); //jump関数を呼び出す
}

例えばここをこう変えたとします。

//3⃣ キー操作の検知
function keyPressed() {
  if (key == ' ')
   unicorn.jump(); //jump関数を呼び出す
  else if (key == "ArrowRight")
    unicorn.x += 10;
  else if (key == "ArrowLeft")
    unicorn.x -= 10;
}

ロジックとしては問題ありません。keyが"ArrowRight"(右矢印)ならXの位置を10増やして右に行きます。反対に左矢印なら10引いて左に行きます。

でもこのように変更して実行すると、左右の動きがちょっと変ですよね。左右には動くのですが、キーを何回も押さないと動き続けません。これはキーを一回押した(keyPressed)ということに反応するので、押し続けることに反応しません。ちょっと難しいですよね。

そこで左右のキーを押し続けることに反応させたい場合はdraw関数の中で毎回毎回キーをチェックすればよいのです。このコードを見てください。


function draw() {
 background(220);
 fill(200, 0, 200);
 
 //左右のキーに動きを反応させる
 if (keyIsPressed) {
   if (key == "ArrowRight")
     unicorn.x += 10;
   else if (key == "ArrowLeft")
     unicorn.x -= 10;
 }
 
 unicorn.move(); //ユニコーンを動かす.
 unicorn.show(); //ユニコーンを表示させる
}

こするとスペースバーでジャンプした直後に左右の矢印キーを押すとふわっと左右に動きますよね。

画像3

「ジャンプと左右でコードを書く場所が別々なのはなんだかいや。ジャンプの部分もこのdrawの中のIF文に入れたらよいのでは?」と考えたあなた。もっともなポイントです!でもそれはちょっとまずいのです。ジャンプ操作をdrawの中に入れると、ちょっとゆったり目にスペースバーを押すとジャンプが何回か連続して発生してしまいます。瞬間的にポンと素早く押さないと一回のジャンプにならないのです。これはこれでまずいですよね。なので、ジャンプは一回のキー操作を検知するkeyPressed関数の中で処理し、連続してキーを検知してほしい左右の動きはdraw関数に入れるのです。

こういったことは”覚える”必要はどは一切ありません。自分でコードを書く中で、自分が実現したい動きにはどの関数を使うのが最も良いのかをその場その場で見つけていけばよいだけです。あとは自然にいつ何を使うかがわかってきますので、今は心配する必要はありません。

では次回はいよいよ円をユニコーンの絵にしてみましょう。さらにゲームっぽくなるはずです!

この記事が気に入ったらサポートをしてみませんか?