很久以前,发表了几篇SDL在Windows编译的文章,同时也参考网上的一个十分简单的例子写了测试的程序,本文章将以此为基础并添加自己的代码。
回首第1篇关于SDL的文章,那已是去年12月份写的了,时间过得真快。
本文主要写一下在SDL中如何画像素点,以及如何显示字符(中文、英文)。
画像素点:
static void SDL_PixelNolock(SDL_Surface* surface, int x, int y, Uint32 color)
{
int bpp = surface->format->BytesPerPixel;
Uint8* p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch (bpp)
{
case 4:
*(Uint32 *)p = color;
break;
case 1:
*p = color;
break;
case 2:
*(Uint16 *)p = color;
break;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (color >> 16) & 0xff;
p[1] = (color >> 8) & 0xff;
p[2] = color & 0xff;
}
else
{
p[0] = color & 0xff;
p[1] = (color >> 8) & 0xff;
p[2] = (color >> 16) & 0xff;
}
break;
}
}
static void SDL_PixelColor(SDL_Surface* surface, int x, int y, Uint32 color)
{
if (SDL_MUSTLOCK(surface))
{
if (SDL_LockSurface(surface) < 0)
{
return;
}
}
SDL_PixelNolock(surface, x, y, color);
if (SDL_MUSTLOCK(surface))
{
SDL_UnlockSurface(surface);
}
}
void SDL_Pixel(SDL_Surface* surface, int x, int y, Uint32 color)
{
SDL_PixelColor(surface, x, y, color);
}
上面给的是大部分SDL资料中常用的函数。另外,tslib中也有相关的实现画像素的函数,可以参考笔者之前发布的文章。
为了兼容以前写的代码,只好将SDL有关的函数全部封装起来。事实上,只要给出画像素的函数,其它模块完全不用修改,因为它们都是与具体平台无关。在这里,主要是指画图函数以及字符显示函数。实际上使用的需要封装的函数如下:
// somebody must implement these functions
extern int graphic_init(void);
extern void pixel(int x, int y, uint32 color);
extern void myrefresh();
// if you are using color index to show color, do it
extern void init_color(uint32 palette[], int len);
主要涉及图像界面的初始化、画像素、刷新等等。
我们的重点不在SDL高深的用法,所以只需要进行必要的初始化,并按SDL的套路写函数即可。下面是初始化SDL的相关函数:
/
const int WINDOW_WIDTH = 480;
const int WINDOW_HEIGHT = 320;
const char* WINDOW_TITLE = "SDL Hello World -- by Late Lee";
SDL_Surface* g_screen = NULL;
int InitGraphic(SDL_Surface** screen)
{
const SDL_VideoInfo *info;
Uint8 video_bpp;
Uint32 videoflags;
// Initialize SDL
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
return 1;
}
atexit(SDL_Quit);
// Alpha blending doesn't work well at 8-bit color
info = SDL_GetVideoInfo();
if ( info->vfmt->BitsPerPixel > 8 )
{
video_bpp = info->vfmt->BitsPerPixel;
}
else
{
video_bpp = 16;
}
videoflags = SDL_SWSURFACE | SDL_DOUBLEBUF;
// Set 640x480 video mode
if ( (*screen=SDL_SetVideoMode(WINDOW_WIDTH,WINDOW_HEIGHT,video_bpp,videoflags)) == NULL ) {
fprintf(stderr, "Couldn't set %ix%i video mode: %s\n",640,480,SDL_GetError());
return 2;
}
SDL_WM_SetCaption(WINDOW_TITLE, 0);
return 0;
}
/
int sdl_init(void)
{
return InitGraphic(&g_screen);
}
void sdl_doit()
{
SDL_Event event;
int done = 0;
while (!done)
{
/* Slow down polling */
SDL_Delay(500);
/* Check for events */
while (SDL_PollEvent(&event))
{
switch (event.type)
{
//case SDL_KEYDOWN:
/* Any keypress quits the app... */
case SDL_QUIT:
done = 1;
break;
default:
break;
}
}
}
}
void sdl_exit()
{
SDL_Quit();
}
int graphic_init(void)
{
return InitGraphic(&g_screen);
}
void pixel(int x, int y, Uint32 color)
{
SDL_Pixel(g_screen, x, y, color);
}
void myrefresh()
{
SDL_Flip(g_screen);
}
代码很简单,SDL相关的操作就3个:初始化SDL,SDL事件处理,退出SDL。
测试代码如下:
int sdl_test()
{
sdl_init();
line(1, 1, 200, 200, 0xff0000);
rect(100, 20, 200, 100, 0x00ff00);
put_string_ascii(10, 200, "AbcD", 0x0000ff);
FILE* fp = fopen("HZK/HZK24K", "rb");
if (fp == NULL)
return -1;
put_font(fp, 10, 250, "引刀成一快 hello,不负少年头 world", 0xffffff);
sdl_doit();
sdl_exit();
return 0;
}
效果图如下图:
说明: