Learn OpenCV----使用Opencv和Python构建贪吃蛇小游戏

本文介绍如何利用Python与OpenCV构建贪吃蛇小游戏,详细讲解了游戏的基本构成、游戏变量设定、初始化窗口、游戏逻辑及判断条件等步骤。通过这个游戏,读者可以了解如何结合OpenCV进行图形交互和游戏开发。
摘要由CSDN通过智能技术生成

阅读原文

概述

贪吃蛇小游戏,主要是使用方向键来控制小蛇的移动,并让小蛇尽可能多的吃到地图中的小苹果,变得更长。

基础工作

导入基础程序库

首先需要导入我们所需要的各种程序库。

import cv2
import numpy as np
form random import randint
form random import choice

定义小蛇的基础构成

在这个程序中,我们的小蛇由头部和身体组成。

  • 头部:使用Head类来表示蛇头,即蛇头是整条蛇的最开始部分。
  • 身体:对于一条小蛇,除了蛇头外,都是身体。

具体如下图所示。
在这里插入图片描述
接下来,我们分别定义小蛇的头部类和身体类。

头部类

因为整个小蛇是二维平面的小蛇,因此,确定一个蛇头的位置需要xy两个值。此外,对于蛇头的移动方向,需要一个direction变量来确定。具体代码如下。

class Head:
  def __init__(self, direction, x, y):
    # 蛇头运动的方向
    self.direction = direction
    # 蛇头在二维平面的坐标
    self.x = x
    self.y = y

  # 移动函数,通过不同的方向来对蛇头的位置进行更新
  def move(self):
    # 右
    if self.direction == 0:
        self.x += 1
    # 下
    elif self.direction == 1:
        self.y += 1
    # 左
    elif self.direction == 2:
        self.x -= 1
    # 上
    elif self.direction == 3:
        self.y -= 1

身体类

身体类也需要使用xy来确定位置,但由于每个身体但小块的运动均依赖于前一个小块的运动,因此,身体类没有direction变量,有的只是front变量,用来让身体知道自己的上一块的位置。具体代码如下。

class SnakePart:
  def __init__(self, front, x, y):
    self.front = front
    self.x = x
    self.y = y

  # 移动函数,当前小块的下一个位置为当前小块的前一个小块的当前位置
  def move(self):
    self.x = self.front.x
    self.y = self.front.y

定义游戏变量

  • CELL_SIZE:每个单元格的宽度。
  • BOARD_SIZE:每一行有多少个单元格。
  • SPEED:小蛇运动的速度。
  • GROWTH:小蛇每吃掉一个苹果后,苹果出现的速度。
  • 等等。。。
  # 每个单元格的宽度
  CELL_SIZE = 20
  # 每一行有多少个单元格
  BOARD_SIZE = 45
  # 小蛇运动的速度。
  SPEED = 12
  # 小蛇每吃掉一个苹果后,小蛇增长的速度。
  GROWTH = 3

  
  # 判断苹果是否被吃了
  eaten = True
  # 判断是否推出游戏
  quit = False
  # 变量增长. 
  grow = 0
  
  # 使用数组来储存小蛇
  snake = []
  # 初始化小蛇的头部并放在中间
  head = Head(0, int((BOARD_SIZE - 1)/2), int((BOARD_SIZE - 1)/2))
  snake.append(head)

编写游戏

初始化opencv窗口

除了初始化窗口外,这个函数还可以让用户的焦点自动到该贪吃蛇游戏中。

# 构建窗口并获取焦点
def win_focus():
  cv2.namedWindow("Snake Game", cv2.WINDOW_AUTOSIZE);
  board = np.zeros([BOARD_SIZE * CELL_SIZE, BOARD_SIZE * CELL_SIZE, 3])
  cv2.imshow("Snake Game", board);
  cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN);
  cv2.waitKey(2000)
  cv2.setWindowProperty("Snake Game", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_AUTOSIZE)

展现游戏

这个函数需要完成的功能如下。

  • 创建一个用于给小蛇活动的黑色背景板。
  • 把蛇的身体(包括头部)设置为绿色。
  • 把苹果设置成红色。
  • 监听键盘按键信息。

具体代码如下。

def display():
  # 创建黑色背景板
  board = np.zeros([BOARD_SIZE, BOARD_SIZE, 3])
  # 让小蛇变成绿色
  for part in snake:
    board[part.y, part.x] = [0, 255, 0]
  # 让苹果变成红色
  board[appley, applex] = [0, 0, 255]
  
  # 显示背景板,刷新,返回键盘按键信息
  cv2.imshow("Snake Game", np.uint8(board.repeat(CELL_SIZE, 0).repeat(CELL_SIZE, 1)))
  key = cv2.waitKey(int(1000/SPEED))
  
  # 没有任何按键被按下时返回-1
  return key

游戏主循环

在游戏主循环中,主要完成两件事

  • 检查地图中的苹果是否被吃了。
  • 如果被吃,需要增长小蛇长度,并重新生成一个新的不被小蛇覆盖的苹果。
# 判断苹果是否被吃
if eaten:
  # 将二维地图转换为一维序列
  s = list(range(0, BOARD_SIZE ** 2))
  # 将序列中被小蛇占有的值给剔除
  for part in snake:
      s.remove(part.x * BOARD_SIZE + part.y)
  
  # 随机生成一个不被小蛇覆盖的新苹果   
  a = choice(s)
  applex = int(a/BOARD_SIZE)
  appley = a % BOARD_SIZE
  
  eaten = False

刷新屏幕并更新移动方向

# 刷新屏幕
key = display()

# 根据按键的信息来控制小蛇的运动方向
if key == 8 or key == 27:
  break
elif key == ord("d") :
  head.direction = 0
elif key == ord("s") :
  head.direction = 1
elif key == ord("a") :
  head.direction = 2
elif key == ord("w") :
  head.direction = 3

# 移动小蛇
# 从后往前移动,因为后一个小块使用的是前一个小块的位置
for part in snake[::-1]:
  part.move()

小蛇吃到苹果后长大

# 当小蛇吃到苹果后的生长代码   
if grow > 0:
  # 在蛇身的后尾添加上新的蛇身块
  snake.append(SnakePart(snake[-1], subx, suby))
  grow -= 1
  
# 当蛇头碰到苹果,更新变量
if applex == head.x and appley == head.y:
  subx = snake[-1].x
  suby = snake[-1].y
  eaten = True
  grow += GROWTH

游戏失败的判断

# 碰撞墙壁规则
if head.x < 0 or head.x > BOARD_SIZE - 1 or head.y < 0 or head.y > BOARD_SIZE - 1:
  break

# 蛇头碰撞蛇身规则
for part in snake[1:]:
  if head.x == part.x and head.y == part.y:
    quit = True
    break
    
if quit:
  break

小结

这只是一个小的Demo,大家感兴趣可以去下载源代码,并让这个游戏变得更加的具有可玩性。我在这里给出了一个带中文注释的版本,大家可以免费下载。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值