知识点:什么是掌控板?
掌控板是一块普及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小游戏是一种新兴起的游戏形式,以游戏简单,操作方便,绿色,无需安装,文件体积小等优点渐渐被广大网友喜爱。
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 实验图形编程
mPython X 实验图形编程2
弹球游戏(实验视频)
https://v.youku.com/v_show/id_XNDcyNzU1MjkwNA==.html?spm=a2h0c.8166622.PhoneSokuUgc_1.dtitle
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)
简单连连看