LoginSignup
1
3

More than 5 years have passed since last update.

Delphi アプリ - スマホのシェイクをざっくりと検知

Last updated at Posted at 2017-11-20

スマホを振った時に何か処理させたいときですが、OnShake のような便利なイベントというのはありません。
残念ながら、振られたのか、ただの移動なのかはセンサーだけでは判断はできないのです。
「Android shake 検出」などのキーワードで、検索すると皆さんいろいろなロジックで検知しています。
( 基本的に、加速度センサーを使って検知します )

Delphi で作ったアプリで実装してみました。
加速度センサーのコンポーネント TMotionSensor と TTimer を使って、振り幅と、速度から、ざっくりとしたアルゴリズムで検知しています。

ざっくりとしたアルゴリズム

一定時間内(0.3秒)で、振り幅が ±1 以上であればカウントを行い、カウントが 3 以上になったらシェイクとみなしています。
シェイクの方向は X, Y, Z それぞれありますので、
( 基点の X + Y + Z ) - ( 時間内終点の X + Y + Z )
の値を振り幅としています。

設計画面

MotionSensor の Active を True にしておくのを忘れずに
sk01.png

サンプルコード

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.Controls.Presentation, System.Sensors, System.Sensors.Components;

type
  TForm1 = class(TForm)
    ToolBar1: TToolBar;
    Switch1: TSwitch;
    Label1: TLabel;
    Timer1: TTimer;
    MotionSensor1: TMotionSensor;
    procedure Timer1Timer(Sender: TObject);
    procedure Switch1Switch(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private 宣言 }
  public
    keepPoint: Double;      //位置保存
    shakeCount: Integer;  //振りカウント
    { public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormCreate(Sender: TObject);
begin
// 初期化
  keepPoint  := 0;
  shakeCount := 0;
  Label1.Text := ' ';
end;

procedure TForm1.Switch1Switch(Sender: TObject);
begin
//スイッチが ONになったらカウントの初期化と基本ざっくり位置を保存する
  if Switch1.IsChecked then begin
    shakeCount := 0;
    Label1.Text := ' ';
    keepPoint := MotionSensor1.Sensor.AccelerationX
      + MotionSensor1.Sensor.AccelerationY
      + MotionSensor1.Sensor.AccelerationZ;
  end;

//Timerの起動を制御
  Timer1.Enabled := Switch1.IsChecked;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  mPoint: Double;  //作業用
begin
// 振りカウントが 3以上になったらシェイクとみなす
  if shakeCount > 3 then begin
    Label1.Text := 'しぇいく';
    shakeCount := 0;
    Switch1.IsChecked := False;
    exit;
  end;

// 現在位置ざっくり
  mPoint := MotionSensor1.Sensor.AccelerationX
   + MotionSensor1.Sensor.AccelerationY
   + MotionSensor1.Sensor.AccelerationZ;

  if ((keepPoint - mPoint) > 1) or ((keepPoint - mPoint) < -1) then begin
  // 振りカウント +1
    shakeCount := shakeCount + 1;
  end;

// 現在ざっくり位置保存
  keepPoint := mPoint;

end;

end.

実行してみる

アプリを起動して
Screenshot_2017-11-09-17-27-35.png

スイッチを ON にして、スマホをふりふり
Screenshot_2017-11-09-17-27-48.png
と検知しました!

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3