行空板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 手柄,实现交互式游戏。
【程序设计】
#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 灯的显示。
【演示视频】
https://www.bilibili.com/video/BV1zEnZeBE7R/?share_source=copy_web
页:
[1]