您的位置:首页 > 编程语言

3.SDL游戏开发:把代码写长一点(二)

2013-11-04 21:45 155 查看
看问题想本质,读USB驱动源码时,要读至thread_run才到精彩处,那么对于上层的应用来说,那种至高境界估计是到不了,但是还是接着把代码上面代码理解下,从整个代码来看,里面增加的SDL函数就只有两个, 一个是 SDL_DisplayFormat()另外一个 SDL_WM_SetCaption()这两个函数都很简单。

首先我们先找男人 #man SDL_DisplayFormat 结果如下:

#include "SDL.h"
SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);
DESCRIPTION
This  function  takes  a  surface and copies it to a new surface of the
pixel format and colors of the video  framebuffer,  suitable  for  fast
blitting onto the display surface. It calls SDL_ConvertSurface
If you want to take advantage of hardware colorkey or alpha blit accel-
eration, you should set the colorkey and  alpha  value  before  calling
this function.

If you want an alpha channel, see SDL_DisplayFormatAlpha.

使用SDL_DisplayFormat(),将读取的图片文件转换为适合显示的格式[引起的原因是显示不同],其英文好点看函数名就知道了。
SDL_WM_SetCaption设置窗口标题。
我们知道图片有很多种格式,但是SDL标准备只支持rBMP格式的,如果你不相信,回头把sdl02.cpp和sdl01.cpp对应的图片和代码修改,试试——,但是通过扩展就OK,其实这件事,我们早就做了,在安装SDL时就已经安装

yum install SDL-devel SDL_mixer-devel SDL_image-devel SDL_ttf-devel

其中SDL_mixer-devel SDL_ttf-devel SDL_image-devel就是扩展库 使用也很简单

g++ -o my my.cpp -lSDL -lSDL_mixer -lSDL_image -lSDL_ttf

当然要用这些文件还得包含相应的头文件,我们可以看下SDL目录下面的文件,

[root@localhost sdl]# ls /usr/include/SDL/
begin_code.h       SDL_endian.h    SDL_loadso.h    SDL_rwops.h
close_code.h       SDL_error.h     SDL_main.h      SDL_stdinc.h
SDL_active.h       SDL_events.h    SDL_mixer.h     SDL_syswm.h
SDL_audio.h        SDL_getenv.h    SDL_mouse.h     SDL_thread.h
SDL_byteorder.h    SDL.h           SDL_mutex.h     SDL_timer.h
SDL_cdrom.h        SDL_image.h     SDL_name.h      SDL_ttf.h
SDL_config.h       SDL_joystick.h  SDL_opengl.h    SDL_types.h
SDL_config-i386.h  SDL_keyboard.h  SDL_platform.h  SDL_version.h
SDL_cpuinfo.h      SDL_keysym.h    SDL_quit.h      SDL_video.h
[root@localhost sdl]#
擦亮你的眼睛,发现SDL_image.h SDL_mixer.h SDL_ttf.h没??
使用时#include "SDL/SDL_image.h" …… 关于更多SDL_image的文档的可以从这里得到。像之前用的SDL_Surface *SDL_LoadBMP(const char *file);函数就可以用IMG_Load代替。换成其它的图片试试。这里就不拿出来丢人现眼了。

接着把代码写长一点,接下我讲与键盘有关的事。

#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>

const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces
SDL_Surface *image = NULL;
SDL_Surface *screen = NULL;

//The event structure that will be used
SDL_Event event;  /* 注意  */

SDL_Surface *load_image( std::string filename )
{
SDL_Surface* loadedImage = NULL;

//The optimized image that will be used
SDL_Surface* optimizedImage = NULL;

//果断用上
loadedImage = IMG_Load( filename.c_str() );

//If the image loaded
if( loadedImage != NULL ){
//Create an optimized image
optimizedImage = SDL_DisplayFormat( loadedImage );

//Free the old image 如果不是很理解SDL_DisplayFormat()注意old说明使用函数时分配了新的内存空间
SDL_FreeSurface( loadedImage );
}

return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
//Temporary rectangle to hold the offsets
SDL_Rect offset;

//Get the offsets
offset.x = x;
offset.y = y;

//Blit the surface
SDL_BlitSurface( source, NULL, destination, &offset );
}

bool init()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ){
return false;
}

//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

//If there was an error in setting up the screen
if( screen == NULL ){
return false;
}

//Set the window caption
SDL_WM_SetCaption( "Event test", NULL );

//If everything initialized fine
return true;
}

bool load_files()
{
//Load the image
image = load_image( "x.png" );

//If there was an error in loading the image
if( image == NULL ){
return false;
}

//If everything loaded fine
return true;
}

void clean_up()
{
//Free the surface
SDL_FreeSurface( image );

//Quit SDL
SDL_Quit();
}

int main( int argc, char* args[] )
{
//Make sure the program waits for a quit
bool quit = false;

//初始化
if( init() == false ){
return 1;
}

//导入文件
if( load_files() == false ){
return 1;
}

//Apply the surface to the screen
apply_surface( 0, 0, image, screen );

//Update the screen
if( SDL_Flip( screen ) == -1 ){
return 1;
}

//While the user hasn't quit
while( quit == false ) {
//While there's an event to handle
while( SDL_PollEvent( &event ) ) {
//If the user has Xed out the window
if( event.type == SDL_QUIT ){
//退出程序
quit = true;
}
}
}

//Free the surface and quit SDL
clean_up();

return 0;
}

保存为sdl03.cpp 编译

g++ -o sdl03 sdl03.cpp -lSDL -lSDL_image

./sdl03

这个图就不上了,太easy,如果不-lSDL_image会出现什么情况呢!

g++ -o sdl03 sdl03.cpp -lSDL
程序会在编译的出现找不到函数的情况

[bluesky@localhost sdl]$ g++ -o sdl03 sdl03.cpp -lSDL
/tmp/ccAqStJv.o: In function `load_image(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
sdl03.cpp:(.text+0x23): undefined reference to `IMG_Load'
collect2: ld returned 1 exit status
[bluesky@localhost sdl]$
那现在来看代码。程序应该不难理解, 看到SDL_Event通过man SDL_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;

原来SDL_Event是一个共同体,不是每一件事都要寻根究底的,关于每一个字段意思可以到这里查看,关于Uint8 type:

typedef enum {
  SDL_NOEVENT = 0, /* 未使用 */
  SDL_ACTIVEEVENT, /* 应用程序失去焦点或得到焦点*/
  SDL_KEYDOWN, /* 按下某键 */
  SDL_KEYUP, /* 松开某键 */
  SDL_MOUSEMOTION, /* 鼠标移动 */
  SDL_MOUSEBUTTONDOWN, /* 鼠标键按下 */
  SDL_MOUSEBUTTONUP, /* 鼠标键松开 */
  SDL_JOYAXISMOTION, /*游戏杆事件 */
  SDL_JOYBALLMOTION, /*游戏杆事件*/
  SDL_JOYHATMOTION, /*游戏杆事件*/
  SDL_JOYBUTTONDOWN, /*游戏杆事件*/
  SDL_JOYBUTTONUP, /*游戏杆事件*/
  SDL_QUIT, /*离开 */
  SDL_SYSWMEVENT, /* 系统事件 */
  SDL_EVENT_RESERVEDA, /* 保留 */
  SDL_EVENT_RESERVEDB, /* 保留 */
  SDL_VIDEORESIZE, /* 用户改变视频模式 */
  SDL_VIDEOEXPOSE, /* 屏幕重画 */
  SDL_EVENT_RESERVED2, /* 保留*/
  SDL_EVENT_RESERVED3, /* 保留 */
  SDL_EVENT_RESERVED4, /* 保留 */
  SDL_EVENT_RESERVED5, /* 保留 */
  SDL_EVENT_RESERVED6, /* 保留*/
  SDL_EVENT_RESERVED7, /* 保留 */
  SDL_USEREVENT = 24, /* 用户自定义事件 */
  /* This last event is only for bounding internal arrays
  It is the number of bits in the event mask datatype -- Uint32
  */
  SDL_NUMEVENTS = 32
} SDL_EventType;

看到SDL_PollEvent()轮询事件[还有一个SDL_WaitEvent()],谈到这里会引出一个对于游戏开发很重的东西,那就是键盘、鼠标事件[还有一样是操作杆],当这里我前不想打算现在就深入下去,后面会有专门的篇幅来谈这件事。看到

while( SDL_PollEvent( &event ) ) {
//If the user has Xed out the window
if( event.type == SDL_QUIT ){

对比SDL_EventType可以得出退出的条件,运行程序,点击关闭按钮试试。再对之前的sdl02 sdl01发现有什么不同,但是我们按ESC键却无效。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  SDL 教程
相关文章推荐