Skip to content

マウスで円をつかんで動かす

Reputeless edited this page Mar 14, 2017 · 5 revisions

1. 基本

# include <Siv3D.hpp>

void Main()
{
	Circle circle(200, 200, 50);

	// つかんでいたら true, そうでない場合は false
	bool grabbed = false;

	while (System::Update())
	{
		if (circle.leftClicked)
		{
			// 円をクリックしたらつかむ
			grabbed = true;
		}
		else if (Input::MouseL.released)
		{
			// マウスの左クリックが離されたら離す
			grabbed = false;
		}
		else if (grabbed)
		{
			// つかんでいる間はマウスの移動量分だけ円を動かす
			circle.moveBy(Mouse::Delta());
		}

		circle.draw(Palette::Skyblue);
	}
}

2. つかめる場合はカーソルを手の形にする

# include <Siv3D.hpp>

void Main()
{
	Circle circle(200, 200, 50);

	bool grabbed = false;

	while (System::Update())
	{
		if (circle.leftClicked)
		{
			grabbed = true;
		}
		else if (Input::MouseL.released)
		{
			grabbed = false;
		}
		else if (grabbed)
		{
			circle.moveBy(Mouse::Delta());
		}

		// カーソルのアイコンを手の形にするなら true, そうでない場合は false
		const bool handCursor = circle.mouseOver;

		Cursor::SetStyle(handCursor ? CursorStyle::Hand : CursorStyle::Default);

		circle.draw(Palette::Skyblue);
	}
}

3. つかんでいる間は影を付ける

# include <Siv3D.hpp>

void Main()
{
	// 背景色を白に
	Graphics::SetBackground(Palette::White);

	Circle circle(200, 200, 50);

	bool grabbed = false;

	while (System::Update())
	{
		if (circle.leftClicked)
		{
			grabbed = true;
		}
		else if (Input::MouseL.released)
		{
			grabbed = false;
		}
		else if (grabbed)
		{
			circle.moveBy(Mouse::Delta());
		}

		const bool handCursor = circle.mouseOver;

		Cursor::SetStyle(handCursor ? CursorStyle::Hand : CursorStyle::Default);

		if (grabbed)
		{
			// つかんでいる場合、円の影を描く
			circle.drawShadow({ 0,2 }, 12, 3);
		}

		circle.draw(Palette::Skyblue);
	}
}

4. クラスにまとめる

# include <Siv3D.hpp>

class GrabCircle
{
private:

	Circle m_circle;

	Color m_color;

	bool m_grabbed = false;

public:

	GrabCircle() = default;

	explicit GrabCircle(const Circle& circle)
		: m_circle(circle)
		, m_color(RandomColor()) {}

	const Circle& getCircle() const
	{
		return m_circle;
	}

	void update()
	{
		if (m_circle.leftClicked)
		{
			m_grabbed = true;
		}
		else if (Input::MouseL.released)
		{
			m_grabbed = false;
		}
		else if (m_grabbed)
		{
			m_circle.moveBy(Mouse::Delta());
		}
	}

	void draw() const
	{
		if (m_grabbed)
		{
			m_circle.drawShadow({ 0,2 }, 12, 3);
		}

		m_circle.draw(m_color);
	}
};

void Main()
{
	Graphics::SetBackground(Palette::White);

	GrabCircle circle(Circle(200, 200, 50));

	while (System::Update())
	{
		circle.update();

		circle.draw();

		const bool handCursor = circle.getCircle().mouseOver;

		Cursor::SetStyle(handCursor ? CursorStyle::Hand : CursorStyle::Default);
	}
}

5. 複数の円を扱う

# include <Siv3D.hpp>

class GrabCircle
{
private:

	Circle m_circle;

	Color m_color;

	bool m_grabbed = false;

public:

	GrabCircle() = default;

	explicit GrabCircle(const Circle& circle)
		: m_circle(circle)
		, m_color(RandomColor()) {}

	const Circle& getCircle() const
	{
		return m_circle;
	}

	void update()
	{
		if (m_circle.leftClicked)
		{
			m_grabbed = true;
		}
		else if (Input::MouseL.released)
		{
			m_grabbed = false;
		}
		else if (m_grabbed)
		{
			m_circle.moveBy(Mouse::Delta());
		}
	}

	void draw() const
	{
		if (m_grabbed)
		{
			m_circle.drawShadow({ 0,2 }, 12, 3);
		}

		m_circle.draw(m_color);
	}
};

void Main()
{
	Graphics::SetBackground(Palette::White);

	Array<GrabCircle> circles = 
	{
		GrabCircle(Circle(100, 100, 50)),
		GrabCircle(Circle(300, 100, 50)),
		GrabCircle(Circle(500, 100, 50)),
		GrabCircle(Circle(300, 300, 50)),
	};

	while (System::Update())
	{
		for (auto& circle : circles)
		{
			circle.update();
		}

		for (const auto& circle : circles)
		{
			circle.draw();
		}

		bool handCursor = false;

		for (const auto& circle : circles)
		{
			if (circle.getCircle().mouseOver)
			{
				handCursor = true;
				break;
			}
		}

		Cursor::SetStyle(handCursor ? CursorStyle::Hand : CursorStyle::Default);
	}
}

6. 重なり順を考慮する

# include <Siv3D.hpp>

class GrabCircle
{
private:

	Circle m_circle;

	Color m_color;

	// 最後につかまれた時刻(ミリ秒)
	uint32 m_lastUpdateTimeSec = 0;

	bool m_grabbed = false;

public:

	GrabCircle() = default;

	explicit GrabCircle(const Circle& circle)
		: m_circle(circle)
		, m_color(RandomColor()) {}

	const Circle& getCircle() const
	{
		return m_circle;
	}

	bool update()
	{
		if (m_circle.leftClicked)
		{
			m_grabbed = true;

			m_lastUpdateTimeSec = Time::GetMillisec();

			return true;
		}
		else if (Input::MouseL.released)
		{
			m_grabbed = false;
		}
		else if (m_grabbed)
		{
			m_circle.moveBy(Mouse::Delta());
		}

		return false;
	}

	void draw() const
	{
		if (m_grabbed)
		{
			m_circle.drawShadow({ 0,2 }, 12, 3);
		}

		m_circle.draw(m_color);
	}

	uint32 getLastUpdateTime() const
	{
		return m_lastUpdateTimeSec;
	}
};

void Main()
{
	Graphics::SetBackground(Palette::White);

	Array<GrabCircle> circles = 
	{
		GrabCircle(Circle(100, 100, 50)),
		GrabCircle(Circle(300, 100, 50)),
		GrabCircle(Circle(500, 100, 50)),
		GrabCircle(Circle(300, 300, 50)),
	};

	while (System::Update())
	{
		for (auto& circle : circles)
		{
			// 1 つの円がつかまれたら、それ以外の円は処理しない
			if (circle.update())
			{
				break;
			}
		}

		// 最後につかんだ円が配列の先頭にくるようにソートする
		std::sort(circles.begin(), circles.end(),[](const GrabCircle& a, const GrabCircle& b)
		{
			return a.getLastUpdateTime() > b.getLastUpdateTime();
		});

		// 下の円から順に描く
		for (auto it = circles.rbegin(); it != circles.rend(); ++it)
		{
			it->draw();
		}

		bool handCursor = false;

		for (const auto& circle : circles)
		{
			if (circle.getCircle().mouseOver)
			{
				handCursor = true;
				break;
			}
		}

		Cursor::SetStyle(handCursor ? CursorStyle::Hand : CursorStyle::Default);
	}
}

Siv3D について

  1. Siv3D の基本
  2. 図形を描く
  3. テクスチャを描く
  4. テキストを描く
  5. 文字列と数値の変換
  6. キーボード入力
  7. マウス入力
  8. サウンドの再生
  9. MIDI の再生
  10. ウィンドウと背景
  11. 図形のあたり判定
  12. 乱数
  13. ダイアログ
  14. ドラッグ & ドロップ
  15. アプリの状態
  16. テキストファイル
  17. INI, CSV, JSON
  18. バイナリファイル
  19. GUI
  20. アセット管理
  21. 画像編集
  22. Web カメラ
  23. マイク入力
  24. 経過時間の測定
  25. HSV カラー
  26. ファイルダウンロード
  27. 3D 描画
  28. 2D のレンダーステート
  29. 3D のレンダーステート
  30. パーティクル
  31. スクリーンショット
  32. アプリケーションの公開
  33. さらに学ぶには

表現テクニック集

入出力デバイス

開発のヒント

Clone this wiki locally