当前位置:首页 > 工业控制 > 电路设计项目集锦
[导读]用Arduino Nano和SSD1306 OLED与PCBX仿真构建推盒游戏!创造有趣的互动体验。

用Arduino Nano和SSD1306 OLED与PCBX仿真构建推盒游戏!创造有趣的互动体验。

介绍

Push Box Game基于Arduino Nano和SSD1306 OLED显示屏,主要包括以下几个部分:

在线仿真显示

描述

Arduino Nano:

•作为游戏的控制单元,处理用户输入和游戏逻辑。

SSD1306 OLED显示屏:

•用于显示游戏界面,包括玩家、盒子、目标位置和边界。

按钮:

•四个按钮用于控制玩家的上下左右移动。

连接方法:

•SSD1306 OLED显示屏通过I2C接口与Arduino Nano相连。

•四个按钮连接到Arduino Nano的数字引脚上,每个按钮都需要一个上拉电阻,以确保稳定的信号读取。

项目简介:

该程序的主要功能和特点如下:

初始化(设置):

•设置串行通信。

•初始化OLED显示屏并显示游戏标题。

•将按钮引脚初始化为输入上拉模式。

•调用initGame()函数来设置游戏的初始状态。

游戏循环(循环):

•主游戏循环,即持续读取按键状态,更新游戏状态,并在游戏进行期间重新绘制游戏地图(gameRunning为真)。

初始化游戏:

•设置玩家的初始位置。

•随机生成盒子和目标的位置,确保它们距离边界至少有10个像素(即两个块单元)。

绘制游戏地图(drawMap):

•清除显示并重新绘制游戏地图,包括边界、玩家、盒子和目标位置。

读取按钮(readButtons):

•检测按钮状态,如果按钮被按下,调用movePlayer()函数来移动播放器。

移动播放器(movePlayer):

•根据按键输入更新玩家的位置。

•如果玩家移动到一个盒子的位置,尝试推动盒子。

•检查游戏是否获胜。

检查获胜条件(checkWinCondition):

•如果所有方块都在目标位置,则显示获胜消息并重新开始游戏。

更新游戏(updateGame):

•可以在这里添加额外的游戏逻辑,如得分或关卡更改。

预防措施:

•确保所有连接正确,特别是I2C连接和按钮的上拉电阻。

•在实际部署前测试每个组件,以确保它们正常工作。

•该程序使用随机数来初始化盒子和目标的位置,这可能导致一些游戏配置无法解决。您可能需要添加额外的逻辑来确保生成的布局是可解决的。

代码

#include

#include

#include

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

// 初始化OLED显示屏

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// 游戏地图的尺寸(以方块为单位)

#define MAP_WIDTH 16 // 地图宽度,方块数

#define MAP_HEIGHT 8 // 地图高度,方块数

// 玩家、箱子和目标的位置

int playerX = 1;

int playerY = 1;

int boxX[2] = {2, 4};

int boxY[2] = {1, 3};

int targetX[2] = {3, 5}; // 两个目标位置

int targetY[2] = {1, 3};

bool gameRunning = true;

// 按钮引脚

const int buttonUp = 2;

const int buttonDown = 3;

const int buttonLeft = 4;

const int buttonRight = 5;

void setup() {

Serial.begin(9600);

display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x64

display.clearDisplay();

display.setTextSize(1);

display.setTextColor(WHITE);

display.setCursor(0, 0);

display.println("推箱子游戏");

display.display();

delay(2000); // 显示初始化效果2秒

initGame();

// 初始化按钮引脚为输入上拉模式

pinMode(buttonUp, INPUT_PULLUP);

pinMode(buttonDown, INPUT_PULLUP);

pinMode(buttonLeft, INPUT_PULLUP);

pinMode(buttonRight, INPUT_PULLUP);

}

void loop() {

if (gameRunning) {

readButtons();

updateGame();

drawMap();

delay(100);

}

}

void initGame() {

// 初始化游戏状态

playerX = 1;

playerY = 1;

boxX[0] = 2;

boxY[0] = 1;

boxX[1] = 4;

boxY[1] = 3;

gameRunning = true;

}

// 绘制游戏地图

void drawMap() {

display.clearDisplay();

// 绘制游戏边界框的线条

display.drawLine(0, 0, MAP_WIDTH * 5 - 1, 0, BLACK); // 上边框

display.drawLine(0, 5 * MAP_HEIGHT - 1, MAP_WIDTH * 5 - 1, 5 * MAP_HEIGHT - 1, WHITE); // 下边框

display.drawLine(0, 0, 0, 5 * MAP_HEIGHT - 1, WHITE); // 左边框

display.drawLine(5 * MAP_WIDTH - 1, 0, 5 * MAP_WIDTH - 1, 5 * MAP_HEIGHT - 1, WHITE); // 右边框

// 绘制玩家位置

display.drawRect(playerX * 5, playerY * 5, 5, 5, WHITE); // 玩家方块尺寸:5x5

// 绘制箱子位置

for (int i = 0; i < 2; i++) {

display.fillRect(boxX[i] * 5, boxY[i] * 5, 5, 5, WHITE); // 箱子方块尺寸:5x5

}

// 绘制目标位置,使用黄色表示

for (int i = 0; i < 2; i++) {

display.drawRect(targetX[i] * 5, targetY[i] * 5, 5, 5, WHITE); // 目标方块尺寸:5x5,颜色:黄色(0xFFFF)

}

display.display();

}

// 按钮读取和消抖逻辑

void readButtons() {

static unsigned long lastDebounceTime = 0;

static unsigned long debounceDelay = 50;

unsigned long currentMillis = millis();

if (digitalRead(buttonUp) == LOW && (currentMillis - lastDebounceTime) > debounceDelay) {

lastDebounceTime = currentMillis;

movePlayer(0, -1);

}

if (digitalRead(buttonDown) == LOW && (currentMillis - lastDebounceTime) > debounceDelay) {

lastDebounceTime = currentMillis;

movePlayer(0, 1);

}

if (digitalRead(buttonLeft) == LOW && (currentMillis - lastDebounceTime) > debounceDelay) {

lastDebounceTime = currentMillis;

movePlayer(-1, 0);

}

if (digitalRead(buttonRight) == LOW && (currentMillis - lastDebounceTime) > debounceDelay) {

lastDebounceTime = currentMillis;

movePlayer(1, 0);

}

}

void movePlayer(int dx, int dy) {

// 玩家移动逻辑

int newX = playerX + dx;

int newY = playerY + dy;

// 检查新位置是否在地图范围内

if (newX >= 0 && newX < MAP_WIDTH && newY >= 0 && newY < MAP_HEIGHT) {

// 检查新位置是否不是墙壁

if (!isWall(newX, newY)) {

// 检查新位置是否是箱子

for (int i = 0; i < 2; i++) {

if (newX == boxX[i] && newY == boxY[i]) {

// 尝试推动箱子

int boxNewX = boxX[i] + dx;

int boxNewY = boxY[i] + dy;

if (!isWall(boxNewX, boxNewY) && !isBox(boxNewX, boxNewY)) {

boxX[i] = boxNewX;

boxY[i] = boxNewY;

playerX = newX;

playerY = newY;

checkWinCondition();

return;

}

}

}

// 移动玩家

playerX = newX;

playerY = newY;

}

}

}

bool isWall(int x, int y) {

// 定义墙壁位置

return (x == 0 || x == MAP_WIDTH - 1) || (y == 0 || y == MAP_HEIGHT - 1);

}

bool isBox(int x, int y) {

// 检查位置是否有箱子

for (int i = 0; i < 2; i++) {

if (x == boxX[i] && y == boxY[i]) {

return true;

}

}

return false;

}

void checkWinCondition() {

// 检查所有箱子是否都在目标位置

bool allBoxesAtTarget = true;

for (int i = 0; i < 2; i++) {

if (boxX[i] != targetX[i] || boxY[i] != targetY[i]) {

allBoxesAtTarget = false;

break;

}

}

if (allBoxesAtTarget) {

gameRunning = false;

display.clearDisplay();

display.setTextSize(1);

display.setTextColor(WHITE);

display.setCursor(0, 0);

display.println("Congratulations!!");

display.println("You win!");

display.display();

delay(300);

initGame(); // 重新开始游戏

}

}

void updateGame() {

// 游戏逻辑更新

}

本文编译自hackster.io

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭