论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > Flash AS编程教程
Tag:2.0,3.0菜鸟,游戏,,cs,技巧,源码,,文本,文字,函数,音乐,随机,拖拽,asp,access,xml,mc,视频教程

连网数据同步示意

文章类别:Flash AS编程 | 发表日期:2008-10-6 17:35:28


趁着今天有空更新写下自己用fms做连网游戏的同步数据传输的处理方法~
大家用fms做连网游戏有一个概念,是一定要注意的,那就是同一个客户端文件因为为不同客户所用,当我们编写脚本时就得理清客户端既作为我自己的客户端的同时,也作为别人的客户端。

在这个的前提下我们就要涉及数据传输的问题了~
我个人认为,为了减轻服务端的负担,不是太重要的处理事件就得尽量写到客户端的脚本里去的~~,那样做有利于我们文件运行时的效率,而在那前提下数据同步的问题就不得不好好的在客户端写好了

下边看看我写的一个例子可能脚本会多了点:
//////////////////////////////////////////服务端脚本//////////////////////////////////////
application.onAppStart = function () {
 menber = [];
 id = 0;
 ingame_num=0
};
application.onConnect = function (newClient, arr) {
 ingame_num++
 menber.push (arr[0][0]);
 application.acceptConnection (newClient);
 if(ingame_num<=100){
 for (var i = 0; i < application.clients.length; i++) {
   if (application.clients[i] == newClient) {
    trace("呼叫ready")
    application.clients[i].call ("ready", null, ingame_num);
   }
  }}
 
 
};
Client.prototype.reCall = function (obj) {
 if (obj.type_ == "public" || obj.type_ == true) {
  //广播信息
  application.broadcastMsg (obj.func, obj.info);
 }
 //私聊机制
 else if (obj.type_ == "private" || obj.type_ == false) {
  for (var i = 0; i < application.clients.length; i++) {
   if (menber[i] == obj.condition) {
    application.clients[i].call (obj.func, null, obj.info);
   }
  }
 }
 //调用服务器自身函数
 else if (obj.type_ == "main") {
  this[obj.func](obj.info);
 }     
};




/////////////////////////////////////客户端部分////////////////////////////////////////////

/////////////////////////////上传数据帧听处理类////////////////////////
class watch_func {
 function watch_func(obj:Object, name:String, info_arr:Array, mync2) {
  var func = function (prop, oldVal, newVal, info_arr) {
   if (arguments[1].x != arguments[2].x || arguments[1].y != arguments[2].y) {
    function call_appliaction(who, func, info, type, condition) {
     var Send = {};
     Send.func = func;
     Send.info = info;
     Send.type_ = type;
     Send.condition = condition;
     //呼叫服务器中介函数
     who.call("reCall", null, Send);
    }
    //移动物更新坐标~
    info_arr[8][1] = obj.info;
    //服务器调用的更新信息处理函数(根据type的定义类型为广播),用于同步更新其他客户端处于更新状态的移动物的信息
    call_appliaction(mync2, "call_move", info_arr, true);
   }
   return newVal;
  };
  obj.watch(name, func, info_arr);
 }
}
/////////////////////////////帧听数据及影射同步类//////////////////////////////////
class watch_func_E {
 function watch_func_E(obj:Object, name:String, map:MovieClip, name_, info) {
  var w = [map, name_, info];
  var Em_func = function (prop, oldVal, newVal, w) {
   //arguments[3] 在这里是参数w的内容
   //arguments[3][0]这里等于类的自身参数map元件,这里用于表示路径
   //arguments[3][0][arguments[2][8][1].name_等于场景中map元件内的元件(具体元件名由obj所帧听的对象决定)
   for (var i in arguments[3][0][arguments[2][8][1].name_]) {
    //遍历mc的属性
    for (var j = 0; j     //i 为属性名,arguments[2][j][0]为更新对象的信息,if条件用于检测属性名是否一致
     if (i == arguments[2][j][0]) {
      //将更新的属性值赋值给场景中对应的元件属性
      arguments[3][0][arguments[2][8][1].name_][i] = arguments[2][j][1];
     }
    }
   }
   //更新场景对应的元件的坐标
   trace("x="+arguments[3][0][arguments[2][8][1].name_].info.x)
   trace("y="+arguments[3][0][arguments[2][8][1].name_].info.y)
   arguments[3][0][arguments[2][8][1].name_]._x = arguments[3][0][arguments[2][8][1].name_].info.x;
   arguments[3][0][arguments[2][8][1].name_]._y = arguments[3][0][arguments[2][8][1].name_].info.y;
  };
  obj.watch(name, Em_func, w);
 }
}
/////////////////////////////////////客户端部分//////////////////////////////////////////
//////////////////导入as部分///////////////////
function init_info(me, menber, info_arr) {
 //for (var i =1; i <=11; i++) {
 //var me = where["menber" + i];
  me.side = info_arr[0];
 me.status = info_arr[1];
 me.appointment = info_arr[2];
 me.power = info_arr[3];
 me.spess = info_arr[4];
 me.shoot = info_arr[5];
 me.lost = info_arr[6];
 me.id = i;
 me.info = {name_:me._name, x:me._x, y:me._y};
 menber.push(me);
 //}
 return menber;
}
//求两者距离
function dis_func(mc1, mc2) {
 if (typeof (mc1) != "movieclip") {
  var dx = mc1.x-mc2._x;
  var dy = mc1.y-mc2._y;
 } else if (typeof (mc2) != "movieclip") {
  var dx = mc1._x-mc2.x;
  var dy = mc1._y-mc2.y;
 } else {
  var dx = mc1._x-mc2._x;
  var dy = mc1._y-mc2._y;
 }
 dis = Math.sqrt(Math.pow(dx, 2)+Math.pow(dy, 2));
 return dis;
}
//寻最近者
function fine_nearest(arr, ball) {
 //将距离放入数组
 for (var i = 0; i  arr[i][4] = dis_func(ball, arr[i][0]);
 }
 //排序
 for (var i = 0; i  for (var j = i+1; j   if (arr[i][4]>arr[j][4]) {
    var tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
   }
   if (arr[i][4] == arr[j][4]) {
   }
  }
 }
 //返回
 var Obj = {};
 Obj.near = arr[0];
 Obj.arr = arr;
 return Obj;
}
//距离
function dis_init(arr, target_obj) {
 for (var i = 0; i  var m = this["m"+i];
  if (dis_func(m, target_obj)<60) {
   follow_move(target_obj, m, m.spees);
  }
 }
}
//方向
function degree_func(trget_obj, move_obj) {
 if (typeof (trget_obj) != "movieclip") {
  var dx = move_obj._x-trget_obj.x;
  var dy = move_obj._y-trget_obj.y;
 } else if (typeof (move_obj) != "movieclip") {
  var dx = move_obj.x-trget_obj._x;
  var dy = move_obj.y-trget_obj._y;
 } else {
  var dx = move_obj._x-trget_obj._x;
  var dy = move_obj._y-trget_obj._y;
 }
 if (dy == 0) {
  if (dx>0) {
   degree = 90;
  } else {
   degree = 270;
  }
 } else {
  if (dy>0) {
   degree = Math.atan(dx/dy)*180/Math.PI;
  } else {
   degree = Math.atan(dx/dy)*180/Math.PI+180;
  }
 }
 move_obj.degree = -degree;
 return move_obj.degree;
}
//跟随函数
function follow_move(trget_obj, move_obj, speed) {
 var degree = -degree_func(trget_obj, move_obj);
 if (dis_func(trget_obj, move_obj)<=10) {
 } else {
  move_obj._y += speed*Math.cos(degree*(Math.PI/180))*-1;
  move_obj._x += speed*Math.sin(degree*(Math.PI/180))*-1;
 }
 return move_obj;
}
//斜率
function k_(obj1, obj2) {
 if (typeof (obj1) != "movieclip") {
  var k = (obj1.y-obj2._y)/(obj1.x-obj2._x);
 } else if (typeof (obj2) != "movieclip") {
  var k = (obj1._y-obj2.y)/(obj1._x-obj2.x);
 } else {
  var k = (obj1._y-obj2._y)/(obj1._x-obj2._x);
 }
 return k;
}


//////////////////第一帧///////////////////
stop();
var ID;
#include "player.as"
var mync2 = new NetConnection();
mync2.ready = function(what) {
 ID = what;
 gotoAndStop("play_game");
};
mync2.init_full = function(what) {
 gotoAndStop("full");
};
play_btn.onPress = function() {
 if (txt.text != "") {
  ID_ = txt.text;
  list_arr = [[ID_, 123456]];
  mync2.connect("rtmp://localhost/ball_v1", list_arr);
  mync2.onStatus = function(info) {
   if (info.code == "NetConnection.Connect.Success") {
   } else {
    gotoAndStop("lost_game");
   }
  };
 }
};

///////////////////第2帧/////////////////////////////////////
import flash.geom.Point;
stop();
////////中介函数////////
function call_appliaction(who, func, info, type, condition) {
 var Send = {};
 Send.func = func;
 Send.info = info;
 Send.type_ = type;
 Send.condition = condition;
 who.call("reCall", null, Send);
}
///广播我方成员变更信息给其他玩家函数
mync2.call_move = function(info) {
 if (int(info[info.length-1]) != ID) {
  for (var i = 0; i<=11; i++) {
   EM_arr[i].info = info;
  }
 } else {
 }
};
////////编历储存信息函数//////
function putin(what, arr) {
 for (var i in what) {
  arr.push([i, mm[i]]);
 }
}
///////
info_Marr = [];
info_Earr = [];
info_arr1 = ["m", "attack", 1, 5, 8, 1, 1];
info_arr2 = ["e", "attack", 1, 5, 8, 1, 1];
var cnt = 1;
ME_arr = [];
EM_arr = [];
for (var i = 1; i<=11; i++) {
 ////创建对象////
 var ME = "ME"+i;
 var EM = "EM"+i;
 ME = {};
 EM = {};
 ME_arr.push(ME);
 EM_arr.push(EM);
 ////创建对象////
 ////记录信息////
 var m = map["m"+i];
 var e = map["e"+i];
 m.gotoAndStop(2);
 e.gotoAndStop(3);
 init_info(m, info_Marr, info_arr1);
 init_info(e, info_Earr, info_arr2);
 ////记录信息////
}
///区分玩家敌我类型///
if (ID%2 == 0) {
 var conter = map.m1;
 play_side = "m";
} else {
 var conter = map.e1;
 play_side = "e";
}
for (var i = 1; i<=11; i++) {
 var mm = map[play_side+i];
 ///创建信息数组
 var info_arr = "info_arr"+i;
 info_arr = [];
 //编历储存对象信息
 putin(mm, info_arr);
 //信息整理
 info_arr.reverse();
 //添加id信息
 info_arr.push(ID);
 ///////创建影射帧听实例/////
 Em = EM_arr[i];
 Em.info;
 new watch_func_E(Em, "info", map, name_, info);
 //创建玩家帧听控制对象帧听实例
 var player = ME_arr[i-1];
 player.info = mm.info;
 new watch_func(player, "info", info_arr, mync2);
}
this.point_x = new Point(map[play_side+1]._x, map[play_side+1]._y);
/////////////////////玩家控制执行部分/////////////////
this.onEnterFrame = function() {
 if (down) {
  this.point_x = new Point(_xmouse, _ymouse);
 }
 for (var i = 1; i<=11; i++) {
  var mm_ = map[play_side+i];
  mm_.info = {name_:mm_._name, x:mm_._x, y:mm_._y};
  var mc_ = map[play_side+i];
  ME_arr[i-1].info = mm_.info;
  if (mc_.hitTest(_xmouse, _ymouse, true)) {
   conter = mc_;
   break;
  }
 }
 follow_move(this.point_x, conter, 5);
};
this.onMouseDown = function() {
 down = true;
};
this.onMouseUp = function() {
 down = false;
};
///////////////////////////////////////////////////////////////////////////////////////////////


当我们处理涉及多个元件的数据同步时~一般的过程是:帧听数据对象数据改变-------------》将要传输的数据放到一个对象或数组里------------》经由服务器传输,--------------》在服务器处理返回形式------------》解释返回数据-------------------》影射同步数据


上边的例子可能大家也发现了我服务端调用的函数很少,大多情况都是调用了我写的那个中介函数来处理,服务端主要的职能在这里只是用于数据的传输,运算的过程主要集中在客户端的。

我们在客户段要做的其实就是帧听对象的数据改变否,改变了我们就给服务端发送信息,然后再经由服务端分析要传输的类型,在返回客户端,再由客户端解释返回数据,然后解释,并影射相关数据。


希望有新学的人能好好看看脚本~已经作了相关注释,希望对大家有用~~~
视频教程列表
文章教程搜索
 
Flash AS推荐教程
Flash AS热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058