龙空技术网

使用OpenCV与Python编写自己的俄罗斯方块小游戏

人工智能研究所 227

前言:

此刻我们对“用python编小游戏”都比较关怀,各位老铁们都想要分析一些“用python编小游戏”的相关资讯。那么小编同时在网上收集了一些关于“用python编小游戏””的相关资讯,希望同学们能喜欢,咱们快快来学习一下吧!

俄罗斯方块小游戏是当年风靡一时的小游戏,该游戏由一个棋盘组成,该棋盘跨度为10个单元格,高度为20个单元格,如下所示。

俄罗斯方块小游戏

关于此小游戏的规则,我们不再介绍,本期文章主要用代码来实现,我们知道俄罗斯方块小游戏主要有如下7个方块组成,我们在代码中使用字母“ O”,“ I”,“ S”,“ Z”,“ L”,“ J”和“ T”表示它们。

俄罗斯方块

使用OpenCV和python创建俄罗斯方块

import cv2import numpy as npfrom random import choiceSPEED = 1 #控制速度board = np.uint8(np.zeros([20, 10, 3]))quit = Falseplace = Falsedrop = Falseswitch = Falseheld_piece = ""flag = 0score = 0

首先我们导入需要的第三方库以及定义好需要的变量

# 所有方块造型next_piece = choice(["O", "I", "S", "Z", "L", "J", "T"])def get_info(piece):    if piece == "I":        coords = np.array([[0, 3], [0, 4], [0, 5], [0, 6]])        color = [255, 155, 15]    elif piece == "T":        coords = np.array([[1, 3], [1, 4], [1, 5], [0, 4]])        color = [138, 41, 175]    elif piece == "L":        coords = np.array([[1, 3], [1, 4], [1, 5], [0, 5]])        color = [2, 91, 227]    elif piece == "J":        coords = np.array([[1, 3], [1, 4], [1, 5], [0, 3]])        color = [198, 65, 33]    elif piece == "S":        coords = np.array([[1, 5], [1, 4], [0, 3], [0, 4]])        color = [55, 15, 215]    elif piece == "Z":        coords = np.array([[1, 3], [1, 4], [0, 4], [0, 5]])        color = [1, 177, 89]    else:        coords = np.array([[0, 4], [0, 5], [1, 4], [1, 5]])        color = [2, 159, 227]    return coords, color

然后我们建立7个俄罗斯方块的造型与颜色,以上建立完成后,我们需要搭建一个游戏界面以及鼠标控制事件

def display(board, coords, color, next_info, held_info, score, SPEED):    border = np.uint8(127 - np.zeros([20, 1, 3]))    border_ = np.uint8(127 - np.zeros([1, 34, 3]))    dummy = board.copy()    dummy[coords[:,0], coords[:,1]] = color    right = np.uint8(np.zeros([20, 10, 3]))    right[next_info[0][:,0] + 2, next_info[0][:,1]] = next_info[1]    left = np.uint8(np.zeros([20, 10, 3]))    left[held_info[0][:,0] + 2, held_info[0][:,1]] = held_info[1]    dummy = np.concatenate((border, left, border, dummy, border, right, border), 1)    dummy = np.concatenate((border_, dummy, border_), 0)    dummy = dummy.repeat(20, 0).repeat(20, 1)    dummy = cv2.putText(dummy, str(score), (520, 200), cv2.FONT_HERSHEY_DUPLEX, 1, [0, 0, 255], 2)# 控制键    dummy = cv2.putText(dummy, "A - move left", (45, 200), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    dummy = cv2.putText(dummy, "D - move right", (45, 225), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    dummy = cv2.putText(dummy, "S - move down", (45, 250), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    dummy = cv2.putText(dummy, "W - hard drop", (45, 275), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    dummy = cv2.putText(dummy, "J - rotate left", (45, 300), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    dummy = cv2.putText(dummy, "L - rotate right", (45, 325), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    dummy = cv2.putText(dummy, "I - hold", (45, 350), cv2.FONT_HERSHEY_DUPLEX, 0.6, [0, 0, 255])    cv2.imshow("Tetris", dummy)    key = cv2.waitKey(int(1000/SPEED))    return key

游戏界面

搭建的游戏界面如上,我们在界面左边显示每个鼠标按键的功能,中间是主游戏区域,最右边为积分区域

以上建立完成后,我们开始主函数的部分

我们有一个while循环,在每次迭代中,我们都会在游戏中放置一个新棋子。

在俄罗斯方块中,我们可以按某个键来固定一块。通过与当前方块交换,可以保留将来使用的一种方块。

在下面的代码中,我们首先检查用户是否要使用switch变量将当前方块与保留的方块交换。如果switch变量设置为false,我们将分配current_piecenext_piece并随机选择一个new next_piece

if __name__ == "__main__":    while not quit:           if switch:            held_piece, current_piece = current_piece, held_piece            switch = False        else:            current_piece = next_piece            next_piece = choice(["I", "T", "L", "J", "Z", "S", "O"])·			
        if flag > 0:            flag -= 1	#确定方块的颜色和位置current_piece,next_piece以及held_piece        if held_piece == "":            held_info = np.array([[0, 0]]), [0, 0, 0]        else:           held_info = get_info(held_piece)               next_info = get_info(next_piece)        coords, color = get_info(current_piece)        if current_piece == "I":            top_left = [-2, 3]         #这个if语句只是检查游戏是否需要终止           if not np.all(board[coords[:,0], coords[:,1]] == 0):            break

接下来我们 在主程序里面设置while true死循环用来我们一直检测键盘输入,直到游戏结束

首先,我们使用display()功能显示板子并接收键盘输入,并复制原始位置

        while True:            key = display(board, coords, color, next_info, held_info, score, SPEED)            dummy = coords.copy() 

然后我们检测键盘输入的字母以便控制方块的移动旋转等操作

            if key == ord("a"):                if np.min(coords[:,1]) > 0:                    coords[:,1] -= 1                if current_piece == "I":                    top_left[1] -= 1                          elif key == ord("d"):                if np.max(coords[:,1]) < 9:                    coords[:,1] += 1                    if current_piece == "I":                        top_left[1] += 1                         elif key == ord("j") or key == ord("l"):                               if current_piece != "I" and current_piece != "O":                    if coords[1,1] > 0 and coords[1,1] < 9:                        arr = coords[1] - 1 + np.array([[[x, y] for y in range(3)] for x in range(3)])                        pov = coords - coords[1] + 1                               elif current_piece == "I":                                     arr = top_left + np.array([[[x, y] for y in range(4)] for x in range(4)])                    pov = np.array([np.where(np.logical_and(arr[:,:,0] == pos[0], arr[:,:,1] == pos[1])) for pos in coords])                    pov = np.array([k[0] for k in np.swapaxes(pov, 1, 2)])                           if current_piece != "O":                    if key == ord("j"):                        arr = np.rot90(arr, -1)                    else:                        arr = np.rot90(arr)                    coords = arr[pov[:,0], pov[:,1]]                       elif key == ord("w"):                drop = True            elif key == ord("i"):                if flag == 0:                    if held_piece == "":                        held_piece = current_piece                    else:                        switch = True                    flag = 2                    break            elif key == 8 or key == 27:                quit = True                break               

这里我们分别检测字母:

a:左移动

d:右移动

W:直接到底部

S:往下加速

j&l:旋转

I:更换方块

接下来,我们需要检查与其他方块的碰撞,并防止该方块进入或旋转到另一方块中。如果发生这种冲突,我们将使用coords存储在dummy变量中的副本将新位置更改回原始位置

            if np.max(coords[:,0]) < 20 and np.min(coords[:,0]) >= 0:                if not (current_piece == "I" and (np.max(coords[:,1]) >= 10 or np.min(coords[:,1]) < 0)):                    if not np.all(board[coords[:,0], coords[:,1]] == 0):                        coords = dummy.copy()                else:                    coords = dummy.copy()            else:                coords = dummy.copy()

如果它与现有棋子碰撞或到达棋板的底部,则停止向下移动

            if drop:                           while not place:                    if np.max(coords[:,0]) != 19:                        for pos in coords:                            if not np.array_equal(board[pos[0] + 1, pos[1]], [0, 0, 0]):                                place = True                                break                    else:                        place = True                                  if place:                        break                                       coords[:,0] += 1                    score += 1                    if current_piece == "I":                        top_left[0] += 1                                   drop = False

当一块到达底部或碰到另一块时,将放置方块,否则将方块向下移动

            else:                if np.max(coords[:,0]) != 19:                    for pos in coords:                        if not np.array_equal(board[pos[0] + 1, pos[1]], [0, 0, 0]):                            place = True                            break                else:                    place = True                    if place:                for pos in coords:                    board[tuple(pos)] = color                                    place = False                break            coords[:,0] += 1            if key == ord("s"):                score += 1            if current_piece == "I":                top_left[0] += 1

最后,我们按照设计规则,更新每次的得分,并实时记录

        # 计算得分                   lines = 0                        for line in range(20):            if np.all([np.any(pos != 0) for pos in board[line]]):                lines += 1                board[1:line+1] = board[:line]                          if lines == 1:            score += 40        elif lines == 2:            score += 100        elif lines == 3:            score += 300        elif lines == 4:            score += 1200

视频加载中...

以上便是本期完整的代码,运行此代码,我们便可以看到一个我设计完成的游戏界面,这里按照左屏的键盘字母提示就可以愉快的来玩游戏了

标签: #用python编小游戏 #俄罗斯方块python #python俄罗斯方块