移動的精靈,示例 SDL2 的圖片分割、鍵盤消息

這是一個移動的精靈,用到了SDL2 的圖片分割、鍵盤事件。ui

// 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;

    // 初始化:SDL二、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  百度吧找來的。spa

人物移動位置沒有進行合理性檢查,這須要對地圖進行分格定性。指針

相關文章
相關標籤/搜索