您的位置:首页 > 其它

游戏中实时更新数据的实现方式

2013-07-30 19:08 351 查看
在游戏中,玩家的信息会实时变动,我们需要把改变后的信息在页面中体现出来。

需求:航海游戏中,玩家出航,从港口A到港口B,目前他处于的A港口位于地中海,港口B处于太平洋,在未到B港口时,他所处的海域发生了变化,在太平洋海域。 需要在页面中实时展现玩家所处于的海域。

为了满足以上需求,需要做到2点:
1,在数据库层面上,出航的时候,更新玩家所处于的海域
2,在展现层面上,需要把玩家改变的信息显示在页面上。

问题:
QA: 玩家信息如何实时更新
ans:  玩家在航海的过程中,他的相关的数据会被修改。
QB  页面如何知道玩家的信息
ans: 页面中实现一个AJAX函数,这个函数每5秒中请求服务器,并获取玩家最新的相关数据, 如果有多个页面都涉及到实时展现玩家最新信息,建议把这个AJAX函数写在一个公共页面中,如footer,并每次都自动执行。这样,避免了在很多页面中,都写这个AJAX函数

QC: 最新的玩家信息如何被展现到页面中
ans: 页面需要重新渲染数据,一般都是刷新页面,重新给页面分配,还有一种做法就是使用JS函数,操作页面的dome结构。我们已经获取到了玩家的信息,如何把这个信息展现到页面中呢,我们使用JS函数,获取的信息作为他的参数,把获取到的信息,重新分配到页面。
这里就要求:服务器除了把玩家的信息返回给我之外,还有注册一个JS函数,并通知页面执行一个特定的JS函数 !!!!!!!!!!!! 如果要执行这个JS函数,需要调用这个函数,如果在页面刷新的前提下 我们使用:
$(function () {
specaiJsFunction(data)
})


这样可以保证specailJsFunction()这个函数可以被自动执行。但是,我们的请求是AJAX,页面不会刷新,所以,这样的做法行不通。我们可以在ajax请求的回调函数里面执行这个函数,所以要求这个函数必须是AJAX函数的返回值,否则程序不知道调用那个函数!!!!!

实现流程图:


实现具体过程:

客户端 页面发起AJAX请求:

// 更新页面中的“当前海域”信息
if (<?=$user.isSailing?>) {
$(function () {
setInterval(function () {
$._getJSON('/ajax/polling', null, function (resp) {
// 处理AJAX响应中的iTips
iTipsInAjaxResponse(resp)
});
}, 5000);
});
}


服务器端:更新玩家的信息是在航海的这个函数中,这里,我只需要读取玩家的信息,并注册JS函数:

public function pollingAction()
{
// 检测玩家是否处于航海状态
if (! $this->_user->isStaying()) {

// 获取玩家的最新信息
$userInfo = array(
// 输出玩家当前所在海域
'seaAreaId'     => $this->_user['sea_area_id'],
'seaAreaName'   => $this->_user['seaArea']['name'],
);

// 注册一个JS函数:updateSeaAreaName,并把玩家的信息当为函数的参数
$this->_user->tips->setTips('updateSeaAreaName', $userInfo);
}
// 在这个函数内,把所有注册的JS函数使用JSON的方式,返回给页面中AJAX的请求。
$this->jsonx('OK');
}


tips类的实现方式:

<?php

/**
* 我的实时提示框
*
*/

class Model_User_Tips extends Model_User_Trait
{
private $_tips = array();

/**
* 是否立即弹出
*
* @var bool
*/
private $_autoPopUp = true;

/**
* 设置iTips
*
* @param string $jsFunc
* @param mixed $jsParam
* @param int $priority 优先级
* @return $this
*/
public function setTips($jsFunc, $jsParam = null, $priority = 0)
{
$this->_tips[] = array(
'jsFunc'    => $jsFunc,
'jsParam'   => $jsParam,
'autoPopUp' => $this->_autoPopUp,
'priority'  => $priority,
);

return $this;
}

public function getTips()
{
return $this->_tips;
}

public function getJsonTips()
{
return $this->_tips ? json_encode($this->_tips) : 0;
}

/**
* 设置是否立即弹出,否则手动弹出
*
* @param int $bool
* @return $this
*/
public function setAutoPopUp($bool)
{
$this->_autoPopUp = (bool) $bool;

return $this;
}
}


jonsx的实现方式:

/**
* 用于 AJAX 响应输出 JSON
*
* @param string $msg
* @param string $resultType success|error|warnings|tips
* @param array $extra
* @param bool $obClean 是否先清除之前的缓冲区
*/
public function jsonx($msg, $resultType = 'success', array $extra = array(), $obClean = false)
{
// 实时提示框信息,如果有JS函数被注册则把注册的JS函数作为返回值返回给页面
if ($this->_user && $iTips = $this->_user->tips->getTips()) {
$extra['iTips'] = $iTips;
}

// 清除之前的缓冲区,防止多余输出
$obClean && ob_clean();

header('Content-type: text/json');
header('Content-type: application/json; charset=UTF-8');
exit(json_encode(array('msg' => $msg, 'status' => $resultType, 'extra' => $extra)));
}


在JS函数中,函数 function iTipsInAjaxResponse (resp){} 专门用于处于返回的JS函数数组 实现方式为:

// 处理AJAX响应中的iTips
function iTipsInAjaxResponse(resp)
{
// 处理 iTips 实时提示框
// 例如经验值、等级提升等提示
if (resp.extra && resp.extra.iTips) {
var iTipsInstant = iTips.filter(resp.extra.iTips, 'autoPopUp', true);
if (iTipsInstant.length > 0) {
// 立即弹出实时提示框
iTips.popUp(iTipsInstant);
}
}
}


实时弹出框的实现方式:

// 实时提示框
var iTips = {

filter : function (iTips, fieldName, fieldValue)
{
var result = [];

if (! iTips || iTips.length < 0) {
return result;
}

for (i in iTips) {
if (iTips[i][fieldName] == fieldValue) {
if (iTips[i]['priority'] == undefined) {
iTips[i]['priority'] = 0;
}
// 需要自动执行的JS函数
result.push(iTips[i]);
}
}

// 按弹窗优先级升序排(优先级数字越小越前面,默认0表示最高级)
result.sort(function (x, y) {
return x.priority - y.priority;
});

return result;
},
// 过滤到不需要执行的函数
remove : function (iTips, fieldName, fieldValue)
{
var result = [];

if (! iTips || iTips.length < 0) {
return result;
}

for (i in iTips) {
if (iTips[i][fieldName] != fieldValue) {
result.push(iTips[i]);
}
}

return result;
},

popUp : function (iTips)
{
if (! iTips || iTips.length < 0) {
return false;
}

for (i in iTips) {
if (iTips[i]) {
// 转化成执行的JS函数,并执行
eval('var jsFunc = ' + iTips[i]['jsFunc'] + ';');
jsFunc(iTips[i]['jsParam']);
}
}
}
};


在服务器注册JS函数,在页面中执行,这样的做法,还有一个用处就是实时弹框,例如,玩家升级的时候,需要弹框提示玩家升级,但是这个提示升级框JS函数,不确定在这个页面中,那个时候会被调用执行到。所以,不能把这个JS“写死”在某个页面中。

如果采用我的方法,就可以动态的调用某个JS函数并执行,不受页面的时间的限制。

这种实现方式,类似于观察者。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: