【雕爷学编程】 MicroPython动手做(35)——体验小游戏

知识点:什么是掌控板?
掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED显示屏、RGB灯、加速度计、麦克风、光线传感器、蜂鸣器、按键开关、触摸开关、金手指外部拓展接口,支持图形化及MicroPython代码编程,可实现智能机器人、创客智造作品等智能控制类应用。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

掌控板硬件特性:
ESP-32主控
处理器:Tensilica LX6双核处理器(一核处理高速连接;一核独立应用开发)
主频:高达240MHz的时钟频率
SRAM:520KB
Flash:8MB
Wi-Fi标准:FCC/CE/TELEC/KCC
Wi-Fi协议:802.11 b/g/n/d/e/i/k/r (802.11n,速度高达150 Mbps),A-MPDU和A-MSDU聚合,支持0.4us防护间隔
频率范围:2.4~2.5 GHz
蓝牙协议:符合蓝牙v4.2 BR/EDR和BLE标准
蓝牙音频:CVSD和SBC音频低功耗:10uA
供电方式:Micro USB供电
工作电压:3.3V
最大工作电流:200mA
最大负载电流:1000mA
掌控板载
三轴加速度计MSA300,测量范围:±2/4/8/16G
地磁传感器MMC5983MA,测量范围:±8 Gauss;精度0.4mGz,电子罗盘误差±0.5°
光线传感器
麦克风
3 颗全彩ws2812灯珠
1.3英寸OLED显示屏,支持16*16字符显示,分辨率128x64
无源蜂鸣器
支持2个物理按键(A/B)、6个触摸按键
支持1路鳄鱼夹接口,可方便接入各种阻性传感器
拓展接口
20通道数字I/O, (其中支持12路PWM,6路触摸输入)
5通道12bit模拟输入ADC,P0~P4
1路的外部输入鳄鱼夹接口:EXT/GND
支持I2C、UART、SPI通讯协议

在这里插入图片描述
在这里插入图片描述

小游戏 (体积较小、玩法简单的游戏)
小游戏是一个较模糊的概念,它是相对于体积庞大的单机游戏及网络游戏而言的,泛指所有体积较小、玩法简单的游戏,通常这类游戏以休闲益智类为主,有单机版有网页版,在网页上嵌入的多为FLASH格式。当下小游戏主要是指在线玩的flash版本游戏,统称小游戏,其实小游戏还包含单机游戏,小型游戏机等。一般游戏大小小于10m的游戏都统称为小游戏,一些街机类小游戏。因其游戏安装简便,耐玩性强,无依赖性而广受白领及小朋友的喜爱。

“小游戏”这个词的型含义其实很简单,它不是一些大的游戏,不必花费更多的时间和精力。小游戏是原始的游戏娱乐方式,小游戏本身是为了叫人们在工作,学习后的一种娱乐、休闲的一种方式,不是为了叫玩家为之花费金钱、花费精力,更不是叫玩家为他痴迷。小游戏也可以理解为“Flash游戏”,是以SWF为后缀的游戏的总称.这些游戏是通过Flash软件和 Flash 编程语言 Flash ActionScript 制作而成。由于Flash是矢量软件,所以小游戏放大后几乎不影响画面效果。Flash小游戏是一种新兴起的游戏形式,以游戏简单,操作方便,绿色,无需安装,文件体积小等优点渐渐被广大网友喜爱。

【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第1张图片

1、弹球游戏

#MicroPython动手做(35)——体验小游戏
#弹球游戏

from mpython import *
import music
import time

def func():
    global a, b, FMQ, loc, staart_flag, Start, X, Y
    music.pitch(131, 500)
    loc = 44
    a = 2
    b = 2
    staart_flag = False
    Start = True
    Y = 48
    X = 64
    FMQ = False

def a1():
    global a, b, FMQ, loc, staart_flag, Start, X, Y
    if FMQ:
        music.pitch(131, 500)
        FMQ = False

def a3():
    global a, b, FMQ, loc, staart_flag, Start, X, Y
    if Start:
        if button_a.value() == 0:
            staart_flag = True
            loc = loc - 2
            if loc < 0:
                loc = 0
        if button_b.value() == 0:
            staart_flag = True
            loc = loc + 2
            if loc > 88:
                loc = 88

def a2():
    global a, b, FMQ, loc, staart_flag, Start, X, Y
    oled.fill(0)
    oled.fill_rect(loc, 55, 40, 5, 1)
    oled.fill_circle(X, Y, 5, 1)
    oled.show()
    if button_a.value() == 0 and button_b.value() == 0:
        func()
        while button_a.value() == 0 and button_b.value() == 0:
            pass
        time.sleep_ms(100)

def a4():
    global a, b, FMQ, loc, staart_flag, Start, X, Y
    if staart_flag:
        X = X + a
        Y = Y - b
        if X >= 122:
            a = a * -1
        if X <= 5:
            a = a * -1
        if Y <= 5:
            b = b * -1
        if Y >= 48:
            if not (X > loc + 50 or X < loc - 10):
                b = b * -1
            if X > loc + 50 or X < loc - 10:
                staart_flag = False
                Start = False
                FMQ = True


func()
while True:
    a1()
    a2()
    a3()
    a4()

mPython X 实验图形编程

【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第2张图片

mPython X 实验图形编程2

【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第3张图片

Mind+ 实验图形编程
【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第4张图片

弹球游戏(实验视频)

https://v.youku.com/v_show/id_XNDcyNzU1MjkwNA==.html?spm=a2h0c.8166622.PhoneSokuUgc_1.dtitle

添加链接描述【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第5张图片

2、简单连连看(shworld)

玩法说明
按A键左移动
按B键右移动
按金手指T或H来选择

#MicroPython动手做(35)——体验小游戏
#简单连连看

from mpython import *
import random

#--------------------------------------------------------
#图片转换参考https://mpython.readthedocs.io/zh/master/tutorials/basics/oled.html#id3
#图片定义
#苹果
apple = bytearray([\
0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X00,0X01,0X80,0X00,0X00,0X01,0X80,0X18,0X70,0X01,
0X80,0X00,0X0C,0X01,0X80,0X00,0X03,0X01,0X84,0X01,0XC0,0X81,0X88,0X3F,0XF0,0X61,
0X98,0X3F,0XF8,0X31,0X90,0X3F,0XFC,0X31,0XB0,0X3F,0XFC,0X19,0XB0,0X3F,0XFE,0X19,
0XB0,0X0F,0XF6,0X19,0XB8,0X00,0X80,0X19,0XBC,0X00,0X00,0X19,0XBE,0X00,0X00,0X39,
0XBF,0X80,0X00,0X79,0XBF,0XE0,0X07,0XF9,0X9F,0XFF,0XFF,0XF9,0X9F,0XFF,0XFF,0XF1,
0X8F,0XFF,0XFF,0XF1,0X8F,0XFF,0XFF,0XE1,0X87,0XFF,0XFF,0XE1,0X83,0XFF,0XFF,0XC1,
0X81,0XFF,0XFF,0X81,0X81,0XFF,0XFF,0X01,0X80,0XFF,0XFE,0X01,0X80,0X7F,0XFC,0X01,
0X80,0X3F,0XF0,0X01,0X80,0X00,0X00,0X01,0X80,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,
])

#樱桃
cherry = bytearray([\
0XFF,0XFF,0XFF,0XFF,0X80,0XC0,0X00,0X01,0X81,0XC0,0X00,0X01,0X80,0XC0,0X00,0X01,
0X80,0XC0,0X00,0X01,0X80,0XA0,0X00,0X01,0X80,0X10,0X00,0X01,0X80,0X90,0X00,0X01,
0X80,0X88,0X00,0X01,0X80,0X8C,0X00,0X01,0X80,0X84,0X00,0X01,0X80,0X83,0X00,0X01,
0X80,0X81,0X80,0X01,0X80,0X00,0XCF,0X21,0X80,0X40,0X7F,0X11,0X80,0X79,0XFF,0X19,
0X87,0XFC,0XFF,0XF9,0X8F,0XFC,0X7F,0XF9,0X9F,0XF8,0X7F,0XFD,0XBF,0XF8,0X7F,0XFD,
0XBF,0XF8,0X7F,0XFD,0XBF,0XF8,0X7F,0XFD,0XBF,0XFF,0XFF,0XFD,0XBF,0XFF,0XFF,0XF9,
0XBF,0XFF,0XFF,0XF9,0XBF,0XFF,0XFF,0XF1,0XBF,0XFF,0XFF,0XF1,0X9F,0XFF,0XFF,0XE1,
0X8F,0XFF,0X9F,0X81,0X87,0XFF,0X00,0X01,0X81,0XFC,0X00,0X01,0XFF,0XFF,0XFF,0XFF,
])

#桑葚
mulberry = bytearray([\
0XFF,0XFF,0XFF,0XFF,0X80,0X21,0X00,0X01,0X80,0X10,0X00,0X01,0X81,0X08,0X80,0X01,
0X82,0X38,0X80,0X01,0X82,0X3F,0X80,0X01,0X82,0X3F,0XE0,0X01,0X86,0X3F,0XF0,0X01,
0X86,0X3F,0XF8,0X01,0X83,0XFF,0XFC,0X01,0X83,0XFF,0XFE,0X01,0X87,0XFF,0XFF,0X01,
0X8F,0XFF,0XFF,0X01,0X8F,0XFF,0XFF,0X01,0X8F,0XFF,0XFF,0X81,0X8F,0XFF,0XFF,0X81,
0X8F,0XFF,0XFF,0X81,0X8F,0XFF,0XFF,0X81,0X8F,0XFF,0XFF,0X81,0X87,0XFF,0XFF,0X81,
0X87,0XFF,0XFF,0X81,0X83,0XFF,0XFF,0XC1,0X81,0XFF,0XFF,0XC1,0X80,0XFF,0XFF,0XC1,
0X80,0XFF,0XFF,0XC1,0X80,0X7F,0XFF,0XC1,0X80,0X3F,0XFF,0X81,0X80,0X1F,0XFF,0X81,
0X80,0X0F,0XFF,0X81,0X80,0X03,0XFF,0X01,0X80,0X01,0XFC,0X01,0XFF,0XFF,0XFF,0XFF,
])

#草莓
strawberry = bytearray([\
0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X00,0X01,0X80,0X00,0X00,0X01,0X80,0X00,0X00,0X01,
0X80,0X00,0X00,0X01,0X80,0X00,0XC0,0X01,0X80,0X03,0XE8,0X01,0X80,0X0D,0XE4,0X01,
0X80,0X1F,0XFE,0X01,0X80,0X3F,0XFF,0X01,0X80,0X7F,0XFF,0X01,0X80,0XFF,0XDF,0X81,
0X81,0XFF,0XFF,0XF9,0X83,0XFF,0XFF,0XC1,0X83,0XFF,0XFF,0XC1,0X87,0XFF,0XFF,0XC1,
0X8F,0XFF,0XFF,0XE1,0X9F,0X7F,0XFF,0XE1,0XBF,0XFF,0XFF,0XE1,0XBF,0XFF,0XFF,0XE1,
0XBF,0XFE,0XFF,0XE1,0XBF,0XDF,0XFF,0XE1,0XBF,0XFF,0XFF,0XC1,0X9F,0XFF,0XFE,0XC1,
0X9F,0XFF,0XBF,0X81,0X8F,0XFF,0XFF,0X01,0X81,0XFF,0XFC,0X01,0X80,0X07,0XF0,0X01,
0X80,0X00,0X00,0X01,0X80,0X00,0X00,0X01,0X80,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,
])

#打勾
tick = bytearray([\
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XC0,0X00,0X00,0X03,0XC0,0X00,0X00,0X03,
0XC0,0X00,0X00,0X03,0XC0,0X00,0X00,0X63,0XC0,0X00,0X00,0XE3,0XC0,0X00,0X01,0XE3,
0XC0,0X00,0X03,0XE3,0XC0,0X00,0X07,0XE3,0XC0,0X00,0X0F,0XE3,0XC0,0X00,0X1F,0XE3,
0XC0,0X00,0X1F,0XF3,0XC0,0X00,0X3F,0XF3,0XC0,0X00,0X7F,0XC3,0XC0,0X00,0X7F,0X83,
0XC0,0XC0,0XFF,0X03,0XC1,0XE0,0XFE,0X03,0XC7,0XE1,0XFC,0X03,0XCF,0XF1,0XF8,0X03,
0XCF,0XF3,0XF0,0X03,0XC3,0XFB,0XE0,0X03,0XC1,0XFF,0XC0,0X03,0XC0,0X7F,0X80,0X03,
0XC0,0X3F,0X80,0X03,0XC0,0X1F,0X00,0X03,0XC0,0X0E,0X00,0X03,0XC0,0X06,0X00,0X03,
0XC0,0X04,0X00,0X03,0XC0,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
])


#--------------------------------------------------------
#函数定义
#生成8个随机水果下标
#默认数组[0,1,2,3],循环2次,就有个8了,如何避免每次生成重复的呢,下面请看
def getFruitRand():
    fruitsIndex=[0,1,2,3]
    fruitsIndex_random=[]
    for i in range(2):                                 #对[0,1,2,3]循环2次加入到fruitsIndex_random中
        fruitsIndex_=fruitsIndex.copy()                #这里不直接用fruitsIndex,因为下面有del删除,我们拷贝一份副本
        for j in range(4):                             #循环4次
            rand=random.randint(0,len(fruitsIndex_)-1) #随机0-3,因j从0开始最大为3,而len(fruitsIndex)返回的是4,所以-1
            randIndex=fruitsIndex_[rand]               #取随机下标,范围在0-3中, fruitsIndex=[0,1,2,3]               
            fruitsIndex_random.append(randIndex)       #添加到fruitsIndex_random中
            del(fruitsIndex_[rand])                    #这里核心,添加完成后删除掉fruitsIndex中的内容                     
                                                       #删除掉后,随机就肯定不会出现重复的了
                                                       #比如每次都随机删除最后一个
                                                       #循环第一次fruitsIndex_长度为[0,1,2,3]
                                                       #循环第二次fruitsIndex_长度为[0,1,2]
                                                       #循环第三次fruitsIndex_长度为[0,1]
                                                       #循环第四次fruitsIndex_长度为[0]
                                                       #这样随机肯定不会重复
    #返回得到的8位随机水果下标fruitsIndex_random    
    return fruitsIndex_random
            
 

#显示8个水果图片
#isShow主要控制是否最后oled.show(),因为我可能会再show()之前插入一些文字
#fruitsIndex传输的8位随机水果下标,如[2,1,3,0,2,0,1,3]
def showFruit(fruitsIndex,isShow=True):
    i=0
    for index in fruitsIndex:                           #遍历fruitsIndex下标,i计次,从0开始
        if i<4:                                         #控制一行显示4个
            if index==-1:                               #下标为何出现-1,在其他函数中连连看完成会置下标-1
                oled.Bitmap(32*i, 0, tick, 32, 32, 1)   #显示打勾图片(x每次递增32,因为每张图32*32,屏宽128)
            else:                                       #否则显示水果图
                oled.Bitmap(32*i, 0, fruits[index], 32, 32, 1)  
        if i>=4:                                        #如果显示第5个图了,换行显示,y坐标变成32
            if index==-1:                               #以此类题,显示打勾图片
                oled.Bitmap(32*(i-4), 32, tick, 32, 32, 1)
            else:
                oled.Bitmap(32*(i-4), 32, fruits[index], 32, 32, 1)
        i=i+1                                           #i递增
    
    #是否显示输出
    if isShow:
        oled.show()

#按键A触发事件,向左移动判断
def on_button_a_down(_):
    global cursor_X,cursor_Y,chose1XY,isFinish  #引用全局变量
    time.sleep_ms(10)                           #防抖,可以不写 
    if button_a.value() == 1: return            #按钮按下状态
    if isFinish==True:                          #如果全部连完了,重新开始游戏
        start()
        return
    oled.fill(0)                                #清空屏幕显示        
    showFruit(fruitsIndex,False)                #显示水果,传入随机的8个水果下标
    cursor_X=cursor_X-32                        #全局光标坐标-32(因图片宽高为32)  
    if cursor_X<0 and cursor_Y==8:              #如果光标在第一行且X到最左端了,那么换到第二行最右侧
        cursor_X=100                            #换到第二行最右侧
        cursor_Y=40
    if cursor_X<4 and cursor_Y==40:             #如果光标在第二行且X在最左端了,那么换到第一行最右侧
        cursor_X=100
        cursor_Y=8
        
    if chose1XY:                                         #如果第1个位置已经选中状态
        oled.DispChar('选中', chose1XY[0], chose1XY[1])  #显示那个"光标"的文字位置
    oled.DispChar('光标', cursor_X, cursor_Y)            #否则显示"光标"文字
    oled.show()                                          #显示生效

    
#按键B触发事件,向右移动判断
def on_button_b_down(_):
    global cursor_X,cursor_Y,chose1XY,isFinish   #按键B与按键A没有区别,就是到极端时换行不同
    time.sleep_ms(10)
    if button_b.value() == 1: return
    if isFinish==True:
        start()
        return
    oled.fill(0)   
    showFruit(fruitsIndex,False)
    cursor_X=cursor_X+32
    if cursor_X>128 and cursor_Y==40:
        cursor_X=4
        cursor_Y=8
    if cursor_X>128 and cursor_Y==8:
        cursor_X=4
        cursor_Y=40
    
    if chose1XY :
        oled.DispChar('选中', chose1XY[0], chose1XY[1])
    oled.DispChar('光标', cursor_X, cursor_Y)
    oled.show()


#验证是否完成8个水果的连连看
def checkIsFinish():
    global isFinish                             #引用全局变量
    i=0                                         #初始化i变量
    for index in fruitsIndex:                   #遍历fruitsIndex下标情况
        if index==-1:                           #如果为-1,i递增(在其他函数中连连看完成会置下标-1)
            i=i+1
    if i>=8:                                    #如果i等于8说明8个连连看都完成了
        isFinish=True                           #置全局变量
        oled.fill(0)                            #清空屏幕显示
        oled.DispChar('恭喜您,通关了!', 28, 15) #填充文字
        oled.DispChar('按A或B重新开始', 22, 30) #填充文字
        oled.show()                             #显示生效
        
#通过金手指T和H来选择水果       
def choseFruit(cursor_X,cursor_Y):
    global fruitsIndex,chose1Index,chose2Index,chose1XY,chose2XY
    i=0
    for x,y in fruitXY:                         #遍历8张图的预定义坐标
        if cursor_X==x and cursor_Y==y:         #如果当前光标位置=预定义坐标位置,即可得到水果下标
            if fruitsIndex[i]==-1:              #如果光标位置下标为-1,说明已是打勾状态,不重复选中
                return                          #返回
            if chose1XY:                        #如果第1个位置已经选中状态             
                chose2XY=[x,y]                  #把光标位置赋给第2个选择位置
                chose2Index=fruitsIndex[i]      #同时得到水果下标
            else:
                chose1XY=[x,y]                  #否则赋值第1个选择位置
                chose1Index=fruitsIndex[i]      #同时得到水果下标
        i=i+1                                   #i递增         
    showFruit(fruitsIndex,False)                #显示水果,不立即显示生效
    
    if chose2XY:                                                             #如果第2个位置选中了,此时可进行匹配
        if chose1Index==chose2Index and chose1XY!=chose2XY:                  #如果位置1和位置2的下标相同且坐标不相同(否则连自身就匹配成功了)
            oled.line(chose1XY[0], chose1XY[1], chose2XY[0], chose2XY[1], 1) #画线,位置1到位置2
            oled.DispChar('成功', cursor_X, cursor_Y)                        #填充文字
            for i in range(len(fruitsIndex)):                                #遍历全局fruitsIndex,把该水果的下标置-1
                if fruitsIndex[i]==chose2Index:
                    fruitsIndex[i]=-1
            chose1XY=[]                                                      #清空位置1坐标
            chose2XY=[]                                                      #清空位置2坐标
            oled.show()                                                      #显示生效
            checkIsFinish()                                                  #检测是否全部匹配完成
    else:
        oled.DispChar('选中', cursor_X, cursor_Y)                            #否则继续显示"选中"文字
        oled.show()                                                          #显示生效
    
#开始游戏
def start():
    #引用全局变量并初始化默认值,因为重新开始游戏时必须初始化
    global fruitsIndex,cursor_X,cursor_Y,chose1XY,chose1Index,chose2XY,chose2Index,fruitsIndex,isFinish
    
    #初始化变量
    chose1XY=[]
    chose1Index=''
    chose2XY=[]
    chose2Index=''
    fruitsIndex=[]
    cursor_X=4
    cursor_Y=8
    isFinish=False
    
    oled.fill(0)                   #清空屏幕显示
    fruitsIndex=getFruitRand()     #获取随机的8个水果下标
    showFruit(fruitsIndex,False)   #第一次开始游戏先显示水果,传入8个随机水果下标
    oled.DispChar('光标', cursor_X, cursor_Y)   #第一次开始游戏,光标出现在默认的x,y4,8位置
    oled.show()                    #显示生效




#--------------------------------------------------------
#变量定义
fruits=[apple,cherry,mulberry,strawberry] #4个图片的bitmap数组
fruitsIndex=[]                            #水果的下标数组,用来存放随机的8个水果
fruitXY=[[4,8],[36,8],[68,8],[100,8],[4,40],[36,40],[68,40],[100,40]]  #8张图的预定义坐标,从左到右,从上到下

chose1XY=[]                               #位置1选择的水果坐标
chose1Index=''                            #位置1选择的水果下标

chose2XY=[]                               #位置2选择的水果坐标
chose2Index=''                            #位置2选择的水果下标

cursor_X=4                                #全局光标坐标,默认为第一个图的位置4,8(居中显示)
cursor_Y=8                               

isFinish=False                            #是否已完成

start()                                   #开始游戏



#--------------------------------------------------------
#按键监听
#按键A/B触发监视
button_a.irq(trigger=Pin.IRQ_FALLING, handler=on_button_a_down)
button_b.irq(trigger=Pin.IRQ_FALLING, handler=on_button_b_down)

#通过金手指T和H来选择水果
while True:
    if(touchPad_T.read() < 100):
        choseFruit(cursor_X,cursor_Y)
    elif(touchPad_H.read() < 100):
        choseFruit(cursor_X,cursor_Y)

简单连连看

【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第6张图片
【雕爷学编程】 MicroPython动手做(35)——体验小游戏_第7张图片

你可能感兴趣的:(MicroPython动手做,物联网,人工智能,单片机,嵌入式硬件,python,小游戏)