SDL库基础学习

初始化

int SDL_Init(Uint32 flags);
 * `flags` may be any of the following OR'd together:
 *
 * - `SDL_INIT_TIMER`: timer subsystem
 * - `SDL_INIT_AUDIO`: audio subsystem
 * - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events
 *   subsystem
 * - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the
 *   events subsystem
 * - `SDL_INIT_HAPTIC`: haptic (force feedback) subsystem
 * - `SDL_INIT_GAMECONTROLLER`: controller subsystem; automatically
 *   initializes the joystick subsystem
 * - `SDL_INIT_EVENTS`: events subsystem
 * - `SDL_INIT_EVERYTHING`: all of the above subsystems
 * - `SDL_INIT_NOPARACHUTE`: compatibility; this flag is ignored

退出

void SDL_Quit(void);

窗口创建与销毁

SDL_Window * SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags);
void SDL_DestroyWindow(SDL_Window * window);

延迟(阻塞)

void SDL_Delay(Uint32 ms);

事件

  事件检测

  int SDL_PollEvent(SDL_Event * event)

  事件类型 SDL_Event与SDL_EventType

typedef union SDL_Event
{
    Uint32 type;                            /**< Event type, shared with all events */
    SDL_CommonEvent common;                 /**< Common event data */
    SDL_DisplayEvent display;               /**< Display event data */
    SDL_WindowEvent window;                 /**< Window event data */
    SDL_KeyboardEvent key;                  /**< Keyboard event data */
    SDL_TextEditingEvent edit;              /**< Text editing event data */
    SDL_TextEditingExtEvent editExt;        /**< Extended 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_JoyBatteryEvent jbattery;           /**< Joystick battery 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_ControllerTouchpadEvent ctouchpad;  /**< Game Controller touchpad event data */
    SDL_ControllerSensorEvent csensor;      /**< Game Controller sensor event data */
    SDL_AudioDeviceEvent adevice;           /**< Audio device event data */
    SDL_SensorEvent sensor;                 /**< Sensor 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 (size of
       SDL_TextEditingEvent, the largest structure for 32-bit and 64-bit
       architectures) for this union, and GCC will use the alignment of the
       largest datatype within the union, which is 8 bytes on 64-bit
       architectures.

       So... we'll add padding to force the size to be 56 bytes for both.

       On architectures where pointers are 16 bytes, this needs rounding up to
       the next multiple of 16, 64, and on architectures where pointers are
       even larger the size of SDL_UserEvent will dominate as being 3 pointers.
    */
    Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)];
} SDL_Event;

typedef enum
{
    SDL_FIRSTEVENT     = 0,     /**< Unused (do not remove) */

    /* Application events */
    SDL_QUIT           = 0x100, /**< User-requested quit */

    /* These application events have special meaning on iOS, see README-ios.md for details */
    SDL_APP_TERMINATING,        /**< The application is being terminated by the OS
                                     Called on iOS in applicationWillTerminate()
                                     Called on Android in onDestroy()
                                */
    SDL_APP_LOWMEMORY,          /**< The application is low on memory, free memory if possible.
                                     Called on iOS in applicationDidReceiveMemoryWarning()
                                     Called on Android in onLowMemory()
                                */
    SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
                                     Called on iOS in applicationWillResignActive()
                                     Called on Android in onPause()
                                */
    SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
                                     Called on iOS in applicationDidEnterBackground()
                                     Called on Android in onPause()
                                */
    SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
                                     Called on iOS in applicationWillEnterForeground()
                                     Called on Android in onResume()
                                */
    SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive
                                     Called on iOS in applicationDidBecomeActive()
                                     Called on Android in onResume()
                                */

    SDL_LOCALECHANGED,  /**< The user's locale preferences have changed. */

    /* Display events */
    SDL_DISPLAYEVENT   = 0x150,  /**< Display state change */

    /* Window events */
    SDL_WINDOWEVENT    = 0x200, /**< Window state change */
    SDL_SYSWMEVENT,             /**< System specific event */

    /* Keyboard events */
    SDL_KEYDOWN        = 0x300, /**< Key pressed */
    SDL_KEYUP,                  /**< Key released */
    SDL_TEXTEDITING,            /**< Keyboard text editing (composition) */
    SDL_TEXTINPUT,              /**< Keyboard text input */
    SDL_KEYMAPCHANGED,          /**< Keymap changed due to a system event such as an
                                     input language or keyboard layout change.
                                */
    SDL_TEXTEDITING_EXT,       /**< Extended keyboard text editing (composition) */

    /* Mouse events */
    SDL_MOUSEMOTION    = 0x400, /**< Mouse moved */
    SDL_MOUSEBUTTONDOWN,        /**< Mouse button pressed */
    SDL_MOUSEBUTTONUP,          /**< Mouse button released */
    SDL_MOUSEWHEEL,             /**< Mouse wheel motion */

    /* Joystick events */
    SDL_JOYAXISMOTION  = 0x600, /**< Joystick axis motion */
    SDL_JOYBALLMOTION,          /**< Joystick trackball motion */
    SDL_JOYHATMOTION,           /**< Joystick hat position change */
    SDL_JOYBUTTONDOWN,          /**< Joystick button pressed */
    SDL_JOYBUTTONUP,            /**< Joystick button released */
    SDL_JOYDEVICEADDED,         /**< A new joystick has been inserted into the system */
    SDL_JOYDEVICEREMOVED,       /**< An opened joystick has been removed */
    SDL_JOYBATTERYUPDATED,      /**< Joystick battery level change */

    /* Game controller events */
    SDL_CONTROLLERAXISMOTION  = 0x650, /**< Game controller axis motion */
    SDL_CONTROLLERBUTTONDOWN,          /**< Game controller button pressed */
    SDL_CONTROLLERBUTTONUP,            /**< Game controller button released */
    SDL_CONTROLLERDEVICEADDED,         /**< A new Game controller has been inserted into the system */
    SDL_CONTROLLERDEVICEREMOVED,       /**< An opened Game controller has been removed */
    SDL_CONTROLLERDEVICEREMAPPED,      /**< The controller mapping was updated */
    SDL_CONTROLLERTOUCHPADDOWN,        /**< Game controller touchpad was touched */
    SDL_CONTROLLERTOUCHPADMOTION,      /**< Game controller touchpad finger was moved */
    SDL_CONTROLLERTOUCHPADUP,          /**< Game controller touchpad finger was lifted */
    SDL_CONTROLLERSENSORUPDATE,        /**< Game controller sensor was updated */
    SDL_CONTROLLERUPDATECOMPLETE_RESERVED_FOR_SDL3,
    SDL_CONTROLLERSTEAMHANDLEUPDATED,  /**< Game controller Steam handle has changed */

    /* Touch events */
    SDL_FINGERDOWN      = 0x700,
    SDL_FINGERUP,
    SDL_FINGERMOTION,

    /* Gesture events */
    SDL_DOLLARGESTURE   = 0x800,
    SDL_DOLLARRECORD,
    SDL_MULTIGESTURE,

    /* Clipboard events */
    SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard or primary selection changed */

    /* Drag and drop events */
    SDL_DROPFILE        = 0x1000, /**< The system requests a file open */
    SDL_DROPTEXT,                 /**< text/plain drag-and-drop event */
    SDL_DROPBEGIN,                /**< A new set of drops is beginning (NULL filename) */
    SDL_DROPCOMPLETE,             /**< Current set of drops is now complete (NULL filename) */

    /* Audio hotplug events */
    SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
    SDL_AUDIODEVICEREMOVED,        /**< An audio device has been removed. */

    /* Sensor events */
    SDL_SENSORUPDATE = 0x1200,     /**< A sensor was updated */

    /* Render events */
    SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
    SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */

    /* Internal events */
    SDL_POLLSENTINEL = 0x7F00, /**< Signals the end of an event poll cycle */

    /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
     *  and should be allocated with SDL_RegisterEvents()
     */
    SDL_USEREVENT    = 0x8000,

    /**
     *  This last event is only for bounding internal arrays
     */
    SDL_LASTEVENT    = 0xFFFF
} SDL_EventType;
事件类型结构

 

图形绘制

SDL_Surface * SDL_GetWindowSurface(SDL_Window * window);//获取与window关联的SDL_Surface指针。失败返回NULL
int SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color);//在指定的surface(dst)上绘制(填充)一个指定区域(rect)的矩形。
int SDL_UpdateWindowSurface(SDL_Window * window)//将Surface的数据更新到屏幕上,不要忘了
void SDL_FreeSurface(SDL_Surface * surface);//记得释放指针

图片导入

SDL_Surface *img_surf = SDL_LoadBMP("filepathOfBmp"); //导入bmp文件。如需操作更多格式的图片,需要SDL2_image库,同样需要注意surf指针的释放SDL_FreeSurface
SDL_BlitSurface(img_surf, NULL, surf, NULL); // 块移动,将图片Surface复制到窗口Surface上,NULL默认窗口Surface
 
#define SDL_BlitSurface SDL_UpperBlit

/**
 * Perform a fast blit from the source surface to the destination surface.
 *
 * SDL_UpperBlit() has been replaced by SDL_BlitSurface(), which is merely a
 * macro for this function with a less confusing name.
 * ...
 */
extern DECLSPEC int SDLCALL SDL_UpperBlit
    (SDL_Surface * src, const SDL_Rect * srcrect,
     SDL_Surface * dst, SDL_Rect * dstrect);
 

修改像素点值

    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
    if (NULL == win) {***}
  // 操作像素点
    // 1. 获取与窗口关联的Surface
    SDL_Surface *surf = SDL_GetWindowSurface(win);
    if (NULL == surf) {***}
    // 2. 修改像素点颜色值
    Uint32 *px = (Uint32 *)surf->pixels;
    px[20000] = 0xffffff; 

 渲染

SDL_Renderer * SDL_CreateRenderer(SDL_Window * window,int index, Uint32 flags);//给指定窗口创建一个2D渲染环境。
void SDL_DestroyRenderer(SDL_Renderer * renderer);//销毁渲染环境并释放关联的texture
int SDL_SetRenderDrawColor(SDL_Renderer * renderer,Uint8 r, Uint8 g, Uint8 b,Uint8 a);//设置绘制操作(绘制/填充矩形、线条、点以及清除屏幕)的颜色
int SDL_RenderClear(SDL_Renderer * renderer);//利用SDL_SetRenderDrawColor设置的颜色清除当前渲染目标。
void SDL_RenderPresent(SDL_Renderer * renderer);//将渲染操作的数据更新到屏幕上。

 

点与线

int SDL_RenderDrawPoint(SDL_Renderer * renderer,int x, int y);//根据提供的坐标在当前渲染目标上绘制一个点。
int SDL_RenderDrawPoints(SDL_Renderer * renderer,const SDL_Point * points,int count);//在当前渲染环境上绘制多个点。
int SDL_RenderDrawLine(SDL_Renderer * renderer,int x1, int y1, int x2, int y2);//根据提供的两个点的坐标在当前渲染环境上绘制一条线。
int SDLCALL SDL_RenderDrawLines(SDL_Renderer * renderer,const SDL_Point * points,int count);//沿着提供的多个点绘制线段。

矩形

int SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect);//在当前渲染目标上指定区域绘制一个矩形(边框)。
int SDL_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count);根据提供的区域数组在当前渲染目标上绘制多个矩形。
int SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect);//在当前渲染目标上指定区域填充一个矩形
int SDL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count);//根据提供的区域数组在当前渲染目标上填充多个矩形。
int SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer,SDL_BlendMode blendMode);// 为绘制操作设置颜色混合模式。
typedef enum
{
    SDL_BLENDMODE_NONE = 0x00000000,     // 默认模式。无混合,透明通道不生效
    SDL_BLENDMODE_BLEND = 0x00000001,    // Alpha通道混合,透明通道生效

    SDL_BLENDMODE_ADD = 0x00000002,      
    SDL_BLENDMODE_MOD = 0x00000004,     
    SDL_BLENDMODE_MUL = 0x00000008, 
    SDL_BLENDMODE_INVALID = 0x7FFFFFFF
} SDL_BlendMode;

 导入图片

DL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface);//由已存在的Surface创建Texture。
void SDL_DestroyTexture(SDL_Texture * texture);//记得销毁指针
int SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * dstrect);//从Texture中复制指定部分到渲染目标中。当源区域与指定区域大小不一致时,会进行相应缩放。srcrect:源区域,NULL表示整个区域 dstrect:目标区域,NULL表示整个区域
int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,  const SDL_Rect * srcrect, const SDL_Rect * dstrect, const double angle, const SDL_Point *center, const SDL_RendererFlip flip);
//angle:顺时针旋转角度, center:旋转中心点,为相对dstrect左上角的坐标。NULL表示围绕dstrect中心旋转,flip:翻转
typedef enum
{
    SDL_FLIP_NONE = 0x00000000,     // 不进行翻转
    SDL_FLIP_HORIZONTAL = 0x00000001,    // 进行水平镜像翻转
    SDL_FLIP_VERTICAL = 0x00000002     // 进行垂直镜像翻转
} SDL_RendererFlip;

#include <SDL.h>
#define W 1369
#define H 768

int main()
{
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
    {
        SDL_Log("Init failed: %s", SDL_GetError());
        return -1;
    }

    SDL_Window *win = SDL_CreateWindow("Hello", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        W, H, SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN);
    if (NULL == win)
    {
        SDL_Log("SDL_CreateWindow failed: %s", SDL_GetError());
        return -1;
    }

    // 创建渲染器与清屏
    SDL_Renderer *rdr  = SDL_CreateRenderer(win, -1, 0);
    if (NULL == rdr)
    {
        SDL_Log("SDL_CreateRenderer failed: %s", SDL_GetError());
        return -1;
    }
    // 设置渲染颜色
    SDL_SetRenderDrawColor(rdr, 0, 255, 0, 255);
    // 清除屏幕
    SDL_RenderClear(rdr);
    
    // 渲染图片
    // 1. 导入图片
    SDL_Surface *img_surf = SDL_LoadBMP("../SDL/img/1.bmp"); // 1296*864
    
    if (NULL == img_surf)
    {
        SDL_Log("SDL_LoadBMP failed: %s", SDL_GetError());
        return -1;
    }
    SDL_SetWindowSize(win, img_surf->w, img_surf->h);
    
    // 2. 创建Texture
    SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, img_surf);
    if (NULL == texture)
    {
        SDL_Log("SDL_CreateTextureFromSurface failed: %s", SDL_GetError());
        return -1;
    }

    SDL_Rect rect = {200, 200, 648, 432};
    SDL_Point pt = {0, 0};
    // 3. 复制Texture    
    //SDL_RenderCopy(rdr, texture, NULL, &rect);
    SDL_RenderCopyEx(rdr, texture, NULL, &rect, 90, NULL, SDL_FLIP_NONE);

    // 渲染呈现
    SDL_RenderPresent(rdr);

    SDL_Event event;
    while (true)
    {
        if (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
            {
                break;
            }
        }
    }
    
    // 5. 销毁Texture
    SDL_DestroyTexture(texture);
    SDL_FreeSurface(img_surf);
    SDL_DestroyRenderer(rdr);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}
 

事件

  事件类型参照SDL_EventType

  窗口事件SDL_WINDOWEVENT

  

/**
 *  \brief Window state change event data (event.window.*)
 */
typedef struct SDL_WindowEvent
{
    Uint32 type;        /**< ::SDL_WINDOWEVENT */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;    /**< The associated window */
    Uint8 event;        /**< ::SDL_WindowEventID */
    Uint8 padding1;
    Uint8 padding2;
    Uint8 padding3;
    Sint32 data1;       /**< event dependent data */
    Sint32 data2;       /**< event dependent data */
} SDL_WindowEvent;

/**
 *  \brief Event subtype for window events
 */
typedef enum
{
    SDL_WINDOWEVENT_NONE,           /**< Never used */
    SDL_WINDOWEVENT_SHOWN,          /**< Window has been shown */
    SDL_WINDOWEVENT_HIDDEN,         /**< Window has been hidden */
    SDL_WINDOWEVENT_EXPOSED,        /**< Window has been exposed and should be
                                         redrawn */
    SDL_WINDOWEVENT_MOVED,          /**< Window has been moved to data1, data2
                                     */
    SDL_WINDOWEVENT_RESIZED,        /**< Window has been resized to data1xdata2 */
    SDL_WINDOWEVENT_SIZE_CHANGED,   /**< The window size has changed, either as
                                         a result of an API call or through the
                                         system or user changing the window size. */
    SDL_WINDOWEVENT_MINIMIZED,      /**< Window has been minimized */
    SDL_WINDOWEVENT_MAXIMIZED,      /**< Window has been maximized */
    SDL_WINDOWEVENT_RESTORED,       /**< Window has been restored to normal size
                                         and position */
    SDL_WINDOWEVENT_ENTER,          /**< Window has gained mouse focus */
    SDL_WINDOWEVENT_LEAVE,          /**< Window has lost mouse focus */
    SDL_WINDOWEVENT_FOCUS_GAINED,   /**< Window has gained keyboard focus */
    SDL_WINDOWEVENT_FOCUS_LOST,     /**< Window has lost keyboard focus */
    SDL_WINDOWEVENT_CLOSE,          /**< The window manager requests that the window be closed */
    SDL_WINDOWEVENT_TAKE_FOCUS,     /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */
    SDL_WINDOWEVENT_HIT_TEST,       /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */
    SDL_WINDOWEVENT_ICCPROF_CHANGED,/**< The ICC profile of the window's display has changed. */
    SDL_WINDOWEVENT_DISPLAY_CHANGED /**< Window has been moved to display data1. */
} SDL_WindowEventID;
View Code

 

  鼠标事件:移动,按下,弹回,滚轮。SDL_MOUSEMOTION、SDL_MOUSEBUTTONDOWN、SDL_MOUSEBUTTONUP、SDL_MOUSEWHEEL

  关键成员of SDL_Event:

    SDL_MouseMotionEvent motion; /**< Mouse motion event data */
    SDL_MouseButtonEvent button; /**< Mouse button event data */
    SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */

/**
 *  \brief Mouse motion event structure (event.motion.*)
 */
typedef struct SDL_MouseMotionEvent
{
    Uint32 type;        /**< ::SDL_MOUSEMOTION */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;    /**< The window with mouse focus, if any */
    Uint32 which;       /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
    Uint32 state;       /**< The current button state */
    Sint32 x;           /**< X coordinate, relative to window */
    Sint32 y;           /**< Y coordinate, relative to window */
    Sint32 xrel;        /**< The relative motion in the X direction */
    Sint32 yrel;        /**< The relative motion in the Y direction */
} SDL_MouseMotionEvent;

/**
 *  \brief Mouse button event structure (event.button.*)
 */
typedef struct SDL_MouseButtonEvent
{
    Uint32 type;        /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;    /**< The window with mouse focus, if any */
    Uint32 which;       /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
    Uint8 button;       /**< The mouse button index */
    Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
    Uint8 clicks;       /**< 1 for single-click, 2 for double-click, etc. */
    Uint8 padding1;
    Sint32 x;           /**< X coordinate, relative to window */
    Sint32 y;           /**< Y coordinate, relative to window */
} SDL_MouseButtonEvent;

/**
 *  \brief Mouse wheel event structure (event.wheel.*)
 */
typedef struct SDL_MouseWheelEvent
{
    Uint32 type;        /**< ::SDL_MOUSEWHEEL */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;    /**< The window with mouse focus, if any */
    Uint32 which;       /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
    Sint32 x;           /**< The amount scrolled horizontally, positive to the right and negative to the left */
    Sint32 y;           /**< The amount scrolled vertically, positive away from the user and negative toward the user */
    Uint32 direction;   /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
    float preciseX;     /**< The amount scrolled horizontally, positive to the right and negative to the left, with float precision (added in 2.0.18) */
    float preciseY;     /**< The amount scrolled vertically, positive away from the user and negative toward the user, with float precision (added in 2.0.18) */
    Sint32 mouseX;      /**< X coordinate, relative to window (added in 2.26.0) */
    Sint32 mouseY;      /**< Y coordinate, relative to window (added in 2.26.0) */
} SDL_MouseWheelEvent;
View Code


  键盘事件:按键按下与回弹、文本编辑进行中、文本输入。SDL_KEYDOWN、SDL_KEYUP、SDL_TEXTEDITING、SDL_TEXTINPUT

    关键成员of SDL_Event:

      键盘按键 SDL_KeyboardEvent key;                  /**< Keyboard event data */

      文本编辑进行时 SDL_TextEditingEvent edit;     /**< Text editing event data */

      文本输入 SDL_TextInputEvent text;                 /**< Text input event data */

//用于定位键盘按键的scancode与sym
typedef struct SDL_Keysym
{
    SDL_Scancode scancode;      /**< SDL physical key code - see ::SDL_Scancode for details */
    SDL_Keycode sym;            /**< SDL virtual key code - see ::SDL_Keycode for details */
    Uint16 mod;                 /**< current key modifiers */
    Uint32 unused;
} SDL_Keysym;
typedef struct SDL_KeyboardEvent
{
    Uint32 type;        /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
    Uint32 timestamp;   /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;    /**< The window with keyboard focus, if any */
    Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
    Uint8 repeat;       /**< Non-zero if this is a key repeat */
    Uint8 padding2;
    Uint8 padding3;
    SDL_Keysym keysym;  /**< The key that was pressed or released */
} SDL_KeyboardEvent;

#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32)
/**
 *  \brief Keyboard text editing event structure (event.edit.*)
 */
typedef struct SDL_TextEditingEvent
{
    Uint32 type;                                /**< ::SDL_TEXTEDITING */
    Uint32 timestamp;                           /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;                            /**< The window with keyboard focus, if any */
    char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE];  /**< The editing text */
    Sint32 start;                               /**< The start cursor of selected editing text */
    Sint32 length;                              /**< The length of selected editing text */
} SDL_TextEditingEvent;

/**
 *  \brief Extended keyboard text editing event structure (event.editExt.*) when text would be
 *  truncated if stored in the text buffer SDL_TextEditingEvent
 */
typedef struct SDL_TextEditingExtEvent
{
    Uint32 type;                                /**< ::SDL_TEXTEDITING_EXT */
    Uint32 timestamp;                           /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;                            /**< The window with keyboard focus, if any */
    char* text;                                 /**< The editing text, which should be freed with SDL_free(), and will not be NULL */
    Sint32 start;                               /**< The start cursor of selected editing text */
    Sint32 length;                              /**< The length of selected editing text */
} SDL_TextEditingExtEvent;
/**
 *  \brief Keyboard text input event structure (event.text.*)
 */
typedef struct SDL_TextInputEvent
{
    Uint32 type;                              /**< ::SDL_TEXTINPUT */
    Uint32 timestamp;                         /**< In milliseconds, populated using SDL_GetTicks() */
    Uint32 windowID;                          /**< The window with keyboard focus, if any */
    char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];  /**< The input text */
} SDL_TextInputEvent;
View Code

  事件的简单用法

void event_loop()
{
    SDL_Event event;
    while (true)
    {
        while (SDL_PollEvent(&event))
        {
            switch (event.type)
            {
            case SDL_QUIT:
                return;
            case SDL_WINDOWEVENT:
                if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
                {
                    draw();//窗口改变重新作图
                }
                break;
            case SDL_MOUSEMOTION://鼠标操作
                // SDL_Log("x = %d, y = %d", event.motion.x, event.motion.y);
                // draw(event.motion.x,event.motion.y);作图函数可以获取鼠标的坐标
                break;
            case SDL_MOUSEBUTTONDOWN:
                //鼠标点击坐标,与点击次数(比如双击)
                SDL_Log("SDL_MOUSEBUTTONDOWN x = %d, y = %d, button = %d, clicks = %d", 
                    event.button.x, event.button.y, event.button.button, event.button.clicks);
                break;
            case SDL_MOUSEBUTTONUP:
                //同SDL_MOUSEBUTTONDOWN
                break;
            case SDL_KEYDOWN:
                if (event.key.keysym.sym == SDLK_UP/SDLK_DOWN/SDLK_LEFT/SDLK_RIGHT) //伪代码,请勿使用/来输入事件组合
                {operation();}
                break;
            case SDL_KEYUP:
                //同SDL_KEYDOWN
                break;
            case SDL_TEXTEDITING:
                SDL_Log("Edit %s", event.edit.text);
                break;
            case SDL_TEXTINPUT:
                SDL_Log("Input %s", event.text.text); 
                break;
            default:
                break;
            }
        }
    }
}
 

音频(WAV文件)

  导入WAV文件

/**
 *  Loads a WAV from a file.
 *  Compatibility convenience function.
 */
#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
    SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
/**
 * \param src The data source for the WAVE data
 * \param freesrc If non-zero, SDL will _always_ free the data source
 * \param spec An SDL_AudioSpec that will be filled in with the wave file's
 *             format details
 * \param audio_buf A pointer filled with the audio data, allocated by the
 *                  function.
 * \param audio_len A pointer filled with the length of the audio data buffer
 *                  in bytes
 * \returns This function, if successfully called, returns `spec`, which will
 *          be filled with the audio data format of the wave source data.
 *          `audio_buf` will be filled with a pointer to an allocated buffer
 *          containing the audio data, and `audio_len` is filled with the
 *          length of that audio buffer in bytes.
 *
 *          This function returns NULL if the .WAV file cannot be opened, uses
 *          an unknown data format, or is corrupt; call SDL_GetError() for
 *          more information.
 *
 *          When the application is done with the data returned in
 *          `audio_buf`, it should call SDL_FreeWAV() to dispose of it.
 */
extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
                                                      int freesrc,
                                                      SDL_AudioSpec * spec,
                                                      Uint8 ** audio_buf,
                                                      Uint32 * audio_len);

  定义播放回调函数

    audio_spec.userdata = (void *)"丫儿哟,c++好难学";
    audio_spec.callback = 你定义的函数名(函数指针);
/**
 *  This function is called when the audio device needs more data.
 *
 *  \param userdata An application-specific parameter saved in
 *                  the SDL_AudioSpec structure
 *  \param stream A pointer to the audio data buffer.
 *  \param len    The length of that buffer in bytes.
 *
 *  Once the callback returns, the buffer will no longer be valid.
 *  Stereo samples are stored in a LRLRLR ordering.
 *
 *  You can choose to avoid callbacks and use SDL_QueueAudio() instead, if
 *  you like. Just open your audio device with a NULL callback.
 */
typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
                                            int len);
  SDL_AudioSpec
typedef struct SDL_AudioSpec
{
    int freq;                   /**< DSP frequency -- samples per second */
    SDL_AudioFormat format;     /**< Audio data format */
    Uint8 channels;             /**< Number of channels: 1 mono, 2 stereo */
    Uint8 silence;              /**< Audio buffer silence value (calculated) */
    Uint16 samples;             /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
    Uint16 padding;             /**< Necessary for some compile environments */
    Uint32 size;                /**< Audio buffer size in bytes (calculated) */
    SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
    void *userdata;             /**< Userdata passed to callback (ignored for NULL callbacks). */
} SDL_AudioSpec;

  打开音频设备

    SDL_AudioDeviceID SDL_OpenAudioDevice(const char *device, int iscapture, const SDL_AudioSpec *desired, SDL_AudioSpec *obtained, int allowed_changes);

 * \param device a UTF-8 string -》设备名称,由SDL_GetAudioDeviceName获得,为NULL则请求能使用的默认设备
 * \param iscapture 是否是录音设备,0表示播放设备,非0表示录音设备
 * \param desired an SDL_AudioSpec structure -》期望输出格式; see SDL_OpenAudio() for more information
 * \param obtained an SDL_AudioSpec structure -》实际输出格式; see SDL_OpenAudio() for more information
 * \param allowed_changes 当硬件不支持时是否允许改变。通常为0
 * \returns a valid device ID that is > 0 on success or 0 on failure; call
 *          SDL_GetError() for more information.
 *
 *          For compatibility with SDL 1.2, this will never return 1, since
 *          SDL reserves that ID for the legacy SDL_OpenAudio() function.

  播放与暂停

    void SDL_PauseAudioDevice(SDL_AudioDeviceID dev, int pause_on);//dev: 由SDL_AudioDeviceID 打开的设备ID;pause_on: 暂停/播放,0为播放,非0为暂停。

  释放资源

    void SDL_FreeWAV(Uint8 * audio_buf); //释放SDL_LoadWAV导入的音频数据。

    void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev); //停止音频进程,关闭音频设备

  简单示例:
Uint8* audio_buf;
Uint32 audio_len;
Uint32 audio_pos = 0;
SDL_AudioDeviceID device_id;
void event_quit()
{
    while (1)
    {
        if (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
            {
                break;
            }

        }
    }
}

void callback(void* userdata, Uint8* stream, int len)//param stream A: pointer to the audio data buffer.
{
    int remain = audio_len - audio_pos;
    if (remain > len)
    {
        SDL_memcpy(stream, audio_buf + audio_pos, len);
        audio_pos += len;
    }
    else
    {
        SDL_memcpy(stream, audio_buf + audio_pos, remain);
        audio_pos = 0;
    }
}

void play_wav()
{
    SDL_AudioSpec audio_spec;

    // 1. 导入WAV文件
    SDL_LoadWAV("wav.wav", &audio_spec, &audio_buf, &audio_len); //wav.wav放在exe文件同级目录下

    // 2. 定义播放回调函数
    audio_spec.userdata = (void*)"丫儿哟,c++好难学";
    audio_spec.callback = callback;

    // 3. 打开音频设备
    device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, NULL, 0);

    // 4. 开始播放
    SDL_PauseAudioDevice(device_id, 0);

    event_quit();
    // 5. 释放资源 关闭设备
    SDL_CloseAudioDevice(device_id);
    SDL_FreeWAV(audio_buf);
}
int main()
{
    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
    play_wav();
    SDL_Quit();
    return 0;
}


动画帧率(复数图片周期展示)

  这里仅仅提供一种思路,关键是学习SDL_snprintf()和SDL_GetTicks64();

/**
 * Get the number of milliseconds since SDL library initialization.
 *
 * Note that you should not use the SDL_TICKS_PASSED macro with values
 * returned by this function, as that macro does clever math to compensate for
 * the 32-bit overflow every ~49 days that SDL_GetTicks() suffers from. 64-bit
 * values from this function can be safely compared directly.
 *
 * For example, if you want to wait 100 ms, you could do this:
 *
 * ```c
 * const Uint64 timeout = SDL_GetTicks64() + 100;
 * while (SDL_GetTicks64() < timeout) {
 *     // ... do work until timeout has elapsed
 * }
 * ```
 *
 * \returns an unsigned 64-bit value representing the number of milliseconds
 *          since the SDL library initialized.
 *
 * \since This function is available since SDL 2.0.18.
 */
extern DECLSPEC Uint64 SDLCALL SDL_GetTicks64(void);


    // 部分代码示例
    //规律的获取图片路径
    SDL_snprintf(file, 20, "img/%d.bmp", index++);

    SDL_Surface *surf = SDL_LoadBMP(file);
    SDL_Texture *texture = SDL_CreateTextureFromSurface(rdr, surf);
    SDL_RenderCopy(rdr, texture, NULL, NULL);

void event_loop()
{
    SDL_Event event;
    Uint64 start, end;
    int delay;
    while (true)
    {
        start = SDL_GetTicks64();
        while (SDL_PollEvent(&event))
        {
                switch (event.type)
                {
                    case SDL_QUIT:
                    return;
                    ...
                }
        }
        draw();
        end = SDL_GetTicks64();

        delay = FT - (end -start);//FT,周期,1000/帧率
        if (delay > 0)
        {
            SDL_Delay(delay);
        }
}            


其他库,如SDL_ttf库

  部分代码示例,主要是几个函数的使用举例,具体查看官方文档或者头文件说明。

TTF_Init();TTF_OpenFont(); TTF_RenderUTF8_Shaded(); TTF_CloseFont(font); TTF_Quit();
void draw_text()
{
    init();
    // 1. 初始化TTF
    if (TTF_Init() < 0)
    {
        SDL_Log("TTF_Init failed: %s", TTF_GetError());
        return;
    }

    // 2. 打开字体
    TTF_Font* font = TTF_OpenFont("C:\\Windows\\Fonts\\simkai.ttf", 72);
    if (!font)
    {
        SDL_Log("TTF_OpenFont failed: %s", TTF_GetError());
        return;
    }

    // 3. 渲染字体
    SDL_Surface* txt_surf = TTF_RenderUTF8_Shaded(font, "你好HELLO", {255, 255, 255}, {100, 0, 255, 255});
    if (!txt_surf)
    {
        SDL_Log("TTF_RenderText_Solid failed: %s", TTF_GetError());
        return;
    }

    // 4. 获取与窗口关联的Surface
    SDL_Surface* surf = SDL_GetWindowSurface(win);
    if (!surf)
    {
        SDL_Log("SDL_GetWindowSurface failed: %s", SDL_GetError());
        return;
    }

    // 5. 将字体Surface复制到窗口Surface上
    SDL_Rect rect = { 500, 300, txt_surf->w, txt_surf->h };
    SDL_BlitSurface(txt_surf, NULL, surf, &rect);

    // 6. 更新窗口
    SDL_UpdateWindowSurface(win);

    // 7. 释放与销毁资源
    SDL_FreeSurface(surf);
    SDL_FreeSurface(txt_surf);
    TTF_CloseFont(font);
    TTF_Quit();
}

 

补充几个数据结构:

/**
 * The structure that defines a point (integer)
 *
 * \sa SDL_EnclosePoints
 * \sa SDL_PointInRect
 */
typedef struct SDL_Point
{
    int x;
    int y;
} SDL_Point;

/**
 * A rectangle, with the origin at the upper left (integer).
 *
 * \sa SDL_RectEmpty
 * \sa SDL_RectEquals
 * \sa SDL_HasIntersection
 * \sa SDL_IntersectRect
 * \sa SDL_IntersectRectAndLine
 * \sa SDL_UnionRect
 * \sa SDL_EnclosePoints
 */
typedef struct SDL_Rect
{
    int x, y;
    int w, h;
} SDL_Rect;



参考:

感谢大佬简单直接的分享:https://gitee.com/unlimited13/cpp

详细内容参考官网文档或者源码头文件接口说明,新时代的程序员应该善用AI,当你有小规模需求却怀疑是否官方提供对应接口的时候,可以找AI提问。

官网:https://www.libsdl.org/

git:Simple Directmedia Layer · GitHub

vs2022运行配置:

 

 

posted @ 2024-05-03 19:37  W-cats  阅读(42)  评论(0编辑  收藏  举报