mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-11-29 07:02:58 +08:00
Compare commits
1 Commits
7bf53fe820
...
ffcab68003
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffcab68003 |
@ -131,4 +131,4 @@ export const MyUI = defineComponent(() => {
|
|||||||
- 如果不允许交互,那么光标也不会显示
|
- 如果不允许交互,那么光标也不会显示
|
||||||
- 同 `zIndex` 下,后插入的元素会在上层,但是这也意味着如果是动态插入的元素(例如由于响应式更改而插入了一个新元素),会显示在后面代码的元素之上
|
- 同 `zIndex` 下,后插入的元素会在上层,但是这也意味着如果是动态插入的元素(例如由于响应式更改而插入了一个新元素),会显示在后面代码的元素之上
|
||||||
4. **常见问题**
|
4. **常见问题**
|
||||||
- 参考 [指南](../../guide/ui/faq.md)
|
- 参考 [指南](../../guide/ui-faq.md)
|
||||||
|
|||||||
@ -43,7 +43,7 @@ interface SpriteProps extends BaseProps {
|
|||||||
|
|
||||||
## 使用示例
|
## 使用示例
|
||||||
|
|
||||||
以下的示例代码均应该在**组件内部**编写,哪里是组件内部请参考[指南](../../guide/ui/ui.md)。
|
以下的示例代码均应该在**组件内部**编写,哪里是组件内部请参考[指南](../../guide/ui.md)。
|
||||||
|
|
||||||
### 示例 1:基础图形
|
### 示例 1:基础图形
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ graph LR
|
|||||||
|
|
||||||
## 类描述
|
## 类描述
|
||||||
|
|
||||||
`UIController` 是 UI 控制系统的核心类,负责管理 UI 实例的显示栈、背景控制以及多种显示模式。继承自 `EventEmitter`,支持事件监听。想要编写 UI 请参考[深度指南](../../guide/ui/ui.md)。
|
`UIController` 是 UI 控制系统的核心类,负责管理 UI 实例的显示栈、背景控制以及多种显示模式。继承自 `EventEmitter`,支持事件监听。想要编写 UI 请参考[深度指南](../../guide/ui.md)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ function showAll(stack?: boolean): void;
|
|||||||
function showCustom(config: IUICustomConfig): void;
|
function showCustom(config: IUICustomConfig): void;
|
||||||
```
|
```
|
||||||
|
|
||||||
切换显示模式:使用自定义模式(需实现 `IUICustomConfig`),参考[指南](../../guide/ui/system.md#自定义显示模式)
|
切换显示模式:使用自定义模式(需实现 `IUICustomConfig`),参考[指南](../../guide/ui-system.md#自定义显示模式)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -408,4 +408,4 @@ const userData = await waitbox(
|
|||||||
4. **额外参考**
|
4. **额外参考**
|
||||||
- [组件 ConfirmBox](./组件%20ConfirmBox.md)
|
- [组件 ConfirmBox](./组件%20ConfirmBox.md)
|
||||||
- [组件 Choices](./组件%20Choices.md)
|
- [组件 Choices](./组件%20Choices.md)
|
||||||
- [组件 WaitBox](./组件%20WaitBox.md)
|
- [组件 Waitbox](./组件%20Waitbox.md)
|
||||||
|
|||||||
@ -1,85 +0,0 @@
|
|||||||
# FloorSelector 楼层选择器组件 API 文档
|
|
||||||
|
|
||||||
本文档由 `DeepSeek R1` 模型生成并微调。
|
|
||||||
|
|
||||||
## 组件描述
|
|
||||||
|
|
||||||
楼层选择器组件用于在地图浏览或地图选择场景中切换不同楼层,其尺寸与内置状态栏组件匹配,适合在地图浏览时将状态栏替换为此组件。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Props 属性说明
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 描述 |
|
|
||||||
| -------- | ------------ | ------ | -------------------- |
|
|
||||||
| `floors` | `FloorIds[]` | 必填 | 可选择的楼层 ID 数组 |
|
|
||||||
| `now` | `number` | - | 当前选中的楼层索引 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Events 事件说明
|
|
||||||
|
|
||||||
| 事件名 | 参数类型 | 触发时机 |
|
|
||||||
| ------------ | ------------------------------------ | ---------------------- |
|
|
||||||
| `close` | - | 点击关闭按钮时触发 |
|
|
||||||
| `update` | `(floor: number, floorId: FloorIds)` | 当选中的楼层改变时触发 |
|
|
||||||
| `update:now` | `(value: number)` | v-model 双向绑定事件 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slots 插槽说明
|
|
||||||
|
|
||||||
无插槽
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exposed Methods 暴露方法
|
|
||||||
|
|
||||||
无暴露方法
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基础用法 - 地图浏览界面
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { FloorSelector, STATUS_BAR_HEIGHT } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MapBrowserCom = defineComponent(() => {
|
|
||||||
const currentFloor = ref(0);
|
|
||||||
|
|
||||||
// 可用的楼层列表
|
|
||||||
const availableFloors = core.floorIds;
|
|
||||||
|
|
||||||
const handleFloorChange = (floorIndex: number, floorId: string) => {
|
|
||||||
console.log(`切换到楼层: ${floorId} (索引: ${floorIndex})`);
|
|
||||||
// 这里可以执行切换楼层的逻辑
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
console.log('关闭楼层选择器');
|
|
||||||
// 返回主界面或执行其他关闭逻辑
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<FloorSelector
|
|
||||||
loc={[0, 0, 180, STATUS_BAR_HEIGHT]}
|
|
||||||
floors={availableFloors}
|
|
||||||
v-model:now={currentFloor.value}
|
|
||||||
onUpdate={handleFloorChange}
|
|
||||||
onClose={handleClose}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **尺寸匹配**: 组件设计为与内置状态栏尺寸匹配,可直接替换
|
|
||||||
2. **索引基准**: 楼层索引从 0 开始
|
|
||||||
3. **内置集成**: 通常不需要直接使用,因为样板已内置完整的地图浏览界面
|
|
||||||
4. **倒序排列**: 楼层列表会自动倒序排列
|
|
||||||
@ -1,113 +0,0 @@
|
|||||||
# Input 输入框组件 API 文档
|
|
||||||
|
|
||||||
本文档由 `DeepSeek` 生成并微调。
|
|
||||||
|
|
||||||
## 组件描述
|
|
||||||
|
|
||||||
输入框组件用于接收用户的文本输入,支持单行和多行模式,提供边框样式自定义和实时/确认两种值变化事件。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Props 属性说明
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 描述 |
|
|
||||||
| ------------------------- | ------------------- | ------- | ----------------------------------------------------- |
|
|
||||||
| `placeholder` | `string` | - | 输入框的提示内容 |
|
|
||||||
| `value` | `string` | - | 输入框的值 |
|
|
||||||
| `multiline` | `boolean` | `false` | 是否是多行输入,多行输入时允许换行 |
|
|
||||||
| `border` | `string` | - | 边框颜色 |
|
|
||||||
| `circle` | `RectRCircleParams` | - | 边框圆角 |
|
|
||||||
| `borderWidth` | `number` | - | 边框宽度 |
|
|
||||||
| `pad` | `number` | - | 内边距 |
|
|
||||||
| 继承自 `TextContentProps` | - | - | [查看完整属性](./组件%20TextContent#Props%20属性说明) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Events 事件说明
|
|
||||||
|
|
||||||
| 事件名 | 参数类型 | 触发时机 |
|
|
||||||
| -------------- | ----------------- | ---------------------------------------- |
|
|
||||||
| `change` | `(value: string)` | 当输入框的值被确认时触发,例如失焦时 |
|
|
||||||
| `input` | `(value: string)` | 当输入框的值发生改变时触发,例如实时输入 |
|
|
||||||
| `update:value` | `(value: string)` | v-model 双向绑定事件 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slots 插槽说明
|
|
||||||
|
|
||||||
无插槽
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exposed Methods 暴露方法
|
|
||||||
|
|
||||||
无暴露方法
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基础用法 - 单行输入框
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { Input } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MyCom = defineComponent(() => {
|
|
||||||
const inputValue = ref('');
|
|
||||||
|
|
||||||
const handleChange = (value: string) => {
|
|
||||||
console.log('输入确认:', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInput = (value: string) => {
|
|
||||||
console.log('实时输入:', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<Input
|
|
||||||
placeholder="请输入文本"
|
|
||||||
v-model={inputValue.value}
|
|
||||||
onChange={handleChange}
|
|
||||||
onInput={handleInput}
|
|
||||||
loc={[208, 208, 300, 40, 0.5, 0.5]}
|
|
||||||
border="#ccc"
|
|
||||||
borderWidth={1}
|
|
||||||
circle={[4]}
|
|
||||||
pad={8}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 多行文本输入
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { Input } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MyCom = defineComponent(() => {
|
|
||||||
const multilineValue = ref('');
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<Input
|
|
||||||
multiline
|
|
||||||
placeholder="请输入多行文本..."
|
|
||||||
v-model={multilineValue.value}
|
|
||||||
loc={[208, 208, 300, 120, 0.5, 0.5]}
|
|
||||||
border="#007acc"
|
|
||||||
borderWidth={2}
|
|
||||||
circle={[8]}
|
|
||||||
pad={12}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **事件区别**:`input` 事件在每次输入时触发,`change` 事件在失焦或确认时触发
|
|
||||||
2. **多行模式**:启用 `multiline` 后支持换行输入,高度需要足够容纳多行文本
|
|
||||||
3. **样式继承**:支持从 `TextContentProps` 继承文本相关样式属性
|
|
||||||
@ -1,315 +0,0 @@
|
|||||||
# InputBox 输入对话框组件 API 文档
|
|
||||||
|
|
||||||
本文档由 `DeepSeek` 生成并微调。
|
|
||||||
|
|
||||||
## 组件描述
|
|
||||||
|
|
||||||
输入对话框组件是一个完整的弹出式输入界面,包含提示文本、输入框、确认和取消按钮。适用于需要用户输入文本的交互场景,提供了便捷的异步获取输入方法。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Props 属性说明
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 描述 |
|
|
||||||
| ------------------------- | ---------------- | -------- | ----------------------------------------------------- |
|
|
||||||
| `loc` | `ElementLocator` | 必填 | 输入框对话框的位置 |
|
|
||||||
| `input` | `InputProps` | - | 传递给内部 Input 组件的配置参数 |
|
|
||||||
| `winskin` | `ImageIds` | - | 窗口皮肤图片ID,用于对话框背景绘制 |
|
|
||||||
| `color` | `CanvasStyle` | - | 对话框背景颜色(未设置 winskin 时生效) |
|
|
||||||
| `border` | `CanvasStyle` | - | 对话框边框颜色(未设置 winskin 时生效) |
|
|
||||||
| `pad` | `number` | - | 对话框内部所有元素的内边距 |
|
|
||||||
| `inputHeight` | `number` | - | 内部输入框区域的高度 |
|
|
||||||
| `text` | `string` | - | 对话框顶部的提示文本 |
|
|
||||||
| `yesText` | `string` | `"确认"` | 确认按钮的显示文本 |
|
|
||||||
| `noText` | `string` | `"取消"` | 取消按钮的显示文本 |
|
|
||||||
| `selFont` | `Font` | - | 确认/取消按钮的字体样式 |
|
|
||||||
| `selFill` | `CanvasStyle` | - | 确认/取消按钮的文本颜色 |
|
|
||||||
| 继承自 `TextContentProps` | - | - | [查看完整属性](./组件%20TextContent#Props%20属性说明) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Events 事件说明
|
|
||||||
|
|
||||||
| 事件名 | 参数类型 | 触发时机 |
|
|
||||||
| -------------- | ----------------- | ------------------------------------------ |
|
|
||||||
| `confirm` | `(value: string)` | 当确认输入框的内容时触发 |
|
|
||||||
| `cancel` | `(value: string)` | 当取消时触发 |
|
|
||||||
| `change` | `(value: string)` | 继承自 Input 组件 - 输入框值被确认时触发 |
|
|
||||||
| `input` | `(value: string)` | 继承自 Input 组件 - 输入框值实时变化时触发 |
|
|
||||||
| `update:value` | `(value: string)` | 继承自 Input 组件 - v-model 双向绑定 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slots 插槽说明
|
|
||||||
|
|
||||||
无插槽
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exposed Methods 暴露方法
|
|
||||||
|
|
||||||
无暴露方法
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 工具函数
|
|
||||||
|
|
||||||
### `getInput(controller, text, loc, width, props?)`
|
|
||||||
|
|
||||||
弹出一个输入框并异步返回用户输入的结果。
|
|
||||||
|
|
||||||
**参数**
|
|
||||||
|
|
||||||
- `controller: IUIMountable` - UI 控制器
|
|
||||||
- `text: string` - 提示文本内容
|
|
||||||
- `loc: ElementLocator` - 确认框的位置
|
|
||||||
- `width: number` - 确认框的宽度
|
|
||||||
- `props?: InputBoxProps` - 额外的配置属性(可选)
|
|
||||||
|
|
||||||
**返回值**: `Promise<string>`
|
|
||||||
|
|
||||||
### `getInputNumber(controller, text, loc, width, props?)`
|
|
||||||
|
|
||||||
与 `getInput` 类似,但会将结果转换为数字。
|
|
||||||
|
|
||||||
**参数**: 同 `getInput`
|
|
||||||
**返回值**: `Promise<number>`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基础用法 - 组件形式
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { InputBox } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MyCom = defineComponent(() => {
|
|
||||||
const handleConfirm = (value: string) => {
|
|
||||||
console.log('用户输入:', value);
|
|
||||||
// 处理用户输入
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCancel = (value: string) => {
|
|
||||||
console.log('用户取消输入,最后值为:', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<InputBox
|
|
||||||
text="请输入您的姓名:"
|
|
||||||
loc={[240, 240, 300, 180, 0.5, 0.5]}
|
|
||||||
input={{
|
|
||||||
placeholder: '在此输入姓名',
|
|
||||||
border: '#007acc',
|
|
||||||
borderWidth: 1,
|
|
||||||
circle: [4],
|
|
||||||
pad: 8
|
|
||||||
}}
|
|
||||||
color="#ffffff"
|
|
||||||
border="#cccccc"
|
|
||||||
borderWidth={2}
|
|
||||||
pad={16}
|
|
||||||
inputHeight={40}
|
|
||||||
yesText="确定"
|
|
||||||
noText="取消"
|
|
||||||
onConfirm={handleConfirm}
|
|
||||||
onCancel={handleCancel}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用 getInput 工具函数(推荐)
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { getInput, getInputNumber } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MyCom = defineComponent(props => {
|
|
||||||
const handleGetName = async () => {
|
|
||||||
// 获取文本输入
|
|
||||||
const name = await getInput(
|
|
||||||
props.controller,
|
|
||||||
'请输入您的姓名:',
|
|
||||||
[208, 208, void 0, void 0, 0.5, 0.5],
|
|
||||||
280,
|
|
||||||
{
|
|
||||||
input: {
|
|
||||||
placeholder: '姓名'
|
|
||||||
},
|
|
||||||
color: '#f8f8f8'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (name) {
|
|
||||||
console.log('用户姓名:', name);
|
|
||||||
// 处理姓名
|
|
||||||
} else {
|
|
||||||
console.log('用户取消了输入');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleGetAge = async () => {
|
|
||||||
// 获取数字输入
|
|
||||||
const age = await getInputNumber(
|
|
||||||
props.controller,
|
|
||||||
'请输入您的年龄:',
|
|
||||||
[208, 208, void 0, void 0, 0.5, 0.5],
|
|
||||||
280
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!isNaN(age)) {
|
|
||||||
console.log('用户年龄:', age);
|
|
||||||
// 处理年龄
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<container>
|
|
||||||
<text
|
|
||||||
loc={[240, 180, void 0, void 0, 0.5, 0.5]}
|
|
||||||
onClick={handleGetName}
|
|
||||||
text="输入姓名"
|
|
||||||
/>
|
|
||||||
<text
|
|
||||||
loc={[240, 220, void 0, void 0, 0.5, 0.5]}
|
|
||||||
onClick={handleGetAge}
|
|
||||||
text="输入年龄"
|
|
||||||
/>
|
|
||||||
</container>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 带自定义样式的输入对话框
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { getInput } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const StyledInputCom = defineComponent(props => {
|
|
||||||
const handleStyledInput = async () => {
|
|
||||||
const value = await getInput(
|
|
||||||
props.controller,
|
|
||||||
'请输入任务描述:',
|
|
||||||
[240, 240, void 0, void 0, 0.5, 0.5],
|
|
||||||
320,
|
|
||||||
{
|
|
||||||
text: '任务创建',
|
|
||||||
input: {
|
|
||||||
placeholder: '描述任务内容...',
|
|
||||||
multiline: true,
|
|
||||||
border: '#4CAF50',
|
|
||||||
borderWidth: 2,
|
|
||||||
circle: 8,
|
|
||||||
pad: 12
|
|
||||||
},
|
|
||||||
color: '#ffffff',
|
|
||||||
border: '#4CAF50',
|
|
||||||
borderWidth: 3,
|
|
||||||
pad: 20,
|
|
||||||
inputHeight: 80,
|
|
||||||
yesText: '创建',
|
|
||||||
noText: '取消',
|
|
||||||
selFill: '#4CAF50'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
console.log('创建任务:', value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<text
|
|
||||||
loc={[240, 240, void 0, void 0, 0.5, 0.5]}
|
|
||||||
onClick={handleStyledInput}
|
|
||||||
text="创建新任务"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 游戏中的设置界面
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { getInput } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const SettingsCom = defineComponent(props => {
|
|
||||||
const settings = ref({
|
|
||||||
playerName: '玩家',
|
|
||||||
serverIP: '127.0.0.1'
|
|
||||||
});
|
|
||||||
|
|
||||||
const changePlayerName = async () => {
|
|
||||||
const newName = await getInput(
|
|
||||||
props.controller,
|
|
||||||
'修改玩家名称:',
|
|
||||||
[240, 240, void 0, void 0, 0.5, 0.5],
|
|
||||||
280,
|
|
||||||
{
|
|
||||||
input: {
|
|
||||||
value: settings.value.playerName,
|
|
||||||
placeholder: '玩家名称',
|
|
||||||
border: '#FF9800',
|
|
||||||
borderWidth: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (newName) {
|
|
||||||
settings.value.playerName = newName;
|
|
||||||
console.log('玩家名称已更新:', newName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeServerIP = async () => {
|
|
||||||
const newIP = await getInput(
|
|
||||||
props.controller,
|
|
||||||
'修改服务器IP:',
|
|
||||||
[240, 240, void 0, void 0, 0.5, 0.5],
|
|
||||||
280,
|
|
||||||
{
|
|
||||||
input: {
|
|
||||||
value: settings.value.serverIP,
|
|
||||||
placeholder: '服务器IP地址',
|
|
||||||
border: '#2196F3',
|
|
||||||
borderWidth: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (newIP) {
|
|
||||||
settings.value.serverIP = newIP;
|
|
||||||
console.log('服务器IP已更新:', newIP);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<container loc={[240, 240, 300, 200, 0.5, 0.5]}>
|
|
||||||
<text
|
|
||||||
loc={[0, -40, void 0, void 0, 0.5, 0.5]}
|
|
||||||
onClick={changePlayerName}
|
|
||||||
text={`玩家名称: ${settings.value.playerName}`}
|
|
||||||
/>
|
|
||||||
<text
|
|
||||||
loc={[0, 0, void 0, void 0, 0.5, 0.5]}
|
|
||||||
onClick={changeServerIP}
|
|
||||||
text={`服务器IP: ${settings.value.serverIP}`}
|
|
||||||
/>
|
|
||||||
</container>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **推荐使用工具函数**: `getInput` 和 `getInputNumber` 提供了更简洁的异步输入获取方式
|
|
||||||
2. **宽度设置**: 在使用工具函数时,高度由组件自动计算,只需指定宽度
|
|
||||||
3. **皮肤优先级**: 如果设置了 `winskin`,则 `color` 和 `border` 设置将失效
|
|
||||||
4. **异步处理**: 工具函数返回 Promise,需要使用 `await` 或 `.then()` 处理结果
|
|
||||||
5. **空值处理**: 用户取消输入时,`getInput` 返回空字符串,`getInputNumber` 返回 `NaN`
|
|
||||||
@ -1,184 +0,0 @@
|
|||||||
# List 列表组件 API 文档
|
|
||||||
|
|
||||||
本文档由 `DeepSeek` 生成并微调。
|
|
||||||
|
|
||||||
## 组件描述
|
|
||||||
|
|
||||||
列表组件用于展示可选择的项目列表,内置滚动条功能和选中项高亮效果。适用于菜单选择、内容导航、设置选项等场景。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Props 属性说明
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 描述 |
|
|
||||||
| ------------ | -------------------- | ------ | ------------------------------- |
|
|
||||||
| `list` | `[string, string][]` | 必填 | 列表内容,[id, 显示文本] 的数组 |
|
|
||||||
| `selected` | `string` | 必填 | 当前选中的项 ID |
|
|
||||||
| `loc` | `ElementLocator` | 必填 | 列表的位置和尺寸 |
|
|
||||||
| `lineHeight` | `number` | `18` | 每行的高度 |
|
|
||||||
| `font` | `Font` | - | 列表项的字体样式 |
|
|
||||||
| `winskin` | `ImageIds` | - | 使用 winskin 作为光标背景 |
|
|
||||||
| `color` | `CanvasStyle` | - | 使用指定样式作为光标背景 |
|
|
||||||
| `border` | `CanvasStyle` | - | 使用指定样式作为光标边框 |
|
|
||||||
| `alphaRange` | `[number, number]` | - | 选择图标的不透明度范围 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Events 事件说明
|
|
||||||
|
|
||||||
| 事件名 | 参数类型 | 触发时机 |
|
|
||||||
| ----------------- | ----------------- | ---------------------- |
|
|
||||||
| `update` | `(key: string)` | 当用户选中某一项时触发 |
|
|
||||||
| `update:selected` | `(value: string)` | v-model 双向绑定事件 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slots 插槽说明
|
|
||||||
|
|
||||||
无插槽
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exposed Methods 暴露方法
|
|
||||||
|
|
||||||
无暴露方法
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基础用法 - 简单列表
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { List } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MyCom = defineComponent(() => {
|
|
||||||
const selectedItem = ref('item1');
|
|
||||||
|
|
||||||
// 列表数据:[id, 显示文本]
|
|
||||||
const listData = [
|
|
||||||
['item1', '第一项'],
|
|
||||||
['item2', '第二项'],
|
|
||||||
['item3', '第三项'],
|
|
||||||
['item4', '第四项']
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleSelect = (key: string) => {
|
|
||||||
console.log('选中项:', key);
|
|
||||||
selectedItem.value = key;
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<List
|
|
||||||
list={listData}
|
|
||||||
v-model:selected={selectedItem.value}
|
|
||||||
loc={[0, 0, 100, 300, 0, 0]}
|
|
||||||
selected={selectedItem.value}
|
|
||||||
onUpdate={handleSelect}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 带样式的列表
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { List } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const StyledListCom = defineComponent(() => {
|
|
||||||
const selected = ref('opt2');
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
['opt1', '开始游戏'],
|
|
||||||
['opt2', '游戏设置'],
|
|
||||||
['opt3', '帮助文档'],
|
|
||||||
['opt4', '关于我们']
|
|
||||||
];
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<List
|
|
||||||
list={options}
|
|
||||||
v-model:selected={selected.value}
|
|
||||||
loc={[0, 0, 100, 300, 0, 0]}
|
|
||||||
lineHeight={24}
|
|
||||||
color="#e3f2fd"
|
|
||||||
border="#2196f3"
|
|
||||||
borderWidth={1}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用皮肤图片的列表
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { List } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const SkinnedListCom = defineComponent(() => {
|
|
||||||
const currentSelection = ref('cat');
|
|
||||||
|
|
||||||
const animalList = [
|
|
||||||
['cat', '猫咪'],
|
|
||||||
['dog', '小狗'],
|
|
||||||
['bird', '小鸟'],
|
|
||||||
['fish', '小鱼']
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleUpdate = key => {
|
|
||||||
const item = animalList.find(item => item[0] === key)?.[1];
|
|
||||||
currentSelection.value = key;
|
|
||||||
console.log('选择了:', item);
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<List
|
|
||||||
list={animalList}
|
|
||||||
selected={currentSelection.value}
|
|
||||||
loc={[0, 0, 100, 300, 0, 0]}
|
|
||||||
winskin="winskin.png"
|
|
||||||
lineHeight={20}
|
|
||||||
onUpdate={handleUpdate}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 长列表滚动示例
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { List } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const ScrollListCom = defineComponent(() => {
|
|
||||||
const selected = ref('item5');
|
|
||||||
|
|
||||||
// 创建长列表数据
|
|
||||||
const longList = Array.from({ length: 20 }, (_, i) => [
|
|
||||||
`item${i + 1}`,
|
|
||||||
`列表项 ${i + 1}`
|
|
||||||
]);
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<List
|
|
||||||
list={longList}
|
|
||||||
v-model:selected={selected.value}
|
|
||||||
loc={[0, 0, 100, 300, 0, 0]}
|
|
||||||
lineHeight={20}
|
|
||||||
color="#fff3e0"
|
|
||||||
border="#ff9800"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **数据格式**: `list` 属性需要 `[id, text]` 格式的二维数组
|
|
||||||
2. **选中状态**: `selected` 需要与列表项中的 id 匹配
|
|
||||||
3. **滚动支持**: 自动显示滚动条
|
|
||||||
4. **样式优先级**: 如果设置了 `winskin`,则 `color` 和 `border` 设置将失效
|
|
||||||
@ -1,226 +0,0 @@
|
|||||||
# ListPage 列表页面组件 API 文档
|
|
||||||
|
|
||||||
本文档由 `DeepSeek` 生成并微调。
|
|
||||||
|
|
||||||
## 组件描述
|
|
||||||
|
|
||||||
列表页面组件结合了列表选择和内容展示功能,左侧显示可选项列表,右侧显示选中项的详细内容。适用于说明文档、设置界面、内容导航等场景。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Props 属性说明
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 描述 |
|
|
||||||
| ------------------ | ---------------- | ------- | ---------------------------------------------- |
|
|
||||||
| `loc` | `ElementLocator` | 必填 | 组件整体位置和尺寸 |
|
|
||||||
| `basis` | `number` | - | 列表区域所占比例 |
|
|
||||||
| `right` | `boolean` | `false` | 列表是否排列在右侧 |
|
|
||||||
| `close` | `boolean` | `false` | 是否显示关闭按钮 |
|
|
||||||
| `closeLoc` | `ElementLocator` | - | 关闭按钮的位置(相对于组件定位) |
|
|
||||||
| 继承自 `ListProps` | - | - | [查看完整属性](./组件%20List#Props%20属性说明) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Events 事件说明
|
|
||||||
|
|
||||||
| 事件名 | 参数类型 | 触发时机 |
|
|
||||||
| ----------------- | ----------------- | ------------------------------------ |
|
|
||||||
| `close` | - | 当用户点击关闭按钮时触发 |
|
|
||||||
| `update` | `(key: string)` | 继承自 List - 当用户选中某一项时触发 |
|
|
||||||
| `update:selected` | `(value: string)` | 继承自 List - v-model 双向绑定事件 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slots 插槽说明
|
|
||||||
|
|
||||||
### `default`
|
|
||||||
|
|
||||||
接收当前选中的 key 并返回对应的内容
|
|
||||||
|
|
||||||
**参数**
|
|
||||||
|
|
||||||
- `key: string` 当前选中的项 ID
|
|
||||||
|
|
||||||
### 具名插槽
|
|
||||||
|
|
||||||
以列表项 ID 为名称的具名插槽,用于定义每个选项对应的详细内容
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基础用法 - 说明文档界面
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { ListPage } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const HelpCom = defineComponent(() => {
|
|
||||||
const selected = ref('intro');
|
|
||||||
|
|
||||||
const helpTopics = [
|
|
||||||
['intro', '功能介绍'],
|
|
||||||
['usage', '使用方法'],
|
|
||||||
['settings', '设置说明'],
|
|
||||||
['faq', '常见问题']
|
|
||||||
];
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<ListPage
|
|
||||||
list={helpTopics}
|
|
||||||
v-model:selected={selected.value}
|
|
||||||
loc={[208, 208, 400, 300, 0.5, 0.5]}
|
|
||||||
basis={0.3}
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
// 使用具名插槽定义每个选项的内容
|
|
||||||
intro: () => (
|
|
||||||
<container>
|
|
||||||
<text text="这里是最新版本的功能介绍..." loc={[0, 0]} />
|
|
||||||
<text text="欢迎使用本系统" loc={[0, 40]} />
|
|
||||||
</container>
|
|
||||||
),
|
|
||||||
usage: () => (
|
|
||||||
<container>
|
|
||||||
<text text="使用方法指南" loc={[0, 0]} />
|
|
||||||
<text text="1. 点击左侧菜单选择功能" loc={[0, 40]} />
|
|
||||||
<text text="2. 在右侧查看详细说明" loc={[0, 80]} />
|
|
||||||
</container>
|
|
||||||
),
|
|
||||||
settings: () => <text text="设置说明内容..." loc={[0, 0]} />,
|
|
||||||
faq: () => <text text="常见问题解答..." loc={[0, 0]} />
|
|
||||||
}}
|
|
||||||
</ListPage>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用默认插槽
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { ListPage } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const SimpleCom = defineComponent(() => {
|
|
||||||
const selected = ref('item1');
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
['item1', '选项一'],
|
|
||||||
['item2', '选项二'],
|
|
||||||
['item3', '选项三']
|
|
||||||
];
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<ListPage
|
|
||||||
list={items}
|
|
||||||
v-model:selected={selected.value}
|
|
||||||
loc={[208, 208, 350, 250, 0.5, 0.5]}
|
|
||||||
>
|
|
||||||
{key => (
|
|
||||||
<container>
|
|
||||||
<text
|
|
||||||
text={`当前选中: ${items.find(item => item[0] === key)?.[1]}`}
|
|
||||||
loc={[0, 0]}
|
|
||||||
/>
|
|
||||||
<text text={`ID: ${key}`} loc={[0, 30]} />
|
|
||||||
</container>
|
|
||||||
)}
|
|
||||||
</ListPage>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 带关闭按钮的弹窗
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { ListPage } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const ModalCom = defineComponent(props => {
|
|
||||||
const selected = ref('weapon');
|
|
||||||
|
|
||||||
const gameItems = [
|
|
||||||
['weapon', '武器'],
|
|
||||||
['armor', '防具'],
|
|
||||||
['potion', '药水'],
|
|
||||||
['material', '材料']
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
props.controller.close(props.instance);
|
|
||||||
console.log('关闭物品栏');
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<ListPage
|
|
||||||
list={gameItems}
|
|
||||||
v-model:selected={selected.value}
|
|
||||||
loc={[208, 208, 400, 320, 0.5, 0.5]}
|
|
||||||
close
|
|
||||||
// 设定关闭按钮的位置
|
|
||||||
closeLoc={[0, 300]}
|
|
||||||
basis={0.35}
|
|
||||||
onClose={handleClose}
|
|
||||||
>
|
|
||||||
{{
|
|
||||||
weapon: () => (
|
|
||||||
<container>
|
|
||||||
<text text="武器列表" loc={[0, 0]} />
|
|
||||||
<text text="• 长剑" loc={[0, 30]} />
|
|
||||||
<text text="• 弓箭" loc={[0, 60]} />
|
|
||||||
<text text="• 法杖" loc={[0, 90]} />
|
|
||||||
</container>
|
|
||||||
),
|
|
||||||
armor: () => <text text="防具装备信息..." loc={[0, 0]} />,
|
|
||||||
potion: () => <text text="药水效果说明..." loc={[0, 0]} />,
|
|
||||||
material: () => <text text="合成材料列表..." loc={[0, 0]} />
|
|
||||||
}}
|
|
||||||
</ListPage>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 列表在右侧的布局
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent, ref } from 'vue';
|
|
||||||
import { ListPage } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const RightListCom = defineComponent(() => {
|
|
||||||
const selected = ref('profile');
|
|
||||||
|
|
||||||
const menuItems = [
|
|
||||||
['profile', '个人资料'],
|
|
||||||
['security', '安全设置'],
|
|
||||||
['privacy', '隐私设置'],
|
|
||||||
['notifications', '通知设置']
|
|
||||||
];
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<ListPage
|
|
||||||
list={menuItems}
|
|
||||||
v-model:selected={selected.value}
|
|
||||||
loc={[240, 240, 500, 280, 0.5, 0.5]}
|
|
||||||
right
|
|
||||||
basis={0.4}
|
|
||||||
>
|
|
||||||
{key => (
|
|
||||||
<container>
|
|
||||||
<text text="显示一些内容..." loc={[0, 60]} />
|
|
||||||
<text text="这里是详细的设置内容..." loc={[0, 0]} />
|
|
||||||
</container>
|
|
||||||
)}
|
|
||||||
</ListPage>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **插槽使用**: 可以使用具名插槽(以列表项 ID 为名)或默认插槽来定义内容
|
|
||||||
2. **布局控制**: 通过 `basis` 控制列表区域比例,`right` 控制列表位置
|
|
||||||
3. **关闭功能**: 设置 `close` 为 `true` 显示关闭按钮,通过 `closeLoc` 自定义位置
|
|
||||||
4. **事件处理**: `close` 事件需要手动处理界面关闭逻辑
|
|
||||||
5. **内容更新**: 切换列表选项时,右侧内容会自动更新为对应插槽的内容
|
|
||||||
@ -1,119 +0,0 @@
|
|||||||
# Thumbnail 地图缩略图组件 API 文档
|
|
||||||
|
|
||||||
本文档由 `DeepSeek` 生成并微调。
|
|
||||||
|
|
||||||
## 组件描述
|
|
||||||
|
|
||||||
地图缩略图组件用于在游戏界面中显示当前楼层的迷你地图,可展示地图布局、角色位置、伤害区域等信息。适用于小地图显示、地图预览等场景。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Props 属性说明
|
|
||||||
|
|
||||||
| 属性名 | 类型 | 默认值 | 描述 |
|
|
||||||
| ---------- | ---------------- | ------ | -------------------------------------- |
|
|
||||||
| `loc` | `ElementLocator` | 必填 | 缩略图的位置和尺寸 |
|
|
||||||
| `floorId` | `FloorIds` | 必填 | 楼层 ID |
|
|
||||||
| `padStyle` | `CanvasStyle` | - | 缩略图填充样式 |
|
|
||||||
| `map` | `Block[]` | - | 楼层信息 |
|
|
||||||
| `hero` | `HeroStatus` | - | 角色信息 |
|
|
||||||
| `damage` | `boolean` | - | 是否显示地图伤害 |
|
|
||||||
| `all` | `boolean` | - | 是否完全展示地图(false 时只显示部分) |
|
|
||||||
| `noHD` | `boolean` | - | 是否使用高清模式 |
|
|
||||||
| `size` | `number` | - | 缩略图的比例(1 表示与实际地图一致) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Events 事件说明
|
|
||||||
|
|
||||||
无事件
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Slots 插槽说明
|
|
||||||
|
|
||||||
无插槽
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Exposed Methods 暴露方法
|
|
||||||
|
|
||||||
无暴露方法
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 基础用法 - 显示当前楼层缩略图
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Thumbnail } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MiniMapCom = defineComponent(() => {
|
|
||||||
return () => (
|
|
||||||
<Thumbnail
|
|
||||||
loc={[400, 50, 120, 120, 1, 0]}
|
|
||||||
floorId="main_floor"
|
|
||||||
padStyle="#2c3e50"
|
|
||||||
size={0.1}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 带角色位置的小地图
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Thumbnail } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const GameHUDCom = defineComponent(props => {
|
|
||||||
const heroStatus: HeroStatus = {
|
|
||||||
// 角色状态信息
|
|
||||||
loc: { x: 100, y: 150 }
|
|
||||||
// ... 其他角色属性
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
|
||||||
<container loc={[400, 50, 150, 150, 1, 0]}>
|
|
||||||
<Thumbnail
|
|
||||||
loc={[0, 0, 150, 150, 0.5, 0.5]}
|
|
||||||
floorId="dungeon_1"
|
|
||||||
hero={heroStatus}
|
|
||||||
padStyle="#34495e"
|
|
||||||
damage
|
|
||||||
size={0.08}
|
|
||||||
/>
|
|
||||||
<text text="小地图" loc={[0, 0]} />
|
|
||||||
</container>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 完整地图预览
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { Thumbnail } from '@user/client-modules';
|
|
||||||
|
|
||||||
export const MapPreviewCom = defineComponent(() => {
|
|
||||||
return () => (
|
|
||||||
<Thumbnail
|
|
||||||
loc={[240, 240, 300, 300, 0.5, 0.5]}
|
|
||||||
floorId="boss_arena"
|
|
||||||
all
|
|
||||||
padStyle="#1a1a1a"
|
|
||||||
size={0.3}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **楼层标识**: `floorId` 必须与游戏中的楼层标识匹配
|
|
||||||
2. **比例控制**: `size` 参数控制缩略图与实际地图的比例关系
|
|
||||||
3. **显示范围**: `all` 为 false 时,大地图只会显示当前可视区域
|
|
||||||
@ -28,7 +28,7 @@ lang: zh-CN
|
|||||||
|
|
||||||
相比于 2.10.3 及 2.A,有如下改动:
|
相比于 2.10.3 及 2.A,有如下改动:
|
||||||
|
|
||||||
- [系统说明](./system.md)
|
- [系统说明](./system)
|
||||||
- [UI 编写](./ui/ui.md)
|
- [UI 编写](./ui)
|
||||||
- [UI 系统](./ui/system.md)
|
- [UI 系统](./ui/system)
|
||||||
- [音频系统](./audio.md)
|
- [音频系统](./audio)
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
## 定义动画属性
|
## 定义动画属性
|
||||||
|
|
||||||
我们以一个自定义 UI 为例,来讲述如何编写一段动画。自定义 UI 参考[此指南](./new-ui.md)和[此教程](../../guide/ui/ui.md)。
|
我们以一个自定义 UI 为例,来讲述如何编写一段动画。自定义 UI 参考[此指南](./new-ui.md)和[此教程](../../guide/ui.md)。
|
||||||
|
|
||||||
假设自定义 UI 在 `packages-user/client-modules/src/render/ui` 文件夹下,我们需要引入 `transitioned` 接口,并调用它定义动画属性:
|
假设自定义 UI 在 `packages-user/client-modules/src/render/ui` 文件夹下,我们需要引入 `transitioned` 接口,并调用它定义动画属性:
|
||||||
|
|
||||||
|
|||||||
@ -275,7 +275,7 @@ export const MyCom = defineComponent(props => {
|
|||||||
|
|
||||||
- [ConfirmBox](../../api/user-client-modules/组件%20ConfirmBox.md)
|
- [ConfirmBox](../../api/user-client-modules/组件%20ConfirmBox.md)
|
||||||
- [Choices](../../api/user-client-modules/组件%20Choices.md)
|
- [Choices](../../api/user-client-modules/组件%20Choices.md)
|
||||||
- [WaitBox](../../api/user-client-modules/组件%20WaitBox.md)
|
- [Waitbox](../../api/user-client-modules/组件%20Waitbox.md)
|
||||||
- [getConfirm](../../api/user-client-modules/functions.md#getconfirm)
|
- [getConfirm](../../api/user-client-modules/functions.md#getconfirm)
|
||||||
- [getChoice](../../api/user-client-modules/functions.md#getchoice)
|
- [getChoice](../../api/user-client-modules/functions.md#getchoice)
|
||||||
- [waitbox 方法](../../api/user-client-modules/functions.md#waitbox)
|
- [waitbox](../../api/user-client-modules/functions.md#waitbox)
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
- [新增勇士属性](./status-bar.md#拓展-新增勇士属性) (既包含客户端,也包含数据端)
|
- [新增勇士属性](./status-bar.md#拓展-新增勇士属性) (既包含客户端,也包含数据端)
|
||||||
- [编写新 UI](./new-ui.md)
|
- [编写新 UI](./new-ui.md)
|
||||||
- [UI 与组件的区别](./new-ui.md#拓展-ui-与组件的区别)
|
- [UI 与组件的区别](./new-ui.md#拓展-ui-与组件的区别)
|
||||||
- [UI 编写参考](../ui/ui.md)
|
- [UI 编写参考](../ui.md)
|
||||||
- [新增按键](./hotkey.md)
|
- [新增按键](./hotkey.md)
|
||||||
- [添加辅助按键](./hotkey.md#拓展-添加辅助按键)
|
- [添加辅助按键](./hotkey.md#拓展-添加辅助按键)
|
||||||
- [在 UI 内实现按键](./hotkey.md#拓展-在-ui-内实现按键)
|
- [在 UI 内实现按键](./hotkey.md#拓展-在-ui-内实现按键)
|
||||||
@ -36,6 +36,7 @@
|
|||||||
- [用函数声明属性](./special.md#拓展-用函数声明属性)
|
- [用函数声明属性](./special.md#拓展-用函数声明属性)
|
||||||
- [地图伤害](./special.md#拓展-地图伤害)
|
- [地图伤害](./special.md#拓展-地图伤害)
|
||||||
- [光环属性](./special.md#拓展-光环属性)
|
- [光环属性](./special.md#拓展-光环属性)
|
||||||
|
- [输出回合数](./special.md#拓展-输出回合数)
|
||||||
- [主动技能](./skill.md)
|
- [主动技能](./skill.md)
|
||||||
- [多技能设计思路](./skill.md#拓展-多技能设计思路)
|
- [多技能设计思路](./skill.md#拓展-多技能设计思路)
|
||||||
- [战后自动关闭技能](./skill.md#拓展-战后自动关闭技能)
|
- [战后自动关闭技能](./skill.md#拓展-战后自动关闭技能)
|
||||||
|
|||||||
@ -82,7 +82,7 @@ controller.close(ins);
|
|||||||
|
|
||||||
## UI 编写参考
|
## UI 编写参考
|
||||||
|
|
||||||
参考[此文档](../ui/ui.md),此文档将会教你如何从头开始编写一个 UI,并解释 UI 运行与渲染的基本逻辑。
|
参考[此文档](../ui.md),此文档将会教你如何从头开始编写一个 UI,并解释 UI 运行与渲染的基本逻辑。
|
||||||
|
|
||||||
## 拓展-UI 与组件的区别
|
## 拓展-UI 与组件的区别
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export function toggleSkill1() {
|
|||||||
import { getSkill1Enabled } from '../machanism/skill'; // [!code ++]
|
import { getSkill1Enabled } from '../machanism/skill'; // [!code ++]
|
||||||
|
|
||||||
export function calDamageWith(
|
export function calDamageWith(
|
||||||
info: EnemyInfo,
|
info: UserEnemyInfo,
|
||||||
hero: Partial<HeroStatus>
|
hero: Partial<HeroStatus>
|
||||||
): number | null {
|
): number | null {
|
||||||
// ... 原有内容
|
// ... 原有内容
|
||||||
@ -241,7 +241,7 @@ export function getEnabledSkill() {
|
|||||||
import { getEnabledSkill, SkillType } from './skill';
|
import { getEnabledSkill, SkillType } from './skill';
|
||||||
|
|
||||||
export function calDamageWith(
|
export function calDamageWith(
|
||||||
info: EnemyInfo,
|
info: UserEnemyInfo,
|
||||||
hero: Partial<HeroStatus>
|
hero: Partial<HeroStatus>
|
||||||
): number | null {
|
): number | null {
|
||||||
// ... 原有内容
|
// ... 原有内容
|
||||||
@ -260,7 +260,7 @@ export function calDamageWith(
|
|||||||
import { getEnabledSkill, SkillType } from './skill';
|
import { getEnabledSkill, SkillType } from './skill';
|
||||||
|
|
||||||
export function calDamageWith(
|
export function calDamageWith(
|
||||||
info: EnemyInfo,
|
info: UserEnemyInfo,
|
||||||
hero: Partial<HeroStatus>
|
hero: Partial<HeroStatus>
|
||||||
): number | null {
|
): number | null {
|
||||||
// ... 原有内容
|
// ... 原有内容
|
||||||
|
|||||||
@ -26,13 +26,13 @@ export const specials: SpecialDeclaration[] = [
|
|||||||
|
|
||||||
## 实现特殊属性
|
## 实现特殊属性
|
||||||
|
|
||||||
打开 `packages-user/data-state/src/enemy/damage.ts`,在文件最后的 `calDamageWithTurn` 函数中编写:
|
打开 `packages-user/data-state/src/enemy/damage.ts`,在文件最后的 `calDamageWith` 函数中编写:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export function calDamageWithTurn(
|
export function calDamageWith(
|
||||||
info: EnemyInfo,
|
info: UserEnemyInfo,
|
||||||
hero: Partial<HeroStatus>
|
hero: Partial<HeroStatus>
|
||||||
): DamageWithTurn {
|
): number | null {
|
||||||
// ... 原有内容
|
// ... 原有内容
|
||||||
|
|
||||||
// 在需要降低勇士伤害的地方将勇士伤害乘以 0.9 即可
|
// 在需要降低勇士伤害的地方将勇士伤害乘以 0.9 即可
|
||||||
@ -102,13 +102,13 @@ export const specials: SpecialDeclaration[] = [
|
|||||||
|
|
||||||
### 属性实现
|
### 属性实现
|
||||||
|
|
||||||
修改 `damage.ts` `calDamageWithTurn` 中的实现:
|
修改 `damage.ts` `calDamageWith` 中的实现:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
export function calDamageWithTurn(
|
export function calDamageWith(
|
||||||
info: EnemyInfo,
|
info: UserEnemyInfo,
|
||||||
hero: Partial<HeroStatus>
|
hero: Partial<HeroStatus>
|
||||||
): DamageWithTurn {
|
): number | null {
|
||||||
// ... 原有内容
|
// ... 原有内容
|
||||||
|
|
||||||
// 在乘以 1 - (myAttr / 100),除以 100 是因为 myAttr 是百分制
|
// 在乘以 1 - (myAttr / 100),除以 100 是因为 myAttr 是百分制
|
||||||
@ -210,11 +210,10 @@ class DamageEnemy {
|
|||||||
|
|
||||||
### 自定义形状
|
### 自定义形状
|
||||||
|
|
||||||
如果想要自定义光环形状,我们打开 `packages-user/data-utils/src/range.ts`,拉到最后可以看到形状定义,目前默认的包含这些:
|
如果想要自定义光环形状,我们打开 `packages-user/data-utils/src/range.ts`,拉到最后可以看到形状定义,目前包含两个:
|
||||||
|
|
||||||
- `square`: 中心点+边长的正方形
|
- `square`: 中心点+边长的正方形
|
||||||
- `rect`: 左上角坐标+宽高的矩形
|
- `rect`: 左上角坐标+宽高的矩形
|
||||||
- `manhattan`: 曼哈顿距离,坐标之和小于半径
|
|
||||||
|
|
||||||
我们以曼哈顿距离为例,展示如何自定义形状。
|
我们以曼哈顿距离为例,展示如何自定义形状。
|
||||||
|
|
||||||
@ -263,3 +262,27 @@ col.applyHalo(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 拓展-输出回合数
|
||||||
|
|
||||||
|
样板默认的 `calDamageWith` 函数只允许输出伤害值,而有时候我们可能会需要战斗的回合数,这时候我们需要修改一下这部分内容,将伤害计算逻辑单独提出来,命名为 `calDamageWithTurn`,然后在 `calDamageWith` 中调用它。在需要回合数的时候,我们调用 `calDamageWithTurn` 函数即可,如下例所示:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
/** 包含回合数的伤害计算 */
|
||||||
|
export function calDamageWithTurn(
|
||||||
|
info: UserEnemyInfo,
|
||||||
|
hero: Partial<HeroStatus>
|
||||||
|
) {
|
||||||
|
// ... 原本 calDamageWith 的计算逻辑,记得删除最后返回伤害的那一行返回值
|
||||||
|
|
||||||
|
// 返回回合数和伤害
|
||||||
|
return { turn, damage };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calDamageWith(info: UserEnemyInfo, hero: Partial<HeroStatus>) {
|
||||||
|
// 调用单独提出的函数计算伤害值
|
||||||
|
const damageInfo = calDamageWithTurn(info, hero);
|
||||||
|
// 如果伤害不存在,那么返回无穷大
|
||||||
|
return damageInfo?.damage ?? Infinity;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@ -210,7 +210,7 @@ const realStatus: (keyof HeroStatus)[] = [
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
export function calDamageWith(
|
export function calDamageWith(
|
||||||
info: EnemyInfo,
|
info: UserEnemyInfo,
|
||||||
hero: Partial<HeroStatus>
|
hero: Partial<HeroStatus>
|
||||||
): number {
|
): number {
|
||||||
// ... 原有逻辑
|
// ... 原有逻辑
|
||||||
@ -224,4 +224,4 @@ export function calDamageWith(
|
|||||||
|
|
||||||
## 拓展-了解 UI 编写的基本逻辑
|
## 拓展-了解 UI 编写的基本逻辑
|
||||||
|
|
||||||
参考[此文档](../ui/ui.md),此文档将会教你如何从头开始编写一个 UI,并解释 UI 运行与渲染的基本逻辑。
|
参考[此文档](./ui.md),此文档将会教你如何从头开始编写一个 UI,并解释 UI 运行与渲染的基本逻辑。
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## 常见需求实现指南
|
## 常见需求实现指南
|
||||||
|
|
||||||
参考[此文档](./implements/index.md)
|
参考[此文档](./implements.md)
|
||||||
|
|
||||||
## 热重载
|
## 热重载
|
||||||
|
|
||||||
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
当你**制作完游戏**后,点击构建游戏,即可自动构建游戏,构建结果在 `dist` 文件夹,会自动打包到 `dist.zip` 压缩包,发塔或更新上传此压缩包即可。
|
当你**制作完游戏**后,点击构建游戏,即可自动构建游戏,构建结果在 `dist` 文件夹,会自动打包到 `dist.zip` 压缩包,发塔或更新上传此压缩包即可。
|
||||||
|
|
||||||
此帮助文档远比 2.x 的文档易读,也更容易理解,但是遇到问题时我们依然建议直接在造塔群询问,因为你可能不能判断文档中是否有关于你的问题的解答。
|
此帮助文档远比 2.x 的文档易读,也更容易理解,建议多阅读此文档来解决自己的问题,如果问题很复杂,或是短时间内解决不了,再去造塔群询问。
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
graph TD
|
graph TD
|
||||||
|
|||||||
@ -27,7 +27,7 @@ type ElementLocator = [
|
|||||||
- `w` `h`: 元素的长宽,描述了在没有缩放时元素的矩形长宽,默认是没有放缩的。
|
- `w` `h`: 元素的长宽,描述了在没有缩放时元素的矩形长宽,默认是没有放缩的。
|
||||||
- `ax` `ay`: 元素的锚点位置,描述了元素参考点的位置,所有位置变换等将以此点作为参考点。0 表示元素最左侧或最上侧,1 表示最右侧或最下侧,可以填不在 0-1 范围内的值,例如 `[-1, 1]` 表示锚点横坐标在元素左侧一个元素宽度的位置,纵坐标在元素下边缘的位置。
|
- `ax` `ay`: 元素的锚点位置,描述了元素参考点的位置,所有位置变换等将以此点作为参考点。0 表示元素最左侧或最上侧,1 表示最右侧或最下侧,可以填不在 0-1 范围内的值,例如 `[-1, 1]` 表示锚点横坐标在元素左侧一个元素宽度的位置,纵坐标在元素下边缘的位置。
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
示例如下:
|
示例如下:
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,6 @@
|
|||||||
Unexpected error when posting danmaku. Error info: $1
|
Unexpected error when posting danmaku. Error info: $1
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:发送弹幕时发生报错。
|
- 报错原因:发送弹幕时发生报错。
|
||||||
- 解决方案:查看后面的 Error info,检查报错信息内容,按照报错信息修复问题。
|
- 解决方案:查看后面的 Error info,检查报错信息内容,按照报错信息修复问题。
|
||||||
|
|
||||||
@ -26,8 +24,6 @@ Unexpected loading error in loading resource '$1/$2'. Error info: $3
|
|||||||
Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2
|
Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
||||||
- 解决方案:检查弹幕 CSS 语法是否正确。
|
- 解决方案:检查弹幕 CSS 语法是否正确。
|
||||||
|
|
||||||
@ -37,8 +33,6 @@ Syntax error in parsing CSS: Unexpected ':'. Col: $1. CSS string: '$2
|
|||||||
Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2'
|
Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2'
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
||||||
- 解决方案:检查弹幕 CSS 语法是否正确。
|
- 解决方案:检查弹幕 CSS 语法是否正确。
|
||||||
|
|
||||||
@ -48,8 +42,6 @@ Syntax error in parsing CSS: Unexpected ';'. Col: $1. CSS string: '$2'
|
|||||||
Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS string: '$2'
|
Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS string: '$2'
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
||||||
- 解决方案:检查弹幕 CSS 语法是否正确。
|
- 解决方案:检查弹幕 CSS 语法是否正确。
|
||||||
|
|
||||||
@ -59,8 +51,6 @@ Syntax error in parsing CSS: Missing property name after '-'. Col: $1. CSS strin
|
|||||||
Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS string: '$2'
|
Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS string: '$2'
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
||||||
- 解决方案:检查弹幕 CSS 语法是否正确。
|
- 解决方案:检查弹幕 CSS 语法是否正确。
|
||||||
|
|
||||||
@ -70,8 +60,6 @@ Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: $1. CSS
|
|||||||
Syntax error in parsing CSS: Unexpected end of css, expecting property value. Col: $1. CSS string: '$2'
|
Syntax error in parsing CSS: Unexpected end of css, expecting property value. Col: $1. CSS string: '$2'
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
- 报错原因:解析 CSS 时报错,一般是在发送弹幕时引起。
|
||||||
- 解决方案:检查弹幕 CSS 语法是否正确。
|
- 解决方案:检查弹幕 CSS 语法是否正确。
|
||||||
|
|
||||||
@ -81,8 +69,6 @@ Syntax error in parsing CSS: Unexpected end of css, expecting property value. Co
|
|||||||
Post danmaku with not allowed css. Info: $1
|
Post danmaku with not allowed css. Info: $1
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 报错原因:弹幕 CSS 中使用了不允许的 css 属性类型。
|
- 报错原因:弹幕 CSS 中使用了不允许的 css 属性类型。
|
||||||
- 解决方案:目前仅支持 `color` `background-color` `font-size: x%` 属性。
|
- 解决方案:目前仅支持 `color` `background-color` `font-size: x%` 属性。
|
||||||
|
|
||||||
@ -147,7 +133,7 @@ Cannot use shader program for shader element that does not belong to it.
|
|||||||
## ERROR CODE 18
|
## ERROR CODE 18
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
Cannot delete shader program for shader element that does not belong to it.
|
Cannot delete shader program for shader element that does not belong to
|
||||||
```
|
```
|
||||||
|
|
||||||
- 报错原因:在一个着色器上删除了不属于这个着色器的着色器程序。
|
- 报错原因:在一个着色器上删除了不属于这个着色器的着色器程序。
|
||||||
|
|||||||
@ -24,8 +24,6 @@ Repeat load of resource '$1/$2'.
|
|||||||
Unknown danmaku tag: $1
|
Unknown danmaku tag: $1
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 警告原因:出现了未知的弹幕标签(指 `[xxx:xxx]`)
|
- 警告原因:出现了未知的弹幕标签(指 `[xxx:xxx]`)
|
||||||
- 解决方案:目前仅支持 `[i:xxx]` 标签,如果需要显示方括号,请使用 `\[\]`。
|
- 解决方案:目前仅支持 `[i:xxx]` 标签,如果需要显示方括号,请使用 `\[\]`。
|
||||||
|
|
||||||
@ -35,8 +33,6 @@ Unknown danmaku tag: $1
|
|||||||
Ignored a mismatched ']' in danmaku.
|
Ignored a mismatched ']' in danmaku.
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 警告原因:出现了不能匹配的右方括号。
|
- 警告原因:出现了不能匹配的右方括号。
|
||||||
- 解决方案:如果需要显示方括号,请使用 `\[\]`。
|
- 解决方案:如果需要显示方括号,请使用 `\[\]`。
|
||||||
|
|
||||||
@ -46,8 +42,6 @@ Ignored a mismatched ']' in danmaku.
|
|||||||
Repeat post danmaku.
|
Repeat post danmaku.
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 警告原因:同一个弹幕被发送了两次。
|
- 警告原因:同一个弹幕被发送了两次。
|
||||||
- 解决方案:确保一个弹幕实例只调用了一次 `post` 方法。
|
- 解决方案:确保一个弹幕实例只调用了一次 `post` 方法。
|
||||||
|
|
||||||
@ -57,8 +51,6 @@ Repeat post danmaku.
|
|||||||
Registered special danmaku element: $1.
|
Registered special danmaku element: $1.
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 警告原因:要注册的弹幕标签已经存在。
|
- 警告原因:要注册的弹幕标签已经存在。
|
||||||
- 解决方案:避免使用同一个标签名,如果内容不一样请换一个标签名。
|
- 解决方案:避免使用同一个标签名,如果内容不一样请换一个标签名。
|
||||||
|
|
||||||
@ -158,8 +150,6 @@ Floor-damage extension needs 'floor-binder' extension as dependency.
|
|||||||
Uncaught error in posting like info for danmaku. Danmaku id: $1.
|
Uncaught error in posting like info for danmaku. Danmaku id: $1.
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置弹幕系统。
|
|
||||||
|
|
||||||
- 警告原因:为弹幕点赞时出现报错。
|
- 警告原因:为弹幕点赞时出现报错。
|
||||||
- 解决方案:可能是网络问题,检查网络。
|
- 解决方案:可能是网络问题,检查网络。
|
||||||
|
|
||||||
@ -169,8 +159,6 @@ Uncaught error in posting like info for danmaku. Danmaku id: $1.
|
|||||||
Repeat light id: '$1'
|
Repeat light id: '$1'
|
||||||
```
|
```
|
||||||
|
|
||||||
> 应该不会遇到这个报错,因为样板并不内置点光源。
|
|
||||||
|
|
||||||
- 警告原因:重复的光源 id。
|
- 警告原因:重复的光源 id。
|
||||||
- 解决方案:避免光源 id 出现重复。
|
- 解决方案:避免光源 id 出现重复。
|
||||||
|
|
||||||
@ -296,7 +284,8 @@ Sub-image exceeds texture dimensions, auto adjusting size.
|
|||||||
Cannot modify MotaOffscreenCanvas2D that is freezed.
|
Cannot modify MotaOffscreenCanvas2D that is freezed.
|
||||||
```
|
```
|
||||||
|
|
||||||
- 遇不到这个报错。
|
- 警告原因:不能修改已冻结的画布属性。
|
||||||
|
- 解决方案:如果这个画布后续还需要修改属性,那么就不要冻结它。
|
||||||
|
|
||||||
## WARN CODE 34
|
## WARN CODE 34
|
||||||
|
|
||||||
|
|||||||
@ -116,21 +116,3 @@ Uncaught promise error in waiting box component. Error reason: $1
|
|||||||
|
|
||||||
- 警告原因:在等待 box 组件(选择框、确认框等)时,出现了异步报错。
|
- 警告原因:在等待 box 组件(选择框、确认框等)时,出现了异步报错。
|
||||||
- 解决方案:根据报错内容解决问题。
|
- 解决方案:根据报错内容解决问题。
|
||||||
|
|
||||||
## WARN CODE 64
|
|
||||||
|
|
||||||
```txt
|
|
||||||
Text node type and block type mismatch: '$1' vs '$2'
|
|
||||||
```
|
|
||||||
|
|
||||||
- 警告原因:多行文本(TextContent)解析时节点类型和分块类型不一致。
|
|
||||||
- 解决方案:理应不会遇到这个问题,如果遇到了,请到造塔群寻求帮助。
|
|
||||||
|
|
||||||
## WARN CODE 65
|
|
||||||
|
|
||||||
```txt
|
|
||||||
Cannot bind a weather controller twice.
|
|
||||||
```
|
|
||||||
|
|
||||||
- 警告原因:一个天气控制器不能绑定到两个元素上。
|
|
||||||
- 解决方案:如果两个元素需要天气,那么请创建两个天气控制器,一个天气控制器只能绑定一个,且不能解绑。
|
|
||||||
|
|||||||
@ -715,7 +715,6 @@ export async function routedConfirm(
|
|||||||
const confirm = getChoiceRoute(1) === 0;
|
const confirm = getChoiceRoute(1) === 0;
|
||||||
const timeout = core.control.__replay_getTimeout();
|
const timeout = core.control.__replay_getTimeout();
|
||||||
core.status.route.push(`choices:${confirm ? 0 : 1}`);
|
core.status.route.push(`choices:${confirm ? 0 : 1}`);
|
||||||
core.status.replay.toReplay.shift();
|
|
||||||
if (timeout === 0) return confirm;
|
if (timeout === 0) return confirm;
|
||||||
const instance = controller.open(ConfirmBoxUI, {
|
const instance = controller.open(ConfirmBoxUI, {
|
||||||
...(props ?? {}),
|
...(props ?? {}),
|
||||||
@ -770,7 +769,6 @@ export async function routedChoices<T extends ChoiceKey>(
|
|||||||
const selected = getChoiceRoute(0);
|
const selected = getChoiceRoute(0);
|
||||||
const timeout = core.control.__replay_getTimeout();
|
const timeout = core.control.__replay_getTimeout();
|
||||||
core.status.route.push(`choices:${selected}`);
|
core.status.route.push(`choices:${selected}`);
|
||||||
core.status.replay.toReplay.shift();
|
|
||||||
if (timeout === 0) return choices[selected][0];
|
if (timeout === 0) return choices[selected][0];
|
||||||
const instance = controller.open(ChoicesUI, {
|
const instance = controller.open(ChoicesUI, {
|
||||||
...(props ?? {}),
|
...(props ?? {}),
|
||||||
@ -784,7 +782,7 @@ export async function routedChoices<T extends ChoiceKey>(
|
|||||||
return choices[selected][0];
|
return choices[selected][0];
|
||||||
} else {
|
} else {
|
||||||
const choice = await getChoice(controller, choices, loc, width, props);
|
const choice = await getChoice(controller, choices, loc, width, props);
|
||||||
const index = choices.findIndex(v => v[0] === choice);
|
const index = choices.findIndex(v => v[1] === choice);
|
||||||
core.status.route.push(`choices:${index}`);
|
core.status.route.push(`choices:${index}`);
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -969,13 +969,10 @@ export class TextContentParser {
|
|||||||
continue;
|
continue;
|
||||||
} else if (char === '$') {
|
} else if (char === '$') {
|
||||||
// 表达式
|
// 表达式
|
||||||
const next = text[pointer + 1];
|
|
||||||
if (next === '{') {
|
|
||||||
pointer++;
|
pointer++;
|
||||||
inExpression = true;
|
inExpression = true;
|
||||||
expStart = pointer + 1;
|
expStart = pointer + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
} else if (char === '\n') {
|
} else if (char === '\n') {
|
||||||
// 在这里预先将换行处理为多个 node,会比在分行时再处理更方便
|
// 在这里预先将换行处理为多个 node,会比在分行时再处理更方便
|
||||||
this.addTextNode(pointer + 1, true);
|
this.addTextNode(pointer + 1, true);
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export interface ThumbnailProps extends SpriteProps {
|
|||||||
damage?: boolean;
|
damage?: boolean;
|
||||||
all?: boolean;
|
all?: boolean;
|
||||||
noHD?: boolean;
|
noHD?: boolean;
|
||||||
/** 缩略图的比例,1 表示与实际地图大小一致 */
|
/** 缩略图的比例 */
|
||||||
size?: number;
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -179,7 +179,6 @@ export function getMapData(
|
|||||||
const floor = core.floors[now];
|
const floor = core.floors[now];
|
||||||
const change = floor.changeFloor;
|
const change = floor.changeFloor;
|
||||||
for (const [loc, ev] of Object.entries(change)) {
|
for (const [loc, ev] of Object.entries(change)) {
|
||||||
if (!ev) continue;
|
|
||||||
const target = ev.floorId as FloorIds;
|
const target = ev.floorId as FloorIds;
|
||||||
if (target.startsWith(':')) continue;
|
if (target.startsWith(':')) continue;
|
||||||
const [x, y] = loc.split(',').map(v => parseInt(v));
|
const [x, y] = loc.split(',').map(v => parseInt(v));
|
||||||
|
|||||||
@ -133,6 +133,7 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
// 画布监听
|
// 画布监听
|
||||||
const canvas = this.target.canvas;
|
const canvas = this.target.canvas;
|
||||||
canvas.addEventListener('mousedown', ev => {
|
canvas.addEventListener('mousedown', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
const mouse = this.getMouseType(ev);
|
const mouse = this.getMouseType(ev);
|
||||||
this.lastMouse = mouse;
|
this.lastMouse = mouse;
|
||||||
this.captureEvent(
|
this.captureEvent(
|
||||||
@ -141,11 +142,13 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
canvas.addEventListener('mouseup', ev => {
|
canvas.addEventListener('mouseup', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
const event = this.createMouseAction(ev, ActionType.Up);
|
const event = this.createMouseAction(ev, ActionType.Up);
|
||||||
this.captureEvent(ActionType.Up, event);
|
this.captureEvent(ActionType.Up, event);
|
||||||
this.captureEvent(ActionType.Click, event);
|
this.captureEvent(ActionType.Click, event);
|
||||||
});
|
});
|
||||||
canvas.addEventListener('mousemove', ev => {
|
canvas.addEventListener('mousemove', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
const event = this.createMouseAction(
|
const event = this.createMouseAction(
|
||||||
ev,
|
ev,
|
||||||
ActionType.Move,
|
ActionType.Move,
|
||||||
@ -168,6 +171,7 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
canvas.addEventListener('mouseleave', ev => {
|
canvas.addEventListener('mouseleave', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
const id = this.getMouseIdentifier(
|
const id = this.getMouseIdentifier(
|
||||||
ActionType.Leave,
|
ActionType.Leave,
|
||||||
this.getMouseType(ev)
|
this.getMouseType(ev)
|
||||||
@ -179,11 +183,13 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
this.beforeHovered.clear();
|
this.beforeHovered.clear();
|
||||||
});
|
});
|
||||||
document.addEventListener('touchstart', ev => {
|
document.addEventListener('touchstart', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
this.createTouchAction(ev, ActionType.Down).forEach(v => {
|
this.createTouchAction(ev, ActionType.Down).forEach(v => {
|
||||||
this.captureEvent(ActionType.Down, v);
|
this.captureEvent(ActionType.Down, v);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.addEventListener('touchend', ev => {
|
document.addEventListener('touchend', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
||||||
this.captureEvent(ActionType.Up, v);
|
this.captureEvent(ActionType.Up, v);
|
||||||
this.captureEvent(ActionType.Click, v);
|
this.captureEvent(ActionType.Click, v);
|
||||||
@ -193,6 +199,7 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.addEventListener('touchcancel', ev => {
|
document.addEventListener('touchcancel', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
this.createTouchAction(ev, ActionType.Up).forEach(v => {
|
||||||
this.captureEvent(ActionType.Up, v);
|
this.captureEvent(ActionType.Up, v);
|
||||||
});
|
});
|
||||||
@ -201,6 +208,7 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
document.addEventListener('touchmove', ev => {
|
document.addEventListener('touchmove', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
this.createTouchAction(ev, ActionType.Move).forEach(v => {
|
this.createTouchAction(ev, ActionType.Move).forEach(v => {
|
||||||
const list = this.touchInfo.values();
|
const list = this.touchInfo.values();
|
||||||
if (!list.some(vv => v.identifier === vv.identifier)) {
|
if (!list.some(vv => v.identifier === vv.identifier)) {
|
||||||
@ -220,6 +228,7 @@ export class MotaRenderer extends Container implements IRenderTreeRoot {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
canvas.addEventListener('wheel', ev => {
|
canvas.addEventListener('wheel', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
this.captureEvent(
|
this.captureEvent(
|
||||||
ActionType.Wheel,
|
ActionType.Wheel,
|
||||||
this.createWheelAction(ev, ActionType.Wheel)
|
this.createWheelAction(ev, ActionType.Wheel)
|
||||||
|
|||||||
@ -192,7 +192,6 @@ export class Transform {
|
|||||||
if (this.modified) {
|
if (this.modified) {
|
||||||
const result = new Transform();
|
const result = new Transform();
|
||||||
mat3.multiply(result.mat, this.mat, transform.mat);
|
mat3.multiply(result.mat, this.mat, transform.mat);
|
||||||
result.modified = true;
|
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return transform.clone();
|
return transform.clone();
|
||||||
|
|||||||
@ -13,8 +13,6 @@ import { RequiredData, RequiredIconsData, ResourceType } from './types';
|
|||||||
import { splitResource, SplittedResource } from './build-resource';
|
import { splitResource, SplittedResource } from './build-resource';
|
||||||
import { formatSize } from './utils';
|
import { formatSize } from './utils';
|
||||||
|
|
||||||
const DEBUG_REPLAY = false;
|
|
||||||
|
|
||||||
const ansi = {
|
const ansi = {
|
||||||
clear: '\x1b[2J\x1b[0f'
|
clear: '\x1b[2J\x1b[0f'
|
||||||
};
|
};
|
||||||
@ -94,8 +92,7 @@ async function buildData(outDir: string, entry: string) {
|
|||||||
name: 'ProcessData',
|
name: 'ProcessData',
|
||||||
fileName: 'data',
|
fileName: 'data',
|
||||||
formats: ['iife']
|
formats: ['iife']
|
||||||
},
|
}
|
||||||
minify: !DEBUG_REPLAY
|
|
||||||
}
|
}
|
||||||
} satisfies UserConfig);
|
} satisfies UserConfig);
|
||||||
|
|
||||||
@ -651,7 +648,7 @@ async function buildGame() {
|
|||||||
`⚠️ 压缩包大于 100M,可能导致发塔困难,请考虑降低塔的大小\r\n`
|
`⚠️ 压缩包大于 100M,可能导致发塔困难,请考虑降低塔的大小\r\n`
|
||||||
);
|
);
|
||||||
const suggections: string[] = [];
|
const suggections: string[] = [];
|
||||||
if (dataObject.main.bgms.some(v => !v.endsWith('opus'))) {
|
if (dataObject.main.bgms.some(v => !v.endsWith('opuw'))) {
|
||||||
suggections.push(`将 BGM 和音效换用 opus 格式`);
|
suggections.push(`将 BGM 和音效换用 opus 格式`);
|
||||||
}
|
}
|
||||||
if (dataObject.main.images.some(v => !v.endsWith('webp'))) {
|
if (dataObject.main.images.some(v => !v.endsWith('webp'))) {
|
||||||
|
|||||||
@ -166,20 +166,20 @@ export async function splitResource(
|
|||||||
while (index < files.length) {
|
while (index < files.length) {
|
||||||
let total = 0;
|
let total = 0;
|
||||||
const start = index;
|
const start = index;
|
||||||
let i = index;
|
for (let i = index; i < files.length; i++) {
|
||||||
for (; i < files.length; i++) {
|
|
||||||
const file = files[i];
|
const file = files[i];
|
||||||
if (file.exceed) {
|
if (file.exceed) {
|
||||||
if (i === index) i = index + 1;
|
if (i === index) i = index + 1;
|
||||||
|
index = i;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
total += file.stats.size;
|
total += file.stats.size;
|
||||||
}
|
}
|
||||||
if (total > limit) {
|
if (total > limit) {
|
||||||
|
index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index = i;
|
|
||||||
const toZip = files.slice(start, index);
|
const toZip = files.slice(start, index);
|
||||||
result.push(await compressFiles(toZip));
|
result.push(await compressFiles(toZip));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,55 +0,0 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
import { copy, emptyDir, ensureDir } from 'fs-extra';
|
|
||||||
import { writeFile } from 'fs/promises';
|
|
||||||
import { resolve } from 'path';
|
|
||||||
|
|
||||||
const base = resolve(process.cwd());
|
|
||||||
const template = resolve(base, 'template');
|
|
||||||
|
|
||||||
const serve = `在 2.B 样板中,不再使用先前的启动服务,而使用一个单独的软件。
|
|
||||||
你可以加造塔群 959329661 后,在群文件 - 启动服务 中获取,文件夹中会有一个专门的安装教程。`;
|
|
||||||
|
|
||||||
async function packTemplate() {
|
|
||||||
await ensureDir(template);
|
|
||||||
await emptyDir(template);
|
|
||||||
|
|
||||||
// 复制必要文件
|
|
||||||
const toCopy = [
|
|
||||||
'.vscode',
|
|
||||||
'packages',
|
|
||||||
'packages-user',
|
|
||||||
'public',
|
|
||||||
'script',
|
|
||||||
'src',
|
|
||||||
'.gitignore',
|
|
||||||
'.madgerc',
|
|
||||||
'.prettierignore',
|
|
||||||
'.prettierrc',
|
|
||||||
'eslint.config.js',
|
|
||||||
'index.html',
|
|
||||||
'LICENSE',
|
|
||||||
'package.json',
|
|
||||||
'pnpm-lock.yaml',
|
|
||||||
'pnpm-workspace.yaml',
|
|
||||||
'README.md',
|
|
||||||
'tsconfig.json',
|
|
||||||
'tsconfig.node.json',
|
|
||||||
'vite.config.ts'
|
|
||||||
];
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
toCopy.map(v =>
|
|
||||||
copy(resolve(base, v), resolve(template, v), {
|
|
||||||
filter: src => !src.includes('node_modules')
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
await writeFile(resolve(template, '启动服务呢?.txt'), serve, 'utf-8');
|
|
||||||
|
|
||||||
console.log(`样板打包完成`);
|
|
||||||
}
|
|
||||||
|
|
||||||
(() => {
|
|
||||||
packTemplate();
|
|
||||||
})();
|
|
||||||
Loading…
Reference in New Issue
Block a user