如何创建游戏场景
在Dora SSR引擎中,游戏场景是由节点(Node)组成的树形结构。节点是游戏场景中的基本元素,可以包含其他节点,形成一个层次结构。在这个教程中,我们将介绍如何使用节点来创建游戏场景。
下面是一个简单的游戏场景的示例,父节点的几何变换,颜色和透明度等属性会传递影响到子节点,设置子节点的相关属性时,实际上设置的是在父节点上的相对值。
1. 创建一个节点
要在Dora SSR引擎中创建一个节点,您需要创建一个Node类的实例,并用于后续构建游戏场景树的层次结构。
以下是如何在脚本代码中创建一个新的Node实例的示例:
- Lua
- Teal
- TypeScript
- YueScript
-- 创建一个新的节点实例,它将会自动挂载到游戏场景的根节点
local node = Node()
-- 或者您可以手动将其挂载到游戏场景的根节点上
-- Director.entry:addChild(node)
-- 导入 Node 模块
local Node <const> = require("Node")
-- 创建一个新的节点实例,它将会自动挂载到游戏场景的根节点
local node = Node()
-- 或者您可以手动将其挂载到游戏场景的根节点上
-- Director.entry:addChild(node)
// 导入 Node 模块
import { Node } from "Dora";
// 创建一个新的节点实例,它将会自动挂载到游戏场景的根节点
const node = Node();
// 或者您可以手动将其挂载到游戏场景的根节点上
// Director.entry.addChild(node);
-- 导入 Dora 模块
_ENV = Dora
-- 创建一个新的节点实例,它将会自动挂载到游戏场景的根节点
node = Node!
-- 或者您可以手动将其挂载到游戏场景的根节点上
-- Director.entry\addChild node
2. 设置节点属性
Node类有许多成员变量可供设置,如x
, y
, z
(节点的位置),width
, height
(节点的大小),angle
, angleX
, angleY
(节点的旋转角度),scaleX
, scaleY
(节点的缩放系数),以及visible
(节点是否可见)等。
以下是如何在Lua中设置这些属性的示例:
- Lua
- Teal
- TypeScript
- YueScript
node.x = 100
node.y = 200
node.width = 50
node.height = 50
node.visible = true
node.x = 100
node.y = 200
node.width = 50
node.height = 50
node.visible = true
node.x = 100;
node.y = 200;
node.width = 50;
node.height = 50;
node.visible = true;
with node
.x = 100
.y = 200
.width = 50
.height = 50
.visible = true
3. 添加子节点
在Node类中,可以通过addChild
方法添加子节点。以下是在代码中如何添加子节点的示例:
- Lua
- Teal
- TypeScript
- YueScript
local childNode = Node()
node:addChild(childNode)
local childNode = Node()
node:addChild(childNode)
const childNode = Node();
node.addChild(childNode);
childNode = Node!
node\addChild childNode
在这个例子中,childNode
被添加到node
作为其子节点。
4. 检查节点属性
Node类有一些只读成员变量,如hasChildren
(是否有子节点),children
(子节点的列表),parent
(节点的父节点),以及boundingBox
(节点的包围盒)等。
以下是在Lua中如何检查这些属性的示例:
- Lua
- Teal
- TypeScript
- YueScript
print(node.hasChildren) -- 打印是否有子节点
print(node.children) -- 打印子节点的列表
print(node.parent) -- 打印节点的父节点
print(node.hasChildren) -- 打印是否有子节点
print(node.children) -- 打印子节点的列表
print(node.parent) -- 打印节点的父节点
print(node.hasChildren); // 打印是否有子节点
print(node.children); // 打印子节点的列表
print(node.parent); // 打印节点的父节点
with node
print .hasChildren -- 打印是否有子节点
print .children -- 打印子节点的列表
print .parent -- 打印节点的父节点
5. 节点的事件系统
首先,场景节点类的事件系统支持多种事件类型,如动作结束. 点击开始. 点击结束. 点击移动. 滚动鼠标滚轮等。每种事件类型都有一个特定的回调函数,当该事件发生时,这个回调函数会被触发。
注册和处理事件的基本步骤如下:
- 注册事件:你可以通过在节点上注册事件来监听引擎内置功能触发的事件,比如屏幕触摸,鼠标. 键盘和游戏手柄输入等。可以使用下面的代码编写模式通过节点来注册和监听事件,节点上的事件触发是支持多播的,即可以重复注册多个回调函数来监听同一个事件。示例代码如下:
- Lua
- Teal
- TypeScript
- YueScript
node:slot("事件的名称", function(...)
-- 在这里添加你的代码
end)
node:slot("事件的名称", function(...)
-- 在这里添加你的代码
end)
node.slot("事件的名称", (...: any[]) => {
// 在这里添加你的代码
});
node\slot "事件的名称", (...) ->
-- 在这里添加你的代码
- 处理事件:当注册的事件被触发时,你可以在回调函数中添加处理事件的代码,并获取事件相关的参数。例如,你可以在节点动作执行结束事件的回调函数中添加代码来处理动作结束事件:
- Lua
- Teal
- TypeScript
- YueScript
node:slot("ActionEnd", function(action, target)
print("Action completed: " .. tostring(action) .. " Target node: " .. tostring(target))
end)
node:slot("ActionEnd", function(action: Action.Type, target: Node.Type)
print("Action completed: " .. tostring(action) .. " Target node: " .. tostring(target))
end)
node.slot(Slot.ActionEnd, (action, target) => {
print(`Action completed: ${action} Target node: ${target}`);
});
node\slot "ActionEnd", (action, target) ->
print "完成动作:#{action} 目标节点:#{target}"
- 移除 事件:当你不再需要监听某个事件时,你可以通过下面几种方法来移除事件的监听。示例代码如下:
- Lua
- Teal
- TypeScript
- YueScript
local function callback(...)
-- 在这里添加你的处理代码
end
-- 注册事件
node:slot("事件的名称", callback)
-- 移除事件
node:slot("事件的名称"):remove(callback)
-- 移除所有注册的事件
node:slot("事件的名称", nil)
local function callback(...)
-- 在这里添加你的处理代码
end
-- 注册事件
node:slot("事件的名称", callback)
-- 移除事件
node:slot("事件的名称"):remove(callback)
-- 移除所有注册的事件
node:slot("事件的名称", nil)
const callback = (...: any[]) => {
// 在这里添加你的处理代码
};
// 注册事件
node.slot("事件的名称", callback);
// 移除事件
node.slot("事件的名称").remove(callback);
// 移除所有注册的事件
node.slot("事件的名称").clear();
callback = (...) ->
-- 在这里添加你的处理代码
-- 注册事件
node\slot "事件的名称", callback
-- 移除事件
node\slot("事件的名称")\remove callback
-- 移除所有注册的事件
node\slot "事件的名称", nil
常用的游戏交互相关的节点事件类型和对应的回调函数签名如下,在使用这些事件之前还需要打开节点接收点击事件的开关:
node.touchEnabled = true
- 点击过滤(TapFilter):在点击开始之前触发,可以用于过滤某些点击事件。回调函数签名:
function(touch: Touch)
- 点击开始(TapBegan):在检测到点击时触发。回调函数签名:
function(touch: Touch)
- 点击结束(TapEnded):在点击结束时触发。回调函数签名:
function(touch: Touch)
- 点击成功(Tapped):在检测到并结束点击时触发。回调函数签名:
function(touch: Touch)
- 点击移动(TapMoved):在点击移动时触发。回调函数签名:
function(touch: Touch)
- 滚动鼠标滚轮(MouseWheel):在滚动鼠标滚轮时触发。回调函数签名:
function(delta: Vec2)
通过注册和处理这些事件,你可以轻松地为你的游戏节点添加复杂的交互功能。其它可以监听的节点事件详见这里。
为了简化对事件的处理,我们还提供了一些内置的事件注册函数,如onTapBegan
. onTapEnded
. onTapped
. onTapMoved
. onMouseWheel
等。你可以通过在节点上调用这些函数来注册和处理事件。
例如,你可以通过以下代码来注册和处理点击开始事件:
- Lua
- Teal
- TypeScript
- YueScript
node:onTapBegan(function(touch)
print("点击开始")
end)
-- 等同于代码
--[[
node.touchEnabled = true
node:slot("TapBegan", function(touch)
print("点击开始")
end)
]]
node:onTapBegan(function(touch: Touch)
print("点击开始")
end)
-- 等同于代码
--[[
node.touchEnabled = true
node:slot("TapBegan", function(touch: Touch)
print("点击开始")
end)
]]
node.onTapBegan(touch => {
print("点击开始");
});
// 等同于代码
// node.touchEnabled = true;
// node.slot(Slot.TapBegan, touch => {
// print("点击开始");
// });
node\onTapBegan (touch) -> print "点击开始"
-- 等同于代码
-- node.touchEnabled = true
-- node\slot "TapBegan", (touch) -> print "点击开始"
6. 节点动作
下面将展示如何使用节点动作系统来创建各种动画效果。
- 移动动作(Move):
- Lua
- Teal
- TypeScript
- YueScript
local moveAction = Move(duration, startPosition, stopPosition)
node:perform(moveAction)
local moveAction = Move(duration, startPosition, stopPosition)
node:perform(moveAction)