• 2007-09-27

    连网数据同步

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://wxsr.blogbus.com/logs/10047332.html

     Posted:2007-05-02 15:14 连网数据同步示意

    趁着今天有空更新写下自己用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; }; /////////////////////////////////////////////////////////////////////////////////////////////// 当我们处理涉及多个元件的数据同步时~一般的过程是:帧听数据对象数据改变-------------》将要传输的数据放到一个对象或数组里------------》经由服务器传输,--------------》在服务器处理返回形式------------》解释返回数据-------------------》影射同步数据 上边的例子可能大家也发现了我服务端调用的函数很少,大多情况都是调用了我写的那个中介函数来处理,服务端主要的职能在这里只是用于数据的传输,运算的过程主要集中在客户端的。 我们在客户段要做的其实就是帧听对象的数据改变否,改变了我们就给服务端发送信息,然后再经由服务端分析要传输的类型,在返回客户端,再由客户端解释返回数据,然后解释,并影射相关数据。 希望有新学的人能好好看看脚本~已经作了相关注释,希望对大家有用~~~ 转载请标明出处 ^ ^谢谢 View All.. KeyWord:连网数据同步


    随机文章:

    fms聊天室 2007-09-27
    连网5子棋 2007-09-27
    几个小东西 2007-09-27

    收藏到:Del.icio.us




发表评论

您将收到博主的回复邮件
记住我