Механизм Pushbutton - повторяющиеся / мозаичные объекты искусства по спрайтам - PullRequest
1 голос
/ 09 апреля 2011

Итак, я создаю классический боковой скроллер с использованием механизма Pushbutton Engine (http://www.pushbuttonengine.com)), и я хочу, чтобы биты «мира» были любого заданного размера и, конечно, повторяли / разбивали мои художественные ресурсы. получил следующий код установки рендера в качестве начала:

var Render:SpriteRenderer = new SpriteRenderer();                                                                            
Render.positionProperty = new PropertyReference("@Spatial.position");
Render.sizeProperty = new PropertyReference("@Spatial.size");
Render.fileName = "./media/brick.png";
Render.scene = PBE.scene;
Render.layerIndex = 1;

Однако, он просто берет brick.png и растягивает / сжимает его, чтобы заполнить размер объекта. Ламе. :) Я потратил кучу времени, пытаясь гуглить, как это сделать, но, возможно, я не понимаю правильные условия или некоторые такие, как я ничего не придумал. В основном статьи о создании игр на основе тайлов с использованием PBE.

Хотя я уверен, что смогу взломать что-то, что сработает, я хочу убедиться, что я делаю это правильно, чтобы у меня была лучшая производительность, а что нет. Любые подсказки о том, где я должен искать этот стандартный эффект?

спасибо, Бреда

Ответы [ 2 ]

1 голос
/ 21 января 2012

color me brad предпринял хорошую попытку - и это заставило меня задуматься о проблеме.

Переопределить BitmapRenderer, чтобы разрешить тайлинг, сложно, потому что изменения, вносимые компонентом рендеринга, выполняются с матрицами.Я написал класс, который игнорирует масштабирование и вместо этого создает новое растровое изображение с большими физическими размерами по мере необходимости.

Приведенное ниже решение имеет некоторые небольшие ограничения: мне пришлось округлять изменения масштабирования и проверять измененияс точностью до 1 знака после запятой (тестирование доказывает, что иногда это необходимо для тел с определенными коэффициентами масштаба).

Во-вторых, поскольку мы перерисовываем каждый раз, когда изменяется масштаб, он может быть не так хорошо оптимизирован, как если бы мы просто обновлялиматричная шкала.

Тем не менее - она ​​все еще очень быстрая, соответствует «философии» PBE, и сейчас я успешно использую ее в играх.

package render
{
    import com.pblabs.engine.PBUtil;
    import com.pblabs.rendering2D.BitmapRenderer;
    import com.pblabs.rendering2D.SpriteRenderer;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.geom.Vector3D;

    /**
     * Creates a tiles bitmap. The tile is identified as the first bitmap parameter set when this component is created.
     */
    public class TileRenderer extends BitmapRenderer
    {
        public function TileRenderer()
        {

            super();
        }

        protected var lastScaleX:Number = undefined;
        protected var lastScaleY:Number = undefined;

        // the original bitmap contains the single tile we will reuse to fill out the bitmap
        protected var originalBitmapData:BitmapData;


        /**
         * Just set this to the tile you want to reuse. It will automatically figure out tile width and height.
         */
        override public function set bitmapData(value:BitmapData):void{


            if (value === bitmapData)
                return;

            originalBitmapData = value;

            bitmap.bitmapData = advanceRender(value.width, value.height);

            // Due to a bug, this has to be reset after setting bitmapData.
            smoothing = _smoothing;

            // set registration point to get spritesheet-component-style centering
            registrationPoint = new Point(value.width/2,value.height/2);    

            _transformDirty = true;


        }

        /**
         * tile the original bitmap across a new bitmap area
         * the following is adapted from http://stackoverflow.com/users/102373/colour-me-brad:
         */
        protected function advanceRender(targetWidth:Number, targetHeight:Number):BitmapData{

            var target:BitmapData = new BitmapData(targetWidth,targetHeight, true,0x00000000);

            var cx:int = Math.ceil(target.width/originalBitmapData.width);
            var cy:int = Math.ceil(target.height/originalBitmapData.height);

            target = new BitmapData(target.width, target.height, true, 0x000000);


            // fill the bitmapData object with all display info with the provided bitmap 
            for (var ix:int = 0; ix<cx; ix++) {
                for (var iy:int = 0; iy<cy; iy++)
                    target.copyPixels(originalBitmapData,originalBitmapData.rect, new Point(ix*originalBitmapData.width,iy*originalBitmapData.height));
            }
            return target;
        }


        /**
         * heavily override this function to avoid changing scale. We instead redraw the 
         * bitmap to the correct width and height.
         */
        override public function updateTransform(updateProps:Boolean = false):void
        {

            if(!displayObject)
                return;

            if(updateProps)
                updateProperties();

            // If size is active, it always takes precedence over scale.
            var tmpScaleX:Number = _scale.x;
            var tmpScaleY:Number = _scale.y;
            if(_size)
            {
                var localDimensions:Rectangle = displayObject.getBounds(displayObject);
                tmpScaleX = _scale.x * (_size.x / localDimensions.width);
                tmpScaleY = _scale.y * (_size.y / localDimensions.height);
            }


            _transformMatrix.identity();
            //_transformMatrix.scale(tmpScaleX, tmpScaleY);
            _transformMatrix.translate(-_registrationPoint.x * tmpScaleX, -_registrationPoint.y * tmpScaleY);
            _transformMatrix.rotate(PBUtil.getRadiansFromDegrees(_rotation) + _rotationOffset);
            _transformMatrix.translate(_position.x + _positionOffset.x, _position.y + _positionOffset.y);


            if (getRoundDecimal(tmpScaleX,1) != 1 || getRoundDecimal(tmpScaleY,1) != 1) {


                bitmap.bitmapData = advanceRender(originalBitmapData.width*tmpScaleX, originalBitmapData.height * tmpScaleY);
                smoothing = _smoothing;

                // set registration point to get spritesheet-component-style centering
                registrationPoint = new Point(bitmap.bitmapData.width/2,bitmap.bitmapData.height/2);

            }

            displayObject.transform.matrix = _transformMatrix;
            displayObject.alpha = _alpha;
            displayObject.blendMode = _blendMode;
            displayObject.visible = (alpha > 0);


            _transformDirty = false;

        }


        /**
         * taken from: http://swordfish1987.wordpress.com/2009/07/10/decimal-rounding-in-actionscript-3/
         */
        public static function getRoundDecimal(num:Number, precision:int):Number{

            var decimal:Number = Math.pow(10, precision);

            return Math.round(decimal* num) / decimal;

        }

        override protected function onRemove():void{
            originalBitmapData = null;
            super.onRemove();
        }
    }
}
1 голос
/ 16 апреля 2011

Некоторые болтают, и решение достаточно тривиально.

public class TiledBitmapRenderer extends BitmapRenderer
{       
    public function TiledBitmapRenderer(bitmap:Bitmap, width:int, height:int)
    {
        super();

        positionOffset = new Point(width/-2,height/-2);

        var cx:int = Math.ceil(width/bitmap.width);
        var cy:int = Math.ceil(height/bitmap.height);
        bitmapData = new BitmapData(width, height, false, 0x000000);

        // fill the bitmapData object with all display info with the provided bitmap 
        for (var ix:int = 0; ix<cx; ix++) {
            for (var iy:int = 0; iy<cy; iy++)
                bitmapData.copyPixels(bitmap.bitmapData,bitmap.bitmapData.rect, new Point(ix*bitmap.width,iy*bitmap.height));
        }
    }
}
...