c语言奔跑的火柴人游戏源码(附带源码)

C语言实现奔跑的火柴人游戏——详细教程

引言

奔跑的火柴人游戏(Stickman Running)是一款极简风格的横版跑酷游戏。游戏的主角是一个火柴人,他将不断向前奔跑,玩家的目标是控制火柴人跳跃或者滑行,避开障碍物。游戏既有趣又充满挑战,非常适合用来锻炼编程能力,尤其是图形编程和物理碰撞检测等技能。

在这篇博客中,我们将使用 C语言SDL2库 实现这个游戏。SDL2(Simple DirectMedia Layer 2)是一个跨平台的多媒体开发库,广泛应用于游戏开发中。本教程将详细介绍游戏的实现思路、代码结构、每个模块的功能以及如何运用SDL2来构建图形界面、处理用户输入和动画效果。

通过这篇博客,你将学习到如何从零开始开发一个简单的2D跑酷游戏,涵盖了游戏编程的许多基本知识。

项目目标

1. 游戏设计

我们的游戏将包含以下基本要素:

  • 主角(火柴人):一个能够奔跑、跳跃和滑行的火柴人角色。
  • 障碍物:火柴人奔跑过程中会遇到不同的障碍物,玩家需要通过跳跃或滑行来避免这些障碍。
  • 背景和场景:游戏场景会不断滚动,模拟火柴人在一个不断前进的世界中奔跑。
  • 得分机制:玩家每次成功避开一个障碍,分数增加。
  • 游戏结束机制:玩家触碰到障碍物时,游戏结束,显示最终得分。

2. 技术实现

  • 使用C语言:我们将用C语言来实现游戏逻辑,因为它是一种基础且高效的编程语言。
  • 使用SDL2库:SDL2库非常适合用来开发2D游戏,它提供了对图形、输入、音频等方面的支持,非常适合我们这类简单的游戏开发。
  • 碰撞检测:通过检测火柴人和障碍物之间的碰撞,判断游戏是否结束。
  • 动画效果:我们需要实现流畅的角色动画,火柴人可以进行跑步、跳跃等动作。

设计思路

1. 游戏窗口和场景设置

为了创建一个基本的游戏界面,我们首先需要设置一个窗口。在SDL2中,创建一个窗口和渲染器是开发图形界面的第一步。窗口会显示游戏的所有内容,渲染器则负责绘制图形。

我们需要将窗口分为几个部分:

  • 背景:游戏的背景会向右滚动,模拟火柴人不断前进的效果。
  • 火柴人:玩家控制的火柴人角色。
  • 障碍物:随机生成在前方的障碍物。

2. 角色控制

火柴人的控制是游戏的核心。我们需要处理键盘事件,使玩家能够通过按下特定的键来让火柴人进行跳跃或滑行。

  • 跳跃:玩家按下跳跃键(如空格键),火柴人会从地面跳起。
  • 滑行:玩家按下滑行键(如Ctrl键),火柴人会进行滑行动作,穿越低矮的障碍物。

3. 障碍物生成与移动

障碍物会随机生成,并以一定的速度向左移动。当它们移出屏幕后,将重新生成在屏幕右侧,从而保持游戏的持续性。

  • 障碍物种类:可以设置不同种类的障碍物,比如墙壁、坑洞等。
  • 障碍物速度:障碍物的速度可以随着时间的推移逐渐加快,从而增加游戏的难度。

4. 碰撞检测

碰撞检测用于判断火柴人与障碍物是否发生了碰撞。如果火柴人跳跃失败或滑行失败,游戏就结束。

  • 矩形碰撞检测:我们可以将火柴人和障碍物都看作矩形,然后通过检查它们的矩形是否重叠来判断是否发生碰撞。

5. 游戏进程和得分

得分机制基于火柴人成功躲避障碍物的次数。每成功躲避一个障碍,分数就会增加。当游戏结束时,显示最终得分。


代码实现

为了便于理解,下面我将详细解释游戏的核心部分,包括如何创建游戏窗口、绘制背景、控制火柴人、生成障碍物以及实现碰撞检测等。

#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 窗口大小
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

// 火柴人大小
#define PLAYER_WIDTH 50
#define PLAYER_HEIGHT 70

// 障碍物大小
#define OBSTACLE_WIDTH 50
#define OBSTACLE_HEIGHT 50

// 游戏状态
enum GameState {
    RUNNING,
    GAME_OVER
};

// 定义火柴人结构体
typedef struct {
    int x, y;
    int velocityY; // 垂直速度
    int isJumping;
} Player;

// 定义障碍物结构体
typedef struct {
    int x, y;
    int speed;
} Obstacle;

// 游戏变量
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
Player player;
Obstacle obstacles[3];
int score = 0;
int gameState = RUNNING;

// 初始化游戏
void initGame() {
    SDL_Init(SDL_INIT_VIDEO);  // 初始化SDL2库
    window = SDL_CreateWindow("奔跑的火柴人", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    
    // 初始化火柴人
    player.x = 100;
    player.y = WINDOW_HEIGHT - PLAYER_HEIGHT;
    player.velocityY = 0;
    player.isJumping = 0;
    
    // 初始化障碍物
    for (int i = 0; i < 3; i++) {
        obstacles[i].x = WINDOW_WIDTH + i * 300;
        obstacles[i].y = WINDOW_HEIGHT - OBSTACLE_HEIGHT;
        obstacles[i].speed = 5 + rand() % 5;  // 随机速度
    }
}

// 绘制玩家
void drawPlayer() {
    SDL_Rect playerRect = {player.x, player.y, PLAYER_WIDTH, PLAYER_HEIGHT};
    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);  // 设置颜色为黑色
    SDL_RenderFillRect(renderer, &playerRect); // 绘制火柴人
}

// 绘制障碍物
void drawObstacles() {
    SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);  // 设置颜色为红色
    for (int i = 0; i < 3; i++) {
        SDL_Rect obstacleRect = {obstacles[i].x, obstacles[i].y, OBSTACLE_WIDTH, OBSTACLE_HEIGHT};
        SDL_RenderFillRect(renderer, &obstacleRect);
    }
}

// 更新玩家位置
void updatePlayer() {
    if (player.isJumping) {
        player.velocityY += 1;  // 增加垂直速度模拟重力
        player.y += player.velocityY;

        if (player.y >= WINDOW_HEIGHT - PLAYER_HEIGHT) {
            player.y = WINDOW_HEIGHT - PLAYER_HEIGHT;
            player.isJumping = 0;
            player.velocityY = 0;
        }
    }
}

// 更新障碍物位置
void updateObstacles() {
    for (int i = 0; i < 3; i++) {
        obstacles[i].x -= obstacles[i].speed;
        if (obstacles[i].x + OBSTACLE_WIDTH < 0) {
            obstacles[i].x = WINDOW_WIDTH;
            score++;
        }
    }
}

// 碰撞检测
int checkCollision() {
    SDL_Rect playerRect = {player.x, player.y, PLAYER_WIDTH, PLAYER_HEIGHT};
    for (int i = 0; i < 3; i++) {
        SDL_Rect obstacleRect = {obstacles[i].x, obstacles[i].y, OBSTACLE_WIDTH, OBSTACLE_HEIGHT};
        if (SDL_HasIntersection(&playerRect, &obstacleRect)) {
            return 1;  // 碰撞
        }
    }
    return 0;
}

// 处理事件
void handleEvents() {
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        if (e.type == SDL_QUIT) {
            gameState = GAME_OVER;
        }
        if (e.type == SDL_KEYDOWN) {
            if (e.key.keysym.sym == SDLK_SPACE && !player.isJumping) {
                player.isJumping = 1;
                player.velocityY = -20;  // 向上跳跃
            }
        }
    }
}

// 清理资源
void closeGame() {
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

// 主函数
int main() {
    srand(time(NULL));  // 设置随机种子
    initGame();
    
    while (gameState == RUNNING) {
        handleEvents();
        updatePlayer();
        updateObstacles();
        if (checkCollision()) {
            gameState = GAME_OVER;
        }
        
        // 渲染游戏画面
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);  // 设置背景颜色为白色
        SDL_RenderClear(renderer);
        
        drawPlayer();
        drawObstacles();
        
        // 更新屏幕
        SDL_RenderPresent(renderer);
        
        SDL_Delay(16);  // 控制帧率
    }
    
    printf("Game Over! Your score: %d\n", score);
    
    closeGame();
    return 0;
}

代码分析与解读

1. 游戏初始化

我们通过initGame()函数来初始化SDL2库、创建窗口和渲染器,并设置玩家和障碍物的初始位置。在初始化时,火柴人位于屏幕的左下角,障碍物则随机出现在屏幕右侧。

2. 绘制玩家和障碍物

drawPlayer()drawObstacles()分别负责绘制火柴人和障碍物。使用SDL2的SDL_RenderFillRect函数,绘制矩形来表示角色和障碍物。

3. 更新玩家和障碍物的位置

updatePlayer()更新火柴人的垂直位置,模拟跳跃的物理效果。updateObstacles()则使障碍物从右向左移动,形成跑酷效果。

4. 碰撞检测

checkCollision()函数用于检查火柴人与障碍物是否发生碰撞。我们通过SDL_HasIntersection函数检查火柴人与每个障碍物的矩形是否重叠。


结语

通过这个简单的奔跑的火柴人游戏,我们实现了一个基于C语言和SDL2的横版跑酷游戏。在开发过程中,我们学习了如何使用SDL2进行图形渲染、事件处理、动画效果实现以及碰撞检测。虽然游戏相对简单,但它为我们提供了一个良好的学习平台,帮助我们掌握游戏开发的基本技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值