【SDL Android 01】

概要

SDL用途:

  • 窗口管理
  • 軟件(CPU)和硬件(GPU)渲染2D圖形
  • 輸入事件系統
  • 時間管理
  • 音頻處理
  • 文件IO和庫加載
  • 穿線
  • 用於3D圖形的OpenGL API

1、定義日誌打印宏

打印宏

	//頭文件
	#include<android/log.h>
	//定義了一個標籤,用於過濾
	#define TAGS "Test"
	//INFO
	#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAGS,__VA_ARGS__)
	//DEBUG
	#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAGS,__VA_ARGS__)
	//ERROR
	#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAGS,__VA_ARGS__)

用法就和printf一樣,前一個是格式化字符串,後一個是參數
eg:

	LOGI("Initialized!");
	LOGE("Error caused by SDL:%s",SDL_GetError());
	LOGI("This is a int number :%d",114514);
	LOGI("This is a string: %s","Hello World")
......

2、入口

SDL_main

不要奇怪爲什麼入口叫main,因爲在SDL_main.h定義如下

	#define main    SDL_main

必須帶上參數argc,argv

	//頭文件
	#include <SDL.h>
	//必須帶上參數
	int main(int argc,char** args)
	{
	    
	    return 0;
	}

3、初始化

SDL_Init()

定義

	int SDL_Init(Uint32 flags);

參數

flags 說明
SDL_INIT_TIMER 計時器子系統
SDL_INIT_AUDIO 音頻子系統
SDL_INIT_VIDEO 視頻子系統;自動初始化事件子系統
SDL_INIT_JOYSTICK 操作杆子系統;自動初始化事件子系統
SDL_INIT_HAPTIC 觸覺(力反饋)子系統
SDL_INIT_GAMECONTROLLER 控制器子系統;自動初始化操縱桿子系統
SDL_INIT_EVENTS 事件子系統
SDL_INIT_EVERYTHING 以上所有子系統
SDL_INIT_NOPARACHUTE 兼容性; 該標誌被忽略

如果要單獨初始化子系統,則可以先調用SDL_Init(0),然後再調用帶有所需子系統標誌的SDL_InitSubSystem()
返回值
成功返回0,失敗返回負錯誤代碼;調用SDL_GetError()以獲得更多信息。
一般情況下直接用SDL_INIT_EVERYTHING

SDL_Init(SDL_INIT_EVERYTHING);

4、創建一個窗口

創建一個與平臺無關的窗口
爲了管理窗口,SDL方便地提供結構SDL_WindowSDL_CreateWindow()等功能。
定義

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

參數

title 窗口名稱,utf8編碼
x 窗口x位置, SDL_WINDOWPOS_CENTERED(中央), 或者 SDL_WINDOWPOS_UNDEFINED
y 窗口y座標, SDL_WINDOWPOS_CENTERED, or SDL_WINDOWPOS_UNDEFINED
w 寬度
h 高度
flags 0, 或者一個或多個宏,具體看下面

flags

描述
SDL_WINDOW_FULLSCREEN fullscreen window
SDL_WINDOW_FULLSCREEN_DESKTOP fullscreen window at the current desktop resolution
SDL_WINDOW_OPENGL window usable with OpenGL context
SDL_WINDOW_VULKAN window usable with a Vulkan instance
SDL_WINDOW_HIDDEN window is not visible
SDL_WINDOW_BORDERLESS no window decoration
SDL_WINDOW_RESIZABLE window can be resized
SDL_WINDOW_MINIMIZED window is minimized
SDL_WINDOW_MAXIMIZED window is maximized
SDL_WINDOW_INPUT_GRABBED window has grabbed input focus
SDL_WINDOW_ALLOW_HIGHDPI window should be created in high-DPI mode if supported (>= SDL 2.0.1)

SDL_WINDOW_SHOWN被SDL_CreateWindow()忽略。如果未設置SDL_WINDOW_HIDDEN,則隱式顯示SDL_Window。稍後可以使用SDL_GetWindowFlags()查詢SDL_WINDOW_SHOWN
返回值
返回創建的窗口,如果失敗則返回NULL;否則返回NULL。調用SDL_GetError()以獲得更多信息。

4.1、獲取設備屏幕長寬參數

並且在安卓下,我們要創建一個匹配屏幕大小的窗口,所以需要調用SDL_GetDisplayBounds()獲取屏幕個數,
SDL_GetDisplayBounds()再根據每個屏幕的長寬。

由於一般的安卓手機只有一個屏幕
具體代碼如下(SDL_Rect是一個包含屏幕起始座標x,y和長寬w(width),h(height)的結構)

	//看看手機有幾個屏幕
	int nDisplays = SDL_GetNumVideoDisplays();
    SDL_Rect rectDisplay;
    //通常情況下,只有一個屏幕,無需判斷,屏幕id從0開始,故第一個參數爲0
    SDL_GetDisplayBounds(0,&rectDisplay);
    LOGD("number of displays:%d,width:%d,height%d",nDisplays,rectDisplay.w,rectDisplay.h);

這裏我們這樣創建窗口

	SDL_Window *window;
    window = SDL_CreateWindow("application",0,0,1440,2560,SDL_WINDOW_SHOWN);
    if(!window)
    {
        LOGE("Error Creating Window%s",SDL_GetError());
        return 1;
    }

5、表面

創建窗口後,您需要一種繪製方法。SDL將您可以繪製的任何區域(包括加載的圖像)抽象爲“表面”。(這是爲了CPU渲染 - 在未來,我們將進入GPU渲染,它不使用表面。)
結構SDL_Surface和諸如SDL_LoadBMP()SDL_GetWindowSurface()之類的函數提供軟件渲染(也稱爲blitting)API。

正如您所期望的那樣,使用SDL_GetWindowSurface()來獲取窗口的表面。繪製到此表面後,可以通過調用SDL_UpdateWindowSurface()在窗口中看到結果。

		SDL_Surface *winSurface = SDL_GetWindowSurface(window);
    if(!winSurface)
    {
        LOGE("Error Creating winSurface%s",SDL_GetError());
        return 1;
    }

6、繪製矩形

要測試窗口表面是否正常工作,可以用顏色填充它。
一個非常簡單的方法是使用SDL_FillRect()
要填充整個窗口,只需傳遞NULL(in c++11, use nullptr)而不是SDL_Rect指針。
此外,SDL_FillRect()採用表示顏色的特定格式編號。要獲得此格式的顏色,可以使用曲面格式和所需的RGB值調用SDL_MapRGB()

	SDL_FillRect(winSurface, nullptr,SDL_MapRGB(winSurface->format,255,90,120));

一切繪製工作完成後,使用上述的SDL_UpdateWindowSurface()在窗口中看到結果。

	SDL_UpdateWindowSurface(window);

7、退出

一旦程序完成其操作,它必須銷燬窗口並釋放相關資源。正如您所料,SDL_DestroyWindow()就是這麼做的。該功能將關閉窗口,釋放相關內存(包括窗口表面)。
爲了防止進入後過快關閉程序,使用SDL_Delay()進行延遲。

	SDL_Delay(3000);
	SDL_DestroyWindow(window);
	window = nullptr;
	winSurface = nullptr;

最後,關閉SDL作爲一個整體,請調用SDL_Quit()。這是非常明確的。

	SDL_Quit();

Extra 1、設置過濾器方便調試

在Android studio LogCat中的 右下角
在這裏插入圖片描述
然後
在這裏插入圖片描述
Log TAG與定義的宏TAG一致

完整代碼

#include <SDL.h>
#include <android/log.h>
#define TAGS "Test"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAGS,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAGS,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAGS,__VA_ARGS__)
using namespace std;
int main(int argc,char** args)
{
    //SDL初始化
    SDL_Init(SDL_INIT_EVERYTHING);
    LOGD("Initialized");
    SDL_Window *window;
    window = SDL_CreateWindow("application",0,0,1440,2560,SDL_WINDOW_SHOWN);
    if(!window)
    {
        LOGE("Error Creating Window%s",SDL_GetError());
        return 1;
    }
    SDL_Surface *winSurface = SDL_GetWindowSurface(window);
    if(!winSurface)
    {
        LOGE("Error Creating winSurface%s",SDL_GetError());
        return 1;
    }
    SDL_FillRect(winSurface, nullptr,SDL_MapRGB(winSurface->format,255,90,120));
    SDL_UpdateWindowSurface(window);
    SDL_Delay(3000);
    SDL_DestroyWindow(window);
    window = nullptr;
    winSurface = nullptr;
    SDL_Quit();
    return 0;
}

參考

CSDN博主「Dwyane05」
原文鏈接:https://blog.csdn.net/cyf15238622067/article/details/82905897

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章