0

我遇到了 AS3 和 AIR 的问题。我正在为带有飞机的智能手机开发横向滚动游戏,我使用不同的背景作为图层。

最重要的是:我使用 GPU 并且只使用位图,质量设置为低。所以性能设置都是为智能手机使用而设置的。

我使用绘图 API 将它们放入一个矩形中,并使用矩阵移动背景:

protected var scrollingBitmap:BitmapData;
protected var canvas:Graphics;
protected var matrix:Matrix;

public function move(dx:Number, dy:Number):void {
    matrix.translate(dx, dy);
    if(dx != 0) matrix.tx %= scrollingBitmap.width;
    if(dy != 0) matrix.ty %= scrollingBitmap.height;
    drawCanvas();
}

protected function drawCanvas():void {
    canvas.clear();
    canvas.beginBitmapFill(scrollingBitmap, matrix, true, true);
    canvas.drawRect(0, -scrollingBitmap.height, 1404, scrollingBitmap.height);
}

更新2(

看看这个: http: //plasticsturgeon.com/2010/06/infinite-scrolling-bitmap-backgrounds-in-as3/

我用它来创建我的背景。

有了这个,我可以模拟我的飞机在不移动整个背景的情况下向右飞行,我可以使用一个每次重复的小图形(对于前景层)。

对于背景层,我也使用这种方法,但图形要大得多,而且我只以较低的飞机速度移动它来模拟远处的背景。

我的移动方法是在一个 enterframe 事件上。所以我可以用我的飞机的“运动”来更新每一帧的背景。

)

平面可以超过位图的高度。每次位图回到窗口/屏幕时,都会发生真正的长时间滞后。当飞机飞得很快时,游戏也开始滞后。

我的第一种方法是使用 .PNG 文件(但它们非常大:1-3MB 大小)。我的下一个方法是使用 .GIF 文件(大小要小得多)。

两者都是一样的。所以不可能是这样。

我阅读了有关 draw() 和 copyPixels() 的信息,但我不知道如何使用它们来重复图像。

更新1:

protected var scrollingBitmap:BitmapData;
protected var canvas:Bitmap;

protected function init(e:Event):void {
    removeEventListener(Event.ADDED_TO_STAGE, init);
    canvas = new Bitmap(new BitmapData(1404, scrollingBitmap.height, true), "auto", true);
    this.addChild(canvas);
    drawCanvas();
}

public function move(dx:Number, dy:Number):void {
    if(dx != 0) dx %= scrollingBitmap.width;
    if(dy != 0) dy %= scrollingBitmap.height;
    drawCanvas(dx, dy);
}

protected function drawCanvas(xPos:Number = 0, yPos:Number =  0):void {
    canvas.bitmapData.copyPixels(scrollingBitmap, new Rectangle(0, 0, 1404, scrollingBitmap.height), new Point(xPos, yPos), scrollingBitmap);
}
4

2 回答 2

3

我认为您最好使用位图而不是使用带有填充的图形对象。copyPixels 非常快。所以你要做的只是在之前的任何东西的顶部复制像素,假设一切都是不透明的。如果一切都不是不透明的,你需要使用你的源位图作为它自己的 alpha 数据,这样以前绘制的像素就不会显示出来。

让我们重新构建您的画布,使其成为位图而不是 MC。您的新代码将如下所示:

protected function drawCanvas():void {
   canvas.bitmapData.copyPixels(scrollingBitmap, new Rectangle(0, 0, scrollingBitmap.width, scrollingBitmap.height), new Point(0,0), scrollingBitmap);
}

哦,看看那个!这段代码不仅更快,而且只有一行代码!

编辑:添加了工作代码

package  {
    import flash.display.MovieClip;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.geom.Rectangle;
    import flash.geom.Point;


    public class EndlessBG extends MovieClip{
        //this one stays stationary, we're getting the pixels for the right side of the pic from here
        private var _source:BitmapData;
        //this is the one moving to the left (the pixels for the right side are not visible except for once a cycle);
        private var _movingPixels:BitmapData;
        private var _canvas:Bitmap;
        private var _xOffset:int = 0;
        private var _rect:Rectangle = new Rectangle();;
        private var _point:Point = new Point();

        public function EndlessBG() {
            super();
            _source = new BathroomStillLife();
            _canvas = new Bitmap(new BitmapData(_source.width, _source.height));
            _canvas.bitmapData.draw(_source);
            _canvas.x = stage.stageWidth/2 - _canvas.width/2;
            _canvas.y = 5;
            addChild(_canvas);
            addEventListener(Event.ENTER_FRAME, gameLoop);
            setGeometryDefaults();
            _movingPixels = new BitmapData(_source.width, _source.height);
            _movingPixels.copyPixels(_source, _rect, _point);
            //turn this on to watch red pixels be drawn where the source pixels are coming in
            //_source = new BitmapData(_source.width, _source.height, false, 0xFF0000);
        }

        private function gameLoop(e:Event):void {
            _xOffset--;//where the background is moving to
            if (_xOffset < -_source.width) {
                _xOffset = 0;
                //this doesn't seem to work correctly:
                //_movingPixels.scroll(_source.width, 0);
                _movingPixels = new BitmapData(_source.width, _source.height);
                _movingPixels.copyPixels(_source, _rect, _point);
            }
            trace(_xOffset);
            setGeometryDefaults();
            _movingPixels.scroll(-1, 0);
            //draw the moved part of the canvas
            _canvas.bitmapData.copyPixels(_movingPixels, _rect, _point);
            //If we stop here, we get a smear to the right
            //so, get the remaining pixels directly from the source
            //1) reset our rect and point to be to the right side
            _rect.x = 0;
            _rect.width = -_xOffset;
            _point.x = _source.width + _xOffset;
            //2) copy from the source
            _canvas.bitmapData.copyPixels(_source, _rect, _point);
        }
        private function setGeometryDefaults():void {
            _rect.x=0;
            _rect.y=0;
            _rect.width = _source.width;
            _rect.height = _source.height;
            _point.x = 0;
            _point.y = 0;
        }

    }

}

不理想,也不够完善,不足以写一篇博文,但应该能让你开始。

编辑: 最终我确实写了那篇博文

于 2012-06-04T22:29:41.640 回答
0

http://www.greensock.com/blitmask

这可能会有所帮助,但不是免费的

于 2012-06-04T12:46:52.593 回答