基于STM32的恐龙小跳与躲避障碍游戏

简介: 在STM32平台上实现两款经典小游戏:恐龙小跳(类似Chrome离线游戏)和躲避障碍小游戏。两款游戏均使用OLED显示屏(SSD1306)和简单按键控制,具有完整的游戏逻辑、动画效果和计分系统。

一、项目概述

本项目在STM32平台上实现两款经典小游戏:恐龙小跳(类似Chrome离线游戏)和躲避障碍小游戏。两款游戏均使用OLED显示屏(SSD1306)和简单按键控制,具有完整的游戏逻辑、动画效果和计分系统。

二、系统架构

+-------------------+     +-------------------+     +-------------------+
|    输入处理模块    |     |    游戏逻辑模块    |     |    显示驱动模块    |
| (按键扫描与消抖)   |<--->| (双游戏状态机)     |<--->| (OLED显示控制)    |
+-------------------+     +-------------------+     +-------------------+
                                 |  |  |  |  |  |  |  |  |  |  |  |  |
                                 |  |  |  |  |  |  |  |  |  |  +---->+-------------------+
                                 |  |  |  |  |  |  |  |  |  +-------->|  游戏状态管理     |
                                 |  |  |  |  |  |  |  |  +------------>|  分数计算         |
                                 |  |  |  |  |  |  |  +---------------->|  动画效果         |
                                 |  |  |  |  |  |  +-------------------->|  音效反馈(可选)   |
                                 |  |  |  |  |  +-------------------------------->|                 |
                                 |  |  |  |  +------------------------------------>|                 |
                                 |  |  |  +---------------------------------------->|                 |
                                 |  |  +-------------------------------------------->|                 |
                                 |  +--------------------------------------------------->|                 |
                                 +--------------------------------------------------->|                 |

三、硬件配置

  • 主控芯片:STM32F103C8T6

  • 显示模块:0.96寸OLED(SSD1306,128×64,I2C)

  • 输入设备

    • 按键1:游戏选择/跳跃/上移

    • 按键2:开始/下移/左移

    • 按键3:返回/右移

  • 音频输出:无源蜂鸣器(可选)

四、游戏1:恐龙小跳(Dino Jump)

1. 游戏机制

  • 玩家控制恐龙跳跃躲避仙人掌

  • 随着分数增加,游戏速度逐渐加快

  • 碰撞仙人掌游戏结束

2. 核心代码实现

// dino.h
#define DINO_WIDTH 8
#define DINO_HEIGHT 8
#define GROUND_Y 56
#define GRAVITY 1
#define JUMP_FORCE -12

typedef struct {
   
    int x, y;           // 位置
    int vel_y;          // 垂直速度
    int is_jumping;     // 跳跃状态
    int width, height;  // 尺寸
} Dino;

typedef struct {
   
    int x;              // 位置
    int width, height;  // 尺寸
} Cactus;

// dino.c
void InitDino(Dino* dino) {
   
    dino->x = 20;
    dino->y = GROUND_Y - DINO_HEIGHT;
    dino->vel_y = 0;
    dino->is_jumping = 0;
    dino->width = DINO_WIDTH;
    dino->height = DINO_HEIGHT;
}

void UpdateDino(Dino* dino) {
   
    // 应用重力
    dino->vel_y += GRAVITY;
    dino->y += dino->vel_y;

    // 地面碰撞检测
    if (dino->y > GROUND_Y - DINO_HEIGHT) {
   
        dino->y = GROUND_Y - DINO_HEIGHT;
        dino->vel_y = 0;
        dino->is_jumping = 0;
    }
}

void JumpDino(Dino* dino) {
   
    if (!dino->is_jumping) {
   
        dino->vel_y = JUMP_FORCE;
        dino->is_jumping = 1;
    }
}

void InitCactus(Cactus* cactus) {
   
    cactus->x = 128;
    cactus->width = 6;
    cactus->height = 12;
}

void UpdateCactus(Cactus* cactus, int speed) {
   
    cactus->x -= speed;
    if (cactus->x < -10) {
   
        cactus->x = 128;
    }
}

int CheckCollision(Dino* dino, Cactus* cactus) {
   
    return (dino->x < cactus->x + cactus->width &&
            dino->x + dino->width > cactus->x &&
            dino->y < GROUND_Y &&
            dino->y + dino->height > GROUND_Y - cactus->height);
}

五、游戏2:躲避障碍(Obstacle Avoidance)

1. 游戏机制

  • 玩家控制飞船左右移动躲避陨石

  • 随机生成不同大小和速度的陨石

  • 随着时间增加,陨石数量增多

  • 被陨石击中游戏结束

2. 核心代码实现

// obstacle.h
#define SHIP_WIDTH 12
#define SHIP_HEIGHT 8
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

typedef struct {
   
    int x, y;           // 位置
    int width, height;  // 尺寸
} Ship;

typedef struct {
   
    int x, y;           // 位置
    int width, height;  // 尺寸
    int speed;          // 速度
} Asteroid;

// obstacle.c
void InitShip(Ship* ship) {
   
    ship->x = SCREEN_WIDTH / 2 - SHIP_WIDTH / 2;
    ship->y = SCREEN_HEIGHT - SHIP_HEIGHT - 5;
    ship->width = SHIP_WIDTH;
    ship->height = SHIP_HEIGHT;
}

void MoveShip(Ship* ship, int dir) {
   
    ship->x += dir * 5;
    if (ship->x < 0) ship->x = 0;
    if (ship->x > SCREEN_WIDTH - SHIP_WIDTH) 
        ship->x = SCREEN_WIDTH - SHIP_WIDTH;
}

void GenerateAsteroid(Asteroid* ast) {
   
    ast->x = SCREEN_WIDTH;
    ast->y = rand() % (SCREEN_HEIGHT - 20) + 10;
    ast->width = rand() % 10 + 5;
    ast->height = rand() % 10 + 5;
    ast->speed = rand() % 3 + 1;
}

void UpdateAsteroid(Asteroid* ast) {
   
    ast->x -= ast->speed;
}

int CheckHit(Ship* ship, Asteroid* ast) {
   
    return (ship->x < ast->x + ast->width &&
            ship->x + ship->width > ast->x &&
            ship->y < ast->y + ast->height &&
            ship->y + ship->height > ast->y);
}

六、双游戏整合实现

1. 主游戏状态机

// game.h
typedef enum {
   
    MENU,
    DINO_GAME,
    OBSTACLE_GAME,
    GAME_OVER
} GameState;

typedef struct {
   
    GameState state;
    Dino dino;
    Cactus cactus;
    Ship ship;
    Asteroid asteroids[5];
    int asteroid_count;
    int score;
    int game_speed;
    int selected_game;
} GameManager;

2. 主游戏循环

// main.c
int main(void) {
   
    HAL_Init();
    SystemClock_Config();
    OLED_Init();
    Input_Init();

    GameManager game = {
   0};
    game.state = MENU;
    game.selected_game = 0; // 0: Dino, 1: Obstacle

    while (1) {
   
        ProcessInput(&game);
        UpdateGame(&game);
        RenderGame(&game);
        HAL_Delay(30); // 控制游戏速度
    }
}

void ProcessInput(GameManager* game) {
   
    if (game->state == MENU) {
   
        if (KeyPressed(KEY_UP)) {
   
            game->selected_game = (game->selected_game + 1) % 2;
        } else if (KeyPressed(KEY_DOWN)) {
   
            game->selected_game = (game->selected_game + 1) % 2;
        } else if (KeyPressed(KEY_ENTER)) {
   
            if (game->selected_game == 0) {
   
                game->state = DINO_GAME;
                InitDinoGame(game);
            } else {
   
                game->state = OBSTACLE_GAME;
                InitObstacleGame(game);
            }
        }
    } 
    else if (game->state == DINO_GAME) {
   
        if (KeyPressed(KEY_JUMP)) {
   
            JumpDino(&game->dino);
        }
    } 
    else if (game->state == OBSTACLE_GAME) {
   
        if (KeyPressed(KEY_LEFT)) {
   
            MoveShip(&game->ship, -1);
        } else if (KeyPressed(KEY_RIGHT)) {
   
            MoveShip(&game->ship, 1);
        }
    } 
    else if (game->state == GAME_OVER) {
   
        if (KeyPressed(KEY_ENTER)) {
   
            game->state = MENU;
        }
    }
}

void UpdateGame(GameManager* game) {
   
    if (game->state == DINO_GAME) {
   
        UpdateDino(&game->dino);
        UpdateCactus(&game->cactus, game->game_speed);

        if (CheckCollision(&game->dino, &game->cactus)) {
   
            game->state = GAME_OVER;
        }

        // 计分
        if (game->cactus.x < 0) {
   
            game->score += 10;
            game->game_speed = 3 + game->score / 100;
            InitCactus(&game->cactus);
        }
    } 
    else if (game->state == OBSTACLE_GAME) {
   
        // 随机生成新陨石
        if (rand() % 20 == 0 && game->asteroid_count < 5) {
   
            GenerateAsteroid(&game->asteroids[game->asteroid_count]);
            game->asteroid_count++;
        }

        // 更新所有陨石
        for (int i = 0; i < game->asteroid_count; i++) {
   
            UpdateAsteroid(&game->asteroids[i]);

            if (CheckHit(&game->ship, &game->asteroids[i])) {
   
                game->state = GAME_OVER;
            }

            // 移除超出屏幕的陨石
            if (game->asteroids[i].x < -20) {
   
                // 移动最后一个陨石到当前位置
                if (i < game->asteroid_count - 1) {
   
                    game->asteroids[i] = game->asteroids[game->asteroid_count - 1];
                }
                game->asteroid_count--;
            }
        }

        // 计分
        game->score++;
    }
}

七、显示渲染系统

1. 双游戏渲染

void RenderGame(GameManager* game) {
   
    OLED_Clear();

    switch (game->state) {
   
        case MENU:
            RenderMenu(game);
            break;
        case DINO_GAME:
            RenderDinoGame(game);
            break;
        case OBSTACLE_GAME:
            RenderObstacleGame(game);
            break;
        case GAME_OVER:
            RenderGameOver(game);
            break;
    }

    OLED_Refresh();
}

void RenderDinoGame(GameManager* game) {
   
    // 绘制地面
    OLED_DrawLine(0, GROUND_Y, 127, GROUND_Y);

    // 绘制恐龙
    OLED_DrawRect(game->dino.x, game->dino.y, 
                 game->dino.width, game->dino.height);

    // 绘制仙人掌
    OLED_DrawRect(game->cactus.x, GROUND_Y - game->cactus.height,
                 game->cactus.width, game->cactus.height);

    // 显示分数
    char score_str[20];
    sprintf(score_str, "Score: %d", game->score);
    OLED_ShowString(0, 0, score_str);
}

void RenderObstacleGame(GameManager* game) {
   
    // 绘制飞船
    OLED_DrawTriangle(game->ship.x, game->ship.y + game->ship.height,
                     game->ship.x + game->ship.width/2, game->ship.y,
                     game->ship.x + game->ship.width, game->ship.y + game->ship.height);

    // 绘制所有陨石
    for (int i = 0; i < game->asteroid_count; i++) {
   
        OLED_DrawCircle(game->asteroids[i].x + game->asteroids[i].width/2,
                       game->asteroids[i].y + game->asteroids[i].height/2,
                       game->asteroids[i].width/2);
    }

    // 显示分数
    char score_str[20];
    sprintf(score_str, "Score: %d", game->score);
    OLED_ShowString(0, 0, score_str);
}

八、游戏特色功能

1. 动画效果

// 恐龙动画(奔跑效果)
void AnimateDino(Dino* dino, int frame) {
   
    if (frame % 10 < 5) {
   
        // 绘制站立状态
        OLED_DrawRect(dino->x, dino->y, 8, 8);
    } else {
   
        // 绘制抬腿状态
        OLED_DrawRect(dino->x, dino->y, 8, 4);
        OLED_DrawRect(dino->x, dino->y+4, 4, 4);
    }
}

// 爆炸效果
void DrawExplosion(int x, int y) {
   
    for (int i = 0; i < 8; i++) {
   
        int angle = i * 45;
        int dx = cos(angle) * 5;
        int dy = sin(angle) * 5;
        OLED_DrawPixel(x + dx, y + dy, 1);
    }
}

2. 音效系统(可选)

// 使用PWM驱动蜂鸣器
void PlaySound(int frequency, int duration) {
   
    uint32_t period = 1000000 / frequency;
    uint32_t cycles = duration * 1000 / period;

    for (uint32_t i = 0; i < cycles; i++) {
   
        HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET);
        Delay_us(period / 2);
        HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET);
        Delay_us(period / 2);
    }
}

// 游戏音效
void PlayJumpSound() {
   
    PlaySound(523, 50); // C5
}

void PlayCrashSound() {
   
    PlaySound(196, 200); // G3
    PlaySound(131, 300); // C3
}

3. 游戏难度曲线

// 动态调整游戏难度
void UpdateDifficulty(GameManager* game) {
   
    if (game->state == DINO_GAME) {
   
        // 每100分增加速度
        game->game_speed = 3 + game->score / 100;

        // 每200分增加障碍物频率
        if (game->score % 200 == 0) {
   
            // 增加新障碍物类型
        }
    } 
    else if (game->state == OBSTACLE_GAME) {
   
        // 每500分增加陨石数量
        if (game->score % 500 == 0 && game->asteroid_count < 8) {
   
            // 增加陨石数量上限
        }
    }
}

参考代码 基于stm32的恐龙小跳游戏+躲避障碍小游戏 www.youwenfan.com/contentalh/183117.html

九、项目资源

1. 硬件连接

外设 STM32引脚 功能
OLED_SDA PB7 I2C数据线
OLED_SCL PB6 I2C时钟线
KEY_UP PA0 上/跳跃
KEY_DOWN PA1 下/选择
KEY_LEFT PA2 左移
KEY_RIGHT PA3 右移
KEY_ENTER PA4 确认/开始
BUZZER PA5 音频输出

2. 开发环境

  • IDE: STM32CubeIDE

  • 编译器: GCC ARM Embedded

  • 库依赖:

  • HAL库

  • SSD1306 OLED驱动

  • 标准外设库

3. 项目结构

├── Core/
│   ├── Inc/
│   │   ├── game.h
│   │   ├── dino.h
│   │   ├── obstacle.h
│   │   └── oled.h
│   ├── Src/
│   │   ├── main.c
│   │   ├── game.c
│   │   ├── dino.c
│   │   ├── obstacle.c
│   │   └── oled.c
├── Drivers/
└── STM32F1xx_HAL_Driver/

十、总结

本实现展示了如何在STM32平台上开发两款经典小游戏:恐龙小跳和躲避障碍。项目特点包括:

  1. 双游戏整合:通过状态机实现两款游戏的无缝切换

  2. 完整游戏机制:包含角色控制、碰撞检测、计分系统和难度曲线

  3. 动画效果:实现角色动画和特效

  4. 可扩展性:模块化设计便于添加新游戏或功能

  5. 资源优化:针对嵌入式平台优化资源使用

目录
相关文章
|
5月前
|
算法 数据可视化
基于最小二乘(LS)算法的MIMO-OFDM信道估计MATLAB实现
基于最小二乘(LS)算法的MIMO-OFDM信道估计MATLAB实现
278 8
|
2月前
|
弹性计算 人工智能 监控
零基础上手Hermes Agent 阿里云轻量/ECS/计算巢/无影云电脑部署+Token Plan配置指南
在AI智能体快速普及的当下,Hermes Agent凭借自主学习、长期记忆、多工具协同、任务自主拆解等核心特性,已经成为办公自动化、行业研究、代码开发、数据采集领域的热门开源智能体。和普通对话机器人不同,Hermes Agent不只是简单问答,还能自主拆分复杂工作、调用浏览器、代码解释器、文件管理等工具,完成从资料搜集、文案撰写、数据分析到流程自动化的全链路任务。
350 2
|
4月前
|
算法 数据可视化
基于MATLAB/Simulink的四旋翼无人机仿真程序实现
基于MATLAB/Simulink的四旋翼无人机仿真程序实现
394 3
|
5月前
|
传感器 前端开发 数据可视化
数字孪生项目的开发费用
数字孪生项目定价已告别“按行计费”,核心取决于场景复杂度、数据实时性与渲染精度。本文详解三大档位报价(5万–200万+)、四大成本变量(建模精度、数据接入、交互深度、私有部署)及避坑要点,助您科学预算、精准选型。(239字)
|
6月前
|
存储 缓存 数据挖掘
阿里云服务器通用算力型u1实例2核4G199元/年测评,性能、适用场景、购买与续费注意事项
阿里云推出的通用算力型u1实例(2核4G5M带宽80G ESSD Entry云盘)以199元/年的特惠价,为企业用户提供高性价比的企业级云服务器,计算性能稳定、存储和网络性能出色,适用于中小企业网站、开发测试环境、数据库与缓存服务及轻量级数据分析等多种场景。该实例续费同价,长期使用成本可控,全球地域覆盖,满足企业全球化业务部署需求,是中小企业上云的首选。
|
8月前
|
算法 量子技术 数据库
量子计算云服务初探
本文深入浅出地介绍量子计算云服务,涵盖量子比特、量子门基础,主流平台如阿里云“太章2.0”,核心算法Shor与Grover,编程框架及经典模拟技术,探讨其在化学计算与优化问题中的应用前景,并提供入门学习路径与实践案例,助力开发者迈向量子计算时代。(238字)
394 0
|
10月前
|
机器学习/深度学习 监控 数据挖掘
Python 高效清理 Excel 空白行列:从原理到实战
本文介绍如何使用Python的openpyxl库自动清理Excel中的空白行列。通过代码实现高效识别并删除无数据的行与列,解决文件臃肿、读取错误等问题,提升数据处理效率与准确性,适用于各类批量Excel清理任务。
848 0
|
存储 JSON 前端开发
菜鸟之路Day39一一登录
本文介绍了登录功能的实现及其相关技术细节,包括会话管理、令牌认证和异常处理等内容。作者通过 Java 实现了一个基于用户名和密码的登录接口,调用服务层和数据库层完成用户验证。同时,文章深入探讨了三种会话跟踪技术:Cookie、Session 和 JWT 令牌。 在 JWT 部分,详细讲解了其生成与校验流程,实现了登录成功后返回 JWT 令牌的功能。此外,文章还介绍了过滤器(Filter)和拦截器(Interceptor)的概念及应用,演示了如何利用它们实现登录校验。 最后,为解决前后端交互中异常响应不统一的问题,定义了一个全局异常处理器 将系统异常以统一的 JSON 格式返回给前端。
409 0
|
存储 Cloud Native 大数据
云计算IaaS
云计算IaaS
1374 0

热门文章

最新文章