ぷにコンみたいな処理の作り方（タッチ・ドラック等イベントの取得について）

環境 : Gamemaker Studio 2  (出力するプラットフォームは、HTML5)
結論 : ぷにコンじゃなくて、ただのコン・・。


こんばんは。Aki [@aki_0o0_](https://twitter.com/aki_0o0_)です。
**ぷにっとはしてないです。**ただ上下左右に入力するコントローラーの処理をつくります。
（あと、タッチ処理も）

- ボタン（タップする）
-  上下左右のキー（ドラッグする）


### 実装
- 押したら、その位置が起点になる
- 押している間は、起点から見た４方向どれかの、キー入力の処理
- 離した時、位置が動いていなかったら、タップの処理

### 公式のサンプルを参考にして作っていきましょう

「YoYo Dungeon Lite」というサンプルを基本にします。
そのプロジェクトの MovePlayer.gml　というスクリプトをみます。
キーボード入力で移動させる処理

```MovePlayer.gml
// Process keys....
if( keyboard_check(vk_left)){
    if( dir != DIR_LEFT) {
        dir = DIR_LEFT;
        sprite_index = sprites[dir];
        image_index=0;
        image_speed = 1.0;
        dx = -player_speed;
        dy = 0;
    }
}else if( keyboard_check(vk_right)){
    if( dir != DIR_RIGHT) {
        dir = DIR_RIGHT;
        sprite_index = sprites[dir];
        image_index=0;
        image_speed = 1.0;
        dx = player_speed;
        dy = 0;
    }
}else if( keyboard_check(vk_up)){
    if( dir != DIR_UP) {
        dir = DIR_UP;
        sprite_index = sprites[dir];
        image_index=0;
        image_speed = 1.0;
        dy = -player_speed;
        dx = 0;
    }
}else if( keyboard_check(vk_down)){
    if( dir != DIR_DOWN) {
        dir = DIR_DOWN;
        sprite_index = sprites[dir];
        image_index=0;
        image_speed = 1.0;
        dy = player_speed;
        dx = 0;
    }
}else{
    if( dir != DIR_STOP) {
        dir = DIR_STOP;
        sprite_index = sprites[dir];
        image_index=0;
        image_speed = 1.0;
        dy = 0;
        dx = 0;
    }
}

```

### リファレンスを見てみよう。使えそうな関数を探そう。

https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/
関数一覧が載ってる。

#### タップの検出
Control Functions -> Device Input
（キーボードやマウスからの入力 -> タップ）


```タップ中
if device_mouse_check_button(0, mb_left)

```
https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/controls/device%20input/device_mouse_check_button.html

#### ジェスチャについて。
デバイス機能で行うことができますが、簡単にするために、 GameMaker Studio 2には、インスタンスとグローバルレベルの両方でダブルタップ、ドラッグ、フリック、ピンチとローテーションを検出するための「ジェスチャーイベント」がある。
https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/controls/gesture%20input/index.html

##### Drag
- gesture_drag_time

デフォルト値は0.16

それ以下だとタップイベントになる

- gesture_drag_distance

距離はインチで測定され、デフォルト値は0.1

それ以下は検出しない


##### ジェスチャイベント
https://docs2.yoyogames.com/source/_build/2_interface/1_editors/events/gesture_events.html


**「ドラッグ開始イベント」**は、
タッチから設定した時間（デフォルトで0.16秒）が経過したときに
1回トリガされます。

その後、ユーザーがタッチ/クリックしている間は、解除されるまで
**「ドラッグイベント」**がトリガーされます。

**「ドラッグ終了イベント」**は、ユーザーがタッチを離したときにトリガされます。


グローバルじゃない方は、そのオブジェクトをドラッグしたりするもの。
ぷにコン作るには、グローバルドラッグの方を追加する。

### でも、Dragジェスチャじゃなくて、マウス入力を自力で処理する方法で結局、つくった
ので、ジェスチャのほうについては忘れてくださいー。

#### マウス入力
`device_mouse_x`だと、進めば進むほど起点位置がずれるから、_raw か、_gui をつけた方がよさそう

```
-    var xx = device_mouse_x(0) - drag_offsetX;
-    var yy = device_mouse_y(0) - drag_offsetY;
+    var xx = device_mouse_x_to_gui(0) - drag_offsetX;
+    var yy = device_mouse_y_to_gui(0) - drag_offsetY;

```


#### 最後に、色々試した結果の最終的なコードだけ載せておきますね。

```
// Process keys....
if( device_mouse_check_button_pressed(0, mb_left)){
    drag_offsetX = device_mouse_x_to_gui(0);
    drag_offsetY = device_mouse_y_to_gui(0);
}else if( device_mouse_check_button(0, mb_left)){
    var xx = device_mouse_x_to_gui(0) - drag_offsetX;
    var yy = device_mouse_y_to_gui(0) - drag_offsetY;
    var isHorizontal = abs(xx) > abs(yy);
    var isSame = abs(xx) == abs(yy);

// Process keys....
if( isSame){
    // NOP.
}else if( isHorizontal && xx < 0){
    if( dir != DIR_LEFT) {
        drag_offsetX = device_mouse_x_to_gui(0);
        drag_offsetY = device_mouse_y_to_gui(0);
        dir = DIR_LEFT;
        dx = -player_speed_horizontal;
        dy = 0;
    }
}else if( isHorizontal){
    if( dir != DIR_RIGHT) {
        drag_offsetX = device_mouse_x_to_gui(0);
        drag_offsetY = device_mouse_y_to_gui(0);
        dir = DIR_RIGHT;
        dx = player_speed_horizontal;
        dy = 0;
    }
}else if( yy < 0){
    if( dir != DIR_UP) {
        drag_offsetX = device_mouse_x_to_gui(0);
        drag_offsetY = device_mouse_y_to_gui(0);
        dir = DIR_UP;
        dy = -player_speed_vertical;
        dx = 0;
    }
}else{
    if( dir != DIR_DOWN) {
        drag_offsetX = device_mouse_x_to_gui(0);
        drag_offsetY = device_mouse_y_to_gui(0);
        dir = DIR_DOWN;
        dy = player_speed_vertical;
        dx = 0;
    }
}

}else if( device_mouse_check_button_released(0, mb_left)){
    if( dir == DIR_STOP)
    {
        // tap
    }
    else
    {
        dir = DIR_STOP;
        dy = 0;
        dx = 0;
        drag_offsetX = 0;
        drag_offsetY = 0;
    }
}

// process player collision
//ProcessCollision(id, dx,dy, 16,16,16,2 );

x += dx;
y += dy;

```