贪吃蛇+SDL2库【1】(c语言)

小白的学习记录


一、前置知识

注:博主是小白,所以记录的可能是一些无意中看到,但是不清楚的东西,所以大家择需了解。

JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人类阅读和编写,同时也易于机器解析和生成。JSON 使用文本格式来表示结构化数据,通常用于在服务器和客户端之间传输数据,尤其是在 web 应用程序中。

JSON 的基本特性

  1. 简单易读

    • JSON 的语法结构简单,易于理解和使用。它的格式类似于 JavaScript 对象,因此对于熟悉 JavaScript 的开发者来说特别直观。
  2. 数据结构

    • JSON 支持两种数据结构:
      • 对象:由键值对组成,使用花括号 {} 包围,键是字符串,值可以是字符串、数字、布尔值、数组、对象或 null

        json 

        {
            "name": "Alice",
            "age": 30,
            "isStudent": false
        }
      • 数组:有序值的集合,使用方括号 [] 包围,可以包含多个值(对象或其他类型)。

        json 

        {
            "students": [
                {"name": "Alice", "age": 30},
                {"name": "Bob", "age": 25}
            ]
        }
  3. 数据类型

    • JSON 支持以下基本数据类型:
      • 字符串(String):用双引号括起来的文本。
      • 数字(Number):整数或浮点数。
      • 布尔值(Boolean):true 或 false
      • 数组(Array):值的有序集合。
      • 对象(Object):键值对的无序集合。
      • 空值(null):表示空值。
  4. 语言无关性

    • JSON 是一种语言无关的数据格式,几乎所有编程语言都支持 JSON 的解析和生成,包括 JavaScript、Python、Java、C#、PHP 等。

JSON 的应用场景

  1. Web API

    • JSON 是现代 Web 应用程序中常用的数据交换格式,尤其是在 RESTful API 中。客户端和服务器之间常使用 JSON 格式传输数据。
  2. 配置文件

    • JSON 常用于存储配置信息,比如应用程序的配置文件,因其易于阅读和编辑。
  3. 数据存储

    • 一些 NoSQL 数据库(如 MongoDB)使用 JSON(或类似格式)来表示和存储数据。
  4. 序列化

    • JSON 可以用于将数据结构序列化为字符串,以便于存储或通过网络传输。

JSON 示例

以下是一个完整的 JSON 示例,表示一个学生的信息:

json 

{
    "student": {
        "name": "Alice",
        "age": 20,
        "isGraduate": false,
        "courses": [
            {"courseName": "Mathematics", "credits": 3},
            {"courseName": "Physics", "credits": 4}
        ],
        "address": {
            "street": "123 Main St",
            "city": "Anytown",
            "zip": "12345"
        }
    }
}

JSON 的优缺点

优点:

  • 轻量级:相比 XML 等其他格式,JSON 的数据结构更简洁,传输的数据量较小。
  • 易读性:人类友好,易于理解和维护。
  • 广泛支持:几乎所有编程语言都支持 JSON 数据的解析和生成。

缺点:

  • 功能有限:JSON 不支持复杂的数据类型(如日期、时间)和注释。
  • 不支持函数:JSON 仅用于数据表示,不能包含可执行的代码。

结论

JSON 已成为现代 Web 开发中广泛使用的数据交换格式,因其简单、灵活和易于使用而受到开发者的青睐。无论是在 API 开发、数据存储还是配置管理中,JSON 都发挥着重要作用。

SDL_Event event 

SDL_Event event; 是 SDL (Simple DirectMedia Layer) 库中用于处理各种事件的一个声明。SDL_Event 是一个结构体,用于封装来自用户的输入事件以及系统产生的事件,如键盘按键、鼠标移动、窗口大小变化等。

SDL_Event 结构体

SDL_Event 结构体定义在 SDL_events.h 头文件中,它包含了一个联合体(union)和一个事件类型字段,用于处理不同类型的事件。下面是 SDL_Event 结构体的基本定义:

1typedef struct _SDL_Event {
2    union {
3        // 用于存储不同类型的事件数据
4        // ...
5    } u;
6
7    Uint32 type;  // 事件类型
8} SDL_Event;

事件类型

type 字段是一个 Uint32 类型的成员,用于标识事件的类型。常见的事件类型包括但不限于:

  • SDL_QUIT: 窗口关闭请求。
  • SDL_KEYDOWN 和 SDL_KEYUP: 键盘按键按下和释放。
  • SDL_MOUSEBUTTONDOWN 和 SDL_MOUSEBUTTONUP: 鼠标按钮按下和释放。
  • SDL_MOUSEMOTION: 鼠标移动。
  • SDL_WINDOWEVENT: 窗口事件,如大小变化、最小化等。
  • SDL_JOYAXISMOTION: 手柄轴运动。
  • SDL_CONTROLLERBUTTONDOWN 和 SDL_CONTROLLERBUTTONUP: 控制器按钮按下和释放。
  • SDL_AUDIODEVICEADDED 和 SDL_AUDIODEVICEREMOVED: 音频设备添加和移除。

示例代码

下面是一个简单的示例,展示了如何使用 SDL_Event 结构体来处理事件:

1#include <SDL.h>
2
3int main(int argc, char* argv[])
4{
5    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
6        fprintf(stderr, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
7        return 1;
8    }
9
10    SDL_Window* window = SDL_CreateWindow("Event Handling Example",
11                                          SDL_WINDOWPOS_CENTERED,
12                                          SDL_WINDOWPOS_CENTERED,
13                                          800, 600,
14                                          SDL_WINDOW_SHOWN);
15    if (window == NULL) {
16        fprintf(stderr, "Window could not be created! SDL_Error: %s\n", SDL_GetError());
17        return 1;
18    }
19
20    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
21    if (renderer == NULL) {
22        fprintf(stderr, "Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
23        return 1;
24    }
25
26    bool quit = false;
27    SDL_Event event;
28
29    while (!quit) {
30        while (SDL_PollEvent(&event)) {
31            switch (event.type) {
32                case SDL_QUIT:
33                    quit = true;
34                    break;
35                case SDL_KEYDOWN:
36                    printf("Key pressed: %d\n", event.key.keysym.sym);
37                    break;
38                case SDL_MOUSEBUTTONDOWN:
39                    printf("Mouse button pressed: %d\n", event.button.button);
40                    break;
41                default:
42                    break;
43            }
44        }
45
46        // 清除渲染器
47        SDL_RenderClear(renderer);
48
49        // 更新屏幕
50        SDL_RenderPresent(renderer);
51    }
52
53    // 清理
54    SDL_DestroyRenderer(renderer);
55    SDL_DestroyWindow(window);
56    SDL_Quit();
57
58    return 0;
59}

总结

SDL_Event event; 是一个用于处理 SDL 事件的结构体声明。通过轮询事件队列 (SDL_PollEvent) 或等待事件发生 (SDL_WaitEvent),你可以检查事件的类型,并根据不同的事件类型采取相应的行动。SDL_Event 结构体是 SDL 中处理用户输入和系统事件的核心部分。

二、SDL2环境安装

 可能遇到的问题 



kerror LNK2019: 无法解析的外部符号 __imp___iob_func,该符号在函数 amqp_abort 中被引用,无法解析的外部符号 __imp_vfprintf-CSDN博客

SDL2链接报错:无法解析的外部符号 SDL_main,函数 main_getcmdline 中引用了该符号/main 已经在 main.obj 中定义_sdl库无法解析-CSDN博客

VS使用SDL2时LNK2019无法解析的外部符号_main_sdl2 无法解析的外部符号 main-CSDN博客

注意:如果已经感觉完全没问题了,但依旧报如下的错误{warning C4013: “SDL_Iint”未定义;假设外部返回 int} ,看看是不是写错了代码,比如字母写反了

SDL相关函数:

1.int SDL_Init(Uint32 flags)        作用:用来初始化SDL2.0

参数: flags:可以取下列值:
SDL_INIT_TIMER:定时器
SDL_INIT_AUDIO:音频
SDL_INIT_VIDEO:视频
SDL_INIT_JOYSTICK:摇杆
SDL_INIT_HAPTIC:触摸屏
SDL_INIT_GAMECONTROLLER:游戏控制器
SDL_INIT_EVENTS:事件
SDL_INIT_NOPARACHUTE:不捕获关键信号(这个不理解)
SDL_INIT_EVERYTHING:包含上述所有选项
返回:0初始化成功,其他失败

2.const char* SDL_Geterror(void)         作用:当有错误信息发生时用来获取错误信息

返回值:错误信息

3.SDL_Window* SDL_CreateWindow(const char* title,

                                        int x,

                                        int y,

                                        int w,

                                        int h,

                                        Uint32 flags

)

作用:用来创建一个窗口

参数: title 窗口标题
x :窗口位置 x 坐标。可以设置为 SDL_WINDOWPOS_CENTERED 表示窗口居中显示
y:窗口位置 y 坐标。可以设置为 SDL_WINDOWPOS_CENTERED 表示窗口居中显示
w :窗口宽度
h :窗口高度
flags :支持下列标识。包括了窗口的是否最大化、最小化,能否调整边界等等属性
SDL_WINDOW_FULLSCREEN 窗口全屏
SDL_WINDOW_FULLSCREEN_DESKTOP 在当前分辨率的桌面上全屏
SDL_WINDOW_OPENGL OPENGL 下可用的窗口
SDL_WINDOW_HIDDEN 窗口不可见(隐藏窗口)
SDL_WINDOW_BORDERLESS 没有窗口修饰(没有边框)
SDL_WINDOW_RESIZABLE 窗口可以调整大小
SDL_WINDOW_MINIMIZED 窗口最小化
SDL_WINDOW_MAXIMIZED 窗口最大化
SDL_WINDOW_INPUT_GRABBED 窗口有输入焦点 (鼠标只能在窗口内)
SDL_WINDOW_ALLOW_HIGHDPI 窗口应该创建在 high-DPI 模式下如果大于 SDL2.0.1 版
SDL_WINDOW_SHOWN 窗口是可见的
返回:成功返回指向 SDL_Window 的指针,失败返回 NULL

 4、SDL_Renderer* SDL_CreateRenderer( SDL_Window* window,

                                                                int index,

                                                                Unit32 flags

 )

作用:基于窗口创建渲染器
参数: window : 渲染的目标窗口。
index :打算初始化的渲染设备的索引。设置“-1”则初始化默认的渲染设备。
flags
:支持以下值(位于 SDL_RendererFlags 定义中)
SDL_RENDERER_SOFTWARE :使用软件渲染
SDL_RENDERER_ACCELERATED :使用硬件加速
(PS:用这个的时候要使用 SDL_CreateTextureFromSurface(SDL_Renderer* ,
SDL_Surface* )建立一个硬件加速纹理,或者直接用 IMG_LoadTexture(SDL_Renderer* ,
std::string filename)
SDL_RENDERER_PRESENTVSYNC:和显示器的刷新率同步
SDL_RENDERER_TARGETTEXTURE :渲染器支持渲染纹理
返回:返回值为一个 SDL_Renderer 渲染器指针,成功返回一个指针,失败返回 NULL

5、 SDL_Texture* IMG_LoadTexture(

                                                        SDL_Renderer* render,

                                                        const char* file                                                        

)

作用:加载指定纹理
参数: renderer :渲染器 file : 图片路径
返回:返回值为一个 SDL_Texture 纹理指针,成功返回一个指针,失败返回 NULL 
6、int SDL_RenderCopy(SDL_Renderer* renderer,
                                         SDL_Texture* texture,
                                        const SDL_Rect* srcrect,
                                        const SDL_Rect* dstrect
)
作用:将纹理数据复制给渲染目标
参数: renderer:渲染目标
texture:输入纹理
srcrect:选择输入纹理的一块矩形区域作为输入。设置为 NULL 的时候整个纹理
作为输入
dstrect:选择渲染目标的一块矩形区域作为输出。设置为 NULL 的时候整个渲染
目标作为输出
返回:成功的话返回 0,失败的话返回-1

7. void SDL_RenderPresent(SDL_Renderer* renderer)

作用:更新显示画面

参数:renderer:用于指定渲染器

8. void SDL_Delay(Uint32 ms)

作用:执行到这个函数时会延迟你所设定的毫秒数

参数:ms:为32为(4个字节)无符号整型数,为延迟的毫秒数

9.void SDL_DestroyTexture(SDL_Texture* texture)

作用:使用这个函数摧毁指定的纹理,释放缓存

参数:textrue:创建过的需要释放的SDL_Texture的指针

10.void SDL_DestroyRenderer(SDL_Renderer* renderer)

作用:使用这个函数摧毁的渲染上下文窗口和自由相关的纹理,释放缓存 

参数:render:创建过需要释放的SDL_Renderer指针

 11.void SDL_DestroyWindow(SDL_Window* window)

作用:使用这个函数摧毁一个窗口,释放内存

参数 :window:创建过的需要释放的SDL_Window指针

12.void SDL_Quit(void)

作用:使用此函数来清理所有已初始化的子系统。在退出前调用它 

13.SDL_Surface 是 Simple DirectMedia Layer (SDL) 库中的一个核心数据结构,用于表示图像数据。在 SDL 中,所有的图像和图形操作都是通过 SDL_Surface 对象来进行的。下面是对 SDL_Surface 的详细介绍:

数据结构定义

SDL_Surface 结构体在 SDL 中定义了图像的基本属性,例如宽度、高度、像素格式等。虽然具体的结构体成员是私有的并且不对外公开,但我们可以了解其一些重要的公共成员:

  • void *pixels: 指向图像数据的指针。
  • int w: 图像的宽度(以像素为单位)。
  • int h: 图像的高度(以像素为单位)。
  • int pitch: 图像的行距(以字节为单位),可能大于宽度乘以每个像素的字节数,以确保内存对齐。
  • unsigned int format: 像素格式,定义了每个像素如何存储颜色信息。
  • int depth: 图像的颜色深度,表示每个像素使用的位数。
  • int Rmask: 红色颜色通道的掩码。
  • int Gmask: 绿色颜色通道的掩码。
  • int Bmask: 蓝色颜色通道的掩码。
  • int Amask: Alpha 透明度通道的掩码。

创建和使用 SDL_Surface

创建 SDL_Surface

你可以通过多种方式创建 SDL_Surface 对象:

  • 加载图像文件:

    SDL_Surface *image = IMG_Load("path/to/image.png");
  • 从文件描述符中加载:

    SDL_Surface *image = IMG_LoadTyped_RW(SDL_RWFromFile("path/to/image.png", "rb"), 1, "PNG");
  • 创建空白的表面:

    SDL_Surface *surface = SDL_CreateRGBSurface(0, width, height, bitsPerPixel, Rmask, Gmask, Bmask, Amask);
  • 从现有表面复制:

    SDL_Surface *copy = SDL_DisplayFormat(surface);
使用 SDL_Surface

一旦你有了一个 SDL_Surface 对象,就可以对其进行各种操作,例如绘制到屏幕上、填充颜色、设置像素值等:

  • 绘制到屏幕:

    SDL_BlitSurface(image, NULL, screen, &rect);
  • 填充颜色:

    SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, r, g, b));
  • 访问像素:

    Uint32 *pixel = (Uint32 *) surface->pixels;
    pixel[x + y * surface->w] = SDL_MapRGB(surface->format, r, g, b);
  • 释放资源:

    SDL_FreeSurface(image);

示例

这里是一个简单的例子,展示如何加载一张图像并将其显示在屏幕上:

1#include <SDL.h>
2#include <SDL_image.h>
3
4int main(int argc, char* argv[]) {
5    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
6        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
7        return 1;
8    }
9
10    SDL_Window *window = SDL_CreateWindow("Image Display",
11                                          SDL_WINDOWPOS_UNDEFINED,
12                                          SDL_WINDOWPOS_UNDEFINED,
13                                          640, 480,
14                                          SDL_WINDOW_SHOWN);
15
16    if (window == NULL) {
17        printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
18        return 1;
19    }
20
21    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
22
23    // 加载图像
24    SDL_Surface *image = IMG_Load("path/to/image.png");
25    if (image == NULL) {
26        printf("Unable to load image! SDL Error: %s\n", SDL_GetError());
27        return 1;
28    }
29
30    // 转换为纹理
31    SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, image);
32    SDL_FreeSurface(image);
33
34    // 渲染纹理
35    SDL_RenderClear(renderer);
36    SDL_RenderCopy(renderer, texture, NULL, NULL);
37    SDL_RenderPresent(renderer);
38
39    // 等待用户关闭窗口
40    SDL_Event e;
41    while (SDL_WaitEvent(&e)) {
42        if (e.type == SDL_QUIT) {
43            break;
44        }
45    }
46
47    // 清理
48    SDL_DestroyTexture(texture);
49    SDL_DestroyRenderer(renderer);
50    SDL_DestroyWindow(window);
51    SDL_Quit();
52
53    return 0;
54}

这段代码展示了如何使用 SDL 加载一个图像文件,并将它渲染到屏幕上。注意,你需要链接 SDL 和 SDL_image 库才能编译这个程序。

相关结构体

 SDL_Rect  说明:SDL_Rect定义了屏幕上的一个矩形区域

typedef struct SDL_Rect{

        int x;         //所表示区域的左上角位置,x坐标

        int y        //所表示区域的左上角位置,y坐标                

        int w;        //区域宽度

        int h; //区域高度

}

三、头文件(学习记录)

#pragma once 是一种预处理器指令,用于防止同一个头文件被多次包含。当一个头文件被包含时,编译器会检查该头文件是否已经被包含过,如果是,则不会再次包含该文件。这种方法在很多现代编译器中被广泛使用,尤其是在编写头文件时。

作用

#pragma once 的主要目的是避免头文件被重复包含,从而导致编译错误或效率降低。当一个头文件被多个源文件包含时,如果没有适当的保护措施,可能会导致以下问题:

  1. 多重定义错误:

    • 如果一个头文件被多次包含,其中声明的变量或类型可能会被多次定义,导致编译错误。
  2. 编译效率降低:

    • 重复包含相同的头文件会导致编译时间增加,因为编译器需要多次解析相同的内容。

使用示例

下面是一个使用 #pragma once 的简单示例:

1// my_header.h
2#pragma once
3
4void my_function();

与传统头文件保护的区别

传统的头文件保护通常使用预处理器宏来实现,例如:

1// my_header.h
2#ifndef MY_HEADER_H
3#define MY_HEADER_H
4
5void my_function();
6
7#endif // MY_HEADER_H

优缺点

优点:

  • 简洁性#pragma once 更加简洁,不需要手动定义宏。
  • 易于理解: 对于初学者来说,#pragma once 更容易理解。

缺点:

  • 兼容性: 不是所有编译器都支持 #pragma once。尽管大多数现代编译器如 GCC, Clang 和 MSVC 都支持它,但在一些老旧的编译器中可能不被支持。
  • 非标准#pragma 是编译器特定的预处理器指令,不是 C 或 C++ 标准的一部分。

关于<>和""

在C和C++编程语言中,#include 指令用于引入其他文件,通常用来引入头文件。#include 指令有两种不同的形式来引用头文件:

  1. 角括号 <...>

    • 用途:通常用于包含标准库头文件或系统头文件。
    • 搜索路径:编译器会从标准系统路径开始搜索,这些路径通常指向系统安装的库文件所在的目录。
    • 例子
      1#include <stdio.h>
  2. 双引号 "..."

    • 用途:通常用于包含用户自定义的头文件或项目内的头文件。
    • 搜索路径:编译器首先会从当前源文件所在的目录开始搜索,如果在当前目录找不到,才会去系统路径搜索。
    • 例子
      1#include "myheader.h"

总结:

  • 标准库/系统头文件:使用 <...>,因为这些文件通常位于系统路径下,而且不随项目的不同而改变。
  • 用户自定义头文件:使用 "...",因为这些文件通常与你的源代码文件放在一起,编译器需要先在当前目录查找。

这种区分有助于编译器更快地找到所需的文件,并且可以避免在项目结构发生变化时引发问题。例如,如果你更改了一个用户自定义头文件的位置,使用双引号形式的 #include 指令可能会导致编译失败,因为你可能需要更新包含路径。而对于标准库头文件,由于它们的位置是固定的,所以使用角括号形式的 #include 指令可以避免此类问题。

四、过程记录

一、初步实现背景

注:尝试使用SDL,并非具体实现,具体实现应该分块,很好的利用头文件。

#define  _CRT_SECURE_NO_WARNINGS
#define SDL_MAIN_HANDLED  //把哪些奇奇怪怪的报错搞了
#include<SDL.h>
#include<stdio.h>
#include<SDL_image.h>    //SDL2.0_image库头文件


int main(int argc, char* argv[]) {
    SDL_Window* pWindow = NULL; //窗口
    SDL_Renderer* pRenderer = NULL;    //渲染器
    SDL_Texture* pTexture = NULL;    //纹理
    SDL_Rect dstRect;    //图片要显示的区域
    /*初始化SDL库,参数:初始化所有子系统*/
    if (0 != SDL_Init(SDL_INIT_EVERYTHING))
    {
        printf("SDL初始化失败: %s\n", SDL_GetError());
        return -1;
    }
    printf("SDL初始化成功!\n");

    /*创建窗口*/
    pWindow = SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 756/2, 899/2, SDL_WINDOW_SHOWN);
    if (NULL == pWindow)
    {
        printf("创建窗口失败: %s\n", SDL_GetError());
        return -2;
    }
    printf("创建窗口成功!\n");

    /*创建渲染器*/
    pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED);
    if (NULL == pRenderer)
    {
        printf("创建渲染器失败:%s\n", SDL_GetError());
        return -3;
    }
    printf("创建渲染器成功!\n");

    /*加载图片并创建纹理*/
    pTexture = IMG_LoadTexture(pRenderer, "..\\image\\background.png");
    if (pTexture == NULL)
    {
        printf("加载图片失败:%s\n", IMG_GetError());
        return -4;;
    }
    printf("加载图片成功!\n");

    /*设置图片要显示在窗口中的位置及大小*/
    dstRect.x = 0;
    dstRect.y = 0;
    dstRect.w = 756/2;
    dstRect.h = 899/2;

    /*将图片拷贝到渲染器中*/
    SDL_RenderCopy(pRenderer, pTexture, NULL, &dstRect);
    /*刷新渲染器,实现往窗口中绘制图片*/
    SDL_RenderPresent(pRenderer);
    /*延迟5秒*/
    SDL_Delay(5000);
    /*释放纹理*/
    SDL_DestroyTexture(pTexture);
    /*释放渲染器*/
    SDL_DestroyRenderer(pRenderer);
    /*释放窗口*/
    SDL_DestroyWindow(pWindow);

    /*退出SDL库*/
    SDL_Quit();
    return 0;
}

//main.c

二、一次集成初始化

#include "interface.h"


int main()
{
    Picture pic;
    //初始化SDL库、创建窗口、渲染器
    if (0 != initSDL())
    {
        return -1;
    }
    //加载图片资源
    if (0 != loadPicResources())
    {
        return -2;
    }

    //绘制窗口
    paint();
    //延迟5秒
    SDL_Delay(5000);

    //释放图片
    freePicResources();

    //退出SDL库,释放窗口、渲染器
    freeSDL();
    return 0;
}

//main.c

 三、再次集成

#include "interface.h"
#include"logic.h"

int main()
{
    //初始化
    init();
    //运行
    start();
    //释放
    gameFree();
    return 0;
}
//main

思路整理

一、

int initSDL(void)        //初始化SDL库、窗口、渲染器

{

        //初始化SDL2.0开发库        SDL_Init(SDL_INIT_EVERYTHING)

        //创建窗口 

        g_pWindow = SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED,                 SDL_WINDOWPOS_CENTERED,WINDOW_WIDTH,WINDOW_HEIGHT,                 SDL_WINDOW_SHOWN);                          

        //创建渲染器

        g_pRenderer = SDL_CreateRenderer(g_pWindow,                                                                     -1,SDL_RENDERER_ACCELERATED);                                                                                 

}

二、void freeSDL(void)  //释放SDL库、窗口、渲染器

void freeSDL(void)
{
    //释放渲染器
    SDL_DestroyRenderer(g_pRenderer);
    printf("渲染器释放!\n");

    //释放窗口
    SDL_DestroyWindow(g_pWindow);
    printf("窗口释放!\n");
    //退出SDL2.0
    SDL_Quit();
    printf("SDL库已退出!\n");

}

三、

// 名称:Picture loadPic(const char* path)
// 说明:加载一副图片
// 参数:path本地图片路径
// 返回:图片结构体

Picture loadPic(const char* path)

{

        Picture pic;
        //加载一副图片
        pic.pPic = IMG_LoadTexture(g_pRenderer, path);

}

四、void setPicDstRect(Picture* picture, int x, int y, int w, int h)
//目标区域的映射大小,xy是对左上角的坐标,wh分别是宽高

五、void setPicSrcRect(Picture* picture, int x, int y, int w, int h)

//源图像的映大小,同上

{
    picture->srcRect.x = x;
    picture->srcRect.y = y;
    if (0 == w || 0 == h)
    {
        SDL_QueryTexture(picture->pPic, NULL, NULL, &(picture->srcRect.w), &(picture->srcRect.h));
    }
    else
    {
        picture->srcRect.w = w;
        picture->srcRect.h = h;
    }

 六、具体加载

int loadPicResources(void)

{

        //加载背景图片
        g_picBackGround = loadPic(PATH_BACKGROUND);
        if (g_picBackGround.pPic == NULL)
        {
            return -1;
        }
        setPicSrcRect(&g_picBackGround, 0, 0, 0, 0);
        setPicDstRect(&g_picBackGround, BACKGROUND_PICI_X, BACKGROUND_PICI_Y,         BACKGROUND_PICI_W, BACKGROUND_PICI_H);

        

        ........//其他图片加载类似

}

void freePicResources(void)        //释放图片加载资源

{

        SDL_DestroyTexture(g_picBackGround.pPic);

        

        .......//其他释放类似

}

//往渲染器加载图片

void paintPic(Picture* picture)
{
    SDL_RenderCopy(g_pRenderer, picture->pPic, &(picture->srcRect), &(picture->dstRect));

}

void paint(void)
{
    paintPic(&g_picBackGround);
  

     //更新渲染器图像
    SDL_RenderPresent(g_pRenderer);
}
//绘制窗口

接下来就是具体实现了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值