无尽的重复滚动背景 [英] Endless repeating scrolling background

查看:179
本文介绍了无尽的重复滚动背景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用AS3和AIR的一个问题。我工作的一个横向卷轴游戏的智能手机与飞机,我用不同的背景为图层。

在所有其他:我用的GPU也是唯一的位图,画质设置为低。因此,性能设置都设置为智能手机中使用。

我的推杆成一个长方形使用绘图API和移动与基体的背景:

 保护VAR scrollingBitmap:的BitmapData;
保护VAR帆布:图形;
保护VAR矩阵:矩阵;

公共职能的举动(DX:数字,DY:编号)​​:无效{
    matrix.translate(DX,DY);
    如果(DX!= 0)matrix.tx%= scrollingBitmap.width;
    如果(DY!= 0)matrix.ty%= scrollingBitmap.height;
    drawCanvas();
}

保护功能drawCanvas():无效{
    canvas.clear();
    canvas.beginBitmapFill(scrollingBitmap,矩阵,真正的,真实的);
    canvas.drawRect(0,-scrollingBitmap.height,1404,scrollingBitmap.height);
}
 

UPDATE2(

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

我用这个创建我的背景。

有了这个,我可以模拟,我的飞机飞行的权利,没有移动整个的背景,我可以用一个小的单个图形它会每隔时间(前景层)。

有关我用的是背景层这种方法也一样,但有一个更大的图形,我将它只有我的飞机的速度,更少的模拟远的背景。

我的招法是enterFrame事件。因此,我可以每帧有我的飞机的运动更新背景。

这架飞机可能会超过位图的高度。每次位图回来到窗口/屏幕一个真正的长期滞后发生。而当飞机飞行速度非常快,比赛开始落后了。

我的第一个方法是使用.png文件(但他们是非常大的:1-3MB的大小)。 我的下一个方法是使用gif文件(少得多的大小)。

通过这两个是相同的。因此它不能是

我读到平局()和copyPixels(),但我不知道,我怎么可以使用这些重复的图像。

UPDATE1:

 保护VAR scrollingBitmap:的BitmapData;
保护VAR帆布:位图;

保护功能的init(五:事件):无效{
    removeEventListener(Event.ADDED_TO_STAGE,INIT);
    帆布=新位图(新的BitmapData(1404,scrollingBitmap.height,真),汽车,真正的);
    this.addChild(画布);
    drawCanvas();
}

公共职能的举动(DX:数字,DY:编号)​​:无效{
    如果(DX!= 0)DX(%)= scrollingBitmap.width;
    如果(DY!= 0)DY(%)= scrollingBitmap.height;
    drawCanvas(DX,DY);
}

保护功能drawCanvas(XPOS:数= 0,yPos:数= 0):无效{
    canvas.bitmapData.copyPixels(scrollingBitmap,新的Rectangle(0,0,1404,scrollingBitmap.height),新点(XPOS,yPos),scrollingBitmap);
}
 

解决方案

我想你会更好地与一个位图,而不是使用图形填充对象。 copyPixels是非常快的。所以你会做的仅仅是copyPixels过任何的顶部在那里之前,presuming一切都是不透明的。如果一切是不是不透明的,你需要用你的源位图作为自己的Alpha数据,以便previously绘制像素不显示出来。

让我们重新塑造你的画布所以它是一个位图,而不是MC。新的code将是这样的:

 保护功能drawCanvas():无效{
   canvas.bitmapData.copyPixels(scrollingBitmap,新矩形(0,0,scrollingBitmap.width,scrollingBitmap.height),新点(0,0),scrollingBitmap);
}
 

呵呵,看那个!这不仅是code速度更快,这是只有一行code!

编辑:添加工作code

 包{
    进口的flash.display.MovieClip;
    匹配import flash.display.Bitmap;
    进口flash.display.BitmapData;
    进口对象类型:flash.events.Event;
    进口flash.geom.Rectangle;
    进口flash.geom.Point;


    公共类EndlessBG扩展影片剪辑{
        //这个保持平稳,我们得到的像素右侧的PIC从这里
        私人VAR _source:的BitmapData;
        //这是一个移动到左侧(像素右侧不除了一次循环可见);
        私人VAR _movingPixels:的BitmapData;
        私人VAR _canvas:位图;
        私人VAR _xOffset:= 0;
        私人VAR _rect:矩形=新的Rectangle();;
        私人VAR _point:点=新的点();

        公共职能EndlessBG(){
            超();
            _source =新BathroomStillLife();
            _canvas =新位图(新的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 =新的BitmapData(_source.width,_source.height);
            _movingPixels.copyPixels(_source,_rect,_point);
            //启用此观赏红色像素被绘制在源像素进来
            // _源=新的BitmapData(_source.width,_source.height,假的,为0xFF0000);
        }

        私有函数gameLoop(五:事件):无效{
            _xOffset  - ; //在背景被移动到
            如果(_xOffset< -_source.width){
                _xOffset = 0;
                //这似乎并没有正常工作:
                //_movingPixels.scroll(_source.width,0);
                _movingPixels =新的BitmapData(_source.width,_source.height);
                _movingPixels.copyPixels(_source,_rect,_point);
            }
            跟踪(_xOffset);
            setGeometryDefaults();
            _movingPixels.scroll(-1,0);
            //绘制在画布的移动的部分
            _canvas.bitmapData.copyPixels(_movingPixels,_rect,_point);
            //如果我们停在这里,我们得到一抹黑的权利
            //如此,直接从源得到的剩余像素
            // 1)复位我们的矩形和点为右侧
            _rect.x = 0;
            _rect.width = -_xOffset;
            _point.x = _source.width + _xOffset;
            // 2)从源复制
            _canvas.bitmapData.copyPixels(_source,_rect,_point);
        }
        私有函数setGeometryDefaults():无效{
            _rect.x = 0;
            _rect.y = 0;
            _rect.width = _source.width;
            _rect.height = _source.height;
            _point.x = 0;
            _point.y = 0;
        }

    }

}
 

一个博客帖子

不理想,而不是打磨还不够,而应该让你开始。

编辑: 最终,我没有写博客文章

I got a problem with AS3 and AIR. I'm working on a side-scrolling game for smartphones with a plane and I use different backgrounds as layers.

Before all other: I use GPU and only bitmaps, quality is set to low. So Performance settings are all set for smartphone use.

I putted them into a rectangle using the drawing API and move the background with a matrix:

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 (

Take a look at this: http://plasticsturgeon.com/2010/06/infinite-scrolling-bitmap-backgrounds-in-as3/

I used this to create my backgrounds.

With this I can simulate that my plane is flying to the right without moving the whole background and I can use a small single graphic which repeats every time (for the foreground layer).

For the background layer I use this method, too, but with a much larger graphic and I move it only with less the speed of my plane to simulate a far background.

My move-method is on an enterframe event. So I can update the background every frame with the "movement" of my plane.

)

The plane can exceed the height of the bitmaps. Everytime the bitmap comes back into the window/screen a real long lag occurs. And when the plane flies very fast, the game start to lag, too.

My first approach was to use .PNG files (but they are very big: 1-3MB size). My next approach was to use .GIF files (much less size).

With both it's the same. So it can't be that.

I read about draw() and copyPixels() but I don't know, how I can use those to repeat the image.

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

解决方案

I think you'd be better off with a Bitmap instead of using the graphics object with fill. copyPixels is very fast. So what you'd do is simply copyPixels over the top of whatever was there before, presuming everything is opaque. If everything is not opaque, you'll need to use your source bitmap as its own alpha data so previously drawn pixels don't show through.

Let's reframe your canvas so it is a Bitmap and not a MC. your new code will look like:

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

Oh, and look at that! Not only is this code faster, it's only one line of code!

EDIT: Added working code

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

    }

}

Not ideal, and not polished enough yet for a blog post, but should get you started.

Edit: Eventually I did write that blog post.

这篇关于无尽的重复滚动背景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆