LoginSignup
2
4

More than 5 years have passed since last update.

ドラッグ&ドロップの実装

Posted at

はじめに

 DxLibでGUI開発を行う中でアイテムなどを選択する操作でドラッグ&ドロップ(D&D)で実装したい!ということがあるかと思います。将棋なんかだとポチポチするよりも駒を掴んで動かすほうが気持ちいいですよね。そこで今回はD&Dを実装してみようと思います。

開発の手順

  1. ボタンを作成する -> 疑似ボタンの実装を参照
  2. クリックしている間処理を止める(無限ループ)
  3. マウスの左ボタンを離したときに動作するボタンを作成する

 この手順で実装します。

なぜこうなるの?

 イメージしやすいよう今回は将棋を題材に説明していきます。
 D&Dをする手順としては「駒を掴む -> 駒を移動させる -> 駒を置く」という3ステップで行うことになります。ここにユーザーの操作を付け加えると「駒の上でクリックして駒を掴む -> クリックしたままマウスを動かして移動させる -> マウスのボタンを離して駒を置く」となります。
 もう少しプログラム的な言い方に変えてみると

 1. クリックしたところが駒の上か範囲判定をして真であればD&Dの処理を開始する
 2. 駒の移動が終わるまで待つ
 3. ボタンを離したときにその位置に駒を置く

となります。

ボタンを作成する

 これについては疑似ボタンの実装を参考にして行ってください。

クリックしている間処理を止める(無限ループ)

 DxLibにはWaitKey()という処理待ち用の関数がありますが様々な事情によりよろしくないということ、アニメーションや時間管理を同時に行っている場合にはすべての処理が止まってしまうことから使用しません。無限ループは空で書けば処理待ちのみ、内部に処理を書き込めば続けて実行したい処理のみを行うことができゲームなどでは特に有用です。

while (GetMouseInput() & MOUSE_INPUT_LEFT) {
        // アニメーションなどをつけたければここに処理を書く
}

 基本的にはループを空回ししているだけです。ただ、これだとマウスで掴んだものが半透明になってついてくるようなことはなく、画面上ではただマウスが動くだけなのでアニメーションとしては少し寂しいかもしれませんね。一緒に動かす処理を書くならwhile文の中に、選択中のものをちょっと暗くしたりするならwhile文の前に処理を記述しましょう。

マウスの左ボタンを離したときに動作するボタンを作成する

 少しイメージしづらいかもしれませんが作るのはボタンになります。普通のボタンは"押した"ときに反応しますがその逆を作ります。そのためにはいくつかのステップを踏む必要があります。
 前提としてマウスの左ボタンが押された状態である必要があります。これは先ほどのループで実現しています。つまりさっきの処理を書いておけば普通のボタンと違ってマウスがクリックされたかどうかの判定は必要なくなります。ですから、座標の判定からの処理で問題ありません。このことを把握しておけば後は普通にボタンを作るだけで問題ありません。

実装

 今回は将棋を作るものではないので駒をただ置くだけにしています。これまでのページから画像を張り付けてもらえば問題ないでしょう。

int komaX = 300, komaY = 300; // 持ち駒の座標
int banX = 100, banY = 100;   // 駒を置く座標
int sizeX = 50, sizeY = 50;   // 駒のサイズ

if (GetMouseInput() & MOUSE_INPUT_LEFT) {
  int posX, posY;

  // マウスの座標を取得(何を選択したかを判定する要素)
  GetMousePoint(&posX, &posY);
  if ((posX >= komaX) && (posX < (komaX + sizeX))) {  // 駒の上か判定(X座標)
    if ((posY >= komaY) && (posY < (komaY + sizeY))) {  // 同様(Y座標)    
      while (GetMouseInput() & MOUSE_INPUT_LEFT) {
        // アニメーションなどをつけたければここに処理を書く
      }

      // マウスの座標を取得(どこに置いたかを判定する要素)
      GetMousePoint(&posX, &posY);
      if ((posX >= banX) && (posX < (banX + sizeX))) {
        if ((posY >= banY) && (posY < (banY + sizeY))) {
          DrawString(0, 0, "Conguratulation!", GetColor(255, 0, 0));
        }
      }
    }
  }
}

 判定部に関しては理解しやすいように2文に分けて書いていますがまとめてもらって構いません。Conguratulation!の赤文字が表示されれば成功です。

さいごに

 普段何気なくしていることを少し分解して考えると自分で実装できる機能は意外と多くあります。少し意識して生活してみると開発のアイデアも浮かびそうですね。

2
4
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
2
4