C语言基于SDL2写的贪吃蛇项目

1 篇文章 0 订阅
1 篇文章 0 订阅

copyright-------西南交大利兹 leo

调用到的头文件有

#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <stdbool.h>

#include <time.h>

对于SDL一类的API,codebloakcs的用户可以去这里下载:

SDL2类:http://www.libsdl.org/release/SDL2-devel-2.0.8-mingw.tar.gz

SDL2_mixer类:http://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.2-mingw.tar.gz

vc的在这里:

http://www.libsdl.org/release/SDL2-devel-2.0.8-VC.zip

http://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.2-VC.zip

当然都是用的SDL2来写的项目

这里给出codeblocks的配置方法:

setting —>linker settings --> other linker options 添加 -lmingw32 -lSDL2main -lSDL2 -lSDL2_mixer

然后在search directories 里面加上下载下来的SDL2和SDL_mixer 2.0的include 和lib 目录

这里提醒下,下载下来的两个文件每一个会有几乎相同的子文件夹,如果其中有一个有点问题,可以选另一个

注意下因为没有音乐和图片所以你们运行不了,这里给出例子 

重要事项注意,!!!SDL2_mixer.dll 和SDL2.dll 需要加进项目,可以从下载下来的两个文件里面找到!

为了让代码直接运行这里有傻瓜式直接下载方法

https://download.csdn.net/download/legends0/10435611

这里是源码:

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


#define LEFT  1
#define UP    2
#define DOWN  3
#define RIGHT 4
#define MAX_X 53
#define MAX_Y 25
#define TILE_SIZE 20
#define width 1080
#define height 520
#define size 100


typedef struct game_node {
    int x;
    int y;
} node;


node circle;
node oldcircle;
node square;
node oldone[size];
node olderone[size];


//main functions:
void input(void);
bool update(void);
void next_square(void);
void gameover(void);
void init(void);
void render(void);
void draw_object( node object, SDL_Texture *texture );


//new functions:
void start();
void generated();
void getnode(int number);
void record(node circle);
void oldrecord();
void judgement();
void speed_control();
void loadbgm();
void score();


//the variables
int dir;
bool eaten;
int number;
bool continued = true;
bool pause;
int delay;
int x_coor,y_coor;
int original_x_coor,original_y_coor;
int level,counts;


// game data
SDL_Window *openwindow = NULL;
SDL_Window *window = NULL;
SDL_Window *window2 = NULL;


SDL_Renderer* openrend = NULL;
SDL_Renderer* renderer = NULL;
SDL_Renderer* renderer2 = NULL;


SDL_Surface*  white_surface = NULL;
SDL_Surface*  square_surface = NULL;
SDL_Surface*  circle_surface = NULL;
SDL_Surface*  head_surface  = NULL;


SDL_Texture*  white_texture = NULL;
SDL_Texture*  square_texture = NULL;
SDL_Texture*  circle_texture = NULL;
SDL_Texture*  head_texture = NULL;


int main(int argc, char* argv[])
{
    start();


    delay = 10; //the original speed
    loadbgm(); //load bgm;
    init();   // setup the game data
    render(); // render initial state


    level = 10;
    counts = 0;


    SDL_Event event;
    while( continued )// game loop
    {
        speed_control();
        //control the speed.
        while(SDL_PollEvent(&event))
        {
            if(event.type == SDL_QUIT)
            {
                continued = false;
            }
            else if(event.type == SDL_MOUSEBUTTONDOWN)
            {
                if(event.button.button == SDL_BUTTON_LEFT)
                {
                    pause = true;
                }
                else if(event.button.button == SDL_BUTTON_RIGHT)
                {
                    pause = false;
                }
            }
        }
        if(!pause){
        input();           // keyboard input


        if(counts%level == 0)
        {
            if( !update() )    // update and check
            gameover();    // if finished
        }


        generated();
        judgement();
        render();          // render new state


        SDL_Delay( delay );
        }
        counts++;
    }
    SDL_DestroyWindow(window);
    score();
    SDL_DestroyWindow(window2);
    SDL_Quit();


    return 0;
}
void start()
{
    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2,20480);
    Mix_Music* bgm1 = Mix_LoadMUS("musics/bgm.mp3");
    Mix_PlayMusic(bgm1, 20);//load bgm music.
    SDL_CreateWindowAndRenderer(512, 512, 0, &openwindow, &openrend);
    SDL_SetWindowTitle( openwindow, "eating snake");
    SDL_Surface*  openimage = SDL_LoadBMP("images/openpage.bmp");
    SDL_Texture*  openimages =  SDL_CreateTextureFromSurface(openrend,openimage);
    SDL_SetTextureBlendMode(openimages, SDL_BLENDMODE_BLEND);
    int alpha = 255;
    //SDL_SetRenderDrawColor(openrend, 255, 255, 255, 255);
    SDL_Rect position;
    position.x = 0;
    position.y = 0;
    position.w = openimage -> w;
    position.h = openimage ->h;


    bool escape = false;
    bool change = true;
    SDL_Event event1;


    while(!escape)
    {
        while(SDL_PollEvent(&event1))
        {
            if(event1.type == SDL_QUIT)
            {
                exit(0);
            }
            if(event1.type == SDL_MOUSEBUTTONDOWN)
            {
                if(event1.button.button == SDL_BUTTON_LEFT)
                    escape = true;
            }
        }
    SDL_SetTextureAlphaMod(openimages,alpha);
    if(change == true)
    {
        alpha--;
        if(alpha == 0)
            change = false;
    }
    else
    {
        alpha++;
        if(alpha == 255)
            change = true;
    }
    SDL_RenderCopy(openrend, openimages, NULL, &position);
    SDL_RenderPresent(openrend);
    SDL_RenderClear(openrend);
    SDL_Delay(10);
    }
    SDL_DestroyWindow(openwindow);


}
void loadbgm()
{
    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2,20480);
    Mix_Music* bgm2 = Mix_LoadMUS("musics/bgm2.mp3");
    Mix_PlayMusic(bgm2, 20);//load bgm2 music.
}
void getnode(int number)
{
    oldone[number-1].x = x_coor;
    oldone[number-1].y = y_coor;
    printf("恭喜你吃到第 %d 个食物\n",number);
    if(number == 5)
        printf("开始加速!\n");
    else if (number == 15)
        printf("再次加速~~~~~\n");
    else if (number == 25)
        printf("你真乃神人啊~~~~~~~~~!!!!!无敌");
}
void record(node circle)//每一个节点的基坐标,每次刷新都读取一次
{
    x_coor = circle.x;
    y_coor = circle.y;
}
void oldrecord()//获得上一个节点的坐标,这个坐标就是头后面的那个坐标。
{
    original_x_coor = x_coor;
    original_y_coor = y_coor;
}
void generated()
{
    for(int i = 0; i<number; i++)
    {
        if(i==0)
        {
            oldone[0].x = original_x_coor;
            oldone[0].y = original_y_coor;
        }
        else
        {
            oldone[i].x = olderone[i-1].x;
            oldone[i].y = olderone[i-1].y;
        }
    }
}
void judgement()
{
    for(int i = 0; i < number; i++)
    {
        if(((oldone[i].x==circle.x)&&(oldone[i].y==circle.y))||((olderone[i].x==circle.x)&&(olderone[i].y==circle.y)))
            gameover();
    }
}
void speed_control()
{
    if((number >= 5)&&(number < 15))
    {
        level = 8;
    }
    else if((number >= 15)&&(number < 35))
    {
        level = 5;
    }
    else if ((number >= 35)&&(number < 50))
    {
        level = 3;
    }
    else if (number >= 50)
    {
        level = 2;
    }
}
// initialise the game data
void score()
{
    SDL_CreateWindowAndRenderer(300, 161, 0, &window2, &renderer2);
    SDL_SetWindowTitle( window2, "score");


    SDL_SetRenderDrawColor(renderer2, 255, 255, 255, 255);
    SDL_Surface*  lastimage = SDL_LoadBMP("images/lastimage.bmp");
    SDL_Texture*  lastimages =  SDL_CreateTextureFromSurface(renderer2,lastimage);


    bool escape = false;
    SDL_Event event2;


    SDL_Rect position;
    position.x = 0;
    position.y = 0;
    position.w = lastimage -> w;
    position.h = lastimage -> h;


    Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 20480);
    Mix_Music *bgm3 = Mix_LoadMUS("musics/lastbgm.wav");
    Mix_PlayMusic(bgm3,1);
    //loads wav;


    while(!escape)
    {
        while(SDL_PollEvent(&event2))
        {
            if(event2.type == SDL_QUIT)
            {
                escape = true;
            }
        }
    SDL_RenderCopy(renderer2, lastimages, NULL, &position);
    SDL_RenderPresent(renderer2);
    SDL_RenderClear(renderer2);
    }
}


void init()
{
    if (SDL_Init(SDL_INIT_VIDEO) != 0)
        fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());


    atexit(SDL_Quit); // set for clean-up on exit


    // SDL structures


    SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer);
    SDL_SetWindowTitle( window, "eatsnakes");
    //SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);


    square_surface = SDL_LoadBMP("images/square.bmp");
    circle_surface = SDL_LoadBMP("images/circle.bmp");
    white_surface = SDL_LoadBMP("images/background.bmp");
    head_surface = SDL_LoadBMP("images/head.bmp");


    square_texture = SDL_CreateTextureFromSurface(renderer, square_surface);
    circle_texture = SDL_CreateTextureFromSurface(renderer, circle_surface);
    white_texture = SDL_CreateTextureFromSurface(renderer, white_surface);
    head_texture = SDL_CreateTextureFromSurface(renderer, head_surface);


    SDL_RenderCopy(renderer, white_texture, NULL, NULL);
    // game data
    square.x = 5;
    square.y = 5;


    circle = square;
    oldcircle = circle;


    dir = RIGHT;


    next_square();
    eaten = true;
    number = 0;


    return;
}


// render current game state


void render()
{
    if (eaten)
        draw_object(square,square_texture); // draw new square if required


    draw_object(oldcircle,white_texture);   // redraw old location
    draw_object(circle,head_texture);     // draw new location


    for( int i = 0; i < number; i++)
    {
        if(i==0)
        {
            draw_object(olderone[0],white_texture);
            draw_object(oldone[0],circle_texture);
        }
        else
        {
            draw_object(olderone[i],white_texture);
            draw_object(oldone[i],circle_texture);
        }
    }
    SDL_RenderPresent(renderer);
    return;
}




// read keyboard input
void input()
{
    const Uint8 *state = SDL_GetKeyboardState(NULL);


    SDL_PumpEvents();
    if(dir == RIGHT)
    {
        if (state[SDL_SCANCODE_UP])
        {
            dir = UP;
        }
        else if (state[SDL_SCANCODE_DOWN])
        {
            dir = DOWN;
        }
        else if (state[SDL_SCANCODE_LEFT])
        {
            dir = RIGHT;
        }
        else if (state[SDL_SCANCODE_RIGHT])
        {
            dir = RIGHT;
        }
        else if (state[SDL_SCANCODE_ESCAPE])
        {
            exit(0);
        }
    }
    if(dir == LEFT)
    {
        if (state[SDL_SCANCODE_UP])
        {
            dir = UP;
        }
        else if (state[SDL_SCANCODE_DOWN])
        {
            dir = DOWN;
        }
        else if (state[SDL_SCANCODE_LEFT])
        {
            dir = LEFT;
        }
        else if (state[SDL_SCANCODE_RIGHT])
        {
            dir = LEFT;
        }
        else if (state[SDL_SCANCODE_ESCAPE])
        {
            exit(0);
        }
    }
    if(dir == UP)
    {
        if (state[SDL_SCANCODE_UP])
        {
            dir = UP;
        }
        else if (state[SDL_SCANCODE_DOWN])
        {
            dir = UP;
        }
        else if (state[SDL_SCANCODE_LEFT])
        {
            dir = LEFT;
        }
        else if (state[SDL_SCANCODE_RIGHT])
        {
            dir = RIGHT;
        }
        else if (state[SDL_SCANCODE_ESCAPE])
        {
            exit(0);
        }
    }
    if(dir == DOWN)
    {
        if (state[SDL_SCANCODE_UP])
        {
            dir = DOWN;
        }
        else if (state[SDL_SCANCODE_DOWN])
        {
            dir = DOWN;
        }
        else if (state[SDL_SCANCODE_LEFT])
        {
            dir = LEFT;
        }
        else if (state[SDL_SCANCODE_RIGHT])
        {
            dir = RIGHT;
        }
        else if (state[SDL_SCANCODE_ESCAPE])
        {
            exit(0);
        }
    }
    return;
}


// update player position


bool update()
{
    oldcircle = circle;
    for(int i = 0; i<number; i++)
    {
        olderone[i] = oldone[i];
    }
    oldrecord();
    switch (dir)
    {
        case UP:
            circle.y = circle.y - 1;
            break;
        case DOWN:
            circle.y = circle.y + 1;
            break;
        case LEFT:
            circle.x = circle.x - 1;
            break;
        case RIGHT:
            circle.x = circle.x + 1;
            break;
    }


    if (circle.x < 0 || circle.x > MAX_X || circle.y < 0 || circle.y > MAX_Y) {
        return false; // lose
    }
    if (circle.x == square.x && circle.y == square.y)
    {
        if(number>=size)
            return false;
        eaten = true;
        number++;
        next_square();
        getnode(number);
    }
    else
    {
        eaten = false; // continue
    }
    record(circle);


    return true;
}


// generate new square location


void next_square()
{
    srand( (unsigned)time( NULL ) );
    square.x = rand()%MAX_X;
    square.y = rand()%MAX_Y;
    if ((circle.x == square.x)&&(circle.y == square.y)){
        square.x =  MAX_X;
        square.y = MAX_Y;
    }
    for(int i = 0; i < number; i++)
    {
        if(((oldone[i].x == square.x)&&(oldone[i].y == square.y))||((olderone[i].x == square.x)&&(olderone[i].y == square.y))){
            square.x =  0;
            square.y = MAX_Y;
        }
    }
}


// game over
void gameover()
{
    int count;
    count = number*10;
    printf("你的分数: %d\n", count);
    printf("Game Over\n");
    continued = false;
}


// draw game component
void draw_object( node object, SDL_Texture *texture )
{
    SDL_Rect position;
    position.h = TILE_SIZE;
    position.w = TILE_SIZE;
    position.x = object.x * TILE_SIZE;
    position.y = object.y * TILE_SIZE;
    SDL_RenderCopy(renderer, texture, NULL, &position);
}

欢迎采纳,如果有问题和不懂,评论区留言。勿直接转载。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值