【项目背景】
- 随着科技的发展,教育和娱乐领域越来越注重互动性和学习体验的结合。微型智能弹球游戏项目旨在通过 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 手柄,实现交互式游戏。
【程序设计】
-
- #include "unihiker_k10.h"
- Music music;
- // 创建对象
- UNIHIKER_K10 k10;
- uint8_t screen_dir = 2;
- int speed=0;
- // 定义屏幕宽度和高度
- #define SCREEN_WIDTH 240
- #define SCREEN_HEIGHT 320
- uint8_t score = 0;
- // 游戏对象定义
- #define BALL_SIZE 20
- struct GameObject {
- int x;
- int y;
- int width;
- int height;
- int dx;
- int dy;
- } ball, paddle;
-
- // 初始化游戏对象
- void initGameObjects() {
- ball.x = SCREEN_WIDTH / 2;
- ball.y = SCREEN_HEIGHT / 2;
- ball.width = BALL_SIZE;
- ball.height = BALL_SIZE;
- ball.dx = 2;
- ball.dy = 2;
-
- paddle.x = SCREEN_WIDTH / 2 - 20;
- paddle.y = SCREEN_HEIGHT - 30;
- paddle.width = 80;
- paddle.height = 20;
- paddle.dx = 0;
- }
-
- // 绘制游戏对象
- void drawGameObjects() {
- //k10.canvas->canvasClear();
- k10.canvas->canvasCircle(ball.x, ball.y, BALL_SIZE, 0x000000, 0xFF0000, true);
- k10.canvas->canvasRectangle(paddle.x, paddle.y, paddle.width, paddle.height, 0x000000, 0x00FF00, true);
- k10.canvas->updateCanvas();
- }
- // LED 灯显示分数
- void LEDshow(){
- switch (score) {
- case 0:
- k10.rgb->write(-1, 0x000000);
- break;
- case 1:
- k10.rgb->write(-1, 0x000000);
- k10.rgb->write( 2, 0x0000FF);
-
- break;
- case 2:
- k10.rgb->write(-1, 0x000000);
- k10.rgb->write( 1, 0x0000FF);
- break;
- case 3:
- k10.rgb->write(-1, 0x000000);
- k10.rgb->write( 1, 0x0000FF);
- k10.rgb->write( 2, 0x0000FF);
- break;
- case 4:
- k10.rgb->write(-1, 0x000000);
- k10.rgb->write( 0, 0x0000FF);
- break;
- case 5:
- k10.rgb->write(-1, 0x000000);
- k10.rgb->write( 0, 0x0000FF);
- k10.rgb->write( 2, 0x0000FF);
- break;
- case 6:
- k10.rgb->write(-1, 0x000000);
- k10.rgb->write( 0, 0x0000FF);
- k10.rgb->write( 1, 0x0000FF);
- break;
- case 7:
- k10.rgb->write( 0, 0x0000FF);
- k10.rgb->write( 1, 0x0000FF);
- k10.rgb->write( 2, 0x0000FF);
- break;
- // 可以继续添加case 5, 6, 7...
- default:
- k10.rgb->setRangeColor(0, 2, 0x000000); // 默认所有灯灭
- }
- }
- // 更新游戏逻辑
- void updateGame() {
- // 更新球的位置
- ball.x += ball.dx;
- ball.y += ball.dy;
-
- // 检测球是否碰到左右边界
- if (ball.x <= BALL_SIZE/2 || ball.x >= SCREEN_WIDTH - BALL_SIZE/2) {
- ball.dx = -ball.dx;
- }
- // 检测球是否碰到顶部边界
- if (ball.y <= BALL_SIZE/2) {
- ball.dy = -ball.dy;
- }
- // 检测球是否碰到挡板
- if (ball.x >= paddle.x && ball.x <= paddle.x + paddle.width &&
- ball.y +ball.height/2>= paddle.y && ball.y <= paddle.y + paddle.height) {
- ball.dy = -ball.dy;
- score++;
- LEDshow();
- //music.playTone(262, 1000);
- }
- // 检测球是否掉出底部
- if (ball.y > SCREEN_HEIGHT - BALL_SIZE) {
- // 重置球的位置
- ball.x = SCREEN_WIDTH / 2;
- ball.y = SCREEN_HEIGHT / 2;
- k10.canvas->canvasClear();
- k10.canvas->updateCanvas();
- }
-
- // 绘制更新后的游戏对象
- drawGameObjects();
- }
-
- // 处理用户输入
- void handleInput() {
- if (analogRead(P1) < 1000) {
- paddle.x -= 5;
- } else if (analogRead(P1) > 3000) {
- paddle.x += 5;
- } else if((k10.buttonA->isPressed())){
- speed=speed+100;
- } else if((k10.buttonB->isPressed())){
- speed=speed-100;
- if(speed<0){
- speed=0;
- }
- }
-
- // 确保挡板不会超出屏幕
- if (paddle.x < 0) {
- paddle.x = 0;
- } else if (paddle.x > SCREEN_WIDTH - paddle.width) {
- paddle.x = SCREEN_WIDTH - paddle.width;
- }
- }
-
- void setup() {
- k10.begin();
- k10.initScreen(screen_dir);
- k10.creatCanvas();
- k10.setScreenBackground(0x000000);
- Serial.begin(9600);
- initGameObjects();
- drawGameObjects();
- }
-
- void loop() {
- handleInput();
- updateGame();
- delay(speed); // 控制游戏速度
- }
复制代码
【程序解析】包含头文件
- #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 灯的显示。
【演示视频】
|