回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

【花雕动手做】Kitronik 可编程开发板基于 ARCADE MakeCode 之打砖块游戏 简单

头像 驴友花雕 2025.09.14 4 0

Kitronik ARCADE 是一款由英国教育科技公司 Kitronik 精心打造的可编程游戏机开发板,专为编程教学与创客实践而设计。该设备原生支持微软的 MakeCode Arcade 平台,用户可通过图形化或 JavaScript 编程方式,轻松创建、下载并运行复古风格的街机游戏。

它集成了彩色 LCD 显示屏、方向控制键、功能按键、蜂鸣器和震动马达等交互组件,提供完整的游戏输入输出体验。无论是初学者进行编程启蒙,还是创客群体开发交互式作品,Kitronik ARCADE 都能作为理想的硬件载体,助力创意实现。

凭借其开源友好、易于上手、兼容性强等特点,该开发板广泛应用于中小学编程课程、创客工作坊、游戏开发教学以及个人项目原型设计,深受教育者与技术爱好者的喜爱。

 

00 (2).jpg
00 (3).jpg
00 (4).jpg

作为学习、练习与尝试,这里创建一个打砖块的小游戏。
打开网页版:https://arcade.makecode.com/,设置项目名称:打砖块

MicroPython实验代码
 

代码
@namespace
class SpriteKind:
    block = SpriteKind.create()
def getPos(sprite: Sprite, otherSprite: Sprite):
    global direction
    if sprite.x < otherSprite.x - 8 or sprite.x > otherSprite.x + 8:
        direction = 1
    else:
        direction = 0

def on_on_overlap(sprite2, otherSprite2):
    sprite2.set_velocity(sprite2.vx, -1 * sprite2.vy)
sprites.on_overlap(SpriteKind.projectile, SpriteKind.player, on_on_overlap)

def on_on_overlap2(sprite3, otherSprite3):
    info.change_score_by(1)
    getPos(sprite3, otherSprite3)
    if direction == 1:
        sprite3.set_velocity(-1 * sprite3.vx, sprite3.vy)
    else:
        sprite3.set_velocity(sprite3.vx, -1 * sprite3.vy)
    otherSprite3.destroy()
sprites.on_overlap(SpriteKind.projectile, SpriteKind.block, on_on_overlap2)

direction = 0
tile: Sprite = None
tilePick = 0
x = 0
paddle = sprites.create(img("""
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ................................
        ....bbbbbbbbbbbbbbbbbbbbbb......
        ....bbbbbbbbbbbbbbbbbbbbbb......
        ....bbbbbbbbbbbbbbbbbbbbbb......
        ................................
        ................................
        ................................
        ................................
        """),
    SpriteKind.player)
paddle.set_position(79, 100)
paddle.set_stay_in_screen(True)
controller.move_sprite(paddle, 100, 0)
projectile = sprites.create_projectile_from_sprite(img("""
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . 9 9 9 . . . . . . .
        . . . . . 9 6 7 6 9 . . . . . .
        . . . . 9 6 7 6 7 6 9 . . . . .
        . . . . 1 7 1 7 1 7 1 . . . . .
        . . . . 8 6 7 6 7 6 8 . . . . .
        . . . . . 8 6 7 6 8 . . . . . .
        . . . . . . 8 8 8 . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        """),
    paddle,
    50,
    -55)
projectile.set_flag(SpriteFlag.DESTROY_ON_WALL, False)
projectile.set_bounce_on_wall(True)
for index in range(10):
    for index2 in range(3):
        x = index * 18
        if index2 % 2 == 1:
            x = index * 18 + 8
        tilePick = randint(0, 2)
        if tilePick == 0:
            tile = sprites.create(img("""
                    8 8 1 1 8 8 6 6 1 7 7 7 1 8 8 9
                    8 8 9 1 1 6 6 9 9 8 8 7 1 8 8 9
                    7 6 9 9 9 8 8 7 9 8 8 6 6 1 9 9
                    7 6 6 1 1 8 8 7 9 1 6 6 1 1 9 9
                    7 7 6 1 1 6 6 7 7 8 8 1 1 1 7 9
                    8 8 9 1 6 6 9 9 9 8 8 1 6 1 7 9
                    8 8 9 9 9 7 8 8 9 6 6 1 6 6 7 7
                    7 7 7 8 8 7 8 8 6 6 9 9 9 6 8 8
                    7 6 6 8 8 7 7 6 1 7 7 7 9 1 8 8
                    6 6 7 7 7 1 1 6 6 7 1 8 8 7 7 7
                    1 1 7 9 9 9 1 1 6 1 1 8 8 7 1 9
                    8 8 1 1 6 9 8 8 6 1 9 9 9 1 1 9
                    8 8 9 1 6 6 8 8 6 6 8 8 9 1 9 9
                    7 6 9 9 9 6 9 9 9 6 8 8 6 6 7 7
                    7 6 6 8 8 1 6 6 9 7 9 6 6 8 8 7
                    7 7 6 8 8 6 6 7 7 7 9 9 9 8 8 7
                    """),
                SpriteKind.block)
        elif tilePick == 1:
            tile = sprites.create(img("""
                    3 d 1 3 3 3 3 3 3 3 3 3 3 3 3 3
                    3 d 1 3 d d d d d d d d d d d 3
                    3 d 1 3 d 1 1 1 1 1 1 1 1 1 d 3
                    3 d 1 3 d 1 3 3 3 3 3 3 3 1 d 3
                    3 d 1 3 d 1 3 d d d d d 3 1 d 3
                    3 d 1 3 d 1 3 d 1 1 1 d 3 1 d 3
                    3 d 1 3 d 1 3 d 1 3 1 d 3 1 d 3
                    3 d 1 3 d 1 3 d 1 3 1 d 3 1 d 3
                    3 d 1 3 d 1 3 d d 3 1 d 3 1 d 3
                    3 d 1 3 d 1 3 3 3 3 1 d 3 1 d 3
                    3 d 1 3 d 1 1 1 1 1 1 d 3 1 d 3
                    3 d 1 3 d d d d d d d d 3 1 d 3
                    3 d 1 3 3 3 3 3 3 3 3 3 3 1 d 3
                    3 d 1 1 1 1 1 1 1 1 1 1 1 1 d 3
                    3 d d d d d d d d d d d d d d 3
                    3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
                    """),
                SpriteKind.block)
        else:
            tile = sprites.create(img("""
                    2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1
                    1 2 2 2 2 2 2 2 1 1 1 4 4 4 4 4
                    1 1 2 2 2 2 2 4 4 4 4 4 4 4 4 4
                    4 4 4 2 2 5 5 5 5 5 5 4 4 4 4 4
                    4 4 4 4 2 2 2 2 2 5 5 5 5 5 4 4
                    4 4 b b b b b b b 5 5 5 5 5 5 5
                    b b b b b b b 5 5 5 5 5 2 2 2 2
                    b b b b 5 5 5 5 5 5 5 5 5 5 2 2
                    b b b 2 2 2 2 2 2 2 2 2 1 1 1 1
                    1 1 1 1 1 1 2 2 2 1 1 1 1 1 1 1
                    1 1 4 4 2 2 2 2 2 2 2 1 1 1 1 1
                    4 4 4 4 4 4 2 2 2 2 2 2 2 2 2 4
                    4 4 4 5 5 5 5 5 5 5 5 5 4 4 4 4
                    5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4
                    b b b b b 5 5 5 5 5 5 5 5 4 4 4
                    . b b b b b b b b b b b 4 4 4 4
                    """),
                SpriteKind.block)
        tile.set_position(x, index2 * 18 + 20)
info.set_score(1)
scene.set_background_color(13)
direction = 1

def on_forever():
    if projectile.bottom > 119:
        game.over(False, effects.slash)
    if info.score() == 30:
        game.over(True, effects.bubbles)
forever(on_forever)

这段代码是用 MakeCode Arcade 编写的一个经典的 打砖块游戏(Breakout)。它融合了玩家控制、弹球物理、砖块碰撞、得分系统和游戏胜负判定等机制。解读如下:

一、游戏核心机制概览

 

120-.jpg

二、代码逐段解析
1、玩家挡板初始化
python
paddle = sprites.create(..., SpriteKind.player)
paddle.set_position(79, 100)
controller.move_sprite(paddle, 100, 0)
创建一个宽大的挡板精灵

设置初始位置在屏幕底部

允许玩家左右移动(X 轴速度为 100)

2、弹球初始化
python
projectile = sprites.create_projectile_from_sprite(..., paddle, 50, -55)
projectile.set_bounce_on_wall(True)
projectile.set_flag(SpriteFlag.DESTROY_ON_WALL, False)
从挡板发射一个弹球,初始速度向上

设置为可在墙壁上反弹

不在碰到墙壁时销毁,保持游戏持续性

3、砖块阵列生成
python
for index in range(10):
   for index2 in range(3):
       ...
       tilePick = randint(0, 2)
       tile = sprites.create(..., SpriteKind.block)
       tile.set_position(x, index2 * 18 + 20)
创建 10×3 的砖块阵列

每个砖块随机选择一种图案

使用 SpriteKind.block 类型,便于碰撞检测

4、碰撞逻辑:弹球与挡板
python
sprites.on_overlap(SpriteKind.projectile, SpriteKind.player, on_on_overlap)
def on_on_overlap(sprite2, otherSprite2):
   sprite2.set_velocity(sprite2.vx, -1 * sprite2.vy)
弹球碰到挡板时,垂直速度反向,实现反弹效果

5、 碰撞逻辑:弹球与砖块
python
sprites.on_overlap(SpriteKind.projectile, SpriteKind.block, on_on_overlap2)
def on_on_overlap2(sprite3, otherSprite3):
   info.change_score_by(1)
   getPos(sprite3, otherSprite3)
   ...
   otherSprite3.destroy()
得分 +1

判断弹球与砖块的相对位置,决定反弹方向

销毁被击中的砖块

6、反弹方向判断函数
python
def getPos(sprite, otherSprite):
   if sprite.x < otherSprite.x - 8 or sprite.x > otherSprite.x + 8:
       direction = 1
   else:
       direction = 0
判断弹球是否击中砖块的边缘或中心

边缘碰撞则水平速度反向,中心则垂直速度反向

7、游戏胜负判定
python
def on_forever():
   if projectile.bottom > 119:
       game.over(False, effects.slash)
   if info.score() == 30:
       game.over(True, effects.bubbles)
弹球掉出底部:游戏失败,播放斩击特效

得分达到 30:游戏胜利,播放气泡特效

 

图形编程参考实验程序

 

120.jpg

通过模拟器,调试与模拟运行

 

00210.gif

实验场景记录

 

121 (1).jpg
121 (2).jpg

评论

user-avatar
icon 他的勋章
    展开更多