无休止的重复滚动背景

时间:2012-06-04 09:37:09

标签: actionscript-3 mobile actionscript air

我遇到了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);
}

UPDATE2(

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

我用它来创建我的背景。

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

对于背景图层我也使用这种方法,但是使用更大的图形并且我只使用我的平面速度来移动它来模拟远背景。

我的move-method是针对enterframe事件的。所以我可以用我飞机的“运动”每帧更新背景。

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

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

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

我读过draw()和copyPixels(),但我不知道,我怎么能用它来重复图像。

UPDATE1:

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);
}

2 个答案:

答案 0 :(得分:3)

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

让我们重新构建你的画布,这样它就是一个Bitmap而不是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;
        }

    }

}

不是很理想,而且对博客文章还不够完善,但是应该让你开始。

修改 最后我写了blog post

答案 1 :(得分:0)

http://www.greensock.com/blitmask

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