FLEX开发p2p小游戏简易教程:经典猜拳游戏

最近开始捣鼓小游戏。本人一直很喜欢玩小游戏的HOHO,可惜一直没往开发上发展。呵呵,花了半天搞了个简单的经典小游戏——猜拳,和爱好者一起分享下,高手可以飘过哈。游戏使用stratus实现了游戏双方的p2p连接,游戏数据都是直接发送的,不经过服务器。在此基础上可以开发很多类似的双人互动小游戏。

      准备工作:预装FLEX电脑一台,上网账号一个,好茶一杯-_-

     下面正式开始,程序开发分为三大块:

      一、p2p连接部分

     该部分可参考前面的文章,已经介绍的很详细了。下面就直接上代码了,不清楚的点这里

    

1 //初始化自己的相关流以及在流上定义的方法;
01 private function initStream():void
02             {
03                 listenStream = new NetStream(netConnection,NetStream.DIRECT_CONNECTIONS);
04                 listenStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 
05                 listenStream.publish(myName);   
06                   
07                 var c:Object =new Object();
08                 c.onPeerConnect = function(caller:NetStream):Boolean
09                 {
10   
11                         incomingStream = new NetStream(netConnection,caller.farID);
12                         incomingStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
13                         incomingStream.play("caller");
14                                   
15                         var i:Object = new Object();
16                         i.onIncomingCall = function(caller:String):void
17                         {
18                             show(caller + "已经成功与您连接上\n"); 
19                             remoteName = caller;
20                               
21                             //outgoingStream.send("onCallAccepted", username);
22                             callState = CallOn;
23                             remote_input.visible = false;
24                             action_btn.enabled = true;
25                             //idManager.change(callState);
26                         }   
27                         i.onIm = function(act:String):void
28                         {
29                             remoteAction = act;
30                             //trace("remoteAction: "+remoteAction);
31                             remote_action.text = "出招了";
32                             my_action.text = "";
33                             result_txt.text = "";
34                             if(myAction != null)
35                                 compare(myAction,remoteAction);
36                         }
37                         i.onDisconnected = function(caller:String):void
38                         {
39                             show(caller+"和你断开连接\n");
40                             stop();
41                         }    
42                         incomingStream.client = i;
43                           
44                         outgoingStream = new NetStream(netConnection,NetStream.DIRECT_CONNECTIONS);
45                         outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,callee_outgoingStreamHandler);
46                         outgoingStream.publish("callee");
47                           
48                         return true;
49                     }
50                   listenStream.client = c;
51             }
1 //初始化相关发送流和方法;
01 private function call():void
02             {
03                   
04                 controlStream = new NetStream(netConnection,farPeerID);
05                 controlStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
06                 controlStream.play(remoteName);
07                   
08                 outgoingStream = new NetStream(netConnection,NetStream.DIRECT_CONNECTIONS);
09                 outgoingStream.addEventListener(NetStatusEvent.NET_STATUS,caller_outgoingStreamHandler);
10                 outgoingStream.publish("caller");
11                 //outgoingStream.send("onIncomingCall",username);
12                 //info_txt.text += "正在与"+partnername+"建立连接\n";
13                   
14                 //var o:Object = new Object();
15                 //o.onPeerConnect = function(callee:NetStream):Boolean
16                 //{
17                 incomingStream = new NetStream(netConnection,farPeerID);
18                 incomingStream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);
19                 incomingStream.play("callee");
20                           
21                 var i:Object = new Object();
22                 i.onIm = function(act:String):void
23                 {
24                     remoteAction = act;
25                     //trace("remoteAction: "+remoteAction);
26                     remote_action.text = "出招了";
27                     my_action.text = "";
28                     result_txt.text = "";
29                     if(myAction != null)
30                        compare(myAction,remoteAction);
31                 }
32                 i.onCallAccepted = function(callee:String):void
33                 {
34   
35                     show(callee+"已经成功与您连接上\n");
36                     callState = CallOn;
37                     action_btn.enabled = true;
38                     //send_btn.enabled = true;
39   
40                 }
41                 i.onDisconnected = function(callee:String):void
42                 {
43                     show(callee+"和你断开连接\n");
44   
45                     stop();
46                 }
47                 incomingStream.client = i;
48                 // return true;
49                 // }
50                 // outgoingStream.client = o;
51                   
52                       
53             }

     二、数据库及远程调用部分

     游戏中建立p2p连接是根据对方用户名查找对应的peerID来实现的。相关信息都保存在数据库中,如下图:

   

    FLEX客户端和数据库交互是通过AMFPHP这个代理网关来实现的。AMFPHP在这下载,是PHP的哈。本人只学了PHP-_-

    下载下来解压后得到amfphp 1.9这个文件夹,东东都在这里面了。找到gateway.php这个文件进行编辑,这个就是指的网关文件了。

   

     有两个地方需要注意下:

    

代码
<?php

define("PRODUCTION_SERVER", false);
include "globals.php";
include "core/amf/app/Gateway.php";
$gateway = new Gateway();
//设置PHP类的位置,如果不改默认位置就是services文件夹,在globals可定义
$gateway->setClassPath($servicesPath);
$gateway->setClassMappingsPath($voPath);
//设置php和数据库交互的字符编码集,都用utf8最好,数据库编码也要一致
$gateway->setCharsetHandler("iconv", "UTF-8", "UTF-8");
$gateway->setErrorHandling(E_ALL ^ E_NOTICE);
if(PRODUCTION_SERVER)
{
$gateway->disableDebug();
$gateway->disableStandalonePlayer();
}
$gateway->enableGzipCompression(25*1024);
$gateway->service();
?>

 

 

     然后打开services文件夹,在下面写你的PHP类,也就是下面RemoteObject组件里的source属性。

     贴上我自己的PHP类:

    

代码
<?php
class MySql
{

function MySql()
{
$this->methodTable = array(
'registerData' => array(
'description' => '注册',
'access' => 'remote',
'arguments' => array("username","peerID")
)
,
'fetchData' => array(
'description' => '取值',
'access' => 'remote',
'arguments' => array("username")
)
);
$DATABASE_SERVER= "数据库地址" ;
$DATABASE_USERNAME= "用户名" ;
$DATABASE_PASSWORD= "密码" ;
$DATABASE_NAME= "数据库名" ;
$link = mysql_connect( $DATABASE_SERVER,
$DATABASE_USERNAME,
$DATABASE_PASSWORD)
or
die( mysql_error() );
mysql_query("SET NAMES 'utf8'");
mysql_select_db( $DATABASE_NAME, $link);
}
function registerData($username,$peerID)
{


$query = "SELECT * FROM registrations WHERE m_username='$username' ";
$result = mysql_query( $query );

$isNew = ($result && mysql_num_rows($result) == 0);
if( $isNew ) {
$query = "INSERT INTO registrations SET ";
$query .= "m_username='$username', m_peerID='$peerID';";
}
else {
$query = "UPDATE registrations SET ";
$query .= " m_peerID='$peerID' where m_username='$username';";
}
$result = mysql_query( $query );
return $result;

}

function fetchData($username)
{

$query = "select * from registrations where m_username = '$username' ;";
$result = mysql_query( $query );
$m = mysql_num_rows($result);
if($m != 0) return $result;
else return "no";
}
}
?>

 

 

     里面的methodTable就是定义的方法列表,里面定义了两个方法,分别是登陆服务器时注册用户数据和进行连接时查找对方用户数据的两个方法,比较有特色的东东-_-

 

     FLEX中使用RemoteObject组件进行远程调用:

    

1 <s:RemoteObject id="myService" destination="amfphp" endpoint="http://服务器地址,本地就是localhost/gateway.php" source="PHP类的名字" showBusyCursor="true">
2 //method就是定义的要调用的方法
3             <s:method name="registerData" result="registerData_Result(event)" fault="registerData_Fault(event)" />
4             <s:method name="fetchData" result="fetchData_Result(event)" fault="fetchData_Fault(event)" />
5         </s:RemoteObject>

    使用的时候直接调用myService.methodname就行了。

     三、游戏逻辑部分

      真的很简单,主要是处理好用户双方的执行顺序就行了。简单地概括下吧我就不画图了,打个比方,比如我和你两个人玩猜拳,必须要两个同时出拳才能进行比较。程序里设置了两个变量:myAction和remoteAction,分别指得是我出的拳和对方出的拳。初始值都为null,当双方都出了拳后,进行比较,计算得分:

    

01 private function compare(myAct:String,remoteAct:String):void
02             {
03                 my_action.text = myAction;
04                 remote_action.text = remoteAction;
05                 if(myAct == remoteAct)
06                     result_txt.text = "平手";
07                 if((myAct == QuanTou && remoteAct == JianDao) || (myAct == JianDao && remoteAct == Bu) || (myAct == Bu && remoteAct == QuanTou))
08                     {
09                         result_txt.text = "恭喜,胜利";
10                         myScore ++;
11                     }
12                 if((remoteAct == QuanTou && myAct == JianDao) || (remoteAct == JianDao && myAct == Bu) || (remoteAct == Bu && myAct == QuanTou))
13                     {
14                         result_txt.text = "杯具,失败";
15                         remoteScore++;
16                     }
17                 myAction = null;
18                 remoteAction = null;
19                 action_btn.enabled = true;
20                 send_btn.enabled = false;
21             }

     Demo在这里:http://game1.online.cm/CaiQuanP2P.swf

     上个单机测试截图:

     

     其它的就不多说了,最后放上程序源代码在下面,感兴趣的自己看吧,欢迎跟帖交流,转载请注明出处,谢谢!by 疯狂的八神庵

posted @ 2010-05-28 14:08  rob_2010  阅读(316)  评论(0编辑  收藏  举报