【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

发布了5 篇原创文章 · 获赞 4 · 访问量 1406

猜你喜欢

转载自blog.csdn.net/qq_37435157/article/details/104192234
SDL