游戏场景和 UI 的屏幕自适应
在游戏开发中,屏幕自适应是一项至关重要的功能。无论玩家使用何种设备或窗口尺寸,都希望能获得最佳的视觉体验。本教程将带您一步步了解如何在 Dora SSR 引擎中实现游戏场景和游戏 UI 的屏幕自适应。
1. 理解屏幕自适应
在不同设备上,屏幕尺寸和分辨率各不相同。如果不进行自适应处理,游戏可能会在某些设备上显示不完整,或者元素位置错乱。屏幕自适应的目标是确保游戏内容在各种屏幕上都能正确显示,并保持良好的 用户体验。
2. 实现游戏场景的自适应
游戏场景的自适应主要涉及根据窗口尺寸调整摄像机的视野,以确保场景内容完整地显示在屏幕中。
2.1 定义设计尺寸
首先,定义游戏的设计尺寸。这是您在设计和开发过程中所基于的参考尺寸。
- Lua
- Teal
- TypeScript
- YueScript
local DesignSceneHeight <const> = 1024
local DesignSceneHeight <const> = 1024
const DesignSceneHeight = 1024;
const DesignSceneHeight = 1024
在这里,我们将设计高度设为 1024
。这意味着我们以高度为 1024
的尺寸进行场景设计。并希望游戏在做自适应时,会确保纵向的场景区域得到完整展示,横向超出屏幕区域的场景会被裁减,或是因为小于屏幕区域而被居中展示。
2.2 调整摄像机缩放
接下来,需要根据当前窗口的实际尺寸,调整摄像机的缩放比例。
- Lua
- Teal
- TypeScript
- YueScript
local Director <const> = require("Director")
local View <const> = require("View")
local function updateViewSize()
Director.currentCamera.zoom = View.size.height / DesignSceneHeight
end
local Director <const> = require("Director")
local type Camera2D = require("Camera2D")
local View <const> = require("View")
local function updateViewSize()
local camera = Director.currentCamera as Camera2D.Type
camera.zoom = View.size.height / DesignSceneHeight
end
import { Director, View, TypeName, tolua } from 'Dora';
const updateViewSize = () => {
const camera = tolua.cast(Director.currentCamera, TypeName.Camera2D);
if (camera) {
camera.zoom = View.size.height / DesignSceneHeight;
}
};
_ENV = Dora
updateViewSize = ->
Director.currentCamera.zoom = View.size.height / DesignSceneHeight
说明:
Director.currentCamera
:当前场景的摄像机对象。zoom
:摄像机的缩放属性,影响视野范围。View.size.height
:当前窗口的实际高度。- 通过计算
View.size.height / DesignSceneHeight
,我们得到实际高度与设计高度的比例,然后将其设置为摄像机的缩放值。
2.3 监听窗口尺寸变化
为了在窗口尺寸发生变化时(例如用户调整窗口大小或设备旋转)及时更新摄像机缩放,需要监听应用的尺寸变化事件。
- Lua
- Teal
- TypeScript
- YueScript
updateViewSize() -- 初始化时调用一次
Director.entry:onAppChange(function(settingName)
if settingName == "Size" then
updateViewSize() -- 每次触发尺寸变化时更新
end
end)
updateViewSize() -- 初始化时调用一次
Director.entry:onAppChange(function(settingName: string)
if settingName == "Size" then
updateViewSize() -- 每次触发尺寸变化时更新
end
end)
updateViewSize(); // 初始化时调用一次
Director.entry.onAppChange(settingName => {
if (settingName === 'Size') {
updateViewSize(); // 每次触发尺寸变化时更新
}
});
updateViewSize! -- 初始化时调用一次
Director.entry\onAppChange (settingName) ->
if settingName == "Size"
updateViewSize! -- 每次触发尺寸变 化时更新
说明:
Director.entry:onAppChange
:注册一个监听器,当应用的设置发生变化时被触发。settingName
:表示发生变化的设置项名称。- 当
settingName
为"Size"
时,表示窗口尺寸发生了变化,此时调用updateViewSize()
更新摄像机缩放。
2.4 完整代码
- Lua
- Teal
- TypeScript
- YueScript
-- 自适应游戏场景示例
-- 导入模块
local DrawNode <const> = require("DrawNode")
local Director <const> = require("Director")
local View <const> = require("View")
local Vec2 <const> = require("Vec2")
-- 定义设计尺寸
local DesignSceneHeight <const> = 1024
-- 创建场景
local node = DrawNode()
node:drawDot(Vec2.zero, DesignSceneHeight / 2)
node:addTo(Director.entry)
-- 处理窗口尺寸变化
local function updateViewSize()
Director.currentCamera.zoom = View.size.height / DesignSceneHeight
end
updateViewSize()
-- 注册窗口尺寸变化的事件回调
Director.entry:onAppChange(function(settingName)
if settingName == "Size" then
updateViewSize()
end
end)
-- 自适应游戏场景示例
-- 导入模块
local DrawNode <const> = require("DrawNode")
local Director <const> = require("Director")
local View <const> = require("View")
local Vec2 <const> = require("Vec2")
local type Camera2D = require("Camera2D")
-- 定义设计尺寸
local DesignSceneHeight <const> = 1024
-- 创建场景
local node = DrawNode()
node:drawDot(Vec2.zero, DesignSceneHeight / 2)
node:addTo(Director.entry)
-- 处理窗口尺寸变化
local function updateViewSize()
local camera = Director.currentCamera as Camera2D.Type
camera.zoom = View.size.height / DesignSceneHeight
end
updateViewSize()
-- 注册窗口尺寸变化的事件回调
Director.entry:onAppChange(function(settingName: string)
if settingName == "Size" then
updateViewSize()
end
end)
// 自适应游戏场景示例
// 导入模块
import { DrawNode, Director, View, Vec2, TypeName } from 'Dora';
// 定义设计尺寸
const DesignSceneHeight = 1024;
// 创建场景
const node = DrawNode();
node.drawDot(Vec2.zero, DesignSceneHeight / 2);
node.addTo(Director.entry);
// 处理窗口尺寸变化
const updateViewSize = () => {
const camera = tolua.cast(Director.currentCamera, TypeName.Camera2D);
if (camera) {
camera.zoom = View.size.height / DesignSceneHeight;
}
};
updateViewSize();
// 注册窗口尺寸变化的事件回调
Director.entry.onAppChange(settingName => {
if (settingName === 'Size') {
updateViewSize();
}
});
-- 自适应游戏场景示例
-- 导入模块
_ENV = Dora
-- 定义设计尺寸
const DesignSceneHeight = 1024
-- 创建场景
const node = DrawNode!
node.drawDot Vec2.zero, DesignSceneHeight / 2
node.addTo Director.entry
-- 处理窗口尺寸变化
updateViewSize! -- 初始化时调用一次
Director.entry\onAppChange (settingName) ->
if settingName == "Size"
updateViewSize! -- 每次触发尺寸变化时更新
3. 实现游戏 UI 的自适应
游戏 UI 的自适应需要确保界面元素在不同尺寸的屏幕上都能合理布局。我们将使用 Dora SSR 集成的 Yoga 布局引擎,通过类似 CSS 的 Flex 布局语法来定义元素的布局关系。
3.1 引入 Yoga 布局引擎
Yoga 是一个跨平台的布局引擎,支持基于 Flexbox 的布局方式。它允许我们使用熟 悉的 CSS 语法来定义元素的布局。
- Lua
- Teal
- TypeScript
- YueScript
local AlignNode <const> = require("AlignNode")
local AlignNode <const> = require("AlignNode")
import { AlignNode } from 'Dora';
import "AlignNode"
AlignNode
是 Dora SSR 中支持布局的节点类型。
3.2 使用 CSS Flex 布局
想要快速学习 Flex 布局,可以试试 Flexbox Froggy 这款在线小游戏:https://flexboxfroggy.com/
首先,创建一个根节点,并设置其布局属性。
- Lua
- Teal
- TypeScript
- YueScript
local root = AlignNode(true)
root:css("justify-content: center; align-items: center")
root:addTo(Director.ui)
local root = AlignNode(true)
root:css("justify-content: center; align-items: center")
root:addTo(Director.ui)
const root = AlignNode(true);
root.css("justify-content: center; align-items: center");
root.addTo(Director.ui);
root = with AlignNode true
\css "justify-content: center; align-items: center"
\addTo Director.ui
说明:
AlignNode(true)
:创建一个支持布局的节点,true
表示该节点作为窗口根节点的布局容器。css(...)
:为节点应用 CSS 布局样式。justify-content: center
:水平居中对齐子节点。align-items: center
:垂直居中对齐子节点。
root:addTo(Director.ui)
:将根节点添加到引擎内置 UI 层的场景中。
接下来,创建一个子节点,并设置其尺寸为相对于父节点的百分比。
- Lua
- Teal
- TypeScript
- YueScript
local centerNode = AlignNode()
centerNode:css("width: 60%; height: 60%")
centerNode:addTo(root)