340 likes | 588 Views
《 弹球: SDL 入门 》. 本章授课内容. SDL 安装. 什么是 SDL. SDL 视频子系统. SDL 事件. Linux 的图形编程简介. 在 Linux 图形编程中,基于控制台的图形库主要有: SVGALib : 是最早基于 Linux 的非 X 的图形支持库。 FrameBuffer :出现在 Linux 2.2.x 内核当中的一种驱动程序接口。 GGI :新一代的图形支持库。可在 FrameBuffer, SVGALib 等设备上运行。在所有平台上提供了一致的输入设备接口 , 采用共享库机制 , 实现低层支持库的动态装载等 。
E N D
本章授课内容 SDL安装 什么是SDL SDL视频子系统 SDL事件 版权所有,复制注明出处
Linux的图形编程简介 在Linux 图形编程中,基于控制台的图形库主要有: • SVGALib: 是最早基于Linux的非X的图形支持库。 • FrameBuffer:出现在Linux 2.2.x内核当中的一种驱动程序接口。 • GGI:新一代的图形支持库。可在 FrameBuffer, SVGALib等设备上运行。在所有平台上提供了一致的输入设备接口, 采用共享库机制, 实现低层支持库的动态装载等 。 • OpenGL: 是个专业的3D程序接口,功能强大,调用方便的底层3D图形库。 • SDL:是一个跨平台的多媒体游戏支持库,包含了对图形、声音、游戏杆、线程等的支持。
SDL的安装 • 安装顺序:SDL-1.2.14SDL_image-1.2.8freetype-2.3.11SDL_ttf-2.0.9libmad-0.15.1blibid3tag-0.15.1bSDL_mixer-1.2.9 • 运行SDL的install.sh
本章授课内容 SDL安装 什么是SDL SDL视频子系统 SDL事件 版权所有,复制注明出处
什么是SDL • Simple DirectMedia Layer库,简称 SDL,它是一个跨平台的多媒体库,以用于直接控制底层的多媒体硬件的接口。这些多媒体功能包括了音频、键盘和鼠标(事件)、游戏摇杆等。当然,最为重要的是提供了2D图形帧缓冲(framebuffer)的接口,以及为OpenGL与各种操作系统之间提供了统一的标准接口以实现3D图形。 • 支持平台Linux、Win32 和 BeOS。 • SDL在GNU LGPL version 2下发布,这意味着你可以免费的使用。并且可以免费的用于商业软件的制作。 • 官方网站: http://www.libsdl.org • 常用SDL网站:http://lazyfoo.net/SDL_tutorials/index.php 版权所有,复制注明出处
使用SDL库需要包含头文件:#include "SDL.h" • 编译命令为:gcc –I/usr/include/SDL –lSDL 源程序名 –o 目标文件名 -lpthread • 如果程序中使用了图像库和混音库,在编译的时候还需要加上相应的编译参数,分别是-lSDL_image和-lSDL_mixer。
SDL的组成 最经常使用的子系统 版权所有,复制注明出处
SDL常用的数据类型 • 整型 版权所有,复制注明出处
(x, y) h w SDL常用的数据类型 • SDL_Rect(矩形) typedef struct{ Sint16 x, y; // 左上角坐标 Uint16 w, h; // 宽度和高度,以像素为单位 } SDL_Rect; 版权所有,复制注明出处
初始化SDL • 要使用SDL图形库,必须调用SDL_Init()来初始化SDL子系统之后,才能调用其他的 SDL 函数。 • 原型 int SDL_Init (Uint32 flags); • 参数:flags 用来指定想要初始化的子系统。我们可以代入前页列出的子系统常量名称或它们的位或组合来初始化多个子系统,譬如: • SDL_Init(SDL_INIT_VIDEO); • SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); • 返回值:如果初始化成功,函数返回 0,否则返回 -1 版权所有,复制注明出处
结束SDL • 你应该在结束程序之前调用SDL_Quit函数来关闭SDL 所有的子系统并释放它们所占用的资源。 • void SDL_Quit (void); 版权所有,复制注明出处
示例 #include <SDL/SDL.h> /* 使用SDL必须加载该文件*/ #include <stdio.h> int main(int argc,char *argv[]) //主函数头必须这样写 { printf("Initializing SDL.\n"); /*初始化视频和音频子系统*/ if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) { exit(-1); } printf("SDL initialized.\n"); printf("Quiting SDL.\n"); SDL_Quit();//关闭SDL各个子系统 printf("Quiting....\n"); return 0; } 版权所有,复制注明出处
本章授课内容 SDL安装 什么是SDL SDL视频子系统 SDL事件 版权所有,复制注明出处
SDL视频子系统 • 在SDL初始化之后要做的第一件事情就是设定SDL视频模式,或者说建立SDL的窗口,只有建立窗口才能显示图片,制作动画。 • 要进行图形操作,必须使用SDL的绘图系统,其中有一个很重要的概念就是surface的概念,也可以称之为绘图表面。 • 游戏中最经常使用的就是加载图片,然后对图片进行其他操作,这就涉及到图像的加载、显示。 版权所有,复制注明出处
建立SDL窗口 • SDL_Surface *SDL_SetVideoMode (int width,int height,int bpp,Uint32 flags); • 功能 建立一个指定宽、高和位数的显示模式(窗口) • 参数: • width、height屏幕的宽度和高度 • 如果像素位数为0,SDL会为你自动选择最合适的位数 • flags是一个标记位 • 返回值 • 成功返回一个荧屏绘图表面的指针,失败返回NULL。 版权所有,复制注明出处
标志位的可用选项 • SDL_SWSURFACE • 在系统内存中创建surface • SDL_HWSURFACE • 在显存中创建surface • SDL_DOUBLEBUF * • 允许硬件双缓冲。只有和SDL_HWSURFACE一起使用才有效。调用SDL_Flip来翻转(flip)缓冲并刷新屏幕。所有的绘图不会立即显示在屏幕上。如果不允许双缓冲的话,SDL_Flip函数相当于对整个屏幕调用SDL_UpdateRect。 • SDL_FULLSCREEN * • SDL会尝试使用全屏模式。如果硬件不支持当前的分辨率的话,会使用一个更高的分辨率和黑色的背景。 版权所有,复制注明出处
SDL_RESIZABLE * • 创建可缩放的窗口。当缩放的时候,会产生SDL_VIDEORESIZE事件,此时可通过SDL_SetVideoMode再次改变屏幕surface大小。 • SDL_NOFRAME * • 如果可行的话,SDL会创建无框架无标题栏的窗口。全屏模式自动包含此选项。 版权所有,复制注明出处
这时,会出现一个长宽各600的一个框框,里面什么都没有,以后图片都贴在它上面这时,会出现一个长宽各600的一个框框,里面什么都没有,以后图片都贴在它上面 #include <SDL/SDL.h> /* 使用SDL必须加载该文件*/ #include <stdio.h> SDL_Surface *gpScreen; //屏幕绘图表面 int main(int argc,char *argv[]) //主函数头必须这样写 { if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) { exit(-1); } gpScreen = SDL_SetVideoMode(600,600, 0, SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF ); if( NULL == gpScreen ) { SDL_Quit(); return -1; } SDL_FreeSurface(gpScreen);//退出程序前必须释放 SDL_Quit();//关闭SDL各个子系统 printf("Quiting....\n"); return 0; } 版权所有,复制注明出处
读写图像文件 • 需要加载SDL_image图像库,头文件为: • #include <sdl\sdl_image.h> • 把图像文件存入指定的绘图表面 • SDL_Surface *IMG_Load (const char *file); • 用指定的绘图表面产生一个与荧屏像素格式相同的新绘图表面,然后传回该新绘图表面。 • SDL_Surface *SDL_DisplayFormat (SDL_Surface *surface); 使用SDL_FreeSurface (SDL_Surface *surface)函数来释放绘图表面的指针 版权所有,复制注明出处
//此函数用于从硬盘加载指定文件名字的图像文件,aFilename为文件名字//此函数用于从硬盘加载指定文件名字的图像文件,aFilename为文件名字 SDL_Surface *loadImage(char *aFilename) { SDL_Surface* loadedImage = NULL; SDL_Surface* optimizedImage = NULL;//临时绘图表面 //Load the image using SDL_image loadedImage = IMG_Load( aFilename);//sdl图像载入函数 if( loadedImage != NULL )//If the image loaded { //将图像格式转换成屏幕格式 optimizedImage = SDL_DisplayFormat( loadedImage ); SDL_FreeSurface( loadedImage );//Free the old image } return optimizedImage;//返回图像文件的绘图表面的指针 } 版权所有,复制注明出处
显示图像 • 用loadImage加载图像文件后,并不能显示到屏幕,要想将图像显示到屏幕,必须将加载图像所产生的绘图表面复制到屏幕绘图表面上,所使用的函数是SDL_BlitSurface,然后调用SDL_Flip函数或SDL_UpdateRect函数刷新屏幕。 版权所有,复制注明出处
位块传输Blit • Blit是bit block transfer的缩写 • 把绘图表面中的一块矩形像素值复制到另一绘图表面指定的位置。 源绘图表面 (source surface) 目标绘图表面 (destination surface) 版权所有,复制注明出处
SDL_BlitSurface 本游戏中的srcret为空 • 函数原型 • 如果srcrect为空指针,意味着整个源surface将被blit;如果dstrect为空指针,意味着源surface与目的surface的左上角重合(坐标(0,0))。 • 如果只显示源绘图表面一部分,则srcrect不能为空,要指定源绘图表面在目标绘图表面的显示位置,则dstrect不能省略。 • int SDL_BlitSurface ( • SDL_Surface *src, // 源绘图表面 • SDL_Rect *srcrect, // 源矩形 • SDL_Surface *dst, // 目标绘图表面 • SDL_Rect *dstrect // 目标矩形左上角 • ); 版权所有,复制注明出处
刷新屏幕 • int SDL_Flip(SDL_Surface *screen); • 刷新整个荧屏绘图表面到屏幕上 • screen 得自 SDL_SetVideoMode() 或SDL_GetVideoSurface() 的返回值 • 成功返回0,失败返回-1 • void SDL_UpdateRect (SDL_Surface *screen,Sint32 x, Sint32 y,Sint32 w, Sint32 h); • 刷新由x, y, w, h指定的矩形范围内荧屏绘图表面到屏幕上。 SDL_UpdateRects (SDL_Surface *screen, int numrects, SDL_Rect *rects); 版权所有,复制注明出处
本章授课内容 SDL安装 什么是SDL SDL视频子系统 SDL事件 版权所有,复制注明出处
事件 • 事件可由使用者的操作而产生,如鼠标的移动、鼠标按键、键盘按键等等操作,也可由硬件产生,如主板上的时钟脉冲(clock),或由软件(操作系统或程序本身)产生。操作系统中,有一称之为消息队列(message queue)的数据结构,用来存储事件的信息。操作系统会负责把这些信息送到适当的窗口应用程序来处理,如下一页的图片所示。 版权所有,复制注明出处
msg 1 msg 2 msg n • SDL_Event event; • bool quit = false; • // enter the event loop • while (!quit) • { • while (SDL_PollEvent(&event)) • { • switch(event.type) • { • case SDL_QUIT: • bQuit = true; • break; • case SDL_KEYDOWN: • // Handle a KEYDOWN event • break; • . • . • default: • // Report an unhandled event • } • } • } 版权所有,复制注明出处
事件结构 typedef union SDL_Event { Uint8 type; //消息类型 SDL_ActiveEvent active; //窗口焦点、输入焦点及 鼠标焦点的失去和得到消息 SDL_KeyboardEvent key; //键盘消息,键盘按下和释放 SDL_MouseMotionEvent motion; //鼠标移动消息 SDL_MouseButtonEvent button; //鼠标按键消息 SDL_JoyAxisEvent jaxis; //手柄消息 SDL_JoyBallEvent jball; //手柄消息 SDL_JoyHatEvent jhat; //手柄消息 SDL_JoyButtonEvent jbutton; //手柄消息 SDL_ResizeEvent resize; //窗口大小变化事件 SDL_ExposeEvent expose; //窗口重绘消息 SDL_QuitEvent quit; //退出消息 SDL_UserEvent user; //用户自定义事件 SDL_SysWMEvent syswm; //平台相关的系统消息 } SDL_Event; 版权所有,复制注明出处
事件检测 • int SDL_PollEvent(SDL_Event *event); • 功能:从事件队列中取得事件的信息,保存到event中 • 参数:event用来保存捕获的事件 • 返回值:没有捕获任何事件,函数返回0;否则返回1 • 捕获到事件后,我们可以根据其type 的值来分辨事件的类別,然后再依据类别来取出事件的详细信息。 版权所有,复制注明出处
事件检测代码 • SDL_Event event; /* Event structure */ • /* Check for events */ • while (SDL_PollEvent(&event)) • { // Loop until there are no events left on the queue • switch (event.type) • { // Process the appropiate event type • case SDL_KEYDOWN: • // Handle a KEYDOWN event • break; • case SDL_MOUSEMOTION: …… • case SDL_KEYUP: • if (event.key.keysym.sym == SDLK_F2) • . • default: • // Report an unhandled event • } • } 版权所有,复制注明出处
鼠标事件 • 鼠标按钮事件 • SDL_MOUSEBUTTONDOWN • SDL_MOUSEBUTTONUP • 键盘事件 • SDL_KEYDOWN • SDL_KEYUP event.type 事件类型 event.button.button 值:SDL_BUTTON_LEFT event.type 事件类型:event.key.keysym.sym 值:SDLK_0 ---- SDLK_9, SDLK_BACKSPACE, SDLK_F2,…… 版权所有,复制注明出处
while (SDL_PollEvent(&event)) • { • switch(event.type) • { • case SDL_MOUSEBUTTONDOWN: • swith (event.button.button) • { • case SDL_BUTTON_LEFT: /* 左按鈕 */ break; • case SDL_BUTTON_RIGHT: /* 右按鈕 */ break; • } • break; • case SDL_KEYDOWN: • swith(key.keysym.sym) • case: SDLK_F2 …… • break; • } • } 版权所有,复制注明出处