
回复
游戏一般需要适配不同屏幕尺寸的设备,例如手机、折叠屏、平板等。
游戏通常使用XComponent组件自定义渲染,渲染流程如下图所示:
cke_1686.png
其中OnSurfaceCreated和OnSurfaceChanged两个接口可分别在surface创建和surface大小变化时进行回调,因此适配不同屏幕尺寸设备时,可重点关注这两个接口。
示例说明
下述代码中在OnSurfaceCreated和OnSurfaceChanged设置的显示画面的宽高都跟XComponent组件一致,且每次surface改变后都会重新获取对应的宽高及方向,以达到不同设备及设备显示区域变化的适配。
// OnSurfaceCreated回调
void PluginRender::OnSurfaceCreated(OH_NativeXComponent* component, void* window)
{
OHOS_LOGD("PluginRender::OnSurfaceCreated");
eglCore_ = new EGLCore();
// 获取XComponent组件宽高
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
// OnSurfaceCreated逻辑,通过EGL绘制window上需要显示的画面
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
eglCore_->GLContextInit(window, width_, height_);
// 设置XComponent组件宽高为显示画面宽高,并设置显示方向
native_manager::GetInstance()->onSurfaceCreated(width_, height_, Js_GameEngineHelper::getDisplayOrientation());
}
}
// OnSurfaceChanged回调
void PluginRender::OnSurfaceChanged(OH_NativeXComponent* component, void* window)
{
OHOS_LOGD("PluginRender::OnSurfaceChanged");
// 重新获取XComponent组件宽高
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
// OnSurfaceChanged逻辑
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
native_manager *instance = native_manager::GetInstance();
// 改变XComponent组件宽高为显示画面宽高,并设置显示方向
instance->onSurfaceChanged(width_, height_, Js_GameEngineHelper::getDisplayOrientation());
}
}
部分游戏存在需要适配安全区的情况,在沉浸式体验中内容规避区会做额外处理。下图中展示了竖屏、横屏、反向横屏三种不同情况下的安全区示意图。
cke_2967.png
示例代码
1. 获取安全区信息。
onWindowStageCreate(windowStage: window.WindowStage) {
try {
let windowClass:window.Window = windowStage.getMainWindowSync();
// 获取屏幕安全区域,系统默认区,顶部状态栏位置
let avoidArea: window.AvoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);
// 刘海屏区域 -- 一般为前置摄像头位置
// let avoidArea: window.AvoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_CUTOUT);
// 导航条区域 -- 一般为底部
// let avoidArea: window.AvoidArea = windowClass.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR);
GlobalContext.storeGlobalThis(GlobalContextConstants.AVOID_AREA, avoidArea);
// 省略部分代码
} catch (exception) {
console.error('Failed to get or set the window, cause ' + JSON.stringify(exception));
}
}
2. 计算可显示内容区域的top、bottom、left和right。
static getTop() :number{
let avoidArea: window.AvoidArea = GlobalContext.loadGlobalThis(GlobalContextConstants.AVOID_AREA);
let result:number = 0;
if (avoidArea != undefined && avoidArea.visible) {
let orientation = display.getDefaultDisplaySync().orientation;
if (orientation == display.Orientation.LANDSCAPE) {
// 横屏
result = avoidArea.leftRect.left + avoidArea.leftRect.width; // 0
} else if (orientation == display.Orientation.LANDSCAPE_INVERTED) {
// 反向横屏
result = avoidArea.rightRect.left + avoidArea.rightRect.width; // 0
} else {
// 竖屏
result = avoidArea.topRect.top + avoidArea.topRect.height;
}
} else {
console.log("Cannnot get TopSafeAreaPixel, avoidArea visible false");
}
return result;
}
static getBottom() {
let avoidArea: window.AvoidArea = GlobalContext.loadGlobalThis(GlobalContextConstants.AVOID_AREA)
if (avoidArea != undefined && avoidArea.visible) {
let orientation = display.getDefaultDisplaySync().orientation;
if (orientation == display.Orientation.LANDSCAPE) {
return avoidArea.rightRect.left;
} else if (orientation == display.Orientation.LANDSCAPE_INVERTED) {
return avoidArea.leftRect.left + avoidArea.leftRect.width;
} else {
return avoidArea.bottomRect.top;
}
} else {
console.error("Cannnot get BottomSafeAreaPixel");
return 0;
}
}
static getLeft() {
let avoidArea: window.AvoidArea = GlobalContext.loadGlobalThis(GlobalContextConstants.AVOID_AREA)
if (avoidArea != undefined && avoidArea.visible) {
let orientation = display.getDefaultDisplaySync().orientation;
if (orientation == display.Orientation.LANDSCAPE) {
return avoidArea.bottomRect.top;
} else if (orientation == display.Orientation.LANDSCAPE_INVERTED) {
return avoidArea.topRect.top + avoidArea.topRect.height
} else {
return avoidArea.leftRect.left + avoidArea.leftRect.width;
}
} else {
console.error("Cannnot get LeftSafeAreaPixel");
return 0;
}
}
static getRight() {
let avoidArea: window.AvoidArea = GlobalContext.loadGlobalThis(GlobalContextConstants.AVOID_AREA)
if (avoidArea != undefined && avoidArea.visible) {
let orientation = display.getDefaultDisplaySync().orientation;
if (orientation == display.Orientation.LANDSCAPE) {
return avoidArea.topRect.top + avoidArea.topRect.height
} else if (orientation == display.Orientation.LANDSCAPE_INVERTED) {
return avoidArea.bottomRect.top;
} else {
return avoidArea.rightRect.left;
}
} else {
console.error("Cannnot get RightSafeAreaPixel");
return 0;
}
}
更多问题可关注:
鸿蒙游戏官方网站:已有游戏移植-鸿蒙游戏-华为开发者联盟
公开课:华为开发者学堂