弃天笑(soda.C)的专栏

专注于Flash RIA和Flash网络游戏开发

用户操作
[即时聊天] [发私信] [加为好友]
弃天笑ID:sujun10
20791次访问,排名5710好友7人,关注者29
从事过java应用开发,现在从事flash网络游戏开发
sujun10的文章
原创 34 篇
翻译 4 篇
转载 7 篇
评论 58 篇
弃天笑的公告
我的新blog开张了,以后第一 时间更新的是那个blog了,之后才在这里更新,有兴趣的人可以到那里去看,主要是说Flash RIA和flash游戏的 www.sujun.org
最近评论
FANS8888:xiao18yuan@qq.com
给我发一份吧
hbhjun:我最近也在研究flash网络编程,向你学习QQ441993692
小小菜鸟:这个很不错哇~

有时间给点as和c++的实例教程吧~~:-)
sujun10:没试过,应该要做类似按钮之类的,或者插入html标签
丁仙霖:非常感谢,虽然有些地方,没看懂
文章分类
收藏
    相册
    我的相片
    Flash
    asfox Blog
    弃天笑的小窝
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 Red5作做服务器的玩家移动信息同步例子(网游基础)收藏

    新一篇: Java应用程序中读取8位,24位Microsoft Windows位图 | 旧一篇: arguments的用法(介绍)

     
    玩家移动信息同步例子,我已经写过了两个版本的啦,一个java的,一个是fms的,现在又写了个red5的,其实这些的原理都是差不多的。以前好象没怎么讲解原理,这些就写得详细点吧。用red5做服务器,其实客户端基本是fms一样的。(事实上就是一样,哈哈)。无非就是客户端呼叫服务端的方法,服务端呼叫客户端的方法。(这是同步是没有采用ShareObject的,过阵可能会写吧)
    先看下图片吧

    首先先来看看最基本的(具体的内容我就不写了,代码里有详细的解释,在这里我只说说思路和逻辑)
    var mync:NetConnection = new NetConnection();   mync.connect("rtmp://localhost/game");连接到服务器
    mync.onStatus = function(info)
    {
    if (info.code == "NetConnection.Connect.Success")
    {
      trace("接通");
      //通知服务器,有新用户登陆了
      this.call("userLogin",null,userName);
    }
    };
    看这段代码。当客户端连接服务器成功后,马上呼叫服务端的用户登陆方法,并把新登陆的用户名传了过去。那么我们再看服务端
    /**
      * 用户登陆
      * @param userName:用户名
      */
    public void userLogin(String userName)
    {
      System.out.println("新用户登陆:" + userName);
      //检查是否已经有用户登陆,有登陆,则呼叫其他用户接受新登陆用户的信息
      if(map.size() > 0)
      {
       for(Iterator<IServiceCapableConnection> it = map.values().iterator(); it.hasNext();)
       {
        IServiceCapableConnection ic = it.next();
        //发送用户名过去
        ic.invoke("userLogin", new Object[]{userName});
       }
      }
      //放进map对象中保存
      map.put(userName,getCurrentConn());
    }
    当客户端call的时候,服务器就执行userLogin里的代码。在这里个方法里服务器只做了两件事,一是把map对象里的所有的客户端连接对象进行遍历,把新登陆用户的信息发送给所有已经登陆的客户端。然后再把当前的客户端连接对象保存在服务端的map对象中。接着来看ic.invoke("userLogin", new Object[]{userName})这句代码,他是呼叫客户端方法;既然服务端呼叫客户端的userLogin方法,那么我们可以过来客户端的userLogin方法。
    //当有新用户登陆时,被服务器呼叫
    mync.userLogin = function(name:String)
    {
    //根据名字复制一个新的mc,最近登陆的用户
    var mc:MovieClip = _root.attachMovie("personMC","personMC" + name,depth++);
    userSet.put(name,mc);
    mc.setName(name);
    //马上呼叫客户端,把自己的位置告诉新登陆的客户端
    mync.call("userInfo",null,userName,name,personMC._x,personMC._y);
    };
    在客户端里,该userLogin方法也是做了两件事,一是马上根据传过来用户名,生成了有一个新的mc(在实际中就是玩家,而且真正应用中,传的还不止一个参数),接着又呼叫服务端的一个方法userInfo,因为它必须把自己的信息通知给刚刚登陆的用户,包括自己的名字,位置等等。  接下来我们就看服务端的userInfo方法啦
    /**
      * 已经存在的用户的信息
      * @param userName:用户名
      * @param x:x坐标
      * @param y:y坐标
      */
    public void userInfo(String selfName, String userName,double x,double y)
    {
      Object[] ōbject = new Object[3];
      object[0] = selfName;
      object[1] = new Double(x);
      object[2] = new Double(y);
      map.get(userName).invoke("createUser",object);
    }
    服务端的这个方法就简单啦,只做了一件非常简单的时,就是把当前的传过来的用户信息,转发一个指定的用户就行了(其实就是最新登陆的那个用户)map.get(userName).invoke("createUser",object),呼叫了客户端的createUser方法。客户端:
    //更新已经登陆的用户
    mync.createUser = function(userName,x,y)
    {
    //根据名字复制一个新的mc
    var mc:MovieClip = _root.attachMovie("personMC","personMC" + userName,depth++);
    userSet.put(userName,mc);
    mc.setName(userName);
    mc._x = x;
    mc._y = y;
    }
    客户端的这个方法也很简单,就是根据服务端转发过来的信息,生成一个新的mc(玩家),同时还有位置。
    好啦,到了,一个用户登陆到服务器,在所有客户端同步显示的步骤就完成啦。
    接下来就把最后的功能完成,就是当一个客户端移动时,在其他客户端的也做对应的动作。呵~~不用我说什么也应该想了吧。恩,其实也是很简单,就是当前用户操作时,做自己的操作命令通过服务端转发其他所有的客户端,就达到同步的目的了。例如这一句代码:if( Key.isDown( Key.UP ) )
    {
      personMC.up();
      mync.call("userAction",null,userName,"up");
    }
    当按下键盘的UP时,客户端就呼叫服务起的userAction的方法,同时把自己的名字(才知道哪个用户的动作)和动作(具体哪个动作)传给了服务器,下面是服务端的代码
    public void userAction(String userName, String action)
    {
      Object[] ōbject = new Object[2];
      object[0] = userName;
      object[1] = action;
      //对所有的用户进行遍历
      if(map.size() > 1)
      {
       //取出当前用户的conn
       IServiceCapableConnection temp = getCurrentConn();
       for(Iterator<IServiceCapableConnection> it = map.values().iterator(); it.hasNext();)
       {
        IServiceCapableConnection iconn = it.next();
        //如果不是当前用户,则发送信息
        if(temp != iconn)
        {
         iconn.invoke("userAction", object);
        }
       }
      }
    }
    恩,这个方法也简单,就是把收到的信息发送给所有的客户端,注意这句代码
    IServiceCapableConnection iconn = it.next();
        //如果不是当前用户,则发送信息
        if(temp != iconn)
        {
         iconn.invoke("userAction", object);
        }
    这是为了防止把该信息发送给自己,因为服务器是做遍历的,也就是说会对所有登陆该服务器的用户进行遍历,所以应该排除发送该命令的用户。接下来就看客户端的userAction方法啦
    //当其他用户有动作时,被服务器呼叫
    mync.userAction = function(name:String,action:String)
    {
    var mc:MovieClip = userSet.get(name);
    //执行对应的方法
    mc[action]();
    };
    它也只做了一件事,就是找出该用户对应的mc(玩家),然后执行相应的动作
    OK~~~代码解释就到这里啦。光看我写的这个还是不行,大家还有把源代码提供去看看,大家有什么问题,就到red5的专有论坛去讨论吧。www.openred5.com.这个网站。那里也有red5的配置教什么的。这里所以这里我就不在讲述啦。呵~本来想弄些漂亮的人物进去 。不过没什么时间啦,今天是牺牲中午睡眠时间写的,大概花了一个小时,呵呵。如果很多人喜欢的话,往后会继续发布该系列的东西,例如用户说话,攻击,自己的名字是红色的等等,呵呵。
    附件:

    附件: red5.rar (2007-5-30 16:54, 720.41 K)

    发表于 @ 2007年05月30日 17:02:00|评论(loading...)|编辑

    新一篇: Java应用程序中读取8位,24位Microsoft Windows位图 | 旧一篇: arguments的用法(介绍)

    评论

    #sujun10 发表于2008-02-19 15:19:54  IP: 121.33.139.*
    开始研究red5了...........隔了快一年
    #老严 发表于2008-07-09 09:36:17  IP: 125.120.154.*
    lib中不用放把red5.jar放进去吧. 而且用户登进去以后为什么会重叠在一起?望指教?
    #sujun10 发表于2008-07-09 12:07:43  IP: 121.32.91.*
    不需要
    可能这个问题没处理好
    也就是用户登陆进去后,旧用户没有把自己的当前坐标发送过去给新用户
    #丁仙霖 发表于2008-08-09 07:43:31  IP: 222.173.221.*
    非常感谢,虽然有些地方,没看懂
    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 弃天笑