コンテンツにスキップ

キーでスムーズに図形を動かす小技

※これは実際のプログラムを見た方が分かりやすいと思います。

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;
}
}