1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kaijo Physics ClubAdvent Calendar 2024

Day 21

手の動きでコントロールするブロック崩しゲームの実装

Last updated at Posted at 2024-12-20

はじめに

本記事では、MediaPipeを使用して手の動きを認識し、その動きでコントロールするブロック崩しゲームについて説明します

Kaijo Physics Club Advent Calendar 2024に投稿する記事です

技術スタック

  • Pygame (ゲーム開発ライブラリ)
  • MediaPipe (手の認識用ライブラリ)

システム概要

このゲームは以下の2つの主要な機能で構成されています:

  1. ブロック崩しゲームの基本機能

    • 画面上部に配置された青いブロック
    • 落下する赤い球
    • プレイヤーが操作する白いバー
    • 衝突判定と跳ね返り処理
  2. 手の認識による操作

    • MediaPipeによる手のランドマーク検出
    • 検出された座標に基づくバーの移動

実装

1. 必要なライブラリのインポート

import pygame
import time
import cv2
import mediapipe as mp
from multiprocessing import Process, Value
import math

2. 手を検出するモデルを作成する

mp_hands = mp.solutions.hands
mp_draw = mp.solutions.drawing_utils
hands = mp_hands.Hands()

3. メインゲームループ

画面設定や、壁やブロックに当たったときの跳ね返りなどの処理を行います

動作の仕組み

基本メカニズム

  • ボールは画面の端に当たると跳ね返ります
  • 上部のブロックに当たると、そのブロックが消滅し、ボールが跳ね返ります
  • 下部に落ちるとゲームオーバーとなります

手の認識とバーの制御

  1. MediaPipeが手のランドマーク(21個の特徴点)を検出
  2. 21個から、x座標・y座標の最小値・最大値を求め、それらの平均値の座標を計算する
  3. 計算された座標値でバーの位置を決定
if results.multi_hand_landmarks:  # 手が検出された場合
                # 検出された手を2つに絞る
                hand_landmarks = results.multi_hand_landmarks[:2]  # 最初の1つの手のみ処理

                for hand_lms in hand_landmarks:
                    landmarks = []
                    landmark = []
                    for index, lm in enumerate(hand_lms.landmark):
                        ih, iw, _ = img.shape
                        x, y = int(lm.x * iw), int(lm.y * ih)
                        landmark.append([x, y])
                    landmarks.append(landmark)

                    x_list = []
                    y_list = []
                    for i in range(21):
                        x_list.append(landmarks[0][i][0])
                        y_list.append(landmarks[0][i][1])

                    most_right_x = max(x_list)

                    most_left_x = min(x_list)

                    most_up_y = max(y_list)

                    most_down_y = min(y_list)

                    color = (0, 0, 255)  # 囲む線(赤)

                    average_x_value = (most_left_x + most_right_x) // 2
                    average_x.value = average_x_value
                    print(average_x.value)

まとめ

課題としては、複数の手が画面上にあると、検出する手が変わってしまうことが挙げられます
現状MediaPipeには同じ手を追える機能はなく、ID付与などができないので難しい状態です

参考リンク

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?