当前位置:首页>>平面设计教程>>Flash教程>>正文

Flash MX 编程深层次应用-网络连线游戏(1)

文章出处:设计前沿收集 作者:未知 发布时间:2005-07-03 收藏到QQ书签
第7章 网络连线游戏——四子连

7.1 游戏的登陆

    

作为一个下棋游戏,其最基本的一点内容就是登陆。这个登陆看似简单,其实不然,因为登陆是一个游戏的入口,它完成下面几个功能:

Ö           输入用户名
Ö           输入服务器IP
Ö           发送连接服务器指令
Ö           根据服务器返回信息给用户以反馈

这些功能是一个登陆页面要具备的功能,登陆页面如图7-2所示。

在这里设置一个服务器IP是为了方便调试程序,其实在真正的登陆页中应该不出现,代之出现的应该是密码、性别等其他内容,从图7-2中明显可以看出它有两个输入框和一个按钮。


7-2

7.1.1  游戏初始化

登陆MC中初始化部分的程序代码如下:

    //这个server就是前面说的服务器IP地址,127.0.0.1是代表本地服务

    server = "127.0.0.1";

   //把输入的光标移到服务器IP的文本框中

    Selection.setFocus( "server" );

    function trim(strin)

    {

       //去字符串两边空格命令

             var i,j;

             for(i=0; i < strin.length; i++)

                      if(strin.charAt(i) != ' ')

                                break;

             if(i == strin.length)

                      return "";

             for(j=strin.length-1; j >= i; j--)      

                      if(strin.charAt(j) != ' ')

                                break;

             return strin.substring(i,j+1);

    }

其实也没有什么,就是一个简单的初始化的部分,一个去除字符串头尾空格的函数。Flash已经发展到MX版本了,去空格的函数都没有,还要程序员自己写,真是怪事。其实Flash MX不但没有这个函数,也没有子串替代的函数(replace)。好了,言归正传,这个函数没有什么好讲的,看看登陆按钮的代码吧。

login.onPress = function () {

var port = 1120;

    if (trim(nickname) == "" || nickname == null) {

             status = "名字不能为空";

    } else if (nickname.indexOf(",") != -1 || nickname.indexOf(":") != -1 || nickname.indexOf(" ") != -1) {

             status = "姓名中不可以包含','':'及空格字符";

    } else {

             _root.nickname = trim(nickname);

             _root.chatSocket.connect(server, port);

             status = "正在连接服务器 "+server+":"+port;

    }

}

在这里,这个登陆用的按钮被命名为login,如图7-3所示。

7-3

这里仅支持按钮,并没有支持键盘的回车操作。如果需要支持回车操作,则第一行的程序应做如下修改:

login.onPress = login_in;

Key.addListener(this);

this.onKeyDown = function() {

    if (Key.isDown(Key.ENTER))  login_in();

}

function login_in() {

……

从这个代码来看,Flash MX如果要同时支持按钮与键盘甚至鼠标的话,操作就变得麻烦了,不像以前一个语句on (press, keyPress "<Enter>")便可。不过想想也应该,MX把各种事件响应拆开,这样对每个事件程序方便了,但是代码就增长了。这个按钮响应事件中有一个文本显示框status,还有一个非常重要的Socket实例名_root.chatSocket,这个实例是在主场景被创建的。

7.1.2  游戏主场景

下面是主场景的程序:

//创建一个XML Socket连接

chatSocket = new XMLSocket();

//这个onConnect是用来定义当连接成功所调用的函数

chatSocket.onXML = onXML;

sys = "[公告] ";

chatSocket.onConnect = onConnect;

function onConnect (success) {

    trace("connect = "+success);

    if (success == false) {

             this.close();

             objLogin.status = " 在连接服务器 "+objLogin.server+" 时出错";

    } else {

             objLogin.status = " 您已成功的连到 "+objLogin.server;

       //如果成功连接就发送一条连接命令

             var xmlMsg = new XML();

             var ack = xmlMsg.createElement("CMD");

       //登陆命令

             ack.attributes.VALUE = "LGIN";

       //我的用户名

             ack.attributes.NICK = objLogin.nickname;

       //我的密码

             ack.attributes.PASS = "nothing";

             xmlMsg.appendChild(ack);

             trace ("第一次连接的内容:"+xmlMsg);

       //送出这个XML

             this.send(xmlMsg);

       //命令发出后连接完成,进入通信阶段

    }

}

调试窗口output输出内容如下:

connect = true

第一次连接的内容:<CMD PASS="nothing" NICK="dongua" VALUE="LGIN" />

很明显,这是成功连接的输出提示。至此,登陆部分完成。从前面所列的代码可以看出登陆过程就是先实例化一个Socket对象(new语句),然后发出一个联机请求,等待后台程序返回一个值,如果返回true则表示成功连接,返回false表示连接失败。

在上面的代码中

chatSocket.onConnect = onConnect;

function onConnect (success) {……

这两句代码也可以合起来写成一句代码:

chatSocket.onConnect = function (success) {……

现在让我们来看看后台的Java代码:

if(this.cmd_LOGIN.equals(cmd)) {

    //如果是登陆请求就把用户的名字、密码存起来

    String nickname = (String)root.attributes.get("NICK");

    String password = (String)root.attributes.get("PASS");

    if( nickname != null && user.manager.findNickname(nickname) == null) {

        //ok!

        user.nickname = nickname;

        user.password = password;

        user.status = this.usr_ST_ON;

        user.level = this.usr_LVL_NORMAL;

        user.manager.addUser(user);

        //向登陆的人发出一个服务器已经做好准备接收数据的信息

        user.notify(packMsg(this.m_ACK, "OK", ""));

        //向所有其他已经登陆的人发出有人登陆的信息

        user.manager.notifyAll(packMsg(this.m_USR, "ON", user.nickname));

        //向登陆的人发出其他已与服务器连接的用户的名单信息

        user.notify(packMsg(this.m_USR, user.manager.getUserlist(","), ""));

        //向登陆的人发出其他已与服务器连接的用户坐在哪张桌子的信息

     user.notify(packMsg(this.m_PLA, user.manager.getUserplace(","), ""));

    }

    else {

        //出错,退出

        user.notify(packMsg(this.m_ACK, "401", ""));

        user.onKill();

    }

}

在上面的代码中有一句比较重要的事件函数定义语句就是:

chatSocket.onXML = onXML;

这个其实就是当有XML数据传送过来时就会激发出onXML函数,onXML函数的代码如下:

function onXML(x) {

    if (x.firstChild.nodeName == "ACK") {

             if (x.firstChild.attributes.VALUE == "OK") {

                      //重新指定连接函数,而指向通信函数

                      this.onXML = _root.onXML_Receive;

             } else {

                      this.close();

                      objLogin.status = "nickname already exists";

             }

    } else {

             trace(x);

    }

}

很明显在前面连接成功后就向后台送出一个用户名及其相关信息,如果后台收到这个信息而且已经准备好,就会回送一个<ACK VALUE="OK" />Flash,然后onXML程序部分就会收到并处理这个信息。其实这个过程与前面的登陆联机一起算是一个握手的过程,或者说是连接后台的过程。其方式就像是说:我(用户)要登陆了,你(服务器)准备好了没有?服务器在准备好之后就说:行了,我准备好了,你可以发数据了。至此,通信建立过程完毕,在握手完毕之后,开始正常的通信,此时要将onXML的事件函数指向正常的通信函数_root.onXML_Receive


Flash MX使用UTF8编码。在Flash MX里输入汉字的时候为GB码,生成SWF的时候就会将GB转换为UTF8,在浏览器播放的时候,播放器再将其转为GB。但是LOAD外部TXT变量或者XML通信的时候,如果内容是GB码,就会出现问题,显示为乱码。要解决这个问题只需在程序的最开始处加语句:System.useCodepage = true;便可。

游戏在登陆之后进入主控画面,如图7-4所示。

7-4

从图7-4可以看出整个游戏的画面被分成三个区:左上角是游戏区,主要是摆放游戏台及与游戏相关的内容;下面是聊天区,主要是让连线的玩家聊天与交流;右边是在线用户列表区,显示出连到系统的玩家的名单。好了,下面就逐一介绍这三个区。



Google