キーでスムーズに図形を動かす小技
※これは実際のプログラムを見た方が分かりやすいと思います。
1.利用シーン
シューティングゲームなど、キーボードからの入力でプレーヤーを素早く動かすゲームの場合に使えます。
2.小技を使わない場合
左右矢印キーで移動します。ここでは、keyPressed()の中で位置xを変更しています。こうすると、 キーを押した直後に少し動いてしばらくしてから連続的に動く 、というぎこちない動きになります。また、左右のキーを同時に押してしまった場合、思わぬ動きになることがあります。
float x;
void setup(){ size(600,400);}
void draw() { background(0); rect(x, 350, 100, 30);}
void keyPressed() { if (keyCode == RIGHT) { x += 10; } if (keyCode == LEFT) { x -= 10; }}
3.小技を使った場合
キーを押した直後からスムーズに移動 します。この方法なら、急に反転させた場合や、キーの同時押しをしてしまった場合でも、違和感なく動作します。
ここでのポイントは、冒頭にも書いたように
- 図形の位置xの更新はdraw()の中でする。
- keyPressed()の中では移動量(migi, hidari)を設定するだけ。xの更新はやらない。
- keyReleased()の中で移動量(migi, hidari)を0にする。
です。
float x,migi,hidari; //図形のx座標、左右の移動量
void setup(){ size(600,400);}
void draw() { background(0); x += (migi + hidari); // xの値はdrawの中で変更する rect(x, 350, 100, 30);}
void keyPressed() { if (keyCode == RIGHT) { migi = 10; // keyPressed()の中では、移動量を設定する } if (keyCode == LEFT) { hidari = -10; }}
void keyReleased() { // 「キーを離した」も検知するようにする if (keyCode == RIGHT) { migi = 0; // keyReleased()の中では、移動量を0にする } if (keyCode == LEFT) { hidari = 0; }}
※動作原理さえ分かっていれば、変数名(migi , hidari)、+と-の符号の付け方、+=を使うかどうかなど、自分が覚えやすいように変えても構いませんので、いろいろやってみてください。
4.(応用サンプル)移動しながら弾を撃つ
上記のテクニックを応用して、 移動しながら弾を撃つ ようにすることもできます。スペースキーを押しっぱなしで左右キーを操作してみてください。
サンプルコード
float x, migi, hidari; //発射台のx座標、左右の移動量float sx, sy = -20; //弾の座標。最初に弾が見えないように、syはマイナスの値にしておくboolean spc = false;
void setup() { size(600, 400);}
void draw() { background(0);
//発射台の移動 x += (migi + hidari); rect(x, 350, 30, 30);
//弾の移動 if(spc && (sy < 0)){ //スペースキーが押されている かつ 弾は画面外ならば sy = 350; //弾は発射台に戻る sx = x+15; } sy -= 10; ellipse(sx, sy, 8, 15);}
void keyPressed() { if (keyCode == RIGHT) { migi = 3; } if (keyCode == LEFT) { hidari = -3; } if (key == ' ') { //スペースキーが押された spc = true; }}
void keyReleased() { if (keyCode == RIGHT) { migi = 0; } if (keyCode == LEFT) { hidari = 0; } if (key == ' ') { //スペースキーが離された spc = false; }}
5.(応用サンプル)上下左右に動くバーでボールキャッチ
バーを 上下左右に動かせるように してみましょう。また、キャッチする位置で得点が変わるようにしてみましょう。制限時間を設け、高得点を競いましょう。
サンプルコード
//上下左右ボールキャッチゲーム
//特徴//・落ちてくるボールの色は毎回変わります。//・ただし、キャッチしそこなうと、前回と同じ色で落ちてきます//・矢印キーでバーが上下左右にスムーズに動きます。//・キャッチする位置によって、得点が変わります。上の方でキャッチすると高得点です。//・キャッチした位置に得点が表示されます。//・制限時間内に高得点を目指してください。
float ball_x, ball_y; //ボールの座標float rx, ry ; //ラケットの座標float hit_x, hit_y; //得点の表示位置座標int tokuten, hit;float red, green, blue;float hit_red, hit_green, hit_blue;float migi, hidari, ue, shita;float speed; //ラケットの動くスピードint limit_time, timer, ms ;
void setup() { size(600, 400); noStroke(); ball_y = 0; ball_x = random(600); red = random(255); green = random(255); blue = random(255); speed = 5; rx = 300; ry = 350; PFont font = createFont("MS ゴシック", 14); textFont(font); hit_x = -100; //得点の表示位置の初期値が-100なのは、ゲーム最初にhit点を画面内に表示させないため。 hit_y = -100; tokuten = 0; hit = 0; limit_time = 10; //制限時間}
void draw() { background(255);
//ボールの動き ball_y += 3; fill(red, green, blue); ellipse(ball_x, ball_y, 50, 50); if (ball_y > 400) { ball_y = 0; ball_x = random(600); //ボールをキャッチしそこねたら、次回も同じ色のままに。 }
//ラケットの動き rx += (migi - hidari); ry += (shita - ue); fill(255, 0, 0); rect(rx, ry, 100, 30);
//ラケットとボールの当たり判定 if ((ball_y > (ry-25)) && (ball_y < (ry+55)) && (ball_x > (rx-25)) && (ball_x < (rx+125))) { hit = int((400-ball_y)/10); tokuten += hit; hit_x = ball_x; hit_y = ball_y; ball_y = 0; ball_x = random(600); hit_red = red; hit_green = green; hit_blue = blue; red = random(255); //ボールをキャッチしたら、色を変える。 green = random(255); blue = random(255); }
//得点表示 fill(0); textSize(40); text("得点 ", 50, 50); text(tokuten, 150, 50); textSize(20); fill(hit_red, hit_green, hit_blue); text(hit, hit_x, hit_y);
//タイマー処理 ms = millis()/1000; timer = limit_time - ms; if (timer > 0) { textSize(40); fill(0); text("残り時間: "+timer, 350, 50); } else { textSize(60); fill(255, 0, 0); text("TIME UP!", 200, 150); noLoop(); }}
void keyPressed() { if (keyCode == RIGHT) { migi = speed; } if (keyCode == LEFT) { hidari = speed; } if (keyCode == UP) { ue = speed; } if (keyCode == DOWN) { shita = speed; }}
void keyReleased() { if (keyCode == RIGHT) { migi = 0; } if (keyCode == LEFT) { hidari = 0; } if (keyCode == UP) { ue = 0; } if (keyCode == DOWN) { shita = 0; }}