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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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.<Object>=new Vector.<Object>;
        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;
        }
    }
}

点击舞台后,会输出你是否点击到了图像,若点中图像则输出图像名称,同时图像向右位移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的刷新,但毕竟是整张位图的刷新,期望目标是只更新有改变的部分,而非整张位图。这个坑先挖好,以后再填。

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

发表评论

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.