回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

智能识别滑雪游戏玩起来 中等

头像 _深蓝_ 2024.06.29 20 0

话不多说,来围观效果。

一、选题背景

 

非常高兴能和一众大咖们一起同台竞技,参与Mind+ 互动编程&游戏设计大赛,能力和精力所限,一直徘徊如何选题,直到米菲爸爸发布了他的作品,我的作品雏形渐渐形成,使用Mind+的python模式做一款简单又好玩的小游戏,能把大家带回童年的时光,回味,升华。就是它

不用按键盘和手柄,空中伸出手就可以玩滑雪游戏。

选择做滑雪小游戏的原因有以下三点:

1.游戏目标简单
滑雪小游戏的目标是让玩家控制角色在雪地上滑行,尽可能地躲避障碍物并收集道具,以获得最高的分数或滑行更远的距离。
2.游戏玩法通俗易懂

   角色控制:玩家通过键盘按键来控制滑雪者的移动方向,包括左右移动等,以避开障碍物和陷阱。
   道具收集:在滑行过程中,玩家可以收集各种道具,如硬币、宝石、加速器等,这些道具可以增加分数、延长游戏时间或增强角色的能力。
   障碍物躲避:游戏中会设置各种障碍物,如树木、岩石、其他滑雪者等,玩家需要灵活应对,避免碰撞到这些障碍物,否则游戏可能会结束。
3.加入智能识别程序时,不至于程序复杂影响编程的进度和效率。

 

二、工欲善其事 必先利其器

 

使用mind+作为编程的利器,他不仅支持各种硬件和传感器,还加入了Python模式,不用安装python程序就可以编程了。界面如下

 

图片.png

右上角中实时模式、上传模式、python模式选择python模式。

左上角模块和代码要选择代码,模块指的是图形化编程 的模块。

不仅如此它还具有如下特点:

1.   图形化编程:Mind+提供图形化积木编程功能,用户只需拖动图形化程序块即可完成编程,大大降低了编程的入门门槛,让青少年能够轻松跨入编程世界的大门。
2.   支持多种编程语言:除了图形化编程外,Mind+还支持Python/C/C++等高级编程语言,用户可以根据需要选择适合的编程语言进行编程学习。
3.   集成多种硬件:Mind+集成了各种主流主控板及上百种开源硬件,支持人工智能(AI)与物联网(IoT)功能,让用户能够轻松实现硬件编程与控制。
4.   自动转换代码:在图形化编程时,Mind+可以自动将图形化积木编程转换为Python或C代码,方便用户对照学习,同时也可以手动编辑代码,满足进阶编程需求。
5.   丰富的扩展功能:Mind+拥有强大的硬件扩展功能库,可以直接对上百种硬件模块进行编程控制,包括各种传感器、执行器、通讯模块、显示器、功能模块等。同时,Mind+还开放了扩展库,给用户提供了丰富的扩展空间进行无限的创造。

 


三、项目制作步骤

 

 

步骤1 收集素材,制作图片库

图片.png

搜集或者制作游戏主人公的各种动作。

搜集和制作游戏中的旗帜和障碍物的图片。

并放置到同一个文件夹下,命名为img

步骤2 使用Pygame库编写滑雪小游戏

虽然是小游戏,还是考验码农的逻辑能力,如果太费神就可以从github、gitee或者通过大语言模型来获取滑雪小游戏的模版来改写。

 

图片.png

本人搜的的代码如下

代码
import pygame, sys, random

skier_images = [
    'img/skier_down.png',
    'img/skier_right1.png',
    'img/skier_right2.png',
    'img/skier_left2.png',
    'img/skier_left1.png',
]


class SkierClass(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('img/skier_down.png')
        self.rect = self.image.get_rect()
        self.rect.center = [320, 100]
        self.angle = 0

    def turn(self, direction):
        self.angle = self.angle + direction
        if self.angle < -2:
            self.angle = -2
        if self.angle > 2:
            self.angle = 2
        center = self.rect.center
        self.image = pygame.image.load(skier_images[self.angle])
        self.rect = self.image.get_rect()
        self.rect.center = center
        speed = [self.angle, 6 - abs(self.angle) * 2]
        return speed

    def move(self, speed):
        self.rect.centerx = self.rect.centerx + speed[0]
        if self.rect.centerx < 20:
            self.rect.centerx = 20
        if self.rect.centerx > 620:
            self.rect.centerx = 620


class ObstacleClass(pygame.sprite.Sprite):
    def __init__(self, image_file, location, obs_type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file
        self.image = pygame.image.load(image_file)
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.obs_type = obs_type
        self.passed = False

    def update(self):
        global speed
        self.rect.centery = self.rect.centery - speed[1]
        if self.rect.centery < -32:
            self.kill()


def create_map():
    global obstacles
    locations = []
    for i in range(10):
        row = random.randint(0, 9)
        col = random.randint(0, 9)
        location = [col * 64 + 20, row * 64 + 640]
        if not (location in locations):
            locations.append(location)
            obs_type = random.choice(['tree', 'flag'])
            if obs_type == 'tree':
                img = 'img/skier_tree.png'
            elif obs_type == 'flag':
                img = 'img/skier_flag.png'
            obstacle = ObstacleClass(img, location, obs_type)
            obstacles.add(obstacle)


def animate():
    screen.fill([255, 255, 255])
    obstacles.draw(screen)
    screen.blit(skier.image, skier.rect)
    screen.blit(score_text, [10, 10])
    pygame.display.flip()


pygame.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
obstacles = pygame.sprite.Group()
map_position = 0
points = 0
create_map()
font = pygame.font.SysFont('SimHei', 40)

running = True

while running:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                speed = skier.turn(1)
    skier.move(speed)

    map_position = map_position + speed[1]

    if map_position >= 640:
        create_map()
        map_position = 0

    hit = pygame.sprite.spritecollide(skier, obstacles, False)
    if hit:
        if hit[0].obs_type == 'tree' and not hit[0].passed:
            points = points - 100
            skier.image = pygame.image.load('img/skier_crash.png')
            animate()
            pygame.time.delay(1000)
            skier.image = pygame.image.load('img/skier_down.png')
            skier.angle = 0
            speed = [0, 6]
            hit[0].passed = True
        elif hit[0].obs_type == 'flag' and not hit[0].passed:
            points = points + 10
            hit[0].kill()

    obstacles.update()
    score_text = font.render('得分: ' + str(points), 1, (0, 0, 0))
    animate()
pygame.quit()

步骤3 测试智能识别代码

我使用米菲爸爸的识别代码,使用的是mediapipe库和cv2库。效果也是非常好的,如下图所示

QQ截图20240629063635.png
right.png

如果没有安装加载mediapipe库和cv2库的童鞋需要先安装,打开mind+的python模式选择代码选项,右侧有库管理的按钮,点击该按钮

库管理.png

选择pip模式,输入pip install mediapipe

安装成功会提示命令运行完成,其他的库同样可以用该方法。

图片.png

接着上代码,点击运行后可以在frame窗口中看到智能识别左右手了。

代码
import cv2
import numpy as np
import mediapipe as mp
import time
 
# 初始化
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
capture = cv2.VideoCapture(0)
 
last_hand_detected = None
last_detection_time = 0
DETECTION_INTERVAL_SECONDS = 2
 
while capture.isOpened():
    success, frame = capture.read()
    if not success:
        break
 
    results = hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
 
    if results.multi_hand_landmarks:
        for hand_landmarks in results.multi_hand_landmarks:
            landmarks = hand_landmarks.landmark
            current_hand = "Left" if landmarks[mp_hands.HandLandmark.THUMB_TIP].x < landmarks[mp_hands.HandLandmark.PINKY_TIP].x else "Right"
 
            if current_hand != last_hand_detected or time.time() - last_detection_time > DETECTION_INTERVAL_SECONDS:
                print(f"Detected: {current_hand}")
                last_hand_detected = current_hand
                last_detection_time = time.time()
 
            mp.solutions.drawing_utils.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)
 
    cv2.imshow('Frame', frame)
 
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break
 
cv2.destroyAllWindows()
capture.release()

步骤4 将智能识别程序加入滑雪小游戏

打算使用函数的方式,但是这样会造成class类成员无法访问函数内数据,还是为了简单吧,直接将智能识别程序写入到主程序中。点击运行就可以享受小游戏带来的快乐啦。

代码如下;

代码
import pygame, sys, random

import cv2
import numpy as np
import mediapipe as mp
import time
 
# 初始化
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
capture = cv2.VideoCapture(0)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
capture.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
#time.sleep(3000)
last_hand_detected = None
last_detection_time = 0
DETECTION_INTERVAL_SECONDS = 0.15



skier_images = [
    'img/skier_down.png',
    'img/skier_right1.png',
    'img/skier_right2.png',
    'img/skier_left2.png',
    'img/skier_left1.png',
]


class SkierClass(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('img/skier_down.png')
        self.rect = self.image.get_rect()
        self.rect.center = [320, 100]
        self.angle = 0

    def turn(self, direction):
        self.angle = self.angle + direction
        if self.angle < -2:
            self.angle = -2
        if self.angle > 2:
            self.angle = 2
        center = self.rect.center
        self.image = pygame.image.load(skier_images[self.angle])
        self.rect = self.image.get_rect()
        self.rect.center = center
        speed = [self.angle, 6 - abs(self.angle) * 2]
        return speed

    def move(self, speed):
        self.rect.centerx = self.rect.centerx + speed[0]
        if self.rect.centerx < 20:
            self.rect.centerx = 20
        if self.rect.centerx > 620:
            self.rect.centerx = 620


class ObstacleClass(pygame.sprite.Sprite):
    def __init__(self, image_file, location, obs_type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file
        self.image = pygame.image.load(image_file)
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.obs_type = obs_type
        self.passed = False

    def update(self):
        global speed
        self.rect.centery = self.rect.centery - speed[1]
        if self.rect.centery < -32:
            self.kill()


def create_map():
    global obstacles
    locations = []
    for i in range(10):
        row = random.randint(0, 9)
        col = random.randint(0, 9)
        location = [col * 64 + 20, row * 64 + 640]
        if not (location in locations):
            locations.append(location)
            obs_type = random.choice(['tree', 'flag'])
            if obs_type == 'tree':
                img = 'img/skier_tree.png'
            elif obs_type == 'flag':
                img = 'img/skier_flag.png'
            obstacle = ObstacleClass(img, location, obs_type)
            obstacles.add(obstacle)


def animate():
    screen.fill([255, 255, 255])
    obstacles.draw(screen)
    screen.blit(skier.image, skier.rect)
    screen.blit(score_text, [10, 10])
    pygame.display.flip()


pygame.init()
screen = pygame.display.set_mode([640, 640])
clock = pygame.time.Clock()
skier = SkierClass()
speed = [0, 6]
obstacles = pygame.sprite.Group()
map_position = 0
points = 0
create_map()
font = pygame.font.SysFont('SimHei', 40)

running = True

while running:
    clock.tick(60)
    
    if capture.isOpened() and time.time() - last_detection_time > DETECTION_INTERVAL_SECONDS:
        success, frame = capture.read()
        if not success:
            print("NOT success")
            break

        results = hands.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

        if results.multi_hand_landmarks:
            for hand_landmarks in results.multi_hand_landmarks:
                landmarks = hand_landmarks.landmark
                current_hand = "Left" if landmarks[mp_hands.HandLandmark.THUMB_TIP].x < landmarks[mp_hands.HandLandmark.PINKY_TIP].x else "Right"

                print(f"Detected: {current_hand}")
                if current_hand == "Left":
                    
                    speed = skier.turn(-1)
                if current_hand == "Right":
                    
                    speed = skier.turn(1)
                last_hand_detected = current_hand
                last_detection_time = time.time()

                mp.solutions.drawing_utils.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS)

        cv2.imshow('Frame', frame)




    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key ==  event.key == pygame.K_q:
                running = False

        '''    
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT or event.key == pygame.K_a:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                speed = skier.turn(1)


       '''         

    skier.move(speed)

    map_position = map_position + speed[1]

    if map_position >= 640:
        create_map()
        map_position = 0

    hit = pygame.sprite.spritecollide(skier, obstacles, False)
    if hit:
        if hit[0].obs_type == 'tree' and not hit[0].passed:
            points = points - 100
            skier.image = pygame.image.load('img/skier_crash.png')
            animate()
            pygame.time.delay(1000)
            skier.image = pygame.image.load('img/skier_down.png')
            skier.angle = 0
            speed = [0, 6]
            hit[0].passed = True
        elif hit[0].obs_type == 'flag' and not hit[0].passed:
            points = points + 10
            hit[0].kill()

    obstacles.update()
    score_text = font.render('得分: ' + str(points), 1, (0, 0, 0))
    animate()
cv2.destroyAllWindows()
capture.release()

pygame.quit()

四、游戏体验和不足

 

1.该游戏太简单,就是有点费手,上下举着权当做锻炼身体了。

2.该游戏界面单一,一直是一个背景,可以使用多个背景避免视觉疲劳。

3.该游戏障碍物只有大树,都是相同的大树,可以加入石头。

4.该游戏没有背景音乐,没有渲染滑雪时的紧张气氛。

接下来的改进中可以从以上方面进行,如果各位还有什么体验感受或者建议评论告诉我吧。

但是不要弄得太复杂了哦。

 

chess-1080533_1280.jpg

附件

评论

user-avatar