2022年暑假在家一起练 基于M5STICKC PLUSE实现俄罗斯方块
使用手柄遥感陀螺仪实现俄罗斯方块小游戏,并且使用mpy来实现GUI显示,学习UI FLOW 等工具
标签
嵌入式系统
ESP32
俄罗斯方块
2022暑假在家练
m5stickplus
飞跃1989
更新2022-09-06
776

用ESP32 m5stickplus制作经典俄罗斯方块小游戏

 

 

项目介绍

按照官方给出的题目要求,我选择任务3:

任务3:使用姿态传感器完成体感游戏手柄,并设计完成一个游戏,例如俄罗斯方块、左右晃动手柄使方块左右移动

选择这个题目,也是对同年玩的小游戏的一种怀念吧。而且觉得这个比较感兴趣。都说兴趣是最好的老师,所以做自己感兴趣的东西,最能激发自己的主动性。

设计思路

参考了电子森林的很多同学的项目,有了一些启发,在这里要非常感谢电子森林这个平台,真的非常好,能够吸取大家的经验,站在巨人的肩膀上能够飞的更高。加速了我们的开发和学习,学习的过程中了解到了一种俄罗斯方块游戏的设计方法。大概了解到俄罗斯方块就是由一个一个小方块组成的。

如下图所示:

FtlAQvvU300vjAMUYY8LISwu1S8N

所以我们可以设置一个数组

global g_tetris
g_tetris=[]
global g_column
global g_row
g_width_pix = 135
g_hight_pix = 240
g_box_width = 10  
​
g_column = 13    #  当前 有多少列方块 g_width_pix/g_box_width
g_row = 23      #  当前有多少行方块  g_hight_pix/g_box_width
for i in range(g_row):
    g_tetris.append([0]*g_column)

根据官方资料,我们知道LCD屏幕是135*240 的。所以我们可以根据设计方块大小g_box_width来分配有多少行g_row和多少列g_column,数组中如果置1的话,说明当前方块是需要填充的。每次刷新,通过画方块来

框图

下面介绍下主要的框图

Fv5PBZbw-M3lV29fTa2zV9SxYu4-

这个是主要的框图,通过理解,化繁为简。大致的流程是这样的

简单的硬件介绍

这个任务主要用到M5STICKPLUS的硬件有以下部分:

  • LCD屏幕135*240

  • IMU 陀螺仪MPU6886

其他这个模块还有蓝牙、WIFI、麦克风、红外、蜂鸣器、led灯等模块,这次任务我们暂时不需要其他模块。

我觉得下面这张图比较好,标的很清楚

FmuFXbHgDChZ-CuxkfzNkOqU9rO5

实现的功能及图片展示

开机界面:

FlFaBAVhPV0xRouCZOHixS-aZZiw

运行得分界面

FiZGuB1ah7t_0jB2GlpJuJVs0SYN

game over界面:

Fi2IDysMRt3s8eDfakTLny_1poxi

 

主要代码片段及说明 如何设计

前面大体思路讲到如何进入,下面介绍下主体代码:

drawbox

先讲下drawbox,这个是根据数组g_tetris里面的值,如果为1的话,该方块填充相应的颜色

def drawbox():
    global color
    global g_tetris
    global box_column
    setScreenColor(0x0000)
    y=0    
    title0 = M5Title(title="Score", x=3, fgcolor=0xFFFFFF, bgcolor=0x0000FF)
    label0 = M5TextBox(86, 0, str(score), lcd.FONT_DejaVu18, 0xFFFFFF, rotate=0)
​
    for r in g_tetris:
        x=0
        for d in r:
            if d==1:
                M5Rect(x, y, g_box_width, g_box_width, color[3], 0x0640f7)
            x+=g_box_width
        y+=g_box_width

方块移动

在方块移动过程中,分别处理up left 和right

def up():
    leave()
    clockwise()
    if checkvalid()==False:
        counter_clockwise()
    enter()
    
def down():
    global box_row
    leave()
    box_row+=1
    if checkvalid()==False:
        box_row-=1
    enter()
def left():
    global box_column
    leave()
    box_column-=1
    if checkvalid()==False:
        box_column+=1
    enter()
​
def right():
    global box_column
    leave()
    box_column+=1
    if checkvalid()==False:
        box_column-=1
    enter()

方块生成和旋转

 

def newbox():
    box_id=random.randint(0,6)  #随机一个方块形状
    box_org=boxes[box_id]        #获取方块形状数组
    b=[]
    for i in range(len(box_org)):
        b.append(box_org[i][:])    
    return b                     #返回方块
box=newbox()              #当前运动中的方块
​
def clockwise():
    N=len(box)
    a=[]
    for i in range(N):
        a.append(box[i][:])
    for i in range(N):
        for j in range(N):
            box[N-j-1][i]=a[i][j]

判断有效性

def checkvalid():
    global box_row
    global box_column
    global g_tetris
    j=box_row
    for r in box:
        i=box_column
        for d in r:
            if d==1:
                if i<0 or i>=g_column:
                    return False
                if j<0 or j>=g_row:
                    return False
                if g_tetris[j][i]==1:
                    return False
            i+=1
        j+=1
    return True

方向控制

方向控制就要靠IMU了。这边我用了下面的小代码简单调试了一下,通过调试发现,当屏幕左右晃动的时候, x轴的数值绝对值大于0.2的时候,差不多是有所倾斜了。当屏幕竖起来的时候,z轴的绝对值在0~0.7之间。这边我想设计一个快速下降的动作,通过将屏幕竖起来,就可以快速下降。

from m5stack import *
from m5ui import *
from uiflow import *
import imu
from time import sleep
asdf = None
i = None
a = None
​
while True:
    imu0 = imu.IMU()
    c = imu0.acceleration[0]
    z = imu0.acceleration[2]
    print("acceleration[0] x ",c)
    print("acceleration[2] z ",z)
    if c>0 and c > 0.2 :
        if(c > 0.5):
            print("fast left")
        else:
            print("left")
    elif c<0 and c < -0.2:
        if(c < -0.5):
            print("fast right")
        else:
            print("right")
    print("=======")
    time.sleep(1)

下面我们来看代码中是如何操作的

通过A按键,我们来旋转方块的方向。

通过x轴左右晃动,来控制方块左右方向。

通过z轴竖直放置,来控制方块下降方向。

实际用起来也是挺方便的。

       imu0 = imu.IMU()
        x = imu0.acceleration[0]
        z = imu0.acceleration[2]
        if btnA.wasPressed():
            up()
            print("up box changed")
        elif x < 0 and x < -0.2:
            right()
        elif x > 0 and x > 0.2:
            left()
        if z < 0.7 and z > -0.7:
            g_box_download_rate = 0.1
        else:
            g_box_download_rate = 0.5

           

作弊神器

由于当时用的时候,感觉下降的时候,感觉没法完全对齐,所以做了一个小的作弊工具,让游戏体验更佳一些,在方块下降的时候,可以选择实时显示一条直线对其到底部

    for r in g_tetris:
        x=0
        for d in r:
            if d==1:
                cheat
                if x == box_column * g_box_width :
                    M5Line(M5Line.PLINE, x, y, x, 240, 0xFFFFFF)
                M5Rect(x, y, g_box_width, g_box_width, color[3], 0x0640f7)
                #print('draw box x:%d y:%d'%(x,y))
            x+=g_box_width
        y+=g_box_width

 

遇到的主要难题及解决方法 选择mpy还是arduino

刚开始还是很纠结的,在使用mpy的时候,发现thonny搭配固件很难用,根本没法用UI FLOW来编程,或者不是很熟悉mpy和BLOCKLY. 而且官方m5-burn里面都是一些ARDUINO的例程,可以看到arduino的生态还是挺丰富的,但是没有找到参考例程。但是mpy还是有相应的参考例程的。后来经过群里小伙伴的介绍,使用thonny然后按CTRL+C就可以了。之后慢慢摸索,慢慢掌握规律:

  • 如果ctrl+c不起作用的话,插拔一下USB,之后按stop按钮,之后按CTRL+C 直到出现>>> 即可

  • 可以现在PC上写相关的python脚本,之后点击运行,可以在板子上跑。跑的时候也要按一下ctrl+c

出现如下界面,说明正常了

Fs9SjkUI_whnYECQ4WHTMOfdHG37

  • 当然arduino也是可以的,arduino一开始发现,编译一个固件要很久很久。后来发现如果只对一个工程编译的话,arduino编译还是挺快的。所以不要打开多个arduino编译,就在一个窗口中进行修改

最后还是觉得thonny的mpy比较轻量级,编译起来没有那么费劲,甚至不需要编译。

如何熟悉micropython接口

在使用mpy的时候,烧入UI flow固件之后,thonny 一直连接比较困难,vscode也不是很好使,后来通过摸索发现,需要慢慢的按一下CTRL+C 而且还不能按多,按多了不容易成功进去。当看到>>> 的时候说明进入mpy成功了。

之前有个小技巧用help来查函数说明,但是后来发现,有些函数注释都没有写好。只能作罢。

后来发现一个小技巧,点击下图中的文字,可以进入到文档中心的说明

Fv4-GXZXkWYFTTLGHHylgSQU0nAv

不过有一些LCD的API如何使用的,始终没有找到,最后只能问群里小伙伴,之后小伙伴介绍了,可以先用图形界面拉好,然后看下mpy如何实现的。这个方法确实能解决很多问题。点赞。

全局变量

刚开始遇到一个比较恶心的问题,就是第一次失败之后,再次重启游戏的时候,无法清空屏幕。刚开始我认定是全局变量数组g_tetris的问题,发现在进入drawbox函数的时候,这个g_tetris里面的内容都变了,导致我觉得很奇怪,可能之前一直写的C语言,都是认为,全局变量都是唯一的。没曾想到,python里面的变量不需要申明,最后发现drawbox里面的g_tetris是个局部变量。这个问题困恼了我两三天吧。

未来的计划或建议

我已经将代码放到github上面,感兴趣的小伙伴可以尝试PR,一起来维护。通用那部分,我已经将大部分的code进行了调整,后续我会继续完善一些剩余的小功能,比如添加下一个方块的显示,增加音效,增加菜单等等功能

操作来看,屏幕刷新有点晃眼,如果能采用局部刷新的方式的话,可能显示会好一些。

github地址https://github.com/supperthomas/M5stickPlus_game_mpy.git

附件下载
game.py
团队介绍
thomas 霍尼韦尔有限公司
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号