Heim > Backend-Entwicklung > Python-Tutorial > Wie Python Gestenerkennung nutzt, um das Snake-Spiel zu implementieren

Wie Python Gestenerkennung nutzt, um das Snake-Spiel zu implementieren

WBOY
Freigeben: 2023-05-11 20:19:04
nach vorne
1448 Leute haben es durchsucht

    Projekteinführung

    1. Wie man das Spiel bedient

    Jeder kennt das Spiel „Snake“, aber das wenig bekannte Computer Vision + Snake-Spiel bringt den Menschen mehr Beteiligung und Frische. Dieses Projekt nutzt hauptsächlich Gestenerkennung Schließe das einfache Spiel „Snake“ ab. In diesem Spiel erfasst der Computer unsere Gesten durch die Kamera und bestimmt, ob er sich bewegen soll. Der Spieler bewegt seine Hand, um die Nahrung zu steuern, die zufällig auf dem Bildschirm erscheint Punkt, und der Punktestand wird auf dem Bildschirm angezeigt. Wenn der Spieler während des Betriebs versehentlich mit dem Kopf und Körper kollidiert, wird GameOver angezeigt.

    Wie Python Gestenerkennung nutzt, um das Snake-Spiel zu implementieren

    2. Dinge, die während des Entwicklungsprozesses zu beachten sind

    (1) Das linke und rechte Problem des Bildes

    Weil wir Gesten verwenden, um die Bewegung der Schlange zu steuern, aber das Kamerabild zeigt die Perspektive anderer Dies ist also genau das Gegenteil des linken und rechten Bewusstseins des Spielers, daher müssen wir das von der Kamera gelesene Bild nach links und rechts umdrehen. Im Prinzip wird die Position des linken und rechten Pixels vertauscht, aber in Python können Sie eine cv2.flip()-Funktion verwenden, um eine Spiegelung zu erreichen.

    (2) Das Problem der Kamerabildschirmgröße
    Wir müssen Spiele auf den über die Kamera aufgenommenen Bildern spielen. Wenn der Bildschirm zu klein ist, kann dies zu Beginn zu einer Vorverarbeitung führen Wählen Sie die Bildschirmgröße aus und stellen Sie eine angemessenere Größe ein, damit das endgültige Bild beim Spielen nicht beengt aussieht. Die Breite und Höhe des Bildschirms kann über die Funktionen cap.set(3, m) cap.set(4, n) eingestellt werden.

    In diesem Projekt wird es auch einige andere Vorsichtsmaßnahmen geben, z. B. die Bestimmung von Kollisionen, die Bestimmung der Nahrungsaufnahme usw. Ich werde sie später im Projektprozess vorstellen.

    3. Wichtige Punkte der Spielimplementierung

    Einige verwendete Bibliotheken von Drittanbietern:

    import math
    import random
    import cvzone
    import cv2
    import numpy as np
    from cvzone.HandTrackingModule import HandDetector
    Nach dem Login kopieren

    In diesem Projekt verwenden wir hauptsächlich die oben genannten Bibliotheken, darunter die Zufallsbibliothek Wählen Sie Pixel aus, um Essensdonuts zu platzieren, verwenden Sie die Handerkennung in cvzone, um Spielergesten zu erkennen, verwenden Sie cv2, um einige grundlegende Bildoperationen auszuführen, und auch andere Bibliotheken haben ihre eigenen Verwendungszwecke, die später einzeln vorgestellt werden.

    2. Finden Sie die Schlüsselpunkte und markieren Sie sie.

    In diesem Spiel haben wir eine Hand als Zielknoten ausgewählt. Wenn wir also eine Hand auf dem Bildschirm erkennen, müssen wir die Schlüsselpunkte markieren, und dieser Schlüsselpunkt passiert Da wir eine Bibliothek eines Drittanbieters aufrufen, können wir die Hand in 3D markieren, wir benötigen jedoch nur die beiden Koordinatenwerte x und y. Wir verwenden hauptsächlich Folgendes Funktion zum Markieren der Schlüsselknoten der Hand:

    #检测到第一个手,并标记手部位置
        if hands:
            lmList = hands[0]['lmList']
            pointIndex = lmList[8][0:2] #第八个坐标点的 x, y值,其中 z 值不被包括在里面
            cv2.circle(img, pointIndex, 20, (200, 0, 200), cv2.FILLED) #在关键点处绘制一个圆点并进行填充(此处只是示范,后面会更改)
    Nach dem Login kopieren

    3. Erstellen Sie eine Klasse, um alle Funktionen des Spiels zu speichern.

    Das Spiel, das wir implementieren müssen, ist eine Kombination aus vielen Funktionen. Wenn Sie Funktionen verwenden möchten, um diese zu implementieren Funktionen, dann Es wird sehr mühsam sein, es zu vervollständigen, da viele Dinge in derselben Klasse gespeichert werden. In diesem Kurs werden wir viele wichtige Listen erstellen, um einige der von uns verwendeten Schlüsselpunkte zu speichern, wie z. B. alle Punkte auf dem Körper der Schlange, die Länge der Schlange, die Gesamtentfernung der Schlange, die Platzierung der Nahrung, Punkte usw. :

    class SnakeGameClass:
        def __init__(self, pathFood):
            self.points = []  #贪吃蛇身上所有点
            self.lengths = []  #点与点之间的距离
            self.currentLength = 0  #当下蛇的长度
            self.allowedLength = 50  #最大允许长度(阈值)
            self.previousHead = 0, 0  #手部关键点之后的第一个点
     
            self.imgFood = cv2.imread(pathFood, cv2.IMREAD_UNCHANGED) #定义食物
            self.hFood, self.wFood, _ = self.imgFood.shape
            self.foodPoint = 0, 0
            self.randomFoodLocation()
     
            self.score = 0
            self.gameOver = False
    Nach dem Login kopieren

    4. Definieren Sie eine Funktion zur kontinuierlichen Aktualisierung

    Wenn sich unsere Hände bewegen, ändern sich Länge und Position der Schlange, daher müssen wir eine Funktion erstellen, die kontinuierlich aktualisiert wird, um sich ändernden Anforderungen gerecht zu werden (der Teil davon wird auch in ausgeführt). die zuvor erstellte große Klasse):

        def update(self, imgMain, currentHead):
            #游戏结束,打印文本
            if self.gameOver:
                cvzone.putTextRect(imgMain, "Game Over", [300, 400],
                                   scale=7, thickness=5, offset=20)
                cvzone.putTextRect(imgMain, f'Your Score: {self.score}', [300, 550],
                                   scale=7, thickness=5, offset=20)
            else:
                px, py = self.previousHead
                cx, cy = currentHead
     
                self.points.append([cx, cy])
                distance = math.hypot(cx - px, cy - py)
                self.lengths.append(distance)
                self.currentLength += distance
                self.previousHead = cx, cy
     
                #长度缩小
                if self.currentLength > self.allowedLength:
                    for i, length in enumerate(self.lengths):
                        self.currentLength -= length
                        self.lengths.pop(i)
                        self.points.pop(i)
                        if self.currentLength < self.allowedLength:
                            break
     
                #检查贪吃蛇是否已经触碰到食物
                rx, ry = self.foodPoint
                if rx - self.wFood // 2 < cx < rx + self.wFood // 2 and \
                        ry - self.hFood // 2 < cy < ry + self.hFood // 2:
                    self.randomFoodLocation()
                    self.allowedLength += 50
                    self.score += 1
                    print(self.score)
     
                #使用线条绘制贪吃蛇
                if self.points:
                    for i, point in enumerate(self.points):
                        if i != 0:
                            cv2.line(imgMain, self.points[i - 1], self.points[i], (0, 0, 255), 20)
                    cv2.circle(imgMain, self.points[-1], 20, (0, 255, 0), cv2.FILLED)
     
                #显示食物
                imgMain = cvzone.overlayPNG(imgMain, self.imgFood,
                                            (rx - self.wFood // 2, ry - self.hFood // 2))
     
                cvzone.putTextRect(imgMain, f&#39;Score: {self.score}&#39;, [50, 80],
                                   scale=3, thickness=3, offset=10)
     
                #检测是否碰撞
                pts = np.array(self.points[:-2], np.int32)
                pts = pts.reshape((-1, 1, 2))
                cv2.polylines(imgMain, [pts], False, (0, 255, 0), 3)
                minDist = cv2.pointPolygonTest(pts, (cx, cy), True)
     
                if -1 <= minDist <= 1:
                    print("Hit")
                    self.gameOver = True
                    self.points = []  #蛇身上所有的点
                    self.lengths = []  #不同点之间的距离
                    self.currentLength = 0  #当前蛇的长度
                    self.allowedLength = 50  #最大允许长度
                    self.previousHead = 0, 0  #先前的蛇的头部
                    self.randomFoodLocation()
     
            return imgMain
    Nach dem Login kopieren

    In dieser aktualisierten Funktion müssen wir viele Dinge beurteilen, z. B. ob die gierige Schlange das Futter berührt (wenn sie das Futter berührt, müssen wir die Länge der Schlange erhöhen und Punkte sammeln), ob die aktuelle Länge die maximal zulässige Länge überschreitet (die aktuelle Länge muss nicht geändert werden, wenn sie kleiner als die maximale Länge ist, aber wenn die aktuelle Länge größer als die maximale Länge ist, muss sie gekürzt werden), ob die Schlange kollidiert (durch Der Abstand zwischen Schlüsselknoten bestimmt, ob die Schlange kollidiert ist. Wenn eine Kollision auftritt, rufen Sie das Gameover-Modul auf. Wenn nicht, setzen Sie das Spiel fort) usw. werden im obigen Code erläutert.

    Hauptsächlich durch die oben definierte Klasse können wir das aktuelle Snake-Spiel implementieren.

    4. Gesamtcode

    Ich habe das Tutorial auf Station B gesehen und es Schritt für Schritt für dieses Minispiel reproduziert. Wenn Sie interessiert sind, können Sie es natürlich wie immer unten veröffentlichen.

    """
    Author:XiaoMa
    CSDN Address:一马归一码
    """
    import math
    import random
    import cvzone
    import cv2
    import numpy as np
    from cvzone.HandTrackingModule import HandDetector
     
    cap = cv2.VideoCapture(0)
     
    #设置画面的尺寸大小,过小的话导致贪吃蛇活动不开
    cap.set(3, 1280)
    cap.set(4, 720)
     
    detector = HandDetector(detectionCon=0.8, maxHands=1)
     
     
    class SnakeGameClass:
        def __init__(self, pathFood):
            self.points = []  #贪吃蛇身上所有点
            self.lengths = []  #每一个点之间的距离
            self.currentLength = 0  #当下蛇的长度
            self.allowedLength = 50  #最大允许长度(阈值)
            self.previousHead = 0, 0  #手部关键点之后的第一个点
     
            self.imgFood = cv2.imread(pathFood, cv2.IMREAD_UNCHANGED) #定义食物
            self.hFood, self.wFood, _ = self.imgFood.shape
            self.foodPoint = 0, 0
            self.randomFoodLocation()
     
            self.score = 0
            self.gameOver = False
     
        def randomFoodLocation(self):
            self.foodPoint = random.randint(100, 1000), random.randint(100, 600)
     
        def update(self, imgMain, currentHead):
            #游戏结束,打印文本
            if self.gameOver:
                cvzone.putTextRect(imgMain, "Game Over", [300, 400],
                                   scale=7, thickness=5, offset=20)
                cvzone.putTextRect(imgMain, f&#39;Your Score: {self.score}&#39;, [300, 550],
                                   scale=7, thickness=5, offset=20)
            else:
                px, py = self.previousHead
                cx, cy = currentHead
     
                self.points.append([cx, cy])
                distance = math.hypot(cx - px, cy - py)
                self.lengths.append(distance)
                self.currentLength += distance
                self.previousHead = cx, cy
     
                #长度缩小
                if self.currentLength > self.allowedLength:
                    for i, length in enumerate(self.lengths):
                        self.currentLength -= length
                        self.lengths.pop(i)
                        self.points.pop(i)
                        if self.currentLength < self.allowedLength:
                            break
     
                #检查贪吃蛇是否已经触碰到食物
                rx, ry = self.foodPoint
                if rx - self.wFood // 2 < cx < rx + self.wFood // 2 and \
                        ry - self.hFood // 2 < cy < ry + self.hFood // 2:
                    self.randomFoodLocation()
                    self.allowedLength += 50
                    self.score += 1
                    print(self.score)
     
                #使用线条绘制贪吃蛇
                if self.points:
                    for i, point in enumerate(self.points):
                        if i != 0:
                            cv2.line(imgMain, self.points[i - 1], self.points[i], (0, 0, 255), 20)
                    cv2.circle(imgMain, self.points[-1], 20, (0, 255, 0), cv2.FILLED)
     
                #显示食物
                imgMain = cvzone.overlayPNG(imgMain, self.imgFood,
                                            (rx - self.wFood // 2, ry - self.hFood // 2))
     
                cvzone.putTextRect(imgMain, f&#39;Score: {self.score}&#39;, [50, 80],
                                   scale=3, thickness=3, offset=10)
     
                #检测是否碰撞
                pts = np.array(self.points[:-2], np.int32)
                pts = pts.reshape((-1, 1, 2))
                cv2.polylines(imgMain, [pts], False, (0, 255, 0), 3)
                minDist = cv2.pointPolygonTest(pts, (cx, cy), True)
     
                if -1 <= minDist <= 1:
                    print("Hit")
                    self.gameOver = True
                    self.points = []  #蛇身上所有的点
                    self.lengths = []  #不同点之间的距离
                    self.currentLength = 0  #当前蛇的长度
                    self.allowedLength = 50  #最大允许长度
                    self.previousHead = 0, 0  #先前的蛇的头部
                    self.randomFoodLocation()
     
            return imgMain
     
     
    game = SnakeGameClass("Donut.png")
     
    while True:
        success, img = cap.read()
        img = cv2.flip(img, 1) #镜像翻转
        hands, img = detector.findHands(img, flipType=False)
        #检测到第一个手,并标记手部位置
        if hands:
            lmList = hands[0]['lmList']
            pointIndex = lmList[8][0:2] #第八个坐标点的 x, y值,其中 z 值不被包括在里面
            #cv2.circle(img, pointIndex, 20, (200, 0, 200), cv2.FILLED) #在关键点处绘制一个圆点并进行填充(此处只是示范,后面会更改)
            img = game.update(img, pointIndex)
     
        cv2.imshow("Image", img)
        key = cv2.waitKey(1)
        #按下‘r'重新开始游戏
        if key == ord('r'):
            game.gameOver = False
    Nach dem Login kopieren

    Was die Anforderungen angeht: Für das verwendete Donut-Muster können Sie online ein Muster in geeigneter Größe finden, um es zu ersetzen.

    Das obige ist der detaillierte Inhalt vonWie Python Gestenerkennung nutzt, um das Snake-Spiel zu implementieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Verwandte Etiketten:
    Quelle:yisu.com
    Erklärung dieser Website
    Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
    Beliebte Tutorials
    Mehr>
    Neueste Downloads
    Mehr>
    Web-Effekte
    Quellcode der Website
    Website-Materialien
    Frontend-Vorlage