transformações de matriz sobre as imagens móveis adjacentes causando lacunas subpixel

StackOverflow https://stackoverflow.com/questions/780295

  •  13-09-2019
  •  | 
  •  

Pergunta

Eu tenho três sprites, empilhados em cima uns dos outros.

I modificar seu transform.matrix para dar a aparência que eles estão crescendo em uníssono.

No entanto, pequenas fissuras às vezes aparecem entre as telhas, dependendo do fator de escala.

fissuras entre sprites http://img21.imageshack.us/img21/7518/ cracks.png

Eu estou querendo saber como corrigir isso.

Eu sei que objetos de texto em AS3 tem opções para sub-pixel rendering . Talvez existe um cenário semelhante para todos AS3? Outras idéias?

Táticas que não funcionam:. CacheAsBitmap

package
{

import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;

import mx.core.UIComponent;

public class tmpa extends UIComponent
{

    private var _scale:Number;

    private var _s1:Sprite;
    private var _s2:Sprite;
    private var _s3:Sprite;

    private var _s1Pt:Point;
    private var _s2Pt:Point;
    private var _s3Pt:Point;

    private var _tileDim:int;


    public function tmpa( ):void
    {
        _scale = 1;
        _tileDim = 100;

        _s1 = new Sprite();
        _s2 = new Sprite();
        _s3 = new Sprite();

        paintSprite( _s1, _tileDim );
        paintSprite( _s2, _tileDim );
        paintSprite( _s3, _tileDim );

        _s1Pt = new Point( 100, _tileDim );
        _s1.x = _s1Pt.x;
        _s1.y = _s1Pt.y;
        _s2Pt = new Point( 100, _tileDim*2 );
        _s2.x = _s2Pt.x;
        _s2.y = _s2Pt.y;
        _s3Pt = new Point( 100, _tileDim*3 );
        _s3.x = _s3Pt.x;
        _s3.y = _s3Pt.y;

        addChild( _s1 );
        addChild( _s2 );
        addChild( _s3 );

        scale = 1.0394; //cracks
        //scale = 1.0306; // nocracks
    }

    private function paintSprite( s:Sprite, dim:int, color:int=0xFF0000 ):void
    {   s.graphics.beginFill( color, .5 );
        s.graphics.drawRect( 0, 0, dim, dim );
        s.graphics.endFill( );
    }


    public function set scale( s:Number ):void
    {   _scale = s;

        var scaleFromPt:Point = new Point( 20, 20 );
        updateSpriteMatrix( _s1, _s1.globalToLocal(scaleFromPt), _s1Pt );
        updateSpriteMatrix( _s2, _s2.globalToLocal(scaleFromPt), _s2Pt );
        updateSpriteMatrix( _s3, _s3.globalToLocal(scaleFromPt), _s3Pt );
    }

    public function get scale( ):Number
    {   return _scale;
    }

    private function updateSpriteMatrix( t:Sprite, ctrPt:Point, regPt:Point ):void
    {   var mx:Matrix = t.transform.matrix;
        mx.identity();
        mx.scale( _scale, _scale );
        mx.translate( ctrPt.x*(1-_scale), ctrPt.y*(1-_scale));
        mx.translate( regPt.x, regPt.y );
        t.transform.matrix = mx;
    }

}
}

E o mxml:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
            xmlns:a="*"
            width="100%" height="100%"
            paddingTop="0" paddingBottom="0" paddingLeft="0" paddingRight="0"
            backgroundColor="0x000000"
            backgroundGradientAlphas="undefined">
    <a:tmpa id="t" width="100%" height="100%" x="0" y="0" left="0" top="0"/>
</mx:Application>
Foi útil?

Solução

A razão existem lacunas é devido a erros de arredondamento. Flash pode apenas elementos posição para baixo para 1 vigésimo de um pixel (um TWIP). Você estava definindo as posições Y no

  • 3,152000000000008
  • 7,092000000000018
  • 11,032000000000028

respectivamente. Obviamente, isso é muito mais preciso do que um vigésimo de modo arredondamento ocorre. Uma vez que o arredondamento acontece você está propenso a erros.

Na minha opinião, você deve estar colocando todos os itens dentro de algum outro recipiente e depois escalar o recipiente. A maneira como você só executar uma transformação, mas obter o mesmo resultado.

No entanto eu entendo que pode haver uma necessidade para este método em algumas situações. A forma redonda isso é para executar todas as transformações de escala em primeiro lugar. Em seguida, realizar as traduções relação à entidade gráfica anterior. Dessa forma, ele sempre vai ser baseado na poção previamente arredondado. Aqui está um exemplo rápido cortado fora de sua classe. Obviamente, existem muitas maneiras de organizar isso, mas eu tentei brinquedo vara a maneira de trabalhar pela simplicidade.

package
{

import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;

import mx.core.UIComponent;

public class tmpa extends UIComponent
{

        private var _scale:Number;

        private var _s1:Sprite;
        private var _s2:Sprite;
        private var _s3:Sprite;

        private var _s1Pt:Point;
        private var _s2Pt:Point;
        private var _s3Pt:Point;

        private var _tileDim:int;


        public function tmpa( ):void
        {
                _scale = 1;
                _tileDim = 100;

                _s1 = new Sprite();
                _s2 = new Sprite();
                _s3 = new Sprite();

                paintSprite( _s1, _tileDim );
                paintSprite( _s2, _tileDim );
                paintSprite( _s3, _tileDim );

                _s1Pt = new Point( 100, _tileDim );
                _s1.x = _s1Pt.x;
                _s1.y = _s1Pt.y;
                _s2Pt = new Point( 100, _tileDim*2 );
                _s2.x = _s2Pt.x;
                _s2.y = _s2Pt.y;
                _s3Pt = new Point( 100, _tileDim*3 );
                _s3.x = _s3Pt.x;
                _s3.y = _s3Pt.y;

                _s1.transform.matrix = new Matrix();
                _s2.transform.matrix = new Matrix();
                _s3.transform.matrix = new Matrix();

                addChild( _s1 );
                addChild( _s2 );
                addChild( _s3 );

                scale = 1.0394; //cracks
                //scale = 1.0306; // nocracks
        }

        private function paintSprite( s:Sprite, dim:int, color:int=0xFF0000 ):void
        {       s.graphics.beginFill( color, .5 );
                s.graphics.drawRect( 0, 0, dim, dim );
                s.graphics.endFill( );
        }

        public function set scale( s:Number ):void
        {       _scale = s;

                scaleSpriteMatrix( _s1 );
                scaleSpriteMatrix( _s2 );
                scaleSpriteMatrix( _s3 );

                translateSprite(_s2, _s1);
                translateSprite(_s3, _s2);
        }

        public function get scale( ):Number
        {       return _scale;
        }

        private function scaleSpriteMatrix( targetSprite:Sprite):void
        {       var mx:Matrix = targetSprite.transform.matrix;
                mx.scale( _scale, _scale );
                targetSprite.transform.matrix = mx;
        }

        private function translateSprite( targetSprite:Sprite, basedOnSprite:Sprite):void
        {       var mx:Matrix = targetSprite.transform.matrix;
                mx.translate( basedOnSprite.x, basedOnSprite.y + basedOnSprite.height);
                targetSprite.transform.matrix = mx;
        }

}
}

Espero que ajude

James

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top