第二课: 编写Hello World
博客专区 > geange 的博客 > 博客详情
第二课: 编写Hello World
geange 发表于1个月前
第二课: 编写Hello World
  • 发表于 1个月前
  • 阅读 9
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

Lesson 1: 编写Hello World

在这一节课,我们将学习如何创建一个窗口,创建一个着色正文(rendering context)和绘制一个图像文件到屏幕上。下载下面的这个bmp图像到项目中去,让我们开始吧。

开始使用SDL

为了使用SDL,我们先初始化我们需要使用的SDL子系统。下面的操作是通过设置SDL_Init的参数(SDL_INIT_VIDEO)获得需要的子系统。当前我们只需要video子系统,但是还有更多更多类似的参数我们将来可能会用到。请注意,默认情况下文件I/O和线程系统被初始化,如果video系统没有显示请求,则会自动化初始化事件处理系统。如果一切顺利,SDL_Init返回0,如果不是,我们希望打印错误并返回。

if (SDL_Init(SDL_INIT_VIDEO) != 0){
	std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
	return 1;
}

创建窗口

程序需要一个窗口来显示渲染的内容,我们使用SDL_CreateWindow来创建一个窗口。这个方法的参数有“窗口标题”、“x(左上角的横坐标)”、“y(左上角的纵坐标)”、”窗口宽度“、”窗口高度"、“标志位”。创建窗口出现错误了,会返回一个NULL的指针。如果出现错误则需要在退出程序之前清理SDL。

SDL_Window *win = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
if (win == nullptr){
	std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
	SDL_Quit();
	return 1;
}

创建渲染器

我们需要使用SDL_CreateRenderer创建一个渲染器(renderer)去为窗口绘制内容。这个函数将窗口、窗口渲染器、要使用的渲染驱动程序的索引和其他各种标志相关联。在这里。我们要求硬件加速启用了垂直同步的渲染器。如果出现什么异常情况,我们会获得一个空的SDL_Renderer指针。如果出现错误则需要在退出程序之前清理SDL。

SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (ren == nullptr){
	SDL_DestroyWindow(win);
	std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
	SDL_Quit();
	return 1;
}

载入位图

加载一个bmp格式的图像,我们首先需要将它加载进内存,然后再将它加载到我们使用的渲染平台上(在本例中是GPU)。我们使用SDL_LoadBMP加载图像会获得一个SDL_Surface的指针。我们可以把这个指针加载到SDL_Texture,使得渲染器能够使用图像。

SDL_LoadBMP需要图像的路径,你需要根据项目的结果修改源码中的数据,否则出错会返回一个空指针。

std::string imagePath = getResourcePath("Lesson1") + "hello.bmp";
SDL_Surface *bmp = SDL_LoadBMP(imagePath.c_str());
if (bmp == nullptr){
	SDL_DestroyRenderer(ren);
	SDL_DestroyWindow(win);
	std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
	SDL_Quit();
	return 1;
}

图像加载后,我们现在可以使用SDL_CreateTextureFromSurface加载图像到渲染器。我们通过在渲染上下文中上传和内存中的图像 (SDL_Surface), 并得到加载的纹理, 如果有什么错误, 我们会得到返回 NULL。如果出错,我们需要释放内存。

SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);
SDL_FreeSurface(bmp);
if (tex == nullptr){
	SDL_DestroyRenderer(ren);
	SDL_DestroyWindow(win);
	std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
	SDL_Quit();
	return 1;
}

纹理绘制

最后,我们需要做的是将纹理(Texture)绘制到屏幕上!
首先我们需要先清除渲染器,然后渲染我们的纹理,使屏幕更新以呈现新的结果。当我们想要渲染整个图像并使其伸展以填充屏幕,我们将SDL_RenderCopy的源和目标矩阵设置为NULL。最后我们调用SDL_Delay去保持窗口的显示状态,以便看到结果。

我们将全部的渲染代码放进程序的主循环中(一个简单的for循环)。每次迭代通过我们的循环,程序会睡眠1秒钟。我们也可以通过修改睡眠的时间来修改程序的运行时长。当我们得到事件处理,例如用户是否要退出我们的程序 (eg. 单击了窗口中的 X), 我们将跟踪一个布尔值并修改, 然后退出循环。

//A sleepy rendering loop, wait for 3 seconds and render and present the screen each time
for (int i = 0; i < 3; ++i){
	//First clear the renderer
	SDL_RenderClear(ren);
	//Draw the texture
	SDL_RenderCopy(ren, tex, NULL, NULL);
	//Update the screen
	SDL_RenderPresent(ren);
	//Take a quick break after all that hard work
	SDL_Delay(1000);
}

清理数据

在退出之前,我们必须要使用SDL_DestroyX销毁我们创建的全部对象。错误处理需要注意:以前在程序中我们可能遇到了错误并提前退出, 在这种情况下, 我们必须销毁我们创建的任何 sdl 对象, 并退出 sdl 以便在退出之前进行正确清理。在这小节的代码中,我们为了让代码的长短不至于太长,所以错误处理被省略了。但在正常的编程环境中正确的错误处理和清理是绝对必要的。

SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();

结束

如果一切顺利, 你应该看到你加载的图像渲染整个窗口, 等待 2s, 然后退出。如果出现问题, 请确保已安装了 sdl, 并且您的项目配置正确。

共有 人打赏支持
粉丝 0
博文 18
码字总数 9453
×
geange
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: