弹幕Flash-Part4-Flash弹幕层
终于到了本人最拿手的部分,Flash.
第三部分中已经提过了,Flash使用1980*80的大小,刚刚好可以把电影最上面的一条黑色覆盖住,用于显示弹幕.
这个部分可以算是整个工程最复杂的一部分,首先需要Flash向php请求弹幕数据,然后解析数据并且分类,显示在舞台上,另外获取数据时候要避免获取到重复的内容,所以请求时还要将读取的起点一并发送给php,从而既提高了数据拉取的效率.
php需要接收Flash传来的读取起点值,所以要考虑接收一个$_POST或者$_GET值.考虑到弹幕字符很长,并且数量不定,所以决定由php传给Flash的返回数据定为XML格式.xml需要返回一个IP值(暂时没有用处),一个内容值,一个弹幕在Mysql中的索引值,用来确定下次拉取的起点.最后确定XML的格式为:
<?xml version="1.0" encoding="utf-8"?> <Dams> <calc num="拉取到的数据条数" /> <Items> <Item id="1" Content="弹幕内容1" IP="IP1" /> <Item id="2" Content="弹幕内容2" IP="IP2" /> <Item id="3" Content="弹幕内容3" IP="IP3" /> <Item id="4" Content="弹幕内容4" IP="IP4" /> <Item id="5" Content="弹幕内容5" IP="IP5" /> ...... <Item id="n" Content="弹幕内容n" IP="IPn" /> </Items> </Dams>
如果php返回值为xml格式,那么flash必须以GET方式向php发送请求,所以php响应的需要接收一个$_GET的值.
<?php //防止不带参数的直接访问 if(isset($_GET['ID'])){ //连接数据库 require("connectdb.php"); //向数据库请求数据 $data=mysql_query("SELECT * FROM dams WHERE ID>".$_GET['ID'].";"); //获取行数 $rows=mysql_num_rows($data); echo "<?xml version="1.0" encoding="utf-8"?>"; echo "<Dams>"; echo "<calc num="".$rows."" />"; echo "<Items>"; //如果有数据就取出生成XML中的一部分 while($line=mysql_fetch_assoc($data)){ echo '<Item id="'.$line["ID"].'" Content="'.$line["Content"].'" IP="'.$line["IP"].'" />'; } echo "</Items>"; echo "</Dams>"; //关闭数据库连接 mysql_close(); } ?>
php发送了弹幕数据给Flash,那么Flash就必须要接受并且解析这些信息的内容,这里需要一个XML对象用于解析.
另外需要显示弹幕的容器,所以直接在库中直接创建一个含有动态文本的影片剪辑即可,动态文本实例名为
//创建实例 var GetDanM:XML=new XML(); //创建临时弹幕池 var DanPool:Array=new Array(); //定义全局变量作为索引 _global.DanID=0; //发送索引到服务器并读取数据 GetDanM.load("http://localhost/Dam/getDam.php?ID="+_global.DanID); //添加监听器,监听XML加载 GetDanM.onLoad=function(ok){ //确定是否加载成功 if(ok){ //直接截取XML片段等待解析 nodes=GetDanM.childNodes[0].childNodes; //如果是空的,等待0.1秒后再次拉取 if(nodes[0].attributes.num==0){ setTimeout(GetNew,100); }else{ //如果不是空的,按次序将弹幕及相关的信息转存入临时弹幕池 nodes=nodes[1].childNodes; for(i=0;i<nodes.length;i++){ ID=nodes[i].attributes.id; IP=nodes[i].attributes.IP; Content=nodes[i].attributes.Content; DanPool.push({ID:ID,IP:IP,Content:Content}); } //触发显示弹幕的操作 ShowDam(); } } } //显示弹幕 function ShowDam(){ //当临时弹幕池被删光后,获取新的消息 if(DanPool.length==0){ GetNew(); }else{ //需要根据字幕长度计算长度和显示时间 delay=PrintDam(); setTimeout(ShowDam,delay,Index+1); } }; //计算时间并显示 function PrintDam():Number{ //取得数据 ID=DanPool[0].ID; IP=DanPool[0].IP; Content=DanPool[0].Content; //创建舞台上的影片剪辑实例,命名为Dan_索引号 attachMovie("Dan","Dan_"+ID,ID); //设定内容 _root["Dan_"+ID].DanMu.text=Content; //随机颜色 _root["Dan_"+ID].DanMu.textColor=random(0xFFFFFF); //设定速度 _root["Dan_"+ID].V=(1980+Content.length*50)/15/50; //设定终止运动的位置 _root["Dan_"+ID].CL=-Content.length*60; //设定实例的起始位置 _root["Dan_"+ID]._x=1980; //为了防止弹幕重叠,考虑上下两行轮流显示 _root["Dan_"+ID]._y=40*(ID%2+1); //所有内容准备结束后就可以把弹幕池中对应的Object删掉了 DanPool.shift(); //创建一个每帧一次的循环 _root["Dan_"+ID].onEnterFrame=function(){ //每帧运动一个V的长度 this._x-=this.V; //当到达最左端时候停掉循环,释放CPU压力 if(this._x<this.CL){ delete this.onEnterFrame; } } //全局索引值跟进最后一个弹幕 _global.DanID=ID; //计算延迟 if(DanPool.length>0){ //长度不为零表示后面还有,需要较长时间的延迟防止重叠 delay=-_root["Dan_"+ID].CL/_root["Dan_"+ID].V/50*1000+500; }else{ //长度为0后边没有了,可以稍短的延迟 delay=500; } //返回延迟长度 return delay; } //请求新信息 function GetNew (){ //请求数据 GetDanM.load("http://localhost/Dam/getDam.php?ID="+_global.DanID); //测试时可以根据输出Reload标记重新加载 trace("Reload"); }
根据测试,如果相邻两条弹幕都长达20字以上,可能会导致弹幕重合,所以发送时候可以限制长度,另外推荐在弄一个管理员专用的,在没有弹幕发出的时候可以发送一些内容到屏幕上提示一下如何发送弹幕~~
到这里, 弹幕 系统全部都开发完了,感觉好激动,之前以为弹幕一定要用C#啥的神一样的语言写,现在看来并不需要……
前两天听说Adobe放弃Flash的更新了,顿时好心塞ヽ(≧□≦)ノ,看来Flash啥的这种被严重阉割的语言最终定要被历史遗忘…….
啥都不说了,我想静静…….别问我静静是谁(′д` )…彡…彡
评论
您需要 先登录 才可以回复.