一 应用:关心与某逻辑Obj的距离(用于商人或者任务窗口/下拉菜单等,当距离超过一定距离后自动关闭)
二 实现
1 首先注册lua接口
INT CUIWindowItem::LUA_CareObject(LuaPlus::LuaState* pState)
{
LuaStack args(pState);
if(!(args[2].IsInteger()))
{
KLThrow("LUA: CUIWindowItem::LUA_CareObject[2] Wrong Param1");
}
if(!(args[3].IsInteger()))
{
KLThrow("LUA: CUIWindowItem::LUA_CareObject[3] Wrong Param1");
}
if(!(args[4].IsString()))
{
KLThrow("LUA: CUIWindowItem::LUA_CareObject[4] Wrong Param1");
}
INT nObjID = args[2].GetInteger();
INT bCare = args[3].GetInteger()==1;
std::string str = args[4].GetString();
}
{
LuaStack args(pState);
if(!(args[2].IsInteger()))
{
KLThrow("LUA: CUIWindowItem::LUA_CareObject[2] Wrong Param1");
}
if(!(args[3].IsInteger()))
{
KLThrow("LUA: CUIWindowItem::LUA_CareObject[3] Wrong Param1");
}
if(!(args[4].IsString()))
{
KLThrow("LUA: CUIWindowItem::LUA_CareObject[4] Wrong Param1");
}
// Object的ID
INT nObjID = args[2].GetInteger();
// 是否关心
INT bCare = args[3].GetInteger()==1;
// 谁在关心
std::string str = args[4].GetString();
g_pObjectSystem
->CareObject(nObjID, bCare, str);return 0;
}
2 保存到map里面
// 关心某物体的指定事件 id-物体ID, szSign:关心标志(谁关心) bCare-关心或者取消关心
// 修改说明:添加一个“是谁关心”的内容
VOID CObjectManager::CareObject(INT id, BOOL bCare, std::string szSign)
{
//AxTrace(0,0,"C++ id =%d,bCare =%d,szSign =%s",id,(INT)bCare,szSign.c_str());
// 搜索物体
CObject* pObject = (CObject*)FindObject(id);
if(!pObject) return;
std::map< std::string, OBJECT_BECARED >::iterator it;
it = m_mapCaredObject.find(szSign);
if(it != m_mapCaredObject.end())// && !bCare)
{
if(bCare)
{
// 这个界面已经有关心的NPC,去关心新的 Npc 就可以了,
it->second.id = id;
}
else
{
// 取消关心的操作
m_mapCaredObject.erase(it);
}
}
if(it == m_mapCaredObject.end() && bCare)
{
OBJECT_BECARED objNewCared;
objNewCared.id = id;
objNewCared.fLastDistance = KLU_GetDist(fVector2(GetMySelf()->GetPosition().x, GetMySelf()->GetPosition().z),
fVector2(pObject->GetPosition().x, pObject->GetPosition().z));
// 修改说明:添加一个“是谁关心”的内容
VOID CObjectManager::CareObject(INT id, BOOL bCare, std::string szSign)
{
//AxTrace(0,0,"C++ id =%d,bCare =%d,szSign =%s",id,(INT)bCare,szSign.c_str());
// 搜索物体
CObject* pObject = (CObject*)FindObject(id);
if(!pObject) return;
// 是否已经加入
std::map< std::string, OBJECT_BECARED >::iterator it;
it = m_mapCaredObject.find(szSign);
// 在表中已经有
if(it != m_mapCaredObject.end())// && !bCare)
{
if(bCare)
{
// 这个界面已经有关心的NPC,去关心新的 Npc 就可以了,
it->second.id = id;
}
else
{
// 取消关心的操作
m_mapCaredObject.erase(it);
}
}
// 在表中没有
if(it == m_mapCaredObject.end() && bCare)
{
OBJECT_BECARED objNewCared;
objNewCared.id = id;
objNewCared.fLastDistance = KLU_GetDist(fVector2(GetMySelf()->GetPosition().x, GetMySelf()->GetPosition().z),
fVector2(pObject->GetPosition().x, pObject->GetPosition().z));
m_mapCaredObject.insert(std::make_pair(szSign, objNewCared));
}
}
3 Tick遍历
VOID CObjectManager::Tick(VOID)
{
// 检查是否有物体不再被关心
if(CGameProcedure::GetActiveProcedure() == CGameProcedure::s_pProcMain)
m_pLogicalObject->Tick_CheckAlive();
m_pLogicalObject->Tick();
std::map< std::string, OBJECT_BECARED >::iterator it;
for(it=m_mapCaredObject.begin(); it!=m_mapCaredObject.end(); it++)
{
OBJECT_BECARED& obj = it->second;
// 物体是否存在
CObject* pObject = (CObject*)FindObject(obj.id);
if(!pObject)
{
KLAssert(false && "Careobject error find!");
continue;
}
FLOAT fDistance = KLU_GetDist( fVector2(GetMySelf()->GetPosition().x, GetMySelf()->GetPosition().z),
fVector2(pObject->GetPosition().x, pObject->GetPosition().z));
if(fStep > 0.001)
{
// 距离发生改变,产生事件
std::vector< STRING > vParam;
CHAR szTemp[MAX_PATH];
vParam.push_back(szTemp);
vParam.push_back(szTemp);
}
}
if(m_pLoadQueue)
{
m_pLoadQueue->Tick();
}
if(m_pDestoryQueue)
{
m_pDestoryQueue->Tick();
}
}
{
// 检查是否有物体不再被关心
if(CGameProcedure::GetActiveProcedure() == CGameProcedure::s_pProcMain)
m_pLogicalObject->Tick_CheckAlive();
// 执行逻辑函数
m_pLogicalObject->Tick();
// 检查被UI关心的逻辑对象
std::map< std::string, OBJECT_BECARED >::iterator it;
for(it=m_mapCaredObject.begin(); it!=m_mapCaredObject.end(); it++)
{
OBJECT_BECARED& obj = it->second;
// 物体是否存在
CObject* pObject = (CObject*)FindObject(obj.id);
if(!pObject)
{
KLAssert(false && "Careobject error find!");
continue;
}
// 计算目前的距离
FLOAT fDistance = KLU_GetDist( fVector2(GetMySelf()->GetPosition().x, GetMySelf()->GetPosition().z),
fVector2(pObject->GetPosition().x, pObject->GetPosition().z));
float fStep = abs(fDistance-obj.fLastDistance);
if(fStep > 0.001)
{
// 距离发生改变,产生事件
std::vector< STRING > vParam;
CHAR szTemp[MAX_PATH];
_snprintf(szTemp, MAX_PATH,
"%d", pObject->GetID());vParam.push_back(szTemp);
vParam.push_back(
"distance");_snprintf(szTemp, MAX_PATH,
"%.3f", fDistance);vParam.push_back(szTemp);
CEventSystem::GetMe()
->PushEvent(GE_OBJECT_CARED_EVENT, vParam);}
obj.fLastDistance
= fDistance;}
// 加载队列工作
if(m_pLoadQueue)
{
m_pLoadQueue->Tick();
}
// 删除队列
if(m_pDestoryQueue)
{
m_pDestoryQueue->Tick();
}
}
4 事件触发通过event实现,具体以后再分析
5 lua响应,主要是关闭界面
elseif (event == "OBJECT_CARED_EVENT") then
if(tonumber(arg0) ~= objCared) then
return;
end
if( arg1 == "distance" and tonumber(arg2)>MAX_OBJ_DISTANCE or arg1=="destroy" ) then
-- if( arg1 == "destroy" ) then
ContexMenu_HideAll();
this:Hide();
--取消关心
this:CareObject( objCared, 0, "ContexMenu" );
end
if( this:IsVisible() )then
ContexMenu_HideAll();
this:Hide();
end
elseif( event == "PK_MODE_CHANGED" ) then
tempPKMode = Player:GetCurrentPKMode();
if tempPKMode ~= currentPKMode then
currentPKMode = tempPKMode;
PushDebugMessage(PKModeName[currentPKMode]);
end
elseif( event == "ALLOCATION_MODE_CHANGED" ) then
tempAcMode = tonumber(arg0);
if tempAcMode ~= currentAlloCationMode then
currentAlloCationMode = tempAcMode;
end
if(tonumber(arg0) ~= objCared) then
return;
end
--如果和NPC的距离大于一定距离或者被删除,自动关闭
if( arg1 == "distance" and tonumber(arg2)>MAX_OBJ_DISTANCE or arg1=="destroy" ) then
-- if( arg1 == "destroy" ) then
ContexMenu_HideAll();
this:Hide();
--取消关心
this:CareObject( objCared, 0, "ContexMenu" );
end
elseif(
event == "COLSE_SECOND_MENU" ) thenif( this:IsVisible() )then
ContexMenu_HideAll();
this:Hide();
end
elseif( event == "PK_MODE_CHANGED" ) then
tempPKMode = Player:GetCurrentPKMode();
if tempPKMode ~= currentPKMode then
currentPKMode = tempPKMode;
PushDebugMessage(PKModeName[currentPKMode]);
end
elseif( event == "ALLOCATION_MODE_CHANGED" ) then
tempAcMode = tonumber(arg0);
if tempAcMode ~= currentAlloCationMode then
currentAlloCationMode = tempAcMode;
end
end