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

知识点:什么是掌控板?
掌控板是一块普及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小游戏是一种新兴起的游戏形式,以游戏简单,操作方便,绿色,无需安装,文件体积小等优点渐渐被广大网友喜爱。

在这里插入图片描述
Mind+ 实验图形编程

在这里插入图片描述

Mind+ 实验图形编程2

在这里插入图片描述

贪吃蛇
在这里插入图片描述

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

4、平衡自行车(shworld)

#MicroPython动手做(35)——小游戏
#平衡自行车

from mpython import *

#自行车BMP图像转字节数据参考
#https://mpython.readthedocs.io/zh/master/tutorials/basics/oled.html#id4
bmp = bytearray([\
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0X00,0X0F,0XF8,0X00,0X00,
0X00,0X00,0X18,0X00,0X0C,0X0C,0X00,0X00,0X00,0X00,0X08,0X00,0X04,0X04,0X00,0X00,
0X00,0X00,0X04,0X00,0X02,0X38,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0X00,0X00,0X00,
0X00,0X00,0X07,0X00,0X07,0X00,0X00,0X00,0X00,0X00,0X09,0X00,0X04,0X80,0X00,0X00,
0X00,0X00,0X11,0X80,0X0C,0XC0,0X00,0X00,0X00,0XFF,0X30,0X80,0X18,0X7F,0XE0,0X00,
0X03,0X80,0XE0,0XC0,0X30,0X70,0X38,0X00,0X06,0X00,0XF0,0X60,0X21,0XB0,0X06,0X00,
0X08,0X00,0X88,0X20,0X43,0X10,0X03,0X00,0X10,0X01,0X04,0X30,0X86,0X08,0X01,0X00,
0X30,0X03,0X0E,0XFF,0X84,0X0C,0X00,0X80,0X20,0X1F,0XFF,0X31,0X8C,0X04,0X00,0XC0,
0X60,0X32,0X02,0X20,0X8C,0X00,0X00,0XC0,0X60,0X22,0X02,0X24,0XC8,0X00,0X00,0XC0,
0X60,0X1F,0X02,0X3C,0X8C,0X00,0X00,0XC0,0X30,0X0F,0XFF,0XFF,0X04,0X00,0X00,0X80,
0X10,0X00,0X04,0X18,0X04,0X00,0X01,0X80,0X18,0X00,0X0C,0X08,0X02,0X00,0X03,0X00,
0X0C,0X00,0X18,0X00,0X01,0X00,0X06,0X00,0X07,0X00,0X70,0X00,0X00,0XC0,0X0C,0X00,
0X01,0XFF,0XC0,0X00,0X00,0X3F,0XF0,0X00,0X00,0X3E,0X00,0X00,0X00,0X0F,0XC0,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
])
#无限循环
while True:
    bikeWidth=60    #自行车图片宽度
    bikeHeight=30   #自行车图片高度
    bikeInitX=34    #初始化自行车的X中央点,屏幕宽度128/2-补偿自行车宽度30=34
    bikeInitY=35    #初始化自行车的Y点,手动测量调为35即可
    y=accelerometer.get_y() #如官方说明图所示,y轴和x轴是相反的,所以这里获取的是y轴加速度
    if y<=1 and y>=-1:      #定界,其实不定也行。用于下面设定变量转换
        offsetX=int(numberMap(y,1,-1,-60,128)) #-60=最小宽度0-自行车宽度,128为屏幕最大宽度
        #offsetX主要把y轴的加速度转换成屏幕的宽度分辨率
        #numberMap变量转换说明
        #numberMap(输入值,需映射的最小值,需映射的最大值,映射出的最小值,映射出的最大值)
        #比如numberMap(i,1,2,10000,20000)
        #即i是变量,范围在1~2之间,通过numberMap函数你可以得到转换后的范围,在10000-2000之间
        #如i是1.5则返回15000,i是1.8返回18000,以此类推
        move_x=offsetX #移动的坐标
        #清除
        oled.fill(0)
        #填充图形
        oled.Bitmap(move_x,bikeInitY, bmp, bikeWidth  , bikeHeight, 1)
        #填充左侧钉子,手绘坐标
        oled.line(0,64,2,58,1) 
        oled.line(2,58,4,64,1)
        #填充右侧钉子,手绘坐标
        oled.line(127,64,125,58,1)  
        oled.line(125,58,123,64,1)  
        #判断是否碰到左右钉子边界,并填充文字提示
        if move_x+bikeWidth >=125:
            oled.DispChar('老铁,扎前胎了!', 60-14, 0)
        if move_x+bikeWidth<=58:
            oled.DispChar('老铁,扎后胎了!',0,0)
        #显示图形文字
        oled.show()

#MicroPython动手做(35)——小游戏
#平衡自行车(实验视频)

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

在这里插入图片描述

5、贪吃蛇2
使用三轴传感器控制前后左右

#MicroPython动手做(35)——小游戏
#贪吃蛇2

from mpython import *
import random, time

WIDTH, HEIGHT = 127, 63


class Direction():
    """
    贪吃蛇方向,含上下左右
    """

    UP = 0
    DOWN = 1
    LEFT = 2
    RIGHT = 3


class GameState():
    """
    游戏状态
    """
    PLAYING = 0
    PAUSE = 1
    WIN = 2
    FAIL = 3


class Snake():
    """
    贪吃蛇

    构建snake

    :param cube(int): 网格大小默认4
    """

    def __init__(self, cube=4):

        self.cube_width = cube
        self.grid_width_num, self.grid_height_num = WIDTH // self.cube_width, HEIGHT // self.cube_width
        self.snake_body = []
        self.snake_body.append((int(self.grid_width_num // 2 * self.cube_width),
                                int(self.grid_height_num // 2 * self.cube_width)))  # 添加贪吃蛇的“头”
        self.food_pos = self.generate_food()
        self.direction = Direction.LEFT

    def draw_grids(self):
        """
        绘制网格
        """
        for i in range(self.grid_width_num + 1):
            oled.vline(self.cube_width * i, 0, HEIGHT, 1)

        for i in range(self.grid_height_num + 1):
            oled.hline(0, self.cube_width * i, WIDTH, 1)

    def draw_body(self):
        """
        绘制snake
        """
        for sb in self.snake_body:
            # pygame.draw.rect(screen, WHITE, (sb[0], sb[1], CUBE_WIDTH, CUBE_WIDTH))
            oled.fill_rect(sb[0], sb[1], self.cube_width, self.cube_width, 1)

    def generate_food(self):
        """
        随机产生一个食物
        """
        self.food_pos = (random.randint(0, self.cube_width - 1), random.randint(0, self.grid_height_num - 1))
        return self.food_pos

    def draw_food(self):
        """
        绘制食物
        """
        oled.fill_rect(self.food_pos[0] * self.cube_width, self.food_pos[1] * self.cube_width, self.cube_width,
                       self.cube_width, 1)

    def grow(self):
        """
        判断贪吃蛇是否吃到了事物,如果吃到了我们就加长小蛇的身体
        """
        if self.snake_body[0][0] == self.food_pos[0] * self.cube_width and \
            self.snake_body[0][1] == self.food_pos[1] * self.cube_width:
            return True

        return False

    def refresh(self):
        """ 
        更新小蛇身体的位置
        """
        for i in range(len(self.snake_body) - 1, 0, -1):
            self.snake_body[i] = self.snake_body[i - 1]

    def move(self):
        """
        移动snake身体
        """
        if self.direction == Direction.UP:
            self.snake_body[0] = (self.snake_body[0][0], self.snake_body[0][1] - self.cube_width)

        elif self.direction == Direction.DOWN:
            self.snake_body[0] = (self.snake_body[0][0], self.snake_body[0][1] + self.cube_width)

        # top += cube_width
        elif self.direction == Direction.LEFT:

            self.snake_body[0] = (self.snake_body[0][0] - self.cube_width, self.snake_body[0][1])

        # left -= cube_width
        elif self.direction == Direction.RIGHT:
            self.snake_body[0] = (self.snake_body[0][0] + self.cube_width, self.snake_body[0][1])


class Game():
    """
    snake游戏控制
    """

    def __init__(self, fps=8):
        self.snake = Snake()
        self.get_body = self.snake.snake_body
        self.state = None
        self.fps = fps
        self.handles_cb = None

    def is_win(self):
        """
        判断是否赢
        """
        return len(self.get_body) == WIDTH * HEIGHT - 1

    def is_fail(self):
        """
        判断是否输
        """
        if not 0 <= self.get_body[0][0] < WIDTH or not 0 <= self.get_body[0][1] < HEIGHT:
            return True

        return False

    @property
    def score(self):
        """
        游戏分数
        """
        return len(self.get_body) - 1

    def handles_accele(self, threshold=0.2):
        """
        掌控板加速度控制
        """
        x = accelerometer.get_x()
        y = accelerometer.get_y()
        if y <= 1 and y >= -1:
            if abs(y) > threshold:
                if y > 0:
                    self.snake.direction = Direction.LEFT
                else:
                    self.snake.direction = Direction.RIGHT
        if x <= 1 and x >= -1:
            if abs(x) > threshold:
                if x > 0:
                    self.snake.direction = Direction.DOWN
                else:
                    self.snake.direction = Direction.UP

    def handles_callback(self, f):
        """
        游戏控制回调函数,可外部自定义控制方式
        """
        self.handles_cb = f

    def run(self):
        """
        游戏运行
        """
        self.state = GameState.PLAYING
        update_time = time.ticks_ms()

        while self.state == GameState.PLAYING:  # 游戏状态为PLAYING

            self.handles_cb()  # 游戏控制回调函数

            # 显示帧刷新,刷新方块位置
            if time.ticks_diff(time.ticks_ms(), update_time) > (1000 // self.fps):

                last_pos = self.get_body[-1]  # 这里需要保存一下尾部的位置,如果小蛇迟到了食物,需要在尾部增长

                self.snake.refresh()  # 更新小蛇身体的位置
                self.snake.move()  # 改变头部的位置

                if self.snake.grow():  # 判断小蛇是否吃到了事物,吃到了就成长,如果吃到了事物我们就产生一个新的食物
                    self.snake.generate_food()
                    self.get_body.append(last_pos)

                oled.fill(0)  # 清屏
                self.snake.draw_body()  # 画小蛇的身体
                self.snake.draw_food()  # 画出食物

                oled.show()  # 显示生效
                update_time = time.ticks_ms()  # 刷新帧时间

                if self.is_fail():  # 判断if输
                    self.state = GameState.FAIL
                    break
                if self.is_win():  # 判断if赢
                    self.state = GameState.WIN
                    break

        if self.state == GameState.FAIL:  # 输了,显示分数
            oled.fill(0)
            oled.text('Game over!', 25, 20)
            oled.text('Score:%d' % self.score, 25, 32)
            oled.show()

        if self.state == GameState.WIN:  # 赢了!
            oled.fill(0)
            oled.text('You win!', 25, 20)
            oled.show()


if __name__ == '__main__':
    game = Game(fps=8)
    game.handles_callback(game.handles_accele)
    game.run()

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驴友花雕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值