#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include "nothing_menu.h" // 包含图像数据文件
#include "ar.h"
#include "sh.h"
#include "par.h"
#include "88.h"
#define TFT_CS 15
#define TFT_RST 2
#define TFT_DC 4
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
const int powerSwitchPin = 22; // 开关按钮的引脚
const int weaponButtonPin = 21; // 武器按钮的引脚
const int startButtonPin = 5; // 开始游戏按钮的引脚
const int arButtonPin = 17; // AR 按钮的引脚
const int shButtonPin = 16; // SH 按钮的引脚
bool isPoweredOn = false; // 标记是否开机
enum GameState { MAIN_MENU, WEAPON_SELECTION, GAME_RUNNING }; // 定义游戏状态
GameState gameState = MAIN_MENU; // 游戏初始状态为主画面
const char* weaponNames[] = {"kunai", "darts"};
const int weaponDamage[] = {10, 5}; // 攻击力
const int weaponFireRate[] = {1, 2}; // 射速
unsigned long lastFireTime = 0; // 上次发射子弹的时间
const unsigned long fireInterval = 3000; // 子弹发射间隔(毫秒)
unsigned long lastPowerSwitchDebounceTime = 0;
unsigned long lastWeaponButtonDebounceTime = 0;
unsigned long lastStartButtonDebounceTime = 0;
unsigned long lastArButtonDebounceTime = 0;
unsigned long lastShButtonDebounceTime = 0;
const unsigned long debounceDelay = 50; // 按钮消抖延迟
void setup() {
Serial.begin(9600);
pinMode(powerSwitchPin, INPUT_PULLUP); // 设置开关按钮为上拉输入
pinMode(weaponButtonPin, INPUT_PULLUP); // 设置武器按钮为上拉输入
pinMode(startButtonPin, INPUT_PULLUP); // 设置开始游戏按钮为上拉输入
tft.begin();
tft.setRotation(3); // 屏幕旋转角度
tft.fillScreen(ILI9341_BLACK); // 关闭屏幕
pinMode(arButtonPin, INPUT_PULLUP); // 设置 AR 按钮为上拉输入
pinMode(shButtonPin, INPUT_PULLUP); // 设置 SH 按钮为上拉输入
}
void loop() {
int powerSwitchState = digitalRead(powerSwitchPin);
int weaponButtonState = digitalRead(weaponButtonPin);
int startButtonState = digitalRead(startButtonPin);
int arButtonState = digitalRead(arButtonPin);
int shButtonState = digitalRead(shButtonPin);
unsigned long currentMillis = millis();
if (powerSwitchState == LOW && (currentMillis - lastPowerSwitchDebounceTime > debounceDelay)) { // 检测开关按钮是否按下
lastPowerSwitchDebounceTime = currentMillis; // 记录消抖时间
isPoweredOn = !isPoweredOn; // 切换开关状态
if (isPoweredOn == true) {
gameState = MAIN_MENU; // 如果开机,则显示主画面
drawMainMenu();
} else {
tft.fillScreen(ILI9341_BLACK); // 关机后清空屏幕
}
while (digitalRead(powerSwitchPin) == LOW) {} // 等待按钮释放
}
if (gameState == MAIN_MENU) {
if (weaponButtonState == LOW && (currentMillis - lastWeaponButtonDebounceTime > debounceDelay)) {
lastWeaponButtonDebounceTime = currentMillis; // 记录消抖时间
gameState = WEAPON_SELECTION; // 切换到武器选择画面
drawWeaponSelection();
}
if (startButtonState == LOW && (currentMillis - lastStartButtonDebounceTime > debounceDelay)) {
lastStartButtonDebounceTime = currentMillis; // 记录消抖时间
gameState = GAME_RUNNING; // 切换到游戏运行状态
jumpGame();
}
} else if (gameState == WEAPON_SELECTION) {
if (startButtonState == LOW && (currentMillis - lastStartButtonDebounceTime > debounceDelay)) {
lastStartButtonDebounceTime = currentMillis; // 记录消抖时间
gameState = MAIN_MENU; // 返回主画面
drawMainMenu();
} else if (arButtonState == LOW && (currentMillis - lastArButtonDebounceTime > debounceDelay)) {
lastArButtonDebounceTime = currentMillis; // 记录消抖时间
gameState = MAIN_MENU; // 返回主画面
drawMainMenu();
} else if (shButtonState == LOW && (currentMillis - lastShButtonDebounceTime > debounceDelay)) {
lastShButtonDebounceTime = currentMillis; // 记录消抖时间
gameState = MAIN_MENU; // 返回主画面
drawMainMenu();
}
}
}
// 在这里可以添加游戏运行时的其他代码
void drawMainMenu() {
tft.fillScreen(ILI9341_WHITE); // 设置背景为白色
// 绘制主角
tft.drawRGBBitmap(123, 40, image , 70 , 70);
// 绘制武器按钮
tft.fillRect(100, 130, 120, 40, ILI9341_GREEN);
tft.setTextSize(2);
tft.setTextColor(ILI9341_BLACK);
tft.setCursor(126, 141);
tft.println("weapon");
// 绘制开始游戏按钮
tft.fillRect(100, 180, 120, 40, ILI9341_BLUE);
tft.setCursor(130, 193);
tft.setTextColor(ILI9341_WHITE);
tft.println("start");
}
void drawWeaponSelection() {
tft.fillScreen(ILI9341_WHITE); // 设置背景为白色
// 绘制武器选择
for (int i = 0; i < 2; i++) {
tft.fillRect(80, 50 + i * 60, 170, 40, ILI9341_WHITE);
tft.setTextSize(2);
tft.setTextColor(ILI9341_BLACK);
tft.setCursor(140+i*4, 60 + i * 60);
tft.print("atk:");
tft.print(weaponDamage[i]);
tft.print(" sp:");
tft.println(weaponFireRate[i]);
}
tft.drawRGBBitmap(60, 50, ar , 40 , 40);
tft.drawRGBBitmap(60, 110, sh , 40 , 40);
int arButtonState = digitalRead(arButtonPin);
int shButtonState = digitalRead(shButtonPin);
// 绘制返回按钮
tft.fillRect(100, 190, 100, 30, ILI9341_BLUE);
tft.setCursor(128, 198);
tft.setTextColor(ILI9341_WHITE);
tft.println("BACK");
}
// 子弹属性
struct Bullet {
int x, y;
bool isActive;
};
Bullet bullets[10]; // 可以同时存在的最大子弹数量
int currentBullet = 0;
bool fireBullet(int startX, int startY) {
unsigned long currentTime = millis();
if (currentTime - lastFireTime >= fireInterval) {
bullets[currentBullet].x = startX;
bullets[currentBullet].y = startY;
bullets[currentBullet].isActive = true;
currentBullet = (currentBullet + 1) % 10; // 循环使用子弹
lastFireTime = currentTime; // 记录发射时间
return true; // 子弹成功发射
}
return false; // 子弹未能发射
}
void updateBullets() {
for (int i = 0; i < 10; i++) {
if (bullets[i].isActive) {
tft.drawRGBBitmap(bullets[i].x, bullets[i].y, tree + (bullets[i].y * SCREEN_WIDTH + bullets[i].x) * 2, 5, 5); // 擦除子弹,用背景图块覆盖
bullets[i].x += 5; // 子弹向右移动
if (bullets[i].x > SCREEN_WIDTH) {
bullets[i].isActive = false; // 子弹超出屏幕,设置为非激活
} else {
tft.fillRect(bullets[i].x, bullets[i].y, 5, 5, ILI9341_WHITE); // 画出子弹
}
}
}
}
// 在跳跃的过程中逐行擦除和绘制方块的逻辑
void jumpGame() {
tft.drawRGBBitmap(0, 0, tree , 320 , 240);
int boxX = 70; // 方块初始位置
int boxY = 180;
int boxSize = 20;
int gravity = 1;
bool isJumping = false;
int jumpSpeed = -15; // 跳跃速度
int fallSpeed = 0;
int savedFallSpeed = 0;
bool isHovering = false;
tft.fillRect(boxX, boxY, boxSize, boxSize, ILI9341_WHITE); // 画出方块
unsigned long lastJumpMillis = 0;
unsigned long lastHoverMillis = 0;
while (true) {
unsigned long currentMillis = millis();
int buttonState = digitalRead(startButtonPin);
int weaponButtonState = digitalRead(weaponButtonPin);
if (buttonState == LOW && !isJumping) { // 按下按钮开始跳跃
isJumping = true;
fallSpeed = jumpSpeed;
lastJumpMillis = currentMillis;
}
if (isJumping) {
// 擦除方块底部一行
tft.drawRGBBitmap(boxX, boxY + boxSize - 1, tree + ((boxY + boxSize - 1) * SCREEN_WIDTH + boxX) * 2, boxSize, 1);
boxY += fallSpeed;
if (!isHovering) {
fallSpeed += gravity;
}
if (boxY >= 180) { // 方块回到底部
boxY = 180;
isJumping = false;
isHovering = false;
}
// 绘制方块顶部一行
tft.fillRect(boxX, boxY, boxSize, 1, ILI9341_WHITE);
}
if (weaponButtonState == LOW && (currentMillis - lastFireTime >= fireInterval)) { // 检测武器按钮是否按下
if (fireBullet(boxX + boxSize, boxY + boxSize / 2)) { // 成功发射子弹
if (isJumping && !isHovering) {
savedFallSpeed = fallSpeed; // 保存当前下落速度
fallSpeed = 0; // 短暂滞空
isHovering = true;
lastHoverMillis = currentMillis;
}
}
}
if (isHovering && (currentMillis - lastHoverMillis >= 500)) { // 短暂滞空时间结束
fallSpeed = savedFallSpeed; // 恢复原来的下落速度
isHovering = false;
}
// 更新子弹状态
updateBullets();
// 计算子弹冷却时间并显示
unsigned long timeSinceLastFire = currentMillis - lastFireTime;
unsigned long timeUntilNextFire = (timeSinceLastFire < fireInterval) ? (fireInterval - timeSinceLastFire) : 0;
// 显示子弹冷却时间倒计时
tft.fillRect(80, 20, 100, 30, ILI9341_BLACK); // 擦除旧的倒计时
tft.setCursor(80, 20);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("CD: ");
tft.print(timeUntilNextFire / 1000); // 显示剩余时间(秒)
delay(20); // 控制跳跃动画的速度
}
}