170浏览
查看: 170|回复: 0

[K10项目分享] 行空板K10之GamePad弹球游戏

[复制链接]

【项目背景】


  • 随着科技的发展,教育和娱乐领域越来越注重互动性和学习体验的结合。微型智能弹球游戏项目旨在通过 UNIHIKER_K10 硬件平台和 GamePad for micro:bit V4.0 手柄,为用户打造一个既具有教育意义又充满乐趣的互动游戏。这款游戏不仅能够锻炼玩家的反应速度和手眼协调能力,还能通过编程和硬件操作的结合,增加对 STEM(科学、技术、工程和数学)领域的兴趣和理解。
  • UNIHIKER_K10 是一款集成了显示屏、多种传感器和可编程接口的微型计算机,非常适合用于教育和娱乐项目。它支持多种编程语言和库,使得开发者能够轻松地实现复杂的功能。GamePad for micro:bit V4.0 手柄则为游戏提供了直观的控制方式,通过物理操作增强了游戏的互动性。

【项目硬件】UNIHIKER_K10 和 GamePad for micro:bit V4.0 手柄,实现交互式游戏。

行空板K10之GamePad弹球游戏图3

行空板K10之GamePad弹球游戏图1

行空板K10之GamePad弹球游戏图2



【程序设计】
  1. #include "unihiker_k10.h"
  2. Music        music;
  3. // 创建对象
  4. UNIHIKER_K10 k10;
  5. uint8_t screen_dir = 2;
  6. int speed=0;
  7. // 定义屏幕宽度和高度
  8. #define SCREEN_WIDTH 240
  9. #define SCREEN_HEIGHT 320
  10. uint8_t score = 0;
  11. // 游戏对象定义
  12. #define BALL_SIZE 20
  13. struct GameObject {
  14.     int x;
  15.     int y;
  16.     int width;
  17.     int height;
  18.     int dx;
  19.     int dy;
  20. } ball, paddle;
  21. // 初始化游戏对象
  22. void initGameObjects() {
  23.     ball.x = SCREEN_WIDTH / 2;
  24.     ball.y = SCREEN_HEIGHT / 2;
  25.     ball.width = BALL_SIZE;
  26.     ball.height = BALL_SIZE;
  27.     ball.dx = 2;
  28.     ball.dy = 2;
  29.     paddle.x = SCREEN_WIDTH / 2 - 20;
  30.     paddle.y = SCREEN_HEIGHT - 30;
  31.     paddle.width = 80;
  32.     paddle.height = 20;
  33.     paddle.dx = 0;
  34. }
  35. // 绘制游戏对象
  36. void drawGameObjects() {
  37.     //k10.canvas->canvasClear();
  38.     k10.canvas->canvasCircle(ball.x, ball.y, BALL_SIZE, 0x000000, 0xFF0000, true);
  39.     k10.canvas->canvasRectangle(paddle.x, paddle.y, paddle.width, paddle.height, 0x000000, 0x00FF00, true);
  40.     k10.canvas->updateCanvas();
  41. }
  42. // LED 灯显示分数
  43. void LEDshow(){
  44.   switch (score) {
  45.     case 0:
  46.       k10.rgb->write(-1,  0x000000);
  47.       break;
  48.     case 1:
  49.       k10.rgb->write(-1, 0x000000);
  50.       k10.rgb->write( 2, 0x0000FF);
  51.       
  52.       break;
  53.     case 2:
  54.       k10.rgb->write(-1, 0x000000);
  55.       k10.rgb->write( 1, 0x0000FF);
  56.       break;
  57.     case 3:
  58.       k10.rgb->write(-1, 0x000000);
  59.       k10.rgb->write( 1, 0x0000FF);
  60.       k10.rgb->write( 2, 0x0000FF);
  61.       break;
  62.     case 4:
  63.       k10.rgb->write(-1, 0x000000);
  64.       k10.rgb->write( 0, 0x0000FF);
  65.       break;
  66.     case 5:
  67.       k10.rgb->write(-1, 0x000000);
  68.       k10.rgb->write( 0, 0x0000FF);
  69.       k10.rgb->write( 2, 0x0000FF);
  70.       break;
  71.     case 6:
  72.       k10.rgb->write(-1, 0x000000);
  73.       k10.rgb->write( 0, 0x0000FF);
  74.       k10.rgb->write( 1, 0x0000FF);
  75.       break;
  76.     case 7:
  77.       k10.rgb->write( 0, 0x0000FF);
  78.       k10.rgb->write( 1, 0x0000FF);
  79.       k10.rgb->write( 2, 0x0000FF);
  80.       break;
  81.     // 可以继续添加case 5, 6, 7...
  82.     default:
  83.       k10.rgb->setRangeColor(0, 2, 0x000000); // 默认所有灯灭
  84.   }
  85. }
  86. // 更新游戏逻辑
  87. void updateGame() {
  88.     // 更新球的位置
  89.     ball.x += ball.dx;
  90.     ball.y += ball.dy;
  91.     // 检测球是否碰到左右边界
  92.     if (ball.x <= BALL_SIZE/2 || ball.x >= SCREEN_WIDTH - BALL_SIZE/2) {
  93.         ball.dx = -ball.dx;
  94.     }
  95.     // 检测球是否碰到顶部边界
  96.     if (ball.y <= BALL_SIZE/2) {
  97.         ball.dy = -ball.dy;
  98.     }
  99.     // 检测球是否碰到挡板
  100.     if (ball.x >= paddle.x && ball.x <= paddle.x + paddle.width &&
  101.         ball.y +ball.height/2>= paddle.y  && ball.y <= paddle.y + paddle.height) {
  102.         ball.dy = -ball.dy;
  103.         score++;
  104.         LEDshow();
  105.         //music.playTone(262, 1000);
  106.     }
  107.     // 检测球是否掉出底部
  108.     if (ball.y > SCREEN_HEIGHT - BALL_SIZE) {
  109.         // 重置球的位置
  110.         ball.x = SCREEN_WIDTH / 2;
  111.         ball.y = SCREEN_HEIGHT / 2;
  112.         k10.canvas->canvasClear();
  113.               k10.canvas->updateCanvas();
  114.     }
  115.     // 绘制更新后的游戏对象
  116.     drawGameObjects();
  117. }
  118. // 处理用户输入
  119. void handleInput() {
  120.     if (analogRead(P1) < 1000) {
  121.         paddle.x -= 5;
  122.     } else if (analogRead(P1) > 3000) {
  123.         paddle.x += 5;
  124.     } else if((k10.buttonA->isPressed())){
  125.       speed=speed+100;
  126.     } else if((k10.buttonB->isPressed())){
  127.       speed=speed-100;
  128.       if(speed<0){
  129.         speed=0;
  130.       }
  131.     }
  132.     // 确保挡板不会超出屏幕
  133.     if (paddle.x < 0) {
  134.         paddle.x = 0;
  135.     } else if (paddle.x > SCREEN_WIDTH - paddle.width) {
  136.         paddle.x = SCREEN_WIDTH - paddle.width;
  137.     }
  138. }
  139. void setup() {
  140.     k10.begin();
  141.     k10.initScreen(screen_dir);
  142.     k10.creatCanvas();
  143.     k10.setScreenBackground(0x000000);
  144.     Serial.begin(9600);
  145.     initGameObjects();
  146.     drawGameObjects();
  147. }
  148. void loop() {
  149.     handleInput();
  150.     updateGame();
  151.     delay(speed); // 控制游戏速度
  152. }
复制代码
【程序解析】
  • 包含头文件


    • #include "unihiker_k10.h":包含用于控制 UNIHIKER_K10 硬件平台的库。
  • 声明全局变量和对象


    • Music music;:声明一个音乐对象。
    • UNIHIKER_K10 k10;:声明一个 UNIHIKER_K10 类型的对象,用于与硬件进行交互。
    • uint8_t screen_dir = 2;:定义屏幕方向变量,并初始化为 2。
    • int speed = 0;:定义一个速度变量,用于控制游戏循环的速度。
  • 定义屏幕尺寸


    • #define SCREEN_WIDTH 240 和 #define SCREEN_HEIGHT 320:定义屏幕的宽度和高度。
  • 定义分数和游戏对象结构


    • uint8_t score = 0;:定义一个变量来存储玩家的分数。
    • struct GameObject { ... } ball, paddle;:定义一个结构体来存储游戏对象(球和挡板)的属性,包括位置、尺寸和移动速度。
  • 初始化游戏对象


    • void initGameObjects() {...}:初始化球和挡板的位置、尺寸和移动速度。
  • 绘制游戏对象


    • void drawGameObjects() {...}:在屏幕上绘制球和挡板的当前位置。
  • LED 显示分数


    • void LEDshow() {...}:根据当前分数,通过 LED 灯显示分数。
  • 更新游戏逻辑


    • void updateGame() {...}:更新球的位置,检测碰撞,更新分数,并重新绘制游戏对象。
  • 处理用户输入


    • void handleInput() {...}:处理来自手柄的输入,调整挡板的位置和游戏速度。
  • 设置初始化函数


    • void setup() {...}:在程序开始时调用,用于初始化硬件设置和游戏对象。
  • 主循环函数


    • void loop() {...}:程序的主循环,不断调用 handleInput() 和 updateGame() 函数,以及控制循环速度的 delay(speed)。
  • 游戏逻辑细节


    • 球的移动和边界检测:在 updateGame() 函数中,球的位置会根据其速度更新,并且会检测是否与屏幕的边界发生碰撞,如果是,则反转相应的移动方向。
    • 挡板的控制:在 handleInput() 函数中,通过读取手柄的模拟输入来控制挡板的水平移动,并确保挡板不会移出屏幕范围。
    • 得分和LED显示:当球与挡板碰撞时,分数增加,并通过 LEDshow() 函数更新 LED 灯的二进制显示。
  • 程序执行流程


    • 程序首先在 setup() 函数中进行初始化。
    • 然后进入 loop() 函数,不断循环执行用户输入处理和游戏逻辑更新。
    • 游戏状态的每次更新都会在屏幕上重新绘制游戏对象,并根据需要更新 LED 灯的显示。

【演示视频】


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail