SDL2 —— 键盘事件

2017-1-14 Plan C SDL2

www.kurukurumi.com原创,转载请注明出处。

E-mail:hubenchang0515@outlook.com

        http://wiki.libsdl.org/SDL_KeyboardEvent

        使用SDL_PollEvent函数来捕获事件,参数是存放事件相关数据的union指针。

#include <SDL_event.h>
int SDL_PollEvent(SDL_Event* event);
//有事件发生返回1,无事件发生返回0

        捕获一个事件:

SDL_Event e;
if(SDL_PollEvent(&e))
{
    SDL_Log("%s\n","Poll a event.");  //有事件发生
}
esle
{
    SDL_Log("%s\n","No event");       //没有事件发生
}


        SDL_Event是一个union类型的数据,它包含一个表示事件类型的变量type和各种事件的结构体,例如键盘事件的结构体是SDL_KeyboardEvent key。按键按下时type为SDL_KEYDOWN、松开时type为SDL_KEYUP。

typedef union SDL_Event
{
    Uint32 type;                    /**< Event type, shared with all events */
    SDL_CommonEvent common;         /**< Common event data */
    SDL_WindowEvent window;         /**< Window event data */
    SDL_KeyboardEvent key;          /**< Keyboard event data */
    SDL_TextEditingEvent edit;      /**< Text editing event data */
    SDL_TextInputEvent text;        /**< Text input event data */
    SDL_MouseMotionEvent motion;    /**< Mouse motion event data */
    SDL_MouseButtonEvent button;    /**< Mouse button event data */
    SDL_MouseWheelEvent wheel;      /**< Mouse wheel event data */
    SDL_JoyAxisEvent jaxis;         /**< Joystick axis event data */
    SDL_JoyBallEvent jball;         /**< Joystick ball event data */
    SDL_JoyHatEvent jhat;           /**< Joystick hat event data */
    SDL_JoyButtonEvent jbutton;     /**< Joystick button event data */
    SDL_JoyDeviceEvent jdevice;     /**< Joystick device change event data */
    SDL_ControllerAxisEvent caxis;      /**< Game Controller axis event data */
    SDL_ControllerButtonEvent cbutton;  /**< Game Controller button event data */
    SDL_ControllerDeviceEvent cdevice;  /**< Game Controller device event data */
    SDL_AudioDeviceEvent adevice;   /**< Audio device event data */
    SDL_QuitEvent quit;             /**< Quit request event data */
    SDL_UserEvent user;             /**< Custom event data */
    SDL_SysWMEvent syswm;           /**< System dependent window event data */
    SDL_TouchFingerEvent tfinger;   /**< Touch finger event data */
    SDL_MultiGestureEvent mgesture; /**< Gesture event data */
    SDL_DollarGestureEvent dgesture; /**< Gesture event data */
    SDL_DropEvent drop;             /**< Drag and drop event data */

    /* This is necessary for ABI compatibility between Visual C++ and GCC
       Visual C++ will respect the push pack pragma and use 52 bytes for
       this structure, and GCC will use the alignment of the largest datatype
       within the union, which is 8 bytes.

       So... we'll add padding to force the size to be 56 bytes for both.
    */
    Uint8 padding[56];
} SDL_Event;

        e.key.keysym.Scancode里保存了物理按键编码,e.key.keysym.sym里保存了虚拟按键编码,可以使用它们来进行按键检测:

SDL_Event e;
if(SDL_PollEvent(&e))
{
    switch(e.key.keysym.sym)   //虚拟按键编码
    {
        case SDLK_A: SDL_Log("A");break;
        case SDLK_B: SDL_Log("B");break;
        /* ... */
    }
}
else
{
    SDL_Log("%s\n","No event");//没有事件发生
}

        e.key.keysym.mod里保存了按键modifier,通过它可以判断是否同时按下了Shift、Ctrl、Alt等。

        http://wiki.libsdl.org/SDL_Keymod


        下面是一段完整的代码,通过方向键控制人物移动:

/*
Author : PlanC
E-mail : hubenchang0515@outlook.com
Blog   : www.kurukurumi.com
Date   : 2016-12-14
*/

#include <SDL2/SDL.h>

void move(SDL_Keycode direction,SDL_Rect* sel,SDL_Rect* pos);

int main(int argc,char* argv[])
{
    /* 初始化并创建窗口 */
    SDL_Init(SDL_INIT_EVERYTHING);
    SDL_Window* win = NULL;
    win = SDL_CreateWindow("SDL2",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,
                            640,400,SDL_WINDOW_RESIZABLE);
    
    /* 创建Renderer和Texture */
    SDL_Renderer* renderer = NULL;
    renderer = SDL_CreateRenderer(win,-1,SDL_RENDERER_ACCELERATED);
    SDL_Surface* mikubmp = SDL_LoadBMP("miku.bmp");
    SDL_Surface* bgbmp = SDL_LoadBMP("blackground.bmp");
    SDL_Texture* miku = SDL_CreateTextureFromSurface(renderer,mikubmp);
    SDL_Texture* bg = SDL_CreateTextureFromSurface(renderer,bgbmp);
    SDL_FreeSurface(mikubmp);
    SDL_FreeSurface(bgbmp);

    SDL_Rect selector = {0,0,32,48}; //切割角色图片
    SDL_Rect pos = {0,0,32,48};      //角色的位置

    /* 主循环 */
    SDL_Event e;
    while(1)
    {
        /* 清空 */
        SDL_RenderClear(renderer);
        /* 复制背景图片 */
        SDL_RenderCopy(renderer,bg,NULL,NULL);
        /* 复制角色图片 */
        SDL_RenderCopy(renderer,miku,&pos,&selector);
        /* 显示 */
        SDL_RenderPresent(renderer);
        
        if(0 == SDL_PollEvent(&e)) //捕获事件
        {
            continue;  //没有检测到事件,循环继续
        }
        else if(e.type == SDL_QUIT)
        {
            break; //检测到退出事件,退出
        }
        else if(e.type = SDL_KEYDOWN)
        {
            /* 检测到按键事件,移动 */
            move(e.key.keysym.sym,&pos,&selector);
            SDL_Delay(10);
        }
    }

    /* 销毁Texture */
    SDL_DestroyTexture(bg);
    SDL_DestroyTexture(miku);
    /* 销毁renderer */
    SDL_DestroyRenderer(renderer);
    /* 销毁窗口 */
    SDL_DestroyWindow(win);
    /* 关闭SDL子系统 */
    SDL_Quit();
	
    return 0;
}



void move(SDL_Keycode direction,SDL_Rect* sel,SDL_Rect* pos)
{
    static int step = 0;
    /* 每次移动2个像素,根据方向切割角色图 */
    switch(direction)
    {
        case SDLK_LEFT  : pos->x -= 2;sel->y=48;break;
        case SDLK_RIGHT : pos->x += 2;sel->y=48*2;break;
        case SDLK_UP    : pos->y -= 2;sel->y=48*3;break;
        case SDLK_DOWN  : pos->y += 2;sel->y=0;break;
        default: return;
    }
    step++;
    if(step >= 5)//每移动5次,切换一块角色图,让角色动起来
    {
        step = 0;
        if(sel->x >= 96)
            sel->x = 0;
        else
            sel->x += 32;
    }
	
}

发表评论:

Powered by emlog
鄂ICP备16003833号