这是一个移动的精灵,用到了SDL2 的图片分割、键盘事件。
// spirit.c
// SDL2 移动的精灵
//#define _DEBUG_
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
// 图片文件
// 文件名
char *ImageFileName[] =
{
"res/Town.jpg", // 背景图文件
"res/Fighter.png", // Player文件
"res/chick.png" // NPC文件
};
// 图形属性:x = 横向分几幅,y = 纵向分几幅,w = 宽度,h = 高度
SDL_Rect ImageInfo[] =
{
{1, 2, 640, 640},
{4, 4, 128, 192},
{4, 4, 128, 192}
};
// 图片的背景色
int BackColor = 0xFFFFFF;
// 字符串常量
char szWindowTitle[] = "SDL2 移动的精灵";
SDL_Texture *GetImageTexture(SDL_Renderer *pRenderer, char *FileName, _Bool bTransparent, int color);
void UpdateWindow(SDL_Window *pWindow, SDL_Renderer *pRenderer, SDL_Texture **pImageTexture,
int bx, int by, int px, int py, int nx, int ny, SDL_Rect *pd, SDL_Rect *nd);
#undef main
int main(int argc, char **argv)
{
int nWindowWidth = 640; // 屏幕尺寸
int nWindowHeight = 320;
SDL_Window *pWindow; // 主窗口
SDL_Renderer *pRenderer; // 主窗口渲染器
SDL_Texture *pImageTexture[3]; // 棋盘背景、黑白棋子图纹理
SDL_Event event; // 事件
_Bool bRun = 1; // 持续等待事件控制循环标识
// 背景、人物、NPC 的图幅坐标
int bx = 0, by = 0, px = 0, py = 0, nx = 0, ny = 0;
// 人物、NPC 的目标位置及大小
SDL_Rect pr = {300, 300, 32, 48}, nr = {380, 230, 16, 24};
// 移动速度
int speed = 10;
// 初始化:SDL2、SDL_Image(jpg)
if(SDL_Init(SDL_INIT_VIDEO) == -1 || IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG) == -1)
{
#ifdef _DEBUG_
fprintf(stderr, "1 %s", SDL_GetError());
#endif
return 1;
}
// 创建主窗口及其渲染器
if(SDL_CreateWindowAndRenderer(640, 480, SDL_WINDOW_SHOWN, &pWindow, &pRenderer) == -1)
{
#ifdef _DEBUG_
fprintf(stderr, "2 %s", SDL_GetError());
#endif
goto label_error;
}
SDL_SetWindowTitle(pWindow, szWindowTitle);
// 加载图片文件
if(NULL == (pImageTexture[0] = GetImageTexture(pRenderer, ImageFileName[0], 0, 0))
|| NULL == (pImageTexture[1] = GetImageTexture(pRenderer, ImageFileName[1], 1, BackColor))
|| NULL == (pImageTexture[2] = GetImageTexture(pRenderer, ImageFileName[2], 1, BackColor)))
{
#ifdef _DEBUG_
fprintf(stderr, "3 %s", IMG_GetError());
#endif
goto label_error;
}
// 等待事件
while(bRun && SDL_WaitEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN : // 键盘按键消息
switch(event.key.keysym.sym)
{
case SDLK_RIGHT :
py = 2;
px++;
pr.x = SDL_min(pr.x+speed, nWindowWidth-pr.w);
break;
case SDLK_LEFT :
py = 1;
px++;
pr.x = SDL_max(pr.x-speed, 0);
break;
case SDLK_DOWN :
py = 0;
px++;
pr.y = SDL_min(pr.y+speed, nWindowHeight-pr.h);
break;
case SDLK_UP :
py = 3;
px++;
pr.y = SDL_max(pr.y-speed, 0);
break;
default :
break;
}
px %= 4;
UpdateWindow(pWindow, pRenderer, pImageTexture, bx, by, px, py, nx, ny, &pr, &nr);
break;
case SDL_WINDOWEVENT : // 有窗口消息,重新计算窗口尺寸
SDL_GetWindowSize(pWindow, &nWindowWidth, &nWindowHeight);
UpdateWindow(pWindow, pRenderer, pImageTexture, bx, by, px, py, nx, ny, &pr, &nr);
break;
case SDL_QUIT :
bRun = 0;
break;
default :
break;
}
}
label_error:
// 清理
if(pImageTexture[0] != NULL) SDL_DestroyTexture(pImageTexture[0]);
if(pImageTexture[1] != NULL) SDL_DestroyTexture(pImageTexture[1]);
if(pImageTexture[2] != NULL) SDL_DestroyTexture(pImageTexture[2]);
IMG_Quit();
SDL_Quit();
return 0;
}
// 重绘窗口
void UpdateWindow(SDL_Window *pWindow, SDL_Renderer *pRenderer, SDL_Texture **pImageTexture,
int bx, int by, int px, int py, int nx, int ny, SDL_Rect *pr, SDL_Rect *nr)
{
SDL_Rect srt;
SDL_RenderClear(pRenderer);
srt.x = bx*ImageInfo[0].w/ImageInfo[0].x;
srt.y = by*ImageInfo[0].h/ImageInfo[0].y;
srt.w = ImageInfo[0].w/ImageInfo[0].x;
srt.h = ImageInfo[0].h/ImageInfo[0].y;
SDL_RenderCopy(pRenderer, pImageTexture[0], &srt, NULL);
srt.x = px*ImageInfo[1].w/ImageInfo[1].x;
srt.y = py*ImageInfo[1].h/ImageInfo[1].y;
srt.w = ImageInfo[1].w/ImageInfo[1].x;
srt.h = ImageInfo[1].h/ImageInfo[1].y;
SDL_RenderCopy(pRenderer, pImageTexture[1], &srt, pr);
srt.x = nx*ImageInfo[2].w/ImageInfo[2].x;
srt.y = ny*ImageInfo[2].h/ImageInfo[2].y;
srt.w = ImageInfo[2].w/ImageInfo[2].x;
srt.h = ImageInfo[2].h/ImageInfo[2].y;
SDL_RenderCopy(pRenderer, pImageTexture[2], &srt, nr);
SDL_RenderPresent(pRenderer);
}
// 取得图片文件纹理
// 参数:pRenderer = 渲染器;FileName = 图片文件名;bTransparent = 是否透明处理;color = 背景色
// 返回值:纹理指针
SDL_Texture *GetImageTexture(SDL_Renderer *pRenderer, char *FileName, _Bool bTransparent, int color)
{
SDL_Texture *pTexture;
SDL_Surface *pSurface;
if((pSurface = IMG_Load(FileName)) == NULL)
return NULL;
if(bTransparent)
SDL_SetColorKey(pSurface, 1, SDL_MapRGB(pSurface->format, color>>16, (color>>8)&0xFF, color&0xFF));
pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
SDL_FreeSurface(pSurface);
return pTexture;
}
图片是从 C4droid 百度吧找来的。
人物移动位置没有进行合理性检查,这需要对地图进行分格定性。