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

【花雕动手做】Kitronik 可编程开发板基于 ARCADE MakeCode 之红色弹球 简单

头像 驴友花雕 2025.09.09 5 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:
    Projectile2 = SpriteKind.create()
    snake = SpriteKind.create()

def on_on_overlap(sprite, otherSprite):
    global falling
    falling = sprites.create(img("""
            . . 2 2 2 2 . .
            . 2 2 2 2 2 2 .
            2 2 2 2 2 2 2 2
            2 2 2 2 2 2 2 2
            2 2 2 2 2 2 2 2
            2 2 2 2 2 2 2 2
            . 2 2 2 2 2 2 .
            . . 2 2 2 2 . .
            """),
        SpriteKind.projectile)
    falling.set_bounce_on_wall(True)
    falling.set_position(sprite.x, sprite.y - 5)
    falling.set_velocity(sprite.vx, 0 - sprite.vy)
    falling.ay = sprite.ay
    sprite.destroy()
sprites.on_overlap(SpriteKind.Projectile2, SpriteKind.player, on_on_overlap)

def on_on_overlap2(sprite2, otherSprite2):
    info.set_score(info.score() + 1)
    sprite2.destroy()
sprites.on_overlap(SpriteKind.projectile, SpriteKind.player, on_on_overlap2)

def on_hit_wall(sprite3, location):
    if tiles.tile_at_location_equals(location, assets.tile("""
        tile3
        """)):
        info.change_life_by(-1)
        sprite3.destroy()
scene.on_hit_wall(SpriteKind.Projectile2, on_hit_wall)

def on_hit_wall2(sprite4, location2):
    if tiles.tile_at_location_equals(location2, assets.tile("""
        tile3
        """)):
        info.change_life_by(-1)
        sprite4.destroy()
scene.on_hit_wall(SpriteKind.projectile, on_hit_wall2)

limit = 0
falling: Sprite = None
s4Dir = 1
info.set_life(3)
basket = sprites.create(img("""
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        . . 7 7 7 7 7 7 7 7 7 7 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 1 7 1 7 1 7 1 7 1 7 . . .
        . . 7 7 7 7 7 7 7 7 7 7 7 . . .
        . . . . . . . . . . . . . . . .
        """),
    SpriteKind.player)
basket.set_position(80, 100)
controller.move_sprite(basket, 160, 0)
mySprite4 = sprites.create(img("""
        . . . . . . . . . . . . . . . .
        . 8 8 8 8 8 8 8 1 1 1 1 1 . . .
        8 8 8 8 8 8 8 8 1 1 1 1 1 1 . .
        8 8 8 8 8 8 8 8 1 1 1 1 1 1 . .
        8 8 8 8 8 8 8 8 1 1 1 1 1 1 . .
        8 8 8 8 8 1 8 8 1 1 1 1 1 1 . .
        8 8 8 8 8 1 1 8 1 1 1 1 1 1 . .
        8 8 8 8 8 1 1 1 1 1 1 1 1 1 . .
        8 8 8 8 8 1 1 1 1 1 1 1 1 1 . .
        8 8 8 8 8 1 1 8 1 1 1 1 1 1 . .
        8 8 8 8 8 1 8 8 1 1 1 1 1 1 . .
        8 8 8 8 8 8 8 8 1 1 1 1 1 1 . .
        8 8 8 8 8 8 8 8 1 1 1 1 1 1 . .
        . 8 8 8 8 8 8 8 1 1 1 1 1 . . .
        . . . 8 8 8 . . . . . . . . . .
        . . . . . . . . . . . . . . . .
        """),
    SpriteKind.snake)
mySprite4.set_flag(SpriteFlag.GHOST, True)
mySprite4.set_position(-7, 100)
tiles.set_tilemap(tilemap("""
    level
    """))

def on_update_interval():
    global s4Dir
    mySprite4.vx = 10 * s4Dir
    s4Dir = s4Dir * -1
game.on_update_interval(2200, on_update_interval)

def on_update_interval2():
    global falling, limit
    if info.score() < 10 or randint(1, min(50, info.score())) < 10:
        falling = sprites.create(img("""
                . . 2 2 2 2 . .
                . 2 2 2 2 2 2 .
                2 2 2 2 2 2 2 2
                2 2 2 2 2 2 2 2
                2 2 2 2 2 2 2 2
                2 2 2 2 2 2 2 2
                . 2 2 2 2 2 2 .
                . . 2 2 2 2 . .
                """),
            SpriteKind.projectile)
    else:
        falling = sprites.create(img("""
                . . 8 8 8 8 . .
                . 8 8 8 8 8 8 .
                8 8 8 8 8 8 8 8
                8 8 8 8 8 8 8 8
                8 8 8 8 8 8 8 8
                8 8 8 8 8 8 8 8
                . 8 8 8 8 8 8 .
                . . 8 8 8 8 . .
                """),
            SpriteKind.Projectile2)
    falling.set_position(randint(20, 140), 20)
    limit = min(10, info.score())
    falling.set_velocity(randint(-100, 100), randint(0 - limit, 5))
    falling.ay = 20
    falling.set_bounce_on_wall(True)
game.on_update_interval(2000, on_update_interval2)

这是一个弹球收集游戏,玩家控制底部的篮子接住从上方落下的弹球。游戏包含两种弹球:普通弹球(得分)和特殊弹球(需要反弹处理)。玩家有3条生命,碰到危险墙壁会失去生命。

核心代码解析

1. 自定义精灵类型
python
@namespace
class SpriteKind:
   Projectile2 = SpriteKind.create()  # 特殊弹球(需要反弹)
   snake = SpriteKind.create()         # 蛇形障碍物
   
2. 碰撞检测系统
特殊弹球与玩家碰撞
python
def on_on_overlap(sprite, otherSprite):
   global falling
   falling = sprites.create(img("""新弹球"""), SpriteKind.projectile)
   falling.set_bounce_on_wall(True)
   falling.set_position(sprite.x, sprite.y - 5)
   falling.set_velocity(sprite.vx, 0 - sprite.vy)  # 速度反向
   falling.ay = sprite.ay  # 保持相同的重力加速度
   sprite.destroy()  # 销毁原弹球
当特殊弹球(Projectile2)碰到玩家篮子时

创建一个新的普通弹球,位置略高于原弹球

设置反弹速度(垂直方向反向)

保持相同的重力加速度

销毁原特殊弹球

普通弹球与玩家碰撞
python
def on_on_overlap2(sprite2, otherSprite2):
   info.set_score(info.score() + 1)  # 得分+1
   sprite2.destroy()  # 销毁弹球
当普通弹球碰到玩家篮子时

玩家得分增加1分

销毁弹球

弹球碰到危险墙壁
python
def on_hit_wall(sprite3, location):
   if tiles.tile_at_location_equals(location, assets.tile("tile3")):
       info.change_life_by(-1)  # 生命值-1
       sprite3.destroy()  # 销毁弹球
当特殊弹球碰到特定瓦片(tile3)时

玩家失去1条生命

销毁弹球

python
def on_hit_wall2(sprite4, location2):
   if tiles.tile_at_location_equals(location2, assets.tile("tile3")):
       info.change_life_by(-1)  # 生命值-1
       sprite4.destroy()  # 销毁弹球
当普通弹球碰到特定瓦片(tile3)时

玩家失去1条生命

销毁弹球

3. 游戏初始化
玩家设置
python
info.set_life(3)  # 设置3条生命
basket = sprites.create(img("""篮子图像"""), SpriteKind.player)
basket.set_position(80, 100)  # 底部中央位置
controller.move_sprite(basket, 160, 0)  # 只能水平移动
玩家有3条生命

创建篮子精灵,使用ASCII艺术定义外观

将篮子放置在屏幕底部中央

设置只能水平移动(速度160)

蛇形障碍物
python
mySprite4 = sprites.create(img("""蛇图像"""), SpriteKind.snake)
mySprite4.set_flag(SpriteFlag.GHOST, True)  # 设置为幽灵模式(无碰撞)
mySprite4.set_position(-7, 100)  # 初始位置在左侧外部
创建蛇形障碍物,但设置为幽灵模式(不参与碰撞检测)

初始位置在屏幕左侧外部

游戏场景
python
tiles.set_tilemap(tilemap("level"))  # 设置瓦片地图
使用名为"level"的瓦片地图

4. 游戏循环与更新
蛇形障碍物移动
python
def on_update_interval():
   global s4Dir
   mySprite4.vx = 10 * s4Dir  # 设置水平速度
   s4Dir = s4Dir * -1  # 方向反转
game.on_update_interval(2200, on_update_interval)  # 每2200ms更新一次
蛇形障碍物每2.2秒改变一次移动方向

在左右方向之间来回移动

弹球生成系统
python
def on_update_interval2():
   global falling, limit
   if info.score() < 10 or randint(1, min(50, info.score())) < 10:
       falling = sprites.create(img("""红色弹球"""), SpriteKind.projectile)  # 普通弹球
   else:
       falling = sprites.create(img("""蓝色弹球"""), SpriteKind.Projectile2)  # 特殊弹球
   
   falling.set_position(randint(20, 140), 20)  # 随机水平位置,顶部
   limit = min(10, info.score())  # 根据得分限制速度范围
   falling.set_velocity(randint(-100, 100), randint(0 - limit, 5))  # 随机速度
   falling.ay = 20  # 重力加速度
   falling.set_bounce_on_wall(True)  # 开启墙壁反弹
game.on_update_interval(2000, on_update_interval2)  # 每2000ms生成一个弹球
每2秒生成一个新的弹球

根据得分决定生成普通弹球还是特殊弹球:

得分低于10时,主要生成普通弹球

得分高于10时,有概率生成特殊弹球

弹球从顶部随机位置生成

弹球具有随机速度和方向

设置重力加速度使弹球下落

开启墙壁反弹功能

游戏机制总结
控制方式:左右移动篮子接住弹球

得分系统:接住普通弹球得1分

生命系统:初始3条生命,弹球碰到危险墙壁失去1条生命

弹球类型:

普通弹球:直接得分

特殊弹球:需要反弹后才能接住

难度递增:随着得分增加,出现更多特殊弹球

技术特点
动态难度:根据玩家得分调整弹球类型和速度

物理模拟:使用速度、重力和反弹模拟弹球运动

瓦片地图:使用瓦片地图定义游戏场景和危险区域

幽灵模式:蛇形障碍物使用幽灵模式避免不必要的碰撞

图形编程参考实验程序

 

79.jpg

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

 

00205--.gif

 

实验场景记录

 

80 (1).jpg
80 (2).jpg
80 (3).jpg

评论

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