連載
» 2013年11月05日 18時00分 公開

PC制御UIの最先端Leapアプリ開発入門(3):ProcessingやWindows 8.1アプリでLeapの空間ジェスチャを使うには (2/4)

[密葉優,@IT]

ProcessingのLeapジェスチャサンプルを使う

 前回はLeapのライブラリに同梱されているサンプルの「active_fingers.pde」でしたが、今回のプログラムも同様にライブラリのサンプルに「gesture_recognition.pde」として、用意されています。

 ジェスチャのオン/オフ機能やジェスチャ情報の表示用のコードが入っており、前回に比べて、大分長く感じますが、作りは至ってシンプルです。少しずつ読み解いてみましょう。

Leapのジェスチャ用ライブラリをインポート

 初めにジェスチャを含んだ、Leapのライブラリをインポートしています。

import com.leapmotion.leap.CircleGesture;
import com.leapmotion.leap.Gesture.State;
import com.leapmotion.leap.Gesture.Type;
import com.leapmotion.leap.Hand;
import com.leapmotion.leap.KeyTapGesture;
import com.leapmotion.leap.ScreenTapGesture;
import com.leapmotion.leap.SwipeGesture;
import com.onformative.leap.LeapMotionP5;

変数定義

 次に、Leapの変数定義と、最初に表示する文字列を変数に定義しています。

LeapMotionP5 leap;
String lastGesture =
"enabling gestures: \n'c' for CircleGesture\n's' for SwipeGesture\n'k' for KeyTapGesture\n't' for ScreenTapGesture";

setup()メソッド

 setup()ではアプリのサイズを500px×500pxに設定し、表示する文字列のサイズを「17」と設定しています。最後にLeapの初期化を行っています。

public void setup() {
  size(500, 500);
  textSize(17);
  leap = new LeapMotionP5(this);
}

draw()メソッド

 draw()では、背景色を黒に設定し、認識した手の数だけ、認識した位置に円を描画しています。最後に左上から30pxのところに文字列を描画しています。

public void draw() {
  background(0);
  for (Hand hand : leap.getHandList()) {
    PVector handPos = leap.getPosition(hand);
    ellipse(handPos.x, handPos.y, 20, 20);
  }
  text(lastGesture, 30, 30);
}

終了処理

 アプリケーション終了時にはLeapの終了処理を行っています。

public void stop() {
  leap.stop();
}

 ここまでは前回紹介したものとほとんど同じで、ゲームループに沿って書かれています。

keyPressed()メソッド

 続いて、keyPressed()を見てみましょう。keyPressed()はキーボードから何らかのキーが押された時に実行される関数です。もうお気付きかもしれませんが、keyPressed()はゲームループの中にはいない、イベントのように実行される関数です。

 Processingはsetup()、draw()、stop()の3つの関数でゲームループを構築していますが、その他にイベント的に呼べる関数も用意されています。そのため、「ユーザーが何かしたとき、どう振る舞う」というインタラクティブなアプリがとても開発しやすいのです。

 ではkeyPressed()のコードを見てみましょう。上から順番に、「c」が押された時、「s」が押された時、「k」が押された時、「t」が押された時と書かれていますが、どれも同じような処理が記述されています。

public void keyPressed() {
  if (key == 'c') {
    if (leap.isEnabled(Type.TYPE_CIRCLE)) {
      leap.disableGesture(Type.TYPE_CIRCLE);
      lastGesture = "Circle Gesture disabled.";
    } 
    else {
      leap.enableGesture(Type.TYPE_CIRCLE);
      lastGesture = "Circle Gesture enabled.";
    }
  }
  if (key == 's') {
    if (leap.isEnabled(Type.TYPE_SWIPE)) {
      leap.disableGesture(Type.TYPE_SWIPE);
      lastGesture = "Swipe Gesture disabled.";
    } 
    else {
      leap.enableGesture(Type.TYPE_SWIPE);
      lastGesture = "Swipe Gesture enabled.";
    }
  }
  if (key == 'k') {
    if (leap.isEnabled(Type.TYPE_KEY_TAP)) {
      leap.disableGesture(Type.TYPE_KEY_TAP);
      lastGesture = "KeyTap Gesture disabled.";
    } 
    else {
      leap.enableGesture(Type.TYPE_KEY_TAP);
      lastGesture = "KeyTap Gesture enabled.";
    }
  }
  if (key == 't') {
    if (leap.isEnabled(Type.TYPE_SCREEN_TAP)) {
      leap.disableGesture(Type.TYPE_SCREEN_TAP);
      lastGesture = "ScreenTap Gesture disabled. ";
    } 
    else {
      leap.enableGesture(Type.TYPE_SCREEN_TAP);
      lastGesture = "ScreenTap Gesture enabled. ";
    }
  }
}

 cが押された時の処理を見てみると、「leap.isEnabled(Type.TYPE_CIRCLE)」で、Circleのジェスチャが有効化どうかをチェックしています。

 有効であれば、「leap.disableGesture(Type.TYPE_CIRCLE);」で無効化し、「無効にした」と文字列表示用の変数を書き換えています。同様に無効であれば、有効にし、「有効にした」と文字列を書き換えています。

 if (key == 'c') {
    if (leap.isEnabled(Type.TYPE_CIRCLE)) {
      leap.disableGesture(Type.TYPE_CIRCLE);
      lastGesture = "Circle Gesture disabled.";
    } 
    else {
      leap.enableGesture(Type.TYPE_CIRCLE);
      lastGesture = "Circle Gesture enabled.";
    }
  }

ジェスチャ用のメソッド群

 最後にジェスチャ部分のメソッドを見てみましょう。ジェスチャのメソッドはそれぞれ、circleGestureRecognized()、swipeGestureRecognized()、screenTapGestureRecognized()、KeyTapGestureRecognized()、とあります。また、KeyTapGestureRecognized()の動作が不安定なので、KeyTapGestureRecognized()については割愛します。

 各ジェスチャの関数もイベントのように実行されます。この関数名と引数はライブラリ側で指定しているため、それぞれの関数名で関数を定義するだけで利用できます。ジェスチャの代表として、circleGestureRecognized()を見てみましょう。

 System.out.printlnはProcessingのIDEの下にあるコンソールに出力する関数で、デバッグ用に使われます。コンソールに出力したものと同じものを文字列表示用の変数に代入しています。ジェスチャの各情報はgestureのプロパティから取得できます。

 public void circleGestureRecognized(CircleGesture gesture, String clockwiseness) {
  if (gesture.state() == State.STATE_STOP) {
    System.out.println("//////////////////////////////////////");
    System.out.println("Gesture type: " + gesture.type().toString());
    System.out.println("ID: " + gesture.id());
    System.out.println("Radius: " + gesture.radius());
    System.out.println("Normal: " + gesture.normal());
    System.out.println("Clockwiseness: " + clockwiseness);
    System.out.println("Turns: " + gesture.progress());
    System.out.println("Center: " + leap.vectorToPVector(gesture.center()));
    System.out.println("Duration: " + gesture.durationSeconds() + "s");
    System.out.println("//////////////////////////////////////");
    lastGesture = "Gesture type: " + gesture.type().toString() + "\n";
    lastGesture += "ID: " + gesture.id() + "\n";
    lastGesture += "Radius: " + gesture.radius() + "\n";
    lastGesture += "Normal: " + gesture.normal() + "\n";
    lastGesture += "Clockwiseness: " + clockwiseness + "\n";
    lastGesture += "Turns: " + gesture.progress() + "\n";
    lastGesture += "Center: " + leap.vectorToPVector(gesture.center()) + "\n";
    lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n";
  } 
  else if (gesture.state() == State.STATE_START) {
  } 
  else if (gesture.state() == State.STATE_UPDATE) {
  }
}

 これと同じような処理が、swipeGestureRecognized()とscreenTapGestureRecognized()にも記述されています。

 ここまでできれば、後はLeapのジェスチャをどう使って、何を表現・操作するかだけですね! Processingを使って、ぜひ空間ジェスチャ操作のアプリを作ってみてください。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。