-
Notifications
You must be signed in to change notification settings - Fork 116
SDLHelloWord
英文原文地址:http://www.willusher.io/sdl2%20tutorials/2013/08/17/lesson-1-hello-world
这一节我们将学习简单的将一张图片绘制到屏幕上的方法。具体来讲是绘制下面这张图片。

你可以通过右键另存为下载这张图片。如果你丢了资源或者想要偷看一下我的代码,就从这里抓好了。但切忌复制粘贴!
首先在delphi当中File->New->Other,创建一个Console Application,保存为SDLHelloWorld,添加一个新的单元,保存为App.pas。
使用SDL,我们必须先初始化我们想要使用的SDL的各个子系统。将一组“或”关系的标志作为参数传入到SDL_Init可以完成我们要使用的子系统的初始化。现在我们只需要使用视频子系统,但是将来我们会增加更多的标志,因为我们需要更多的特性。注意使用视频子系统的时候,事件处理子系统会被自动初始化,文件I/O和线程系统也会被默认启动。如果所有的初始化都正确SDL_Init会返回0,如果不是我们将会打印错误并退出。
if (SDL_Init(SDL_INIT_VIDEO) <> 0) then
begin
Writeln('SDL_Init Error: ', SDL_GetError);
Exit(1);
end;我们需要一个窗口来显示我们的渲染,我们可以使用SDL_CreateWindow创建一个窗口,参数包括窗口标题,X和Y坐标,窗口的宽度和高度以及一些标志来设置窗口的属性,返回一个PSDL_Window指针。如果创建窗口时出错,该指针将为nil。如果发生错误,我们需要在退出程序之前清理SDL。
win := SDL_CreateWindow('Hello World!', 100, 100, 640, 480, SDL_WINDOW_SHOWN);
// Make sure creating our window went ok
if (win = nil) then
begin
Writeln('SDL_CreateWindow Error: ', SDL_GetError);
Exit(1)
end;现在我们可以创建一个渲染器并使用SDL_CreateRenderer在窗口中进行绘制。这个函数将渲染器与窗口进行关联,需要传入渲染器的驱动索引(或-1选择第一个符合需求的驱动)和渲染器所需的各种标志。在这里,我们请求带有垂直同步硬件加速的渲染器。我们得到一个PSDL_Renderer指针,如果该指针为nil则表示发生了错误。如果发生错误,我们需要清理我们以前创建的任何东西,并在退出程序之前退出SDL。
ren := SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED or SDL_RENDERER_PRESENTVSYNC);
if (ren = nil) then
begin
SDL_DestroyWindow(win);
Writeln('SDL_CreateRenderer Error: ', SDL_GetError);
SDL_Quit();
Exit(1);
end;要渲染BMP图像,我们需要将其加载到内存中,然后加载到我们正在使用的渲染平台(在这种情况下是GPU)。我们可以使用SDL_LoadBMP加载图像,该函数返回PSDL_Surface指针,我们可以上传到一个SDL_Texture供渲染器使用。
SDL_LoadBMP需要传入一个filepath参数指定图像的路径,你应该按照你的应用目录结构进行相应的调整,该函数返回一个PSDL_Surface指针,如果发生错误则返回nil。
SDL_LoadBMP takes the filepath of our image, which you should change to match your project structure, and gives us back an SDL_Surface* or NULL if something went wrong.
imagePath := getResourcePath('Lesson1') + 'hello.bmp';
bmp := SDL_LoadBMP(PAnsiChar(AnsiString(imagePath)));
if (bmp = nil) then
begin
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
Writeln('SDL_LoadBMP Error: ', SDL_GetError);
SDL_Quit();
Exit(1);
end;图像加载后可以通过SDL_CreateTextureFromSurface上传到渲染器使用。我们传入要上传的渲染器上下文和内存中的图像(PSDL_Surface指针)并得到加载的纹理,如果发生错误,我们会得到nil。我们在这里已经得到了窗口和渲染器,所以现在需要释放它们。
tex := SDL_CreateTextureFromSurface(ren, bmp);
SDL_FreeSurface(bmp);
if (tex = nil) then
begin
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
Writeln('SDL_CreateTextureFromSurface Error: ', SDL_GetError);
SDL_Quit();
Exit(1);
end;剩下要做的就是让我们的纹理显示在屏幕上!首先我们要清除渲染器,然后渲染我们的纹理并更新屏幕显示结果。因为我们想图片进行拉伸铺满整个屏幕,我已我们将nil作为源和目标矩形传给SDL_RenderCopy。我们希望窗口在程序推出之前保留一会,以便我方看到显示结果,所以我们添加一个SDL_Delay调用。
把所有这些渲染代码放在程序的主循环中,使用一个简单的for循环。每次循环我们会休眠一秒钟,增加或减少计数器,可以使程序运行更长或更短的时间。当我们讲到事件处理时,我们将跟踪一个布尔值,确定用户是否要退出程序(如单击窗口上的X),并在这种情况下退出循环。
for i := 0 to 2 do
begin
// First clear the renderer
SDL_RenderClear(ren);
// Draw the texture
SDL_RenderCopy(ren, tex, nil, nil);
// Update the screen
SDL_RenderPresent(ren);
// Take a quick break after all that hard work
SDL_Delay(1000);
end;在退出之前我们要通过各种SDL_DestroyX函数销毁所有创建的对象并且退出SDL。错误处理说明:在之前的程序中,我们可能遇到了一个错误并提前退出,在这种情况下,我们必须销毁我们创建的任何SDL对象,并退出SDL以在退出之前正确地清理。错误处理的这一部分从课程中省略了,因为它们是如此小的示例,它有助于使代码缩短一些,但在实际使用的程序中,适当的错误处理和清理是绝对必要的。
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();If everything went well you should see the image you loaded render over the entire window, wait for 2s and then exit. If you have any problems, make sure you’ve got SDL installed and your project configured properly as discussed in Lesson 0: Setting up SDL, or post a question below.
完整代码如下:
SDLHelloWorld.dpr:
program SDLHelloWorld;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
sdl2 in '..\..\Pascal-SDL-2-Headers-master\sdl2.pas',
App in 'App.pas';
begin
Run;
end.App.pas如下:
unit App;
interface
uses
sdl2,
res_path;
function Run: Integer;
implementation
function Run: Integer;
var
win: PSDL_Window;
ren: PSDL_Renderer;
bmp: PSDL_Surface;
tex: PSDL_Texture;
imagePath: string;
i: Integer;
begin
// First we need to start up SDL, and make sure it went ok
if (SDL_Init(SDL_INIT_VIDEO) <> 0) then
begin
Writeln('SDL_Init Error: ', SDL_GetError);
Exit(1);
end;
// Now create a window with title "Hello World" at 100, 100 on the screen with w:640 h:480 and show it
win := SDL_CreateWindow('Hello World!', 100, 100, 640, 480, SDL_WINDOW_SHOWN);
// Make sure creating our window went ok
if (win = nil) then
begin
Writeln('SDL_CreateWindow Error: ', SDL_GetError);
Exit(1)
end;
// Create a renderer that will draw to the window, -1 specifies that we want to load whichever
// video driver supports the flags we're passing
// Flags: SDL_RENDERER_ACCELERATED: We want to use hardware accelerated rendering
// SDL_RENDERER_PRESENTVSYNC: We want the renderer's present function (update screen) to be
// synchronized with the monitor's refresh rate
ren := SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED or SDL_RENDERER_PRESENTVSYNC);
if (ren = nil) then
begin
SDL_DestroyWindow(win);
Writeln('SDL_CreateRenderer Error: ', SDL_GetError);
SDL_Quit();
Exit(1);
end;
// SDL 2.0 now uses textures to draw things but SDL_LoadBMP returns a surface
// this lets us choose when to upload or remove textures from the GPU
imagePath := getResourcePath('Lesson1') + 'hello.bmp';
bmp := SDL_LoadBMP(PAnsiChar(AnsiString(imagePath)));
if (bmp = nil) then
begin
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
Writeln('SDL_LoadBMP Error: ', SDL_GetError);
SDL_Quit();
Exit(1);
end;
// To use a hardware accelerated texture for rendering we can create one from
// the surface we loaded
tex := SDL_CreateTextureFromSurface(ren, bmp);
// We no longer need the surface
SDL_FreeSurface(bmp);
if (tex = nil) then
begin
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
Writeln('SDL_CreateTextureFromSurface Error: ', SDL_GetError);
SDL_Quit();
Exit(1);
end;
// A sleepy rendering loop, wait for 3 seconds and render and present the screen each time
for i := 0 to 2 do
begin
// First clear the renderer
SDL_RenderClear(ren);
// Draw the texture
SDL_RenderCopy(ren, tex, nil, nil);
// Update the screen
SDL_RenderPresent(ren);
// Take a quick break after all that hard work
SDL_Delay(1000);
end;
// Clean up our objects and quit
SDL_DestroyTexture(tex);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
end;
end.