您的位置:首页 > 其它

Red5作做服务器的玩家移动信息同步例子

2008-06-20 21:00 274 查看
http://www.sujun.org/feed.asp?cateID=15

以前的旧文章,归下类而已.....目前也在用red5做服务器开发一款比较小的flash网络游戏,呵呵...期待...

玩家移动信息同步例子,我已经写过了两个版本的啦,一个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源代码下载

AS3与Red5之间的参数传递

2008年2月20日,14:30:47 | sujun10@21cn.com(弃天笑)


差不大一年没去动red5了,现在因为项目需要又开始使用red5,呵呵,先写些基本应用吧

参数传递是最基本的,之前是as2,现在用as3与red5 0.63了,几乎没什么变化.不过flash这边的可以传递的参数也就多了一些.就基本的是

String,int,Number,Boolean,Array,对应到red5这边是String,int,double,boolean,List

下面看基本的代码吧:

Flash:


程序代码

/**

* @(#)ParamRed5.as

* @author soda.C

* @version 1.0

* <br>Copyright (C), 2007 soda.C

* <br>This program is protected by copyright laws.

* <br>Program Name:GameHall

* @data 2008-2-19

*/

package org.sujun.red5.test

{

import flash.display.Sprite;

import flash.net.NetConnection;

import flash.events.NetStatusEvent;

import flash.events.SecurityErrorEvent;

import flash.net.Responder;

/**

* 测试flash与red5之间参数的传递

*/

public class ParamRed5 extends Sprite

{

private var netConnection:NetConnection;

public function ParamRed5():void

{

netConnection = new NetConnection();

netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

netConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);

netConnection.connect("rtmp://localhost/paramtest");

}

private function netStatusHandler(event:NetStatusEvent):void

{

trace("连接状态:" + event.info["code"]);

switch (event.info["code"])

{

case "NetConnection.Connect.Success":

trace("连接成功.....");

//呼叫服务器的baseParam方法,传递基本参数,string,int,number,Boolean

netConnection.call("baseParam", new Responder(baseParamResult),"soda.C",24,1000.1,false);

//封装数组,int

var ary:Array = new Array();

ary.push(1);

ary.push(2);

ary.push(3);

//封装数组,String

var ary1:Array = new Array();

ary1.push("a");

ary1.push("b");

ary1.push("c");

netConnection.call("receiveArray", new Responder(baseParamResult),ary,ary1);

break;

case "NetStream.Play.StreamNotFound":

trace("Stream not found: ");

break;

}

}

private function baseParamResult(obj:Object):void

{

trace(obj);

trace("响应了.....");

}

private function securityErrorHandler(event:SecurityErrorEvent):void

{

trace("securityErrorHandler: " + event);

}

}

}

接下来看java代码

ParamRed5App.java,该类继承了ApplicationAdapt


程序代码

package org.sujun.red5.test;

import java.util.List;

import org.red5.server.adapter.ApplicationAdapter;

/**

* 存放被flash客户端调用的方法

*/

public class ParamRed5App extends ApplicationAdapter

{

public ParamRed5App()

{

System.out.println("被初始化了......");

}

/**

* 接受服务器传过来的基本参数

*/

public void baseParam(String name, int age, double value, boolean flag)

{

System.out.println("----name----" + name);

System.out.println("----age----" + age);

System.out.println("----value----" + value);

System.out.println("----flag----" + flag);

}

/**

* 接受客户端传递过来的数组

*/

public void receiveArray(List<Integer> intArray, List<String> strArray)

{

for(int i = 0; i < intArray.size(); i++)

{

System.out.println("----intArray----" + intArray.get(i).intValue());

}

for(int i = 0; i < intArray.size(); i++)

{

System.out.println("----strArray----" + strArray.get(i));

}

}

}

代码很简单.......直接复制过去,建立一个red5应用就可以使用了

看结果...



不过,还是我是传上源代码


点击下载此源代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: