SDL demo 小结

最近学习 ffmpeg 例程,发现里面常用 SDL 库,进行开发。故最近找了个教程学习了一下,下面对学习的做个小结。

1. 第一大坑: main 函数必须写成下面的形式,不然会报错。
int main(int argc, char* argv[])

应该是 SDL.h 对其进行了一些操作。看源码看到下面这两句,应该就是声明了 int main(int argc, char* argv[]),所以必须实现这个函数,不然就会报错。

#define main    SDL_main
extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]);
2. 对 SDL 进行初始化,最好只初始你需要的功能,这样之后的代码能够自检,你后面的代码是不是有问题,或者把有问题的代码规避掉。
SDL_Init(SDL_INIT_VIDEO);
3.创建一个窗口,使用 SDL 主要是进行图像化展示,所以需要创建一个窗口进行展示。
SDL_CreateWindow("Hello world", 100, 100, 640 ,480, SDL_WINDOW_SHOWN);

第一个参数是窗口的名字,之后的四个参数分别是 窗口的左上角坐标和窗口的大小,最后一个参数是显示的模式(正常显示、最大化、最小化和全屏展示等)。

4.显示图片,有两种方式,一种是 CPU渲染、一种是GPU渲染
CPU 渲染

获得窗口的 surface 、获得图片的 surface 、将图片 surface 数据拷贝到窗口 surface 、更新窗口的 surface。

gScreenSurface = SDL_GetWindowSurface(gWindow);
gHelloWorld = SDL_LoadBMP(path.c_str());
SDL_BlitSurface(gHelloWorld, NULL, gScreenSurface, NULL);
SDL_UpdateWindowSurface(gWindow);
GPU渲染

获得窗口画布、获得图片的 surface、通过 surface 创建纹理、将纹理拷贝到备用缓冲区、交换前和后缓冲区显示图片

	SDL_Renderer* ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	SDL_Surface* bmp = SDL_LoadBMP("../Resource/hello.bmp");
	SDL_Texture* tex = SDL_CreateTextureFromSurface(ren, bmp);
	SDL_RenderCopy(ren, tex, NULL, NULL);
	SDL_RenderPresent(ren);

5. 人机交互,信息的获取

SDL 可以获取鼠标、键盘、窗口本身和其他一些交互设备的输入。
使用下面函数,获取消息队列中的信息。

SDL_PollEvent(&e);
e.type == SDL_QUIT // 退出事件
e.type == SDL_KEYDOWN // 键盘事件
e->type == SDL_MOUSEMOTION || e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEBUTTONUP//鼠标事件

通过 cpp e.key.keysym.sym获取按下的按钮。例如 cpp SDLK_UP、 SDLK_DOWN
通过cpp SDL_GetMouseState(&x, &y);获得鼠标的位置

6.缩放拷贝 surface

SDL_BlitScaled

7.加载除 bmp 的其他类型的图片,可以使用外部库如 SDL_image

此处也有一个坑,最新的 2.0.5 的 SDL_image 与 SDL 不兼容会报错,下载使用 2.0.4 的就好了。从下面的网站找就好了。
SDL_image 下载地址

首先初始化图片的格式,如PNG。之后使用这个库加载图片,考虑兼容问题,还将加载的 surface的格式转换为与 屏幕 surface 相同的格式。

int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))

SDL_Surface* loadedSurface = IMG_Load(path.c_str());
optimizedSurface = SDL_ConvertSurface(loadedSurface, gScreenSurface->format, 0);

8.绘制集合图形

SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF); // 设置颜色
SDL_RenderClear(gRenderer);// 清除屏幕
SDL_RenderFillRect(gRenderer, &fillRect);//实心矩形
SDL_RenderDrawRect(gRenderer, &outlineRect);//空心矩形
SDL_RenderDrawLine(gRenderer, 0, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT / 2); // 线
SDL_RenderDrawPoint(gRenderer, SCREEN_WIDTH / 2, i); // 点

9.设置视角

SDL_RenderSetViewport(gRenderer, &topLeftViewport);

10.设置裁剪

SDL_RenderCopy(gRenderer, mTexture, clip, &renderQuad);

11.设置图片叠加方式

alpha 为0,为前面的图片完全透明,可以看见后面的图片。

SDL_SetTextureBlendMode(mTexture, SDL_BLENDMODE_BLEND);
SDL_SetTextureAlphaMod(mTexture, alpha);

12.旋转和镜像

SDL_RenderCopyEx(gRenderer, mTexture, clip, &renderQuad, angle, center, flip);

13.获得时间

得到的是程序开始运行到现在的时间

SDL_GetTicks();

demo 地址:

LearnSDL

参考文献:

SDL tutorials

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的QEMU SDL界面的示例代码,可以用来启动x86架构的虚拟机: ``` #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <SDL2/SDL.h> #include "qemu-common.h" #include "qemu-option.h" #include "qemu-options.h" #include "qemu-config.h" #include "sysemu/sysemu.h" #include "ui/console.h" #include "ui/sdl.h" #define DEFAULT_WIDTH 800 #define DEFAULT_HEIGHT 600 static SDL_Window *sdl_window = NULL; static SDL_Renderer *sdl_renderer = NULL; static SDL_Texture *sdl_texture = NULL; static int sdl_width = DEFAULT_WIDTH; static int sdl_height = DEFAULT_HEIGHT; static int sdl_stride = DEFAULT_WIDTH * 4; static bool sdl_init() { if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError()); return false; } sdl_window = SDL_CreateWindow("QEMU SDL Demo", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, sdl_width, sdl_height, SDL_WINDOW_SHOWN); if (!sdl_window) { fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); return false; } sdl_renderer = SDL_CreateRenderer(sdl_window, -1, SDL_RENDERER_ACCELERATED); if (!sdl_renderer) { fprintf(stderr, "SDL_CreateRenderer failed: %s\n", SDL_GetError()); return false; } sdl_texture = SDL_CreateTexture(sdl_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, sdl_width, sdl_height); if (!sdl_texture) { fprintf(stderr, "SDL_CreateTexture failed: %s\n", SDL_GetError()); return false; } return true; } static void sdl_render(uint8_t *pixels) { SDL_UpdateTexture(sdl_texture, NULL, pixels, sdl_stride); SDL_RenderClear(sdl_renderer); SDL_RenderCopy(sdl_renderer, sdl_texture, NULL, NULL); SDL_RenderPresent(sdl_renderer); } static void qemu_exit(int ret) { SDL_DestroyTexture(sdl_texture); SDL_DestroyRenderer(sdl_renderer); SDL_DestroyWindow(sdl_window); SDL_Quit(); exit(ret); } int main(int argc, char **argv) { int ret; QemuOpts *opts; const char *machine_type, *kernel_path, *initrd_path, *cmdline; const char *device_opts; qemu_init_main_loop(&argc, &argv); if (!sdl_init()) { fprintf(stderr, "SDL init failed\n"); qemu_exit(1); } opts = qemu_opts_parse(qemu_find_opts("qemu"), argc, argv, 0); machine_type = qemu_opt_get(opts, "machine", "pc-i440fx-2.9"); kernel_path = qemu_opt_get(opts, "kernel", NULL); initrd_path = qemu_opt_get(opts, "initrd", NULL); cmdline = qemu_opt_get(opts, "append", NULL); device_opts = qemu_opt_get(opts, "device", NULL); ret = qemu_run_machine(machine_type, kernel_path, initrd_path, cmdline, device_opts, sdl_render); qemu_opts_del(opts); qemu_exit(ret); } ``` 该示例代码使用SDL库实现了一个简单的窗口,用于显示虚拟机的图像输出。在main()函数中,首先调用sdl_init()函数初始化SDL库,并创建一个窗口、渲染器和纹理对象。然后使用qemu_opts_parse()函数解析命令行参数,获取虚拟机的配置信息。最后调用qemu_run_machine()函数启动虚拟机,并在sdl_render()函数中更新纹理内容,实现图像的显示。 需要注意的是,这只是一个简单的示例代码,实际开发中需要考虑更多的细节和功能实现。同时,由于QEMU的内部实现比较复杂,需要一定的QEMU开发经验才能够理解和修改代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值