背景
前面我们已经实现了游戏的胜利和失败,并做了游戏结束后的资源释放。接下来就是与服务端交互,记录玩家的资源,给与玩家资源,留住玩家,让他对游戏有占有感。先简单实现金币的奖励。
目标
记录玩家资源(金币),胜利后奖励玩家资源(金币)
开发过程
目前设定的有三种资源
体力(ps): 上限共3点,每小时回复一点
金币(gold): 可购买基础资源
钻石(diamond): 可购买高级资源
1、登录页,登录成功后,显示资源数据
2、结算页,获得奖励,显示更新后的资源
1、登录页,登录成功后,显示资源数据
这里主要是vm的视图与数据的双向绑定,原先oops是有一个vm的组件来做的,我就试着问gpt.
js如何监听一个Object内的一个属性变化
gpt回答
你可以使用ES6中引入的
Proxy
对象来监听一个Object内的一个属性变化。以下是一个示例代码:const object = { a: 1, b: 2 }; const handler = { set(obj, prop, value) { console.log(`${prop} 的值由 ${obj[prop]} 变为 ${value}`); obj[prop] = value; } }; const proxy = new Proxy(object, handler); proxy.a = 3;
上面的代码中,我们创建了一个名为"object"的对象和一个名为"handler"的处理器。之后,我们使用
Proxy
对象来包装object
对象,并将handler
作为参数传入,并将结果存储在一个名为"proxy"的变量中。handler
中的set
方法会在object
中的属性被设置时被调用,并输出相关的日志信息。在示例中,我们监测了a
属性的变化,并将其从1改为3。需要注意的是,美观打印对象中的属性变化需要借助一些控制台输出格式化的工具库,例如
prettyprint
或者json-stringify-pretty-compact
等等。
好的,结合gpt,我们就做一个简单的vm数据监听
我在GateViewComp组件中加了一个初始化监听
GateViewSystem.onVMPlayerInfo(this, () => {
let playerInfo = ooxh.game.playerEntity.getComponent(PlayerStateComp).playerInfo
this.vmPlayerInfo.gold = playerInfo.gold
this.vmPlayerInfo.diamond = playerInfo.diamond
this.vmPlayerInfo.ps = playerInfo.ps
this.vmPlayerInfo.last_battle_id = playerInfo.last_battle_id
})
实现
static onVMPlayerInfo(comp: GateViewComp, callback) {
const playerInfo = ooxh.game.playerEntity.getComponent(PlayerStateComp).playerInfo
if (!playerInfo) {
setTimeout(() => {
this.onVMPlayerInfo(comp, callback)
}, 200)
return
}
const handler = {
set(obj, prop, value) {
console.log(`${prop} 的值由 ${obj[prop]} 变为 ${value}`);
if (prop == 'ps') {
comp.node.getChildByName('top').getChildByName('value').getComponent(Label).string = value + '/3'
}
if (prop == 'gold') {
comp.node.getChildByName('top').getChildByName('gold').getChildByName('value').getComponent(Label).string = value
}
if (prop == 'diamond') {
comp.node.getChildByName('top').getChildByName('diamond').getChildByName('value').getComponent(Label).string = value
}
if (prop == 'last_battle_id') {
comp.node.getChildByName('bottom').getChildByName('curBattleIdText').getComponent(Label).string = '当前第' + value + '关'
}
obj[prop] = value;
return true
}
};
comp.vmPlayerInfo = new Proxy(playerInfo, handler);
callback && callback()
}
上面因为PlayerStateComp内的数据获取不确定什么时候完成做了简单循环检测
这样我只要在任何地方改变ooxh.game.playerEntity.getComponent(PlayerStateComp).playerInfo内的值,页面就会自动去更新ui
2、结算页,获得奖励,显示更新后的资源
向后端发起请求后,将获得的奖励数据,追加到用户数据中
public function overBattle($param, $tokenUser)
{
$log = $this->dao->get(['id' => $param['battleLogId']]);
if (!$log) {
return ['status' => 0, 'msg' => '错误的战役记录id'];
}
if ($log['fans_id'] != $tokenUser['id']) {
return ['status' => 0, 'msg' => '不能结束别人的战役' . $log['fans_id'] . '.' . $tokenUser['id']];
}
if ($log['over_datetime']) {
return ['status' => 0, 'msg' => '已结束的战役'];
}
$battle = Db::name('jianchuqiao_battle_online')->where('battle_id', '=', $log['battle_id'])->find();
try {
$save['gold'] = $battle['gold'];
if ($log['is_frist']) {
$save['diamond'] = $battle['diamond'];
} else {
$save['diamond'] = 0;
}
$save['over_datetime'] = Date('Y-m-d H:i:s');
$log->save($save);
// 玩家战役向后一个
$fans = app()->make(FansDao::class)->get(['id' => $tokenUser['id']]);
$update['gold'] = $fans['gold'] + $save['gold'];
$update['diamond'] = $fans['diamond'] + $save['diamond'];
$update['last_battle_id'] = $log['battle_id'] + 1;
$fans->save($update);
return ['status' => 1, 'msg' => 'ok', 'data' => $log];
} catch (\Exception $e) {
Log::error('createBattleLog error' . $e->getMessage());
return ['status' => 0, 'msg' => '失败-' . $e->getMessage()];
}
}
前端
// 记录
HttpUtil.Post('/appletapi/jianchuqiao/overBattle',
{
battleLogId: ooxh.game.playerEntity.getComponent(PlayerStateComp).battleLogId
},
(res) => {
if (res.code == 200) {
// 显示胜利结算页面
ooxh.game.battleEntity.attachComponent(BattleWinViewComp).callback = () => {
const playerInfo = ooxh.game.playerEntity.getComponent(PlayerStateComp).playerInfo
playerInfo.ps += res.data.ps
playerInfo.gold += res.data.gold
playerInfo.diamond += res.data.diamond
};
} else {
// 暂不处理
}
})
测试显示
胜利后,返回首页,数据自动改为了新值
下一个开发计划
激励广告后的额外奖励