某传说中的网络游戏引擎显示模块0.2BETA

最近看了许多开源的2D,3D游戏引擎。比如 pushButton,Flixel , Iso 等。发现各有各的特点。首先必须承认,这个自己写的《某传说中的网络游戏》的引擎肯定有不完善的地方,而且还是很多。比这些开源的引擎差距一定很大吧。 但是直接将网游移植这些成熟的引擎也不太现实。
于是~改写这些线程的引擎成为了我的一个想法。嘛~毕竟《某传说中的网络游戏》只是作为毕业设计交的作品而已。因此这次改写只是把这些开源引擎中优秀的部分“移植”过来。之所以 移植 加引号是因为只是移植了思路,而非源码。
pushButton其显示效率非常的高,原因是所有的显示对象都是显示在一张BitmapData上的,因此无论场景有多少个对象,也只是刷新一张位图而已,这一点我以前完全没想到,于是花了3个小时。写了这个显示模块的demo. 源码如下:
[cc lang=”actionscript3″ nowrap=”false”]
package
{
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.utils.Dictionary;

[SWF(width=”500″,height=”400″,frameRate=”60″)]
public class Bitmap extends Sprite
{
[Embed(source=”../Embeds/小火菊.jpg”)]
private var _pic:Class;

private var _dir:Dictionary=new Dictionary(true);
private var _manager:Vector.=new Vector.;
private var _output:TextField;

public function Bitmap()
{
drawToStage(new _pic().bitmapData,new Rectangle(150,150,148,130),”小火菊”);

var _redSprite:Sprite=makeRect(0xff0000,new Rectangle(0,0,40,40));
drawToStage(turnToBitmapData(_redSprite),new Rectangle(100,100,40,40),”这是红色矩形”);

stage.addEventListener(MouseEvent.CLICK,test);

_output=new TextField();
addChild(_output);
}

//将对象绘制到主场景
private function drawToStage(obj:BitmapData,rect:Rectangle,name:String):void
{
this.graphics.beginBitmapFill(obj,new Matrix(1,0,0,1,rect.width+rect.x,rect.height+rect.y));
this.graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
this.graphics.endFill();
var _obj:Object=new Object();
_obj.name=name;
_obj.x=rect.x;
_obj.y=rect.y;
_dir[_obj]=[];
_dir[_obj]=[obj,rect];
_manager.push(_obj);
}

//绘制矩形
private function makeRect(color:uint,rect:Rectangle):Sprite
{
var _sprite:Sprite=new Sprite();
_sprite.graphics.beginFill(color);
_sprite.graphics.drawRect(rect.x,rect.y,rect.width,rect.height);
_sprite.graphics.endFill();
return _sprite;
}

//通过鼠标点击获取对象
private function findObject():Object
{
for each(var _array:* in _dir)
{
var _rect:Rectangle=_array[1];
var _width:Number=Math.abs(stage.mouseX-_rect.x);
var _height:Number=Math.abs(stage.mouseY-_rect.y);
if(_width<=_rect.width && _height<=_rect.height && stage.mouseX>=_rect.x && stage.mouseY>_rect.y)
{
for(var _prop:* in _dir)
{
if(_dir[_prop][1]==_rect)
{
return _prop;
}
}
}
}
return null;
}

//主场景刷新
private function update():void
{
this.graphics.clear();
for(var _prop:* in _dir)
{
var _bmd:BitmapData=_dir[_prop][0];
var _rect:Rectangle=_dir[_prop][1];
this.graphics.beginBitmapFill(_bmd,new Matrix(1,0,0,1,_rect.width+_prop.x,_rect.height+_prop.y));
this.graphics.drawRect(_prop.x,_prop.y,_rect.width,_rect.height);
this.graphics.endFill();
var _newRect:Rectangle=new Rectangle(_prop.x,_prop.y,_rect.width,_rect.height);
_dir[_prop][1]=_newRect;
}
}

//鼠标点击判断
private function test(e:MouseEvent):void
{
var _obj:Object=findObject();
if(_obj!=null)
{
_output.text=”你点击了: “+_obj.name;
_output.width=_output.textWidth+10;
_obj.x+=10;
update();
}else{
_output.text=”点击处无对象”;
_output.width=_output.textWidth+10;
}
}

//将显示对象转换为BitmapData
private function turnToBitmapData(obj:DisplayObject):BitmapData
{
var _bmd:BitmapData=new BitmapData(obj.width,obj.height);
_bmd.draw(obj,null,null,null,new Rectangle(0,0,obj.width,obj.height));
return _bmd;
}
}
}
[/cc]

点击舞台后,会输出你是否点击到了图像,若点中图像则输出图像名称,同时图像向右位移10像素。

设计的时候遇到这么一个问题,即通过drawRect设定了绘制坐标后,图片确实出现在指定的坐标上,宽高都没问题。但图像出现了错位。
我之前试过 假设我 drawRect(50,50,…) 即 绘制到坐标50,50地方去
然后使用 矩阵 再反向偏移 50,50. 结果图片还是错位的

之后我试着使用 drawRect(图像宽度的整数倍,图像高度的整数倍…)
发现图像成功的绘制到 对应的位置,且图像无错位。
我认识到 即使 drawRect改变了图像的坐标,但是图像的显示仍然是对准舞台0,0 的。
实际上图像是根据舞台0,0进行repeat的。

因此矩阵偏移就不能仅仅是 drawRect 的相反值。而应该是
new Matrix(1,0,0,1,图像.width+偏移.x,图像.height+偏移.y));

实际上,目前虽然实现了单位图bitmapData的刷新,但毕竟是整张位图的刷新,期望目标是只更新有改变的部分,而非整张位图。这个坑先挖好,以后再填。

话说最近挖了好多坑,事件管理器的更新版本的坑还没填啊。。。过几日在填上。
接下来工作是完成显示层级的操作。

发表评论

电子邮件地址不会被公开。 必填项已用*标注