[Flash Media Server]一步一步学Flash Media Server(八)
在上一节中,我们将一些方法进一步封装到了UserList类中了,这样做是有很多好处的,以前经常有朋友问我像聊天室怎么做成多房间,像斗地主怎么做成多个桌子在打,其实原理都是一样的,我们只需要对UserList类做一些改造,就可以达到这个功能了,首先把类的名字改成ChatRoom,这样更好认一些,先看ChatRoom.asc,是由UserList.asc改造而来的:
- function ChatRoom(id){
- this.id = id;
- this.listArray = [];
- this.chatMsgArray = [];
- }
- ChatRoom.prototype.addUser = function(user){
- this.listArray.push(user);
- this.sendUserList();
- }
- ChatRoom.prototype.delUser = function(userName){
- var len = this.listArray.length;
- for(var i=0;i<len;i++){
- if(this.listArray[i].userName == userName){
- this.listArray.splice(i,1);
- break;
- }
- }
- this.sendUserList();
- }
- ChatRoom.prototype.checkOnline = function(userName){
- var len = this.listArray.length;
- for(var i=0;i<len;i++){
- if(this.listArray[i].userName == userName){
- return true;
- }
- }
- return false;
- }
- ChatRoom.prototype.getUserList = function(){
- var result = [];
- var len = this.listArray.length;
- for(var i= 0;i<len;i++){
- result.push(this.listArray[i].userName);
- }
- return result;
- }
- ChatRoom.prototype.sendUserList = function(){
- sendAllRoomNum(this.id,this.listArray.length);
- var len = this.listArray.length;
- for(var i=0;i<len;i++){
- this.listArray[i].client.call("getUserList",null,this.getUserList());
- }
- }
- ChatRoom.prototype.sendMsgToClient = function(chatInfo){
- trace("sendMsgToClient:"+chatInfo);
- this.chatMsgArray.push(chatInfo);
- var len = this.listArray.length;
- for(var i=0;i<len;i++){
- this.listArray[i].client.call("getMsgInfo",null,chatInfo);
- }
- }
来看看ChatRoom类和UserList类有什么区别:
1.在构造中增加了this.id = id,这里的id表示每个房间的编号,这样可以区别当前是哪个房间.
2.this.chatMsgArray,存储聊天信息的数组,之前是放在main.asc里面的,因为之前只有一个房间,而现在有多个房间,所以每个房间都应该有一个自己的聊天信息列表.
User.asc增加一个变量:
- function User(client,userName,roomid){
- this.client = client;
- this.client.roomid = roomid;
- this.userName = this.client.userName = userName;
- }
main.asc文件也做了相应的修改:
- load("ChatRoom.asc");
- load("User.asc");
- application.onAppStart = function() {
- this.roomArray = [];
- this.roomUserNum = [];
- var roomLen = 3;
- for(var i=0;i< roomLen ;i++){
- this.roomArray.push(new ChatRoom(i+1));
- this.roomUserNum.push(0);
- }
- }
- application.onConnect = function(client) {
- this.acceptConnection(client);
- //客户端调用方法
- client.addRoom = function(userName,roomid){
- trace(userName,roomid);
- var isOnline = application.roomArray[roomid - 1].checkOnline(userName);
- if(!isOnline){
- var user = new User(this,userName,roomid);
- application.roomArray[roomid - 1].addUser(user);
- return true;
- }else{
- return false;
- }
- }
- client.getMsg = function(roomid){
- return application.roomArray[roomid - 1].chatMsgArray;
- }
- client.sendMsg = function(roomid,msg){
- var chatInfo = this.userName + " : " + msg;
- application.roomArray[roomid - 1].sendMsgToClient(chatInfo);
- }
- client.getAllUserNum = function(){
- return application.roomUserNum;
- }
- }
- application.onDisconnect = function(client) {
- trace("用户:"+client.userName+" 离开 "+client.roomid);
- this.roomArray[client.roomid - 1].delUser(client.userName);
- }
- application.onAppStop = function() {
- }
- function sendAllRoomNum(roomid,num){
- application.roomUserNum[roomid - 1] = num;
- var len = application.clients.length;
- for(var i= 0;i<len ;i++){
- application.clients[i].call("getAllRoomNum",null,application.roomUserNum);
- }
- }
在这个类中我们主要做了以下修改:
1.this.roomArray,用来存储每个房间实例的数组;this.roomUserNum,所有房间当前在线人数的数组;在这里我定义了三个房间,这个可以任意设定.
2.在客户端连接进来时,直接接受客户端连接,不做判断,把判断改在addRoom完成.
3.在客户端发过来的消息中,多加了个参数,就是roomid,用于区别是哪个房间发来的消息,然后根据roomid来判断调用哪个房间实例的方法.
4.增加sendAllRoomNum方法,用于发送实时的所有房间人数,供客户端的大厅显示,正常大厅的可以实时看到人数变化.
客户端代码也要做相应的修改:
- package net.smilecn.chat{
- import flash.display.Sprite;
- import flash.net.NetConnection;
- import flash.net.Responder;
- import flash.events.NetStatusEvent;
- import flash.events.SyncEvent;
- import flash.events.MouseEvent;
- import fl.controls.TextArea;
- import fl.controls.Button;
- import fl.controls.TextInput;
- import fl.controls.Label;
- import fl.controls.List;
- import fl.data.DataProvider;
- public class Chat extends Sprite{
- private var nc:NetConnection;
- private var rtmpUrl:String = "rtmp://localhost/chat/chatLobby";
- private var msg:Label;
- private var userNameInput:TextInput;
- private var enterBtn:Button;
- private var button:Button;
- private var textArea:TextArea;
- private var textInput:TextInput;
- private var userList:List;
- private var userName:String;
- private var allRoomNum :Array = new Array();
- private var roomBtnArray:Array = new Array();
- private var onlineArray:Array = new Array();
- private var currentRoomid:Number;
- public function Chat():void{
- userNameInput = new TextInput();
- userNameInput.move(100,200);
- addChild(userNameInput);
- enterBtn = new Button();
- enterBtn.move(220,200);
- enterBtn.label = "进入";
- addChild(enterBtn);
- enterBtn.addEventListener(MouseEvent.CLICK,enterBtnClickHandler);
- msg = new Label();
- msg.move(100,230);
- msg.text = "";
- addChild(msg);
- }
- private function enterBtnClickHandler(event:MouseEvent):void{
- if(userNameInput.text!=""){
- userName = userNameInput.text;
- nc=new NetConnection();
- nc.addEventListener (NetStatusEvent.NET_STATUS,netStatusHandler);
- nc.client = this;
- nc.connect (rtmpUrl);
- }else{
- msg.text = "请输入用户名";
- }
- }
- private function netStatusHandler(event:NetStatusEvent):void{
- trace(event.info.code);
- switch (event.info.code) {
- case "NetConnection.Connect.Success" :
- trace("连接成功!");
- nc.call("getAllUserNum",new Responder(getAllUserNumResult,getAllUserNumFault))
- break;
- case "NetConnection.Connect.Rejected" :
- trace("连接被拒绝!");
- break;
- case "NetConnection.Connect.Failed" :
- trace("连接失败!");
- break;
- case "NetConnection.Connect.Closed" :
- trace("连接关闭!");
- break;
- }
- }
- private function getAllUserNumResult(re:Array):void{
- trace("getAllUserNumResult:"+re);
- removeChild(userNameInput);
- removeChild(enterBtn);
- removeChild(msg);
- allRoomNum = re;
- var xpos = 100;
- var ypos = 200;
- var num = 150;
- var len = allRoomNum.length;
- for(var i=0 ;i<len;i++){
- var btn:Button = new Button();
- btn.x = xpos;
- btn.y = ypos;
- xpos += num;
- btn.label = (i+1) + "号房间("+allRoomNum[i]+"/"+(i+1) * 10 + ")";
- addChild(btn);
- btn.addEventListener(MouseEvent.CLICK,roomBtnHandler);
- roomBtnArray.push(btn);
- }
- }
- private function getAllUserNumFault(fe:*):void{
- trace(fe);
- }
- private function intoRoom():void{
- var len = roomBtnArray.length;
- for(var i=0;i<len;i++){
- removeChild(roomBtnArray[i]);
- }
- roomBtnArray = [];
- textArea=new TextArea();
- textArea.setSize (200,300);
- textArea.move (20,20);
- addChild (textArea);
- textInput=new TextInput();
- textInput.width = 140;
- textInput.move (20,330);
- addChild (textInput);
- button=new Button();
- button.width=50;
- button.label="发送";
- button.move (170,330);
- addChild(button);
- button.addEventListener (MouseEvent.CLICK,sendMsg);
- userList = new List();
- userList.move(250,20);
- userList.setSize(100,300);
- addChild(userList);
- userList.dataProvider = new DataProvider(onlineArray);
- nc.call("getMsg",new Responder(getMsgResult,getMsgFault),currentRoomid);
- }
- private function getMsgResult(re:*):void{
- var msg:String = "";
- var len:Number = re.length;
- for(var i=0;i<len;i++){
- msg += re[i]+"\n";
- }
- textArea.text = msg;
- }
- private function getMsgFault(fe:*):void{
- }
- private function roomBtnHandler(event:MouseEvent):void{
- var roomid = Number(event.currentTarget.label.substr(0,1));
- if(allRoomNum[roomid - 1] == roomid * 10){
- event.currentTarget.label = "此房间已满";
- }else{
- nc.call("addRoom",new Responder(addRoomResult,addRoomFault),userName,roomid);
- currentRoomid = roomid;
- }
- }
- private function addRoomResult(re:*):void{
- trace(re);
- if(re){
- intoRoom();
- }
- }
- private function addRoomFault(fe:*):void{
- }
- private function sendMsg (e:MouseEvent):void{
- nc.call("sendMsg",null,currentRoomid,textInput.text);
- textInput.text = "";
- }
- public function getMsgInfo(msg:String):void{
- textArea.appendText(msg+"\n");
- }
- public function getUserList(list:Array):void{
- trace("getuserList:"+list);
- onlineArray = list;
- if(userList){
- userList.dataProvider = new DataProvider(onlineArray);
- }
- }
- public function getAllRoomNum(array:Array):void{
- allRoomNum = array;
- var len = roomBtnArray.length;
- if(len > 0){
- for(var i=0;i<len;i++){
- roomBtnArray[i].label = (i+1) + "号房间("+allRoomNum[i]+"/"+(i+1) * 10 + ")";
- }
- }
- }
- public function close():void{
- }
- }
- }
客户端增加一个大厅,然后再进房间,客户端的代码我就不详细讲解了,因为这不是一个讲AS3的教程,会一些AS3的朋友应该都看得懂,如果不懂,可以先看一下我写的关于AS3的教程,这个客户端代码写得有点乱,只是完成了功能,FMS的教程写完后,我准备写一些关了MVC框架的使用教程,像cairngorm和pureMVC,到时会将代码处理得更好些.
下节继续.
(本教程如需转载请注明出处!)
真是掉胃口诶
写的不错,不过这个如果只连接服务器再断开会报错
另外我写了点简化的东西 希望对你有帮助
我把你的client定义写到Client类里面
Client.prototype.addRoom=function(username,roomid){
//debug(username,roomid)
var online=application.roomArray[roomid-1].checkOnline(username)
debug(”exsit online:”+online)
if(!online){
this.username=username
this.roomid=roomid
var user=new User(this,username,roomid)
application.roomArray[roomid-1].addUser(user)
return true
}else{
return false
}
}
Client.prototype.getMsg=function(roomid){
return application.roomArray[roomid-1].msgList
}
Client.prototype.sendMsg=function(roomid,msg){
var usermsg=this.username+”:”+msg
application.roomArray[roomid-1].sendMsg(msg)
}
Client.prototype.getAllUserNum=function(){
return application.roomUserNum
}
另外 为了简化广播 我写了两个函数 主要是减少重复的东西
function broadcast(array, funStr, param1) {
for(var i=0;i<array.length;i++){
array[i].call(funStr,null,param1)
}
}
function broadcastUnit(array,unitName, funStr, param1) {
for(var i=0;i<array.length;i++){
array[i][unitName].call(funStr,null,param1)
}
}
我觉得这个程序还可以再优化下,这样可以把room[私房]包在hall[大厅]里面,私房可以限制人数
通过Client和broadcast简化,main.asc文件从数十行变成了十几行
application.onAppStart=function(){
this.roomArray=[]
this.roomUserNum=[]
var roomLen=3
for(var i=0;i<roomLen;i++){
this.roomArray.push(new Room(i+1))
this.roomUserNum.push(0)
}
}
application.onConnect=function(client){
this.acceptConnection(client)
}
application.onDisconnect=function(client){
this.roomArray[client.roomid-1].delUser(client.username)
}
继续研究中….
我发现运行不起
运行不起是什么意思??
能把教程的整套代码贴出来么,我想下载学学。
博主能否提供教程的FLA代码了
你这个对初学者来说太深奥了,要是能对着代码再去体验你说的那些就方便多了
不好意思,现在手上已经没这些代码了
怎么不继续写下去了啊、