内容介绍
内容介绍
硬禾学堂2022暑假在家练(2)-使用M5StickC Plus实现小游戏《接住掉落物》
一 项目简介:
该项目是使用M5StickC Plus实现小游戏《接住掉落物》,掉落物在屏幕上由上至下掉落,控制“小人儿”接住掉落物,每接一个得一分。使用UIFlow开发平台开发。
实现的功能和大致方法如下:
- 利用姿态传感器传出的俯仰角的数据来控制“小人儿”移动,A键开始游戏,B键返回开始界面
- 俯仰角越大“小人儿”移动速度越大。
- 显示图形方面,UIFlow对M5StickC Plus有专门的图形控制程序,直接控制横纵坐标变化即可使目标移动。
二 设计思路:
- “小人儿”的移动:判断姿态传感器传出的俯仰角的数据,设定合适移动的阈值。再利用俯仰角大小来对“小人儿”横坐标进行加减,以达到控制“小人儿”的移动和移动速度。
- 目标物的生成与移动:UIFlow自带图形编辑系统,可以使目标物显示(show)和隐藏(hide),设置了五个关键纵坐标标号来确定”掉落物“的五个轨迹。利用随机抽取列表[1,2,3,4,5]中的数来随机掉落五个目标物其中一个。
- 得分检测: 在设计”掉落物“和“小人儿”移动时有意保留了各自横纵坐标值,只需检测是否符合得分范围即可
三 软件流程图:
四 简单的硬件介绍:
- ESP32(240MHz dual core, 600 DMIPS, 520KB SRAM, Wi-Fi)
- 4MB Flash
- 屏幕:0.96 inch, 80*160 Colorful TFT LCD, ST7735SV
- SPM1423麦克风
- 一个红外发射管
- MEMS:MPU6886
- 2.4G 3D天线
- 蜂鸣器
五 实现的功能及图片展示:
- 开始界面如下,按A开始游戏,按B返回开始界面
- 利用姿态传感器传回俯仰角数值判断左右移动以及移动速度
- 当“小人儿”接住"掉落物"时,下方分数显示分数加一
六 主要代码片段及说明:
- 对应标号的KEY(E1_KEY---E5_KEY,默认为0)来更为方便的控制各个"掉落物"的是否运动以及显现,随机值取自数字1到5的列表。
# 五个“掉落物”随机生成,取目标物标号列表里1-5标号,使对应标号的显示&移动开关为开
def choice():
global e1, x, a, X_M1, score, e2, AAA, main_loca, e3, E1_KEY, Main_loca, e4, E2_KEY, b, e5, E3_KEY, E4_KEY, E5_KEY
x = lists_remove_random_item(X_M1)
if x == 1:
E1_KEY = 1
if x == 2:
E2_KEY = 1
if x == 3:
E3_KEY = 1
if x == 4:
E4_KEY = 1
if x == 5:
E5_KEY = 1
- 当某个"掉落物"到达设定的最低端时,KEY值变回0,”掉落物“隐藏,并将取出的相应数字标识返回到列表。
# e1---e5边界设定,到达边界返回初始值
if e1 >= 176:
e1 = -20
E1_KEY = 0
R1.hide()
# 返回标号到目标物别号列表,防止出现空列表(下同)
X_M1.append(1)
if e2 >= 176:
e2 = -20
E2_KEY = 0
R2.hide()
X_M1.append(2)
if e3 >= 176:
e3 = -20
E3_KEY = 0
R3.hide()
X_M1.append(3)
if e4 >= 176:
e4 = -20
E4_KEY = 0
R4.hide()
X_M1.append(4)
if e5 >= 176:
e5 = -20
E5_KEY = 0
R5.hide()
X_M1.append(5)
- 判定“掉落物”是否移动。当KEY等于1时对相应“掉落物”的纵坐标累加,使“掉落物”向下“掉落“。
# 五个“掉落物”的移动、显示和隐藏
def E_MOVE():
global e1, x, a, X_M1, score, e2, AAA, main_loca, e3, E1_KEY, Main_loca, e4, E2_KEY, b, e5, E3_KEY, E4_KEY, E5_KEY
# (e1---e5)显示开关为1时开始移动
if E1_KEY == 1:
# 目标移动速度
e1 = e1 + random.randint(4, 8)
R1.setPosition(y=e1)
if E2_KEY == 1:
e2 = e2 + random.randint(4, 8)
R2.setPosition(y=e2)
if E3_KEY == 1:
e3 = e3 + random.randint(4, 8)
R3.setPosition(y=e3)
if E4_KEY == 1:
e4 = e4 + random.randint(4, 8)
R4.setPosition(y=e4)
if E5_KEY == 1:
e5 = e5 + random.randint(4, 8)
R5.setPosition(y=e5)
- “小人儿”的移动:获取姿态传感器俯仰角数值,大于5横坐标加运算,小于5减运算,加减数值与俯仰角数值正相关,以此达到控制速度的目的。
# 控制“小人儿”左右移动
def MOVE():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
a = round(imu0.ypr[2])
AAA = [a, b]
Main_loca = [main_loca]
# b为a的绝对值
if a >= 0:
b = a
else:
b = 0 - a
# 使移动速度与俯仰角数值有关
if a >= 5:
main_loca = main_loca + round(b * 4 / 10)
rectangle2.setPosition(x=Main_loca[0])
if a <= -5:
main_loca = main_loca - round(b * 4 / 10)
rectangle2.setPosition(x=Main_loca[0])
# 移动边界
if main_loca <= 0:
main_loca = 0
if main_loca >= 109:
main_loca = 109
# 左右检测
if a >= 10:
label2.setText('R')
label2.show()
else:
label2.hide()
if a <= -10:
label1.setText('L')
label1.show()
else:
label1.hide()
- 判定是否得分:利用5个”掉落物“(e1---e5)的纵坐标和“小人儿”的横纵坐标,检测是否得分。
# 利用5个”掉落物“(e1---e5)的纵坐标和“小人儿”的横纵坐标,检测是否得分
def SCORE1():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
if e1 > 170 and e1 < 190 and main_loca + 12 >= 0 and main_loca <= 20:
score = score + 1
if e2 > 170 and e2 < 190 and main_loca + 12 > 24 and main_loca < 40:
score = score + 1
if e3 > 170 and e3 < 190 and main_loca + 12 > 53 and main_loca < 77:
score = score + 1
if e4 > 170 and e4 < 190 and main_loca + 12 > 82 and main_loca < 106:
score = score + 1
if e5 > 170 and e5 < 190 and main_loca + 12 >= 111 and main_loca <= 135:
score = score + 1
七 遇到的主要难题及解决方法:
- “掉落物”的掉落,起初很久没找到很好的方法:
解决过程:先是利用RTC来对各个掉落物纵坐标进行累加,最后发现不能独立控制某个”掉落物“,然后我想利用随机取出列表里的数的方法来对他们独立管控,但最后还是不尽人意。之后想到开关的方法,赋值给KEY=0or1。当为1时,显现掉落物并且纵坐标累加,当到达底部边界时,使KEY为0时,隐藏掉落物,并且初始化“掉落物”。
- “小人儿”的左右移动不是很顺滑,而且不能控制速度:
解决方法:将其横坐标累加值与俯仰角相关联,俯仰角越大,累加的值就越大,让其移动的速度就更快。
八 未来计划:
- 由于对ESP 32 的编程不熟悉,我这次开发用的是图形化编程平台,也是M5官方的平台,对没有编程基础的人很友好,但是对于更高级的需求可能完成不了,因此我仍然需要学习。
- 这个项目的其他任务我也想尝试,迫于本人实力有限,将来对嵌入式开发更加熟练时一定实时其他各种玩法。
#完整代码,本人承诺以下代码均为本人编写
from m5stack import *
from m5ui import *
from uiflow import *
import imu
setScreenColor(0x000000)
x = None
e1 = None
a = None
X_M1 = None
score = None
e2 = None
AAA = None
main_loca = None
E1_KEY = None
e3 = None
Main_loca = None
E2_KEY = None
e4 = None
b = None
E3_KEY = None
e5 = None
E4_KEY = None
E5_KEY = None
imu0 = imu.IMU()
rectangle2 = M5Rect(54, 198, 24, 24, 0xFFFFFF, 0xFFFFFF)
R1 = M5Rect(0, 0, 20, 20, 0xFFFFFF, 0xFFFFFF)
R2 = M5Rect(28, 0, 20, 20, 0xFFFFFF, 0xFFFFFF)
R3 = M5Rect(57, 0, 20, 20, 0xFFFFFF, 0xFFFFFF)
R4 = M5Rect(86, 0, 20, 20, 0xFFFFFF, 0xFFFFFF)
R5 = M5Rect(115, 0, 20, 20, 0xFFFFFF, 0xFFFFFF)
l1 = M5TextBox(54, 225, "0", lcd.FONT_Default, 0xFFFFFF, rotate=0)
label0 = M5TextBox(17, 77, "Press A to play", lcd.FONT_Default, 0xFFFFFF, rotate=0)
label3 = M5TextBox(23, 101, "B to try again", lcd.FONT_Default, 0xFFFFFF, rotate=0)
label1 = M5TextBox(0, 225, "L", lcd.FONT_Default, 0xffffff, rotate=0)
label2 = M5TextBox(124, 225, "R", lcd.FONT_Default, 0xffffff, rotate=0)
rectangle0 = M5Rect(0, 222, 135, 2, 0xFFFFFF, 0xff0000)
import random
import math
def lists_remove_random_item(myList):
x = int(random.random() * len(myList))
return myList.pop(x)
# 五个”掉落物“随机生成,取“掉落物”标号列表里1-5标号,使对应标号的显示&移动开关为开
def choice():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
x = lists_remove_random_item(X_M1)
if x == 1:
E1_KEY = 1
if x == 2:
E2_KEY = 1
if x == 3:
E3_KEY = 1
if x == 4:
E4_KEY = 1
if x == 5:
E5_KEY = 1
# 利用5个”掉落物“(e1---e5)的纵坐标和“小人儿”的横纵坐标,检测是否得分
def SCORE1():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
if e1 > 170 and e1 < 190 and main_loca + 12 >= 0 and main_loca <= 20:
score = score + 1
if e2 > 170 and e2 < 190 and main_loca + 12 > 24 and main_loca < 40:
score = score + 1
if e3 > 170 and e3 < 190 and main_loca + 12 > 53 and main_loca < 77:
score = score + 1
if e4 > 170 and e4 < 190 and main_loca + 12 > 82 and main_loca < 106:
score = score + 1
if e5 > 170 and e5 < 190 and main_loca + 12 >= 111 and main_loca <= 135:
score = score + 1
# 各变量的初始化
def INT_E():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
e1 = -20
e2 = -20
e3 = -20
e4 = -20
e5 = -20
# E1的show与hide开关
E1_KEY = 0
E2_KEY = 0
E3_KEY = 0
E4_KEY = 0
E5_KEY = 0
R1.hide()
R2.hide()
R3.hide()
R4.hide()
R5.hide()
# 控制“小人儿”左右移动
def MOVE():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
a = round(imu0.ypr[2])
AAA = [a, b]
Main_loca = [main_loca]
# b为a的绝对值
if a >= 0:
b = a
else:
b = 0 - a
# 使移动速度与俯仰角数值有关
if a >= 5:
main_loca = main_loca + round(b * 4 / 10)
rectangle2.setPosition(x=Main_loca[0])
if a <= -5:
main_loca = main_loca - round(b * 4 / 10)
rectangle2.setPosition(x=Main_loca[0])
# 移动边界
if main_loca <= 0:
main_loca = 0
if main_loca >= 109:
main_loca = 109
# 左右检测
if a >= 10:
label2.setText('R')
label2.show()
else:
label2.hide()
if a <= -10:
label1.setText('L')
label1.show()
else:
label1.hide()
# 五个“掉落物”的移动、显示和隐藏
def E_MOVE():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
# (e1---e5)显示开关为1时开始移动
if E1_KEY == 1:
# 目标移动速度
e1 = e1 + random.randint(4, 8)
R1.setPosition(y=e1)
if E2_KEY == 1:
e2 = e2 + random.randint(4, 8)
R2.setPosition(y=e2)
if E3_KEY == 1:
e3 = e3 + random.randint(4, 8)
R3.setPosition(y=e3)
if E4_KEY == 1:
e4 = e4 + random.randint(4, 8)
R4.setPosition(y=e4)
if E5_KEY == 1:
e5 = e5 + random.randint(4, 8)
R5.setPosition(y=e5)
# e1---e5边界设定,到达边界返回初始值
if e1 >= 176:
e1 = -20
E1_KEY = 0
R1.hide()
# 返回标号到目标物别号列表,防止出现空列表(下同)
X_M1.append(1)
if e2 >= 176:
e2 = -20
E2_KEY = 0
R2.hide()
X_M1.append(2)
if e3 >= 176:
e3 = -20
E3_KEY = 0
R3.hide()
X_M1.append(3)
if e4 >= 176:
e4 = -20
E4_KEY = 0
R4.hide()
X_M1.append(4)
if e5 >= 176:
e5 = -20
E5_KEY = 0
R5.hide()
X_M1.append(5)
def buttonA_wasPressed():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
timerSch.run('timer', 1000, 0x00)
label0.hide()
label3.hide()
pass
btnA.wasPressed(buttonA_wasPressed)
def buttonB_wasPressed():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
timerSch.stop('timer')
score = 0
label0.show()
label3.show()
pass
btnB.wasPressed(buttonB_wasPressed)
@timerSch.event('timer')
def ttimer():
global x, e1, a, X_M1, score, e2, AAA, main_loca, E1_KEY, e3, Main_loca, E2_KEY, e4, b, E3_KEY, e5, E4_KEY, E5_KEY
choice()
pass
# 5个目标物的标号
X_M1 = [1, 2, 3, 4, 5]
# 控制物的初始横位置
main_loca = 54
# 得分
score = 0
INT_E()
while True:
MOVE()
E_MOVE()
SCORE1()
# 显示得分
l1.setText(str(score))
wait_ms(2)
附件下载
my-game.m5f
my_game.py
团队介绍
团队成员
listeningsnow
评论
0 / 100
查看更多
猜你喜欢
基于ESP32的M5StickC-PlusM5StickC PLUS 是M5StickC的大屏幕版本,主控采用ESP32-PICO-D4模组,具备蓝牙4.2与WIFI功能,小巧的机身内部集成了丰富的硬件资源,如红外、RTC、麦克风、LED、IMU、按键、蜂鸣器、PMU等
理工男
3267
基于M5StickC Plus制作的儿时小游戏——弹珠迷宫2022暑期在家一起练 M5StickC Plus esp32 Arduino 游戏 迷宫 随机深度优先算法 弹珠迷宫 IMU
aramy
1327
2022暑期在家一起练(2)——基于M5StickC Plus的可定时电子沙漏基于M5StickC Plus及其SDK,使用Arduino与VSCode开发,通过软SPI驱动两块LED矩阵,作为电子沙漏显示面板,实现按键控制电子沙漏工作状态、定时、在LCD上显示倒计时,同时在LED矩阵上显示沙漏滴落的动态效果。
葉SiR
1419