作为优秀的游戏网络包tnl最牛的地方就是其ghostobject机制了,用户程序员可以很轻松的控制具体从server到n个client之间的通信逻辑从而使单个玩家收到的场景消息最小,理论上你就是一千,一万个玩家都木有问题,要是你具体介绍看文档..这里分析其实际使用的流程和代码实现,当然你要是不过一些宏和很薄的类封装也可以....
作为客户时,onGhostAdd函数被callback然后可以在这里执行业务逻辑的callback调用,最重要的就是
在客户端把objectInScope里传来的对象给登记上,
至于netobject本身所控制的对象,是作为与server共用的connection的属性而存在的
(只不过一个作为client里的一个作为server里的,client里只有一个connection而server里有n个
,每个connection里仍然是rpc的关系)
传过来的,而执行传递的动作,是由performScopeQuery
里的connection->objectInScope这个方法调用的,此方法只在作为server的时候才被调用
bool Player::onGhostAdd(TNL::GhostConnection *theConnection)
{
addToGame(((TestNetInterface *) theConnection->getInterface())->game);
return true;
}
//addtogame还有个任务就是把属于自己控制的player (不同于client概念) 登记上
void Player::addToGame(TestGame *theGame)
{
// add the player to the list of players in the game.
theGame->players.push_back(this);
game = theGame;
if(myPlayerType == PlayerTypeMyClient)
{
// set the client player for the game for drawing the
// scoping radius circle.
game->clientPlayer = this;
}
}
void Player::performScopeQuery(TNL::GhostConnection *connection)
{
// find all the objects that are "in scope" - for the purposes
// of this test program, all buildings are considered to be in
// scope always, as well as all "players" in a circle of radius
// 0.25 around the scope object, or a radius squared of 0.0625
for(TNL::S32 i = 0; i < game->buildings.size(); i++)
connection->objectInScope(game->buildings[i]);
for(TNL::S32 i = 0; i < game->players.size(); i++)
{
Position playerP = game->players[i]->renderPos;
TNL::F32 dx = playerP.x - renderPos.x;
TNL::F32 dy = playerP.y - renderPos.y;
TNL::F32 distSquared = dx * dx + dy * dy;
if(distSquared < 0.0625)
connection->objectInScope(game->players[i]);
}
}
//connection共享对象在此处定义
class TestConnection : public TNL::GhostConnection
{
typedef TNL::GhostConnection Parent;
public:
/// The TestConnection constructor. This method contains a line that can be
/// uncommented to put the TestConnection into adaptive communications mode.
TestConnection();
/// The player object associated with this connection.
TNL::SafePtr<Player> myPlayer;
....................................