【转】Getting an Image on the Screen
FROM:http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php
Getting an Image on the Screen
Last Updated 1/06/19
Now that you've already got a window open, let's put an image on it.
Note: From now on the tutorials will only cover key parts of source code. For the full program, you will have to download the full source code.
bool init();
//Loads media
bool loadMedia();
//Frees media and shuts down SDL
void close();
Here it means we have functions to handle initialization, loading media, and closing down the SDL application. We declare these near the top of our source file.
I get a lot of e-mails about how calling this function "close" causes conflicts in C because does not support function overloading. This is one of the reasons I am using C++ for this tutorial. So it is not bug that this is function is called "close".
SDL_Window* gWindow = NULL;
//The surface contained by the window
SDL_Surface* gScreenSurface = NULL;
//The image we will load and show on the screen
SDL_Surface* gHelloWorld = NULL;
Here's a new data type called an SDL Surface. An SDL surface is just an image data type that contains the pixels of an image along with all data needed to render it. SDL surfaces use software rendering which means it uses the CPU to render. It is possible to render hardware images but it's a bit more difficult so we're going to learn it the easy way first. In future tutorials we'll cover how to render GPU accelerated images.
The images we're going to be dealing with here are the screen image (what you see inside of the window) and the image we'll be loading from a file.
Notice that these are pointers to SDL surfaces. The reason is that 1) we'll be dynamically allocating memory to load images and 2) it's better to reference an image by memory location. Imagine you had a game with a brick wall that consisted of the same brick image being rendered multiple times (like Super Mario Bros). It's wasteful to have dozens of copies of the image in memory when you can have one copy of the image and render it over and over again.
Also, always remember to initialize your pointers. We set them to NULL immediately when declaring them.
{
//Initialization flag
bool success = true;
//Initialize SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Create window
gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( gWindow == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
success = false;
}
else
{
//Get window surface
gScreenSurface = SDL_GetWindowSurface( gWindow );
}
}
return success;
}
We want to show images inside of the window and in order to do that we need to get the image inside of the window. So we call SDL_GetWindowSurface to grab the surface contained by the window.
{
//Loading success flag
bool success = true;
//Load splash image
gHelloWorld = SDL_LoadBMP( "02_getting_an_image_on_the_screen/hello_world.bmp" );
if( gHelloWorld == NULL )
{
printf( "Unable to load image %s! SDL Error: %s\n", "02_getting_an_image_on_the_screen/hello_world.bmp", SDL_GetError() );
success = false;
}
return success;
}
An important thing to note is that this piece of code assumes you have a directory called "02_getting_an_image_on_the_screen" that contains an image named "hello_world.bmp" in your working directory. The working directory is where your application thinks it is operating. Typically, your working directory is the directory where your executable is at but some programs like Visual Studio change the working directory to where the vcxproj file is located. So if your application can't find the image, make sure it is in the right place.
Again, if the program is running but it can't load the image, you probably have a working directory problem. Working directories function differently from OS to OS and IDE to IDE. If googling how find or fix the working directory can't turn up a solution, I recommend moving around the "02_getting_an_image_on_the_screen" folder with the "hello_world.bmp" around until the program can finally load it.
{
//Deallocate surface
SDL_FreeSurface( gHelloWorld );
gHelloWorld = NULL;
//Destroy window
SDL_DestroyWindow( gWindow );
gWindow = NULL;
//Quit SDL subsystems
SDL_Quit();
}
Make sure to get into the habit of having your pointers point to NULL when they're not pointing to anything.
{
//Start up SDL and create window
if( !init() )
{
printf( "Failed to initialize!\n" );
}
else
{
//Load media
if( !loadMedia() )
{
printf( "Failed to load media!\n" );
}
else
{
//Apply the image
SDL_BlitSurface( gHelloWorld, NULL, gScreenSurface, NULL );
What blitting does is take a source surface and stamps a copy of it onto the destination surface. The first argument of SDL_BlitSurface is the source image. The third argument is the destination. We'll worry about the 2nd and 4th arguments in future tutorials.
Now if this was the only code for drawing we had, we still wouldn't see the image we loaded on the screen. There's one more step.
SDL_UpdateWindowSurface( gWindow );
When you make draw calls like SDL_BlitSurface, you render to the back buffer. What you see on the screen is the front buffer. The reason we do this is because most frames require drawing multiple objects to the screen. If we only had a front buffer, we would be able to see the frame as things are being drawn to it which means we would see unfinished frames. So what we do is draw everything to the back buffer first and once we're done we swap the back and front buffer so now the user can see the finished frame.
This also means that you don't call SDL_UpdateWindowSurface after every blit, only after all the blits for the current frame are done.
SDL_Delay( 2000 );
}
}
//Free resources and close SDL
close();
return 0;
}
最新文章
- 本地项目上传到GitHub
- [Node.js] 闭包和高阶函数
- WinForm------TreeList加载数据方法
- keepalived安装
- Devexpress VCL Build v2015 vol 15.2 开始测试
- 哈希加密算法 MD5,SHA-1,SHA-2,SHA-256,SHA-512,SHA-3,RIPEMD-160 - aTool
- python路径相关
- WPF4多点触摸事件
- 在Java中打开浏览器
- python并发编程之多进程(二):互斥锁(同步锁)&;进程其他属性&;进程间通信(queue)&;生产者消费者模型
- qml 静态编译程序执行错误 无法定位程序输入点 CreateDXGIFactory2 于动态链接库 dxgi.dll 上
- ubuntu 英文系统下安装中文输入法
- 《JAVA程序设计》_第七周学习总结
- css 兼容各种iPhone
- .net 连接 Oracle 可能需要配置
- 实时监听input输入的变化(兼容主流浏览器)【转】
- 十一、K3 WISE 开发插件《VB插件开发如何代码调试 - 步骤讲解》
- 雷林鹏分享:C# 类型转换
- php 冒泡排序的两种思路以及优化
- 黑马程序员_java基础笔记(14)...交通灯管理系统_编码思路及代码
热门文章
- (转载)Altium Designer 17 (AD17)
- Flex、Grid、媒体查询实现响应式布局
- Centos-挂载和卸载分区-mount
- 025 01 Android 零基础入门 01 Java基础语法 03 Java运算符 05 if条件结构
- centos7卸载mariadb安装mysql
- Zookeeper基础理论
- Java中 util 包 Calendar类制作万年历(不用自己写方法,直接用Java写好的包中的类的方法)
- 启动VNC Shell扩展
- RHSA-2018:0007-重要: 内核 安全更新(需要重启、存在EXP)
- 《流畅的Python》 第一部分 序章 【数据模型】