@ adatech/ game- 交互
交互式世界物体的可移动部件(门、抽屉、盖子、接头等)、可取物品的容器和 确定性掠夺,逻辑电网(仪表、电路、插座、开关、装置)、燃料(气瓶、木炭)、逻辑水网, 座椅和床位,柔软的体积会摇动而不会被挡住,效果会释放出出弹器,镜像,相撞和损坏.
包裹什么也不画. 内容包描述对象为 ObjectSpec 数据(参见 src/types.ts),主持人将其添加到一个 World,电话
update(dt) 每个框架和绘制世界报告(部分形式、活性发射器、镜子、相撞器、摇摆等). three 无需.
安装
pnpm add @adatechnology/game-interactables
没有捆绑的浏览器( 全局为 GameInteractables:
<script src="https://unpkg.com/@adatechnology/game-interactables/dist/index.global.js"></script>
<script>
const world = GameInteractables.createWorld({ seed: 'level-1' })
</script>
使用量
import { createWorld, poseOf, type ObjectSpec } from '@adatechnology/game-interactables'
const world = createWorld({
locale: 'en',
seed: 'level-1',
items: { can: { id: 'can', category: 'food', size: [0.07, 0.11, 0.07], weight: 0.4, stack: 6 } },
loot: { pantry: { fill: 0.7, entries: [{ type: 'can', weight: 1, qty: [1, 3] }] } },
strings: { en: { 'prompt.door.closed': 'Open {name}', 'prompt.door.open': 'Close {name}', 'type.cupboard': 'cupboard' } },
onEvent: (e) => console.log(e),
})
const cupboard: ObjectSpec = {
type: 'cupboard',
parts: [{ id: 'door', pivot: [-0.4, 0, 0.3], motion: { kind: 'hinge', angle: -Math.PI / 2 }, sweep: [-0.4, 0.3, 0.4, 1.1], label: 'prompt.door' }],
containers: [{ id: 'main', access: 'door', volume: { center: [0, 0.5, 0], half: [0.4, 0.4, 0.25] }, slots: [{ pos: [0, 0.1, 0], max: [0.3, 0.3, 0.3] }], loot: 'pantry' }],
}
world.add('kitchen_cupboard', cupboard, { x: 2, y: 0, z: -1, ry: Math.PI })
// once, after placing objects next to walls: the door never opens through them
world.fitSweep('kitchen_cupboard', 'door', (x, z) => isWall(x, z))
// every frame
world.update(dt)
const look = world.target({ x: cam.x, y: cam.y, z: cam.z, yaw, pitch }) // best interaction or null
if (look) hud.show(look.label) // "Open cupboard"
if (pressedUse && look) look.act()
// drawing a part: pose is relative to the part's pivot
for (const o of world.objects()) {
for (const p of o.spec.parts ?? []) {
const pose = poseOf(p.motion, world.partT(o.id, p.id)) // { position, rotation: { axis, angle }, scale }
}
}
坐标在某一个 spec中是局部到对象: 前为 +z,起源于地上脚印的中心,米. Transform.ry 旋转
周围 +y 喜欢 three.js (单位:千美元)+z 转向 +x 以正角度表示). 视图 yaw 照相机惯例: -z。 。 。 .
行为
- 部件 向目标前进
motion.speed(默认为2.5 t/s).requires在另一部分未打开时, 不要打开并关闭 拿着那个(门后一个抽屉关上门).fitSweep(object, part, blocked)扫描样本sweep矩形(将叶子旋转为轴,将叶子翻译为幻灯片), 返回最大保险箱t(当一部分宣布)bounds,整个闭塞-pose slab都是通过运动移动的,所以叶子厚度,轴向偏移和水平轴向计数),并永远将部分夹住. 部分算作打开t >= 0.5(或被夹住的限度的90%). 共享的部件 agroup一起移动 :setPart或切换到任何成员都会设定所有成员的目标(盲窗、幕板). - 默认互动: 当一个 spec 不存在时
interactions,世界产生它们。 标签部件给toggle_part; 容器无 访问部分给定open_container; 设备、开关、固定装置、燃烧器(和ignite页:1needsIgnition),气阀和座椅得到 匹配动作。 明确interactions替换衍生的。 药是part.<id>, (中文(简体) ),open.<container>, (中文(简体) ),device.<id>, (中文(简体) ),channel.<id>, (中文(简体) ),switch.<id>, (中文(简体) ),fixture.<id>, (中文(简体) ),burner.<id>, (中文(简体) ),ignite.<id>, (中文(简体) ),fuel.<id>, (中文(简体) ),seat.<id>; 全世界object:interactionId。 。 。 . - 标签:世界抬头看
<label>.open|.closed(部件、阀门、容器)或<label>.on|.off(装置、固定装置、燃烧器, 开关)<label>,然后是引擎默认值(prompt.open, (中文(简体) ),prompt.turn_on(中文(简体) ).{name}改为:type.<type>或人类化 类型编号。 标签从不带"E:"等密钥提示;主机会自加. - 有结构的提示: 每一个
Interactable还有verb("开口")并noun("冰箱")所以一个主机可以分别样式 (单位:千美元)object是自有对象的 ID。 条目<key>.verb编号 :<key>.object在语言中获胜;否则标签的第一个词是动词, 其余的名词,一个单词提示使用对象的类型名作为名词. - 可用性数字 :
Interactable.available与一个reason(一个本地密钥 :requires_open, (中文(简体) ),no_power, (中文(简体) ),locked何时canInteract拒绝,already_lit, (中文(简体) ),needs_ignition, (中文(简体) ),turn_on_first· ;world.t(reason)是文本),而不能使用交互. - 目标数字 :
target(eye, { reach = 1.8, cone = 0.45, filter?, kinds?, includeUnavailable? })按距离和角度对视图的分数 向上转 无法获得的相互作用(闭合容器)take编号 :read,错误的一半ignite,一个部分门由requires跳过(...) 除非includeUnavailable· ;kinds限制动作类型和filter这是任何上游。 硬线灯(装置)kind: 'lamp'带有circuit,没有plug,没有part获得 没有 衍生相互作用:交换机和setDevice驱动它,所以它永远不会偷 交互键. - 从代码驱动状态数字 :
setDevice(object, device, on), (中文(简体) ),setFixture(object, fixture, on)财务报告和审定财务报表setBurner(object, burner, on)做点什么 切换的,device编号 :fixture编号 :burner事件,no_power),并当国家不变时保持安静. - 对撞机数字 :
colliders({ merge: true, gap = 0.02, slack = 0.1 })同一物体相重叠或相邻的固定框(相同) 旋转),当合并框最多添加时slack额外音量; 门相撞者保持相隔.mergeColliders(list, opts)导出为 列表中已经列出. - 集装箱: 内容来自
contents或有决定力的掠夺物seed + object id + container id。当一个项的大小适合一个槽 是在槽内max(宽度和深度可以互换).take需要打开容器,物品可以摘取和发出pickup。 。 。 . - 权力数字 :
grid,每个回路的断路器(默认),套接字(可选在回路上)和插入套接字的设备(auto= 最近的免费 2米内插座,遍及全世界)或硬接通回路.powered = grid && breaker && socket found打开但 无动力继续,报告powered: false并发出no_power留言。 切换到列出的设备( S)object:device或当地身份证明). 这个toggle_breaker动作( e){ do: 'toggle_breaker', circuit, part? })从断面板上翻转一个回路,镜像可选摇滚乐part(t = 1起;拒绝时,该部分由PartSpec.requires,例如闭合面板门)并使用提示符prompt.breaker_on|off(单位:千美元){circuit}是动作的name或电路编号). - 燃料:燃烧器需要燃料,对于有阀门的瓶子,阀门会打开.
fuel: 'auto'=2米以内最近的气体来源。 气体被消耗 被点燃时; 熄灭或关闭阀门会熄灭火焰, 当阀门打开时,一个没有燃气灯的气把手会自己打开。 木炭需求ignite烧到空出toggle_burner把它拿出来. 起火后,固体燃料20 s的烟雾排放器逐渐消失. - 水费: 油罐车(
capacity, (中文(简体) ),level, (中文(简体) ),rainArea),一个默认的罐体,固定装置在运行和供应时会流动. 与options.waterSupply固定装置 画出它(flow / 60 * dt升,一分刷volume一次). 干燥固定装置保持"上" 但报告flowing: false。 。 。 . 一个设备fixture: '<fixtureId>'(相同的物体,例如洗衣机内接器) 固定的驱动器:在设备打开和 电源,当它关闭或失去电源时停止,没有自己的相互作用. - 刚性互动数字 :
InteractionSpec.requires = { object, part }(world-wide object id) 仅允许交互,而其中 部分打开( o)t >= 0.5:target跳过它act否则拒绝(柜子门后有气阀). - 席位:每个座位一个演员.
sit返回世界眼睛的位置和方向,stand返回世界退出点. - 软音量 永远不要挡住,永远不要相撞.
push(pos, radius, vel)挥之以去;他们靠被拦住的泉水安顿下来。 风又加一 小型吞噬力。 A 类panel带有part从前面推入时打开. - 损害数字 :
hp每个目标。 燃料爆炸后被摧毁的气体源(radius = 2 + level / 5和空地;一个被损坏的坦克一次泄漏 下水道; 玻璃只是一个事件. - 保存/装入数字 :
serialize()简洁的JSON;load()将其恢复到一个添加了相同对象的世界。 擦拭限制( E)fitSweep已经 未保存, 装入后再次调用 .
API 密码
createWorld(options?: WorldOptions): World
WorldOptions数字 : locale, (中文(简体) ), strings, (中文(简体) ), items, (中文(简体) ), loot, (中文(简体) ), seed, (中文(简体) ), grid, (中文(简体) ), rain, (中文(简体) ), wind, (中文(简体) ), waterSupply, (中文(简体) ), onEvent, (中文(简体) ), canInteract。 。 。 .
| 组 | 成员 |
|---|---|
| 对象 | add(id, spec, transform), (中文(简体) ), remove(id), (中文(简体) ), get(id), (中文(简体) ), objects() |
| 框架 | update(dt) |
| 互动 | interactables(), (中文(简体) ), target(eye, TargetOptions), (中文(简体) ), act(id, actor?) |
| 部件 | partT, (中文(简体) ), setPart(object, part, target, instant?), (中文(简体) ), fitSweep(object, part, blocked) |
| 驱动 | setDevice(object, device, on), (中文(简体) ), setFixture(object, fixture, on), (中文(简体) ), setBurner(object, burner, on) |
| 集装箱 | contents, (中文(简体) ), accessible, (中文(简体) ), take, (中文(简体) ), put, (中文(简体) ), slotPosition |
| 权力 | power.grid, (中文(简体) ), setGrid, (中文(简体) ), setBreaker, (中文(简体) ), breaker, (中文(简体) ), isPowered, (中文(简体) ), isOn, (中文(简体) ), pluggedInto, (中文(简体) ), channel |
| 燃料 | fuelLevel(object, fuel), (中文(简体) ), isLit(object, burner) |
| 水费 | water.setDefaultTank, (中文(简体) ), level, (中文(简体) ), refill, (中文(简体) ), setRain, (中文(简体) ), isFlowing |
| 席位 | sit, (中文(简体) ), stand, (中文(简体) ), seatOf |
| 软 | push, (中文(简体) ), sway, (中文(简体) ), setWind |
| 绘制 | emitters(), (中文(简体) ), mirrors(eye, maxDistance?, count?), (中文(简体) ), colliders({ merge? }) |
| 损害 | damage(object, target, amount, kind?), (中文(简体) ), hp(object, target) |
| 文本 | t(key, vars?), (中文(简体) ), setLocale(locale) |
| 保存 | serialize(), (中文(简体) ), load(state) |
独立助手 : rng(seed), (中文(简体) ), generateLoot(tables, tableId, slots, seed, items), (中文(简体) ), poseOf(motion, t), (中文(简体) ), localToWorld(transform, v), (中文(简体) ),
worldToLocal, (中文(简体) ), rotY, (中文(简体) ), rotateAxis, (中文(简体) ), fitsSize, (中文(简体) ), fitsSlot, (中文(简体) ), resolveStrings(locale, extra), (中文(简体) ), locales, (中文(简体) ), format, (中文(简体) ), pickLocale。 。 。 .
poseOf(motion, t) 返回时 { position, rotation: { axis, angle }, scale } 相对于该部分的支点:轴,摇杆和拐杆旋转,
幻灯片翻译 axis * distance * t缩放 axis。 。 。 .
活动
onEvent 收到每个更改 :
type | 字段 |
|---|---|
part | object, (中文(简体) ), part, (中文(简体) ), t, (中文(简体) ), target (在一个新目标上,再次到达) |
pickup | object, (中文(简体) ), container, (中文(简体) ), slot, (中文(简体) ), stack, (中文(简体) ), actor |
device | object, (中文(简体) ), device, (中文(简体) ), on, (中文(简体) ), powered, (中文(简体) ), channel? |
switch | object, (中文(简体) ), switch, (中文(简体) ), on |
fixture | object, (中文(简体) ), fixture, (中文(简体) ), on, (中文(简体) ), flowing |
burner | object, (中文(简体) ), burner, (中文(简体) ), on, (中文(简体) ), lit |
seat | object, (中文(简体) ), seat, (中文(简体) ), actor, (中文(简体) ), seated |
damage | object, (中文(简体) ), target, (中文(简体) ), hp, (中文(简体) ), destroyed |
explosion | object, (中文(简体) ), pos, (中文(简体) ), radius |
leak | object, (中文(简体) ), target, (中文(简体) ), pos |
message | key, (中文(简体) ), text (当地化): no_power, (中文(简体) ), no_gas, (中文(简体) ), no_water, (中文(简体) ), locked, (中文(简体) ), empty, (中文(简体) ), full,或项目文本密钥 read |
power | grid |
container | object, (中文(简体) ), container, (中文(简体) ), open (一个打开的架子是"打开") |
语言
引擎级别字符串存在于 en 财务报告和审定财务报表 pt-BR数字 : prompt.open, (中文(简体) ), prompt.close, (中文(简体) ), prompt.turn_on, (中文(简体) ), prompt.turn_off, (中文(简体) ), prompt.take, (中文(简体) ), prompt.sit, (中文(简体) ),
prompt.lie_down, (中文(简体) ), prompt.get_up, (中文(简体) ), prompt.light, (中文(简体) ), prompt.change_channel, (中文(简体) ), prompt.read, (中文(简体) ), prompt.open_valve, (中文(简体) ), prompt.close_valve 编辑
上面的信息。 内容包通过 options.strings;未知的密钥会倒回英文,再倒回密钥本身.
销毁
光谱带标签 共享破坏 SDK, @adatechnology/game-destruction;此软件包不依赖它,只存储平面标识.
PartSpec.destruction数字 :{ material, joint?, piece?, explodes?, contains? }。 。 。 .material是一个 SDK 材料 id (steel, (中文(简体) ),mdf, (中文(简体) ),glass...jointsDK联合型(screw, (中文(简体) ),bolt, (中文(简体) ),nail, (中文(简体) ),weld, (中文(简体) ),glue, (中文(简体) ),hinge, (中文(简体) ),clip, (中文(简体) ),tie, (中文(简体) ),mortar, (中文(简体) ),fused, (中文(简体) ),stem, (中文(简体) ),piece何为部分(door, (中文(简体) ),drawer, (中文(简体) ),lid(......) (中文(简体) ).explodes财务报告和审定财务报表contains形状和SDK一样PartSpec。 。 。 .ObjectSpec.destruction:静态体的同名标记(所有不是可移动的部分).
主机从标记和路线打出SDK部件,向SDK起火并起爆. DamageSpec 财务报告和审定财务报表 world.damage 被贬损:它们继续工作,但没有新的特性.
葡萄牙
运行时间 sem 渲染器 para objetos interativos do mundo: portas, grattas e tampas que se movem, 收受者 com itens e roble deminístico por emente, rede elétrica lógica (医疗,电路, tomadas, 中继器, aparelhos), combustível (botijão de gás, carvão), rede de água lógica, assentos e camas, supers macios (cortinas, folhagem) que balançam sem blopear, issorers de efetos, espelhos, colisores e dano. 中国植物物种信息数据库.
const world = createWorld({ locale: 'pt-BR', seed: 'fase-1' })
world.add('armario', especificacao, { x: 2, y: 0, z: -1, ry: Math.PI })
world.update(dt)
const alvo = world.target({ x, y, z, yaw, pitch }) // ex.: "Abrir armário"
alvo?.act()
(原始内容存档于2018-10-21) (英语). O pacote não desenha nada: você informationa o ObjectSpec (dados),查马 update(dt) 一个卡达四分卫 o desenha o que o mundo reportar. 维基百科中的相关条目: 克多克多克多克多克多克多克多克多克多克多克多克多克多克多克多克多克 Os textos do (英语) (英语)
发动机(Abrir, (中文(简体) ), Ligar, (中文(简体) ), Sem energia, (中文(简体) ), Sem gás, (中文(简体) ), Sem água. . . . . . pt-BR; os pacotes de conteúdo 亩地centam as suas chaves em strings。 。 。 .
销毁代表
过 destruction: { hitPart } (形状 DestructionWorld.hitPart 从 @adatechnology/game-destruction,不依赖它) createWorld 财务报告和审定财务报表 world.damage 把它当作一个 blunt (单位:千美元)explosive 页:1 gas, (中文(简体) ), slash 页:1 fabric击出 energy: amount世界停止了自己的账簿管理 world.hp 返回时 null没有它,堕落者 DamageSpec 行为不变.