# PlayDrop 游戏的全屏、安全区域和 HUD 角落

让 PlayDrop 游戏铺满屏幕，借助 SDK 测得的 reservedCorners，让 HUD 留在 CSS 安全区域内并避开宿主的控件。

Source: https://www.playdrop.ai/zh-hans/create/learn/viewport

PlayDrop 会把整个屏幕交给你的游戏：网站的游戏页面有自己的全屏控件，应用也会全屏运行游戏。在手机上，PlayDrop 会在游戏顶部的角落放置小小的暂停和音频控件（在队伍中还有一个语音控件）。SDK 会准确告诉你它们的位置，让 HUD 既能避开它们，又不浪费空间。

## 铺满视口

从边缘画到边缘，并阻止页面滚动、缩放或选中文字：

```html
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no">
<style>
  html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; background: #000; }
  body { touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
  canvas { display: block; width: 100vw; height: 100dvh; }
</style>
```

用 canvas 的显示尺寸乘以 `devicePixelRatio` 来设置它的大小，并在 `resize` 时重绘；在电脑、平板、折叠屏上，以及手机旋转时，窗口大小都会变化。背景图和游戏场地可以铺到任何地方，包括刘海和宿主控件的下方。只有可交互和需要阅读的 HUD 元素才需要避开它们。你不需要自己的全屏按钮。

## 让 HUD 避开遮挡

有两样东西可能遮住边缘：

- **硬件安全区域**，例如刘海或主屏幕指示条，通过 CSS `env(safe-area-inset-top|right|bottom|left)` 获取。
- **宿主的控件**，通过 `sdk.host.reservedCorners` 获取：`{ topLeft: { width, height }, topRight: { width, height } }`，以 CSS 像素为单位，从游戏视口的左上角和右上角开始测量。

要避开的是两者的并集，绝不是两者之和。左上角的 HUD 元素可以放在角落矩形的下方或旁边；无论哪种方式，每个方向都取较大的那个间距：

```js
const root = document.documentElement.style;
function layoutHud(corners) {
  const left = corners?.topLeft ?? { width: 0, height: 0 };
  const right = corners?.topRight ?? { width: 0, height: 0 };
  root.setProperty("--pd-tl-h", `${left.height}px`);
  root.setProperty("--pd-tr-h", `${right.height}px`);
}
layoutHud(sdk.host.reservedCorners);
const stop = sdk.host.onReservedCornersChange(layoutHud);
```

```css
.score { position: absolute; left: max(12px, env(safe-area-inset-left));
  top: max(12px, env(safe-area-inset-top), var(--pd-tl-h, 0px)); }
.lives { position: absolute; right: max(12px, env(safe-area-inset-right));
  top: max(12px, env(safe-area-inset-top), var(--pd-tr-h, 0px)); }
```

- 宽度和高度为零表示那个角落没有遮挡，例如在电脑版网站上，控件位于游戏外面。
- `null` 表示这是不报告角落的旧宿主：保留你现有的安全区域布局。
- 这些值来自屏幕上实际显示的控件，例如手机上至少 44 点的触控区域，并会随着旋转、调整大小和队伍而变化。请读取它们；绝不能写死某个尺寸，也不要预留一整条全宽的顶部区域。

销毁游戏时，用返回的函数取消订阅。

## 屏幕方向和显示形态

在 [catalogue.json](https://www.playdrop.ai/zh-hans/create/learn/catalogue-json) 中声明游戏适用的地方：`surfaceTargets` 列出 `desktop`、`mobileLandscape` 和 `mobilePortrait`，`primarySurface` 指定游戏设计时针对的那一个。只开启你测试过的显示形态。竖屏游戏在宽屏上显示时，仍应用协调的背景铺满屏幕，而不是留下黑边；[即玩](https://www.playdrop.ai/zh-hans/create/learn/instant-games)游戏必须以竖屏为主。

## 触屏上的输入

让操控适合拇指使用：至少 44 个 CSS 像素，远离预留的角落，以及系统手势开始的屏幕边缘。使用指针事件，对游戏中的触摸调用 `preventDefault()`，并在电脑上支持键盘和鼠标。控制器的内容请参阅[本地队伍和控制器](https://www.playdrop.ai/zh-hans/create/learn/local-party)。

## 相关指南

- [加载、暂停和音频](https://www.playdrop.ai/zh-hans/create/learn/lifecycle): 初始化 PlayDrop SDK，在第一个可玩帧时发出就绪信号，干净地暂停和恢复，遵循宿主的音频策略，并为原生应用和离线游玩预加载文件。
- [本地队伍和控制器](https://www.playdrop.ai/zh-hans/create/learn/local-party): 通过 sdk.device 读取实体手柄和 PlayDrop 手机控制器，跟踪本地玩家槽位，并声明控制器支持和本地队伍人数。
- [客户端 SDK](https://www.playdrop.ai/zh-hans/create/learn/sdk): PlayDrop 浏览器 SDK 参考：初始化、宿主生命周期、玩家身份和存档、设备和控制器、社交、多人游戏、商店、广告、排行榜、成就、素材和 AI。
