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/

これを使って背景を作りました。

これにより、背景全体を動かさずに飛行機が右に飛んでいるようにシミュレートでき、(前景レイヤーに) 毎回繰り返す小さな単一のグラフィックを使用できます。

背景レイヤーにもこの方法を使用しますが、はるかに大きなグラフィックを使用し、飛行機の速度を落として移動して、遠くの背景をシミュレートします。

私の move-method は enterframe イベントにあります。そのため、飛行機の「動き」でフレームごとに背景を更新できます。

)

平面はビットマップの高さを超えることができます。ビットマップがウィンドウ/スクリーンに戻るたびに、非常に長い遅延が発生します。また、飛行機が非常に速く飛ぶと、ゲームも遅れ始めます。

私の最初のアプローチは、.PNG ファイルを使用することでした (ただし、ファイルは非常に大きく、1 ~ 3 MB のサイズです)。私の次のアプローチは、.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 は非常に高速です。したがって、すべてが不透明であると仮定して、以前にあったものの上に単純に copyPixels をコピーするだけです。すべてが不透明でない場合は、ソース ビットマップを独自のアルファ データとして使用して、以前に描画されたピクセルが透けて見えないようにする必要があります。

キャンバスを再構成して、MC ではなくビットマップにします。新しいコードは次のようになります。

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

ああ、それを見てください !このコードは高速であるだけでなく、わずか 1 行のコードです。

編集:作業コードを追加

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 に答える