什么是“数据决定显示”?
举个例子:
在界面中开发音乐的开关时,往往都会使用 nodeA 表示音乐开,nodeB 表示音乐关,用一个按钮事件来控制音乐的开关。
如果是“显示决定显示”,那么按钮开关的逻辑应该为:nodeA.active = !nodeA.active;
nodeB.active = !nodeB.active;
如果是“数据决定显示”,则需要一个新数据(假设为 switch)来表示开关,新的逻辑如下:switch = !switch;
nodeA.active = switch;
nodeB.active = !switch;
可以看到,虽然代码很类似,但是二者在逻辑上却有很大的不同。后者将数据独立出来,成为了一个中间层,那么游戏逻辑只需要操作数据即可,再由数据触发相应的显示逻辑。
分类
“数据决定显示”这一原则下还有很多不同情况的分类:
- 对应关系:
- 一个数据决定多个显示
- 多个数据决定一个显示
- 多个数据决定多个显示
- 显示延迟
- 同步显示,无延迟
- 异步显示,有延迟(一般是显示的动画过程)
- 数据冲突处理
- 在显示过程中传入新数据
- 在显示过程结束后,执行一个新的显示过程
- 触发条件
- 多个数据决定一个显示
- 异步显示,有延迟(一般是显示的动画过程)
- 在显示过程中传入新数据
- 在 update 中获取数据,调用显示逻辑(也可以间隔多帧调用)
代码部分:
// test.ts
const { ccclass, property } = cc._decorator
@ccclass
export class PanelTest extends cc.Component {
start() {
// 每2s加500分
this.schedule(() => {
this.set_score(this.score += 500)
}, 2, 800)
}
update() {
this.update_score()
}
// 数据部分
score: number = 0 // 实际的分数
show_score: number = 0 // 显示的分数
set_score(v: number) {
this.score = v
}
// 显示部分
@property(cc.Label)
label_score: cc.Label = null
update_score() {
// 每一步至少为19,至多为当前分与实际分差距的1/20
let step = Math.max(19, Math.floor((this.score - this.show_score) / 20))
// 加分
this.show_score += step
// 防止分数溢出
this.show_score = Math.min(this.score, this.show_score)
// 修改分数显示
this.label_score.string = `${this.show_score}`
}
}
以上简单实现的优化
以上简单实现还有一些问题:
- 无法明显的显示出数据与显示之间的绑定关系(特别是在多数据时)
使用一个函数绑定数据获取和显示
如下所示的 bind_data_show,如果获得的数据是多个,还可以通过扩展运算符(…)进一步优化。 ```typescript // test.ts
const { ccclass, property } = cc._decorator
/* 绑定数据和显示 /
const bind_data_show =
static ins: Data;
constructor() {
setInterval(() => {
this.set_score(this.score + 500)
}, 2e3)
}
score: number = 0
set_score(v: number) {
this.score = v
}
get_score() {
return this.score
}
} Data.ins = new Data()
@ccclass export class PanelTest extends cc.Component {
update() {
this.update_ui()
}
// 显示部分
update_ui() {
bind_data_show(() => Data.ins.get_score(), (score) => this.update_score(score))
}
@property(cc.Label)
label_score: cc.Label = null
show_score: number = 0 // 显示的分数
update_score(score: number) {
// 每一步至少为19,至多为当前分与实际分差距的1/20
let step = Math.max(19, Math.floor((score - this.show_score) / 20))
// 加分
this.show_score += step
// 防止分数溢出
this.show_score = Math.min(score, this.show_score)
// 修改分数显示
this.label_score.string = `${this.show_score}`
}
} ```