Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   эффект высыхающей капли (http://www.flasher.ru/forum/showthread.php?t=210312)

neonoviiwolf 24.02.2015 14:58

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

ZackMercury 24.02.2015 16:11

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

Добавлено через 1 минуту
Я не мастер шейдеринга, но предполагаю, что язык PixelBender должен работать быстрее стандартных функций работы с пикселами во много раз :D

Ёлочка 25.02.2015 01:29

Вложений: 2
Вот так можно, например:

Код AS3:

package 
{
        import flash.display.Sprite;
 
        public class Drop extends Sprite
        {
                private var drop_parts:Vector.<Sprite> = null;
                private var drop_part:Sprite = null;
 
                public var is_gone:Boolean = false;
 
                public static const COUNT:int = 10;
 
                public function Drop()
                {
                        drop_parts = new <Sprite>[];
 
                        for ( var i:int = 0; i < COUNT; i++ )
                        {
                                drop_part = new DropClip();
                                drop_part.alpha = 1 / COUNT;
                                drop_parts.push( drop_part );
                                this.addChild( drop_part );
                        }
                }
 
                public function updateDrop():void
                {
                        for ( var i:int = COUNT - 1; i >= 0; i-- )
                        {
                                drop_part = drop_parts[ i ];
                                drop_part.scaleX = drop_part.scaleY *= Math.pow( 0.95, 0.5 * ( i * 0.25 + 1 ) );
                        }
 
                        if ( drop_part.scaleX < 0.01 )
                        {
                                is_gone = true;
                        }
                }
 
        }
 
}

Код AS3:

import flash.display.Sprite;
import flash.display.Shape;
import flash.events.Event;
 
var drop:Drop = null;
 
createDrop();
this.addEventListener( Event.ENTER_FRAME, update );
 
function createDrop()
{
        drop = new Drop();
        drop.x = 275;
        drop.y = 200;
        this.addChild( drop );
}
 
function update( e:Event ):void
{
        drop.updateDrop();
        if ( drop.is_gone )
        {
                this.removeChild( drop );
                createDrop();
        }
}

Архив: Вложение 31449

drop.swf   (1.6 Кб)

silin 25.02.2015 10:50

Вложений: 1
вот такой алгоритм у меня нашелся, может сгодится на что
drop.swf   (151.0 Кб)

Код AS3:

package 
{
        import flash.display.Bitmap;
        import flash.display.BitmapData;
        import flash.display.Sprite;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.filters.BlurFilter;
        import flash.geom.Matrix;
        import flash.geom.Point;
 
 
 
        public class Main extends Sprite
        {
                [Embed(source = "bg.png")] public static const bg_png:Class;
                private var src:BitmapData = (new bg_png() as Bitmap).bitmapData;
                private var bmd:BitmapData = new BitmapData(src.width, src.height);
                private var bmp:Bitmap = new Bitmap(bmd);
                private var size:Number = 100;
                private var coef:Number = 1.25;
                private var tX:Number = 100;
                private var tY:Number = 100;
 
                public function Main():void
                {
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                        stage.align = StageAlign.TOP_LEFT;
 
 
                        addChild(bmp);
 
 
                        this.addEventListener(Event.ENTER_FRAME, this_enterFrame);
 
                }
                //=======================================//
                private function this_enterFrame(e:Event):void
                {
                        bmd.copyPixels(src, bmd.rect, new Point());
                        size-= 1;
                        coef *= 0.99;
                        if (size > 0)
                        {
                                drawDrop(bmd, tX, tY, size, 2, coef, true);
                        }else
                        {
                                size = 100;
                                coef = 1.25;
                                tX = 50 + Math.random() * 150;
                                tY = 50 + Math.random() * 150;
                                //this.removeEventListener(Event.ENTER_FRAME, this_enterFrame);
                        }
                }
                //====================================//
                public static function drawDrop(src:BitmapData, dropX:int, dropY:int, dropSize:int = 20, blurVal:int = 2, coeff:Number = 2, append:Boolean=false):BitmapData
 
                {
                        if (dropSize <= 0) return null;
 
                        if (coeff <= 0) coeff = 1;
 
                        dropSize += dropSize % 2;
 
                        var w1:int, h1:int;// , w2:int, h2:int;
                        var halfSize:int = dropSize / 2;
 
                        var radius:Number, oldRadius:Number, angle:Number, div:Number;
 
                        var res:BitmapData = new BitmapData(dropSize + 2 * blurVal, dropSize + 2 * blurVal, true, 0x0);
 
                        div =  halfSize  / Math.log( coeff * halfSize  + 1);
                        for ( var h:int = -halfSize; h <= halfSize; ++h )
                        {
                                for ( var w:int = -halfSize; w <= halfSize; ++w )
                                {
 
                                        radius = Math.sqrt( h * h + w * w );
                                        angle = Math.atan2( h, w );
                                        if ( radius <= halfSize )
                                        {
                                                oldRadius = radius;
                                                radius = (Math.exp(radius/div)-1)/coeff;
                                                w1 =  radius * Math.cos(angle);// + dropX;
                                                h1 =  radius * Math.sin(angle);
 
                                                // подсветка в зависимости от относительного радиуса и угла
                                                var bright:int = 0;
                                                var relRadius:int = Math.ceil(10 * oldRadius / halfSize);
                                                switch(relRadius) {
                                                        case 3:
                                                                if ( (angle >= 0.5) && (angle < 1.75) ) bright = 20;
                                                        break;
                                                        case 4:
                                                                if ( (angle >= 0.0) && (angle < 2.25) )  bright = 30;
                                                        break;
                                                        case 5:
                                                                if ( (angle >= 0.5) && (angle < 1.75) ) bright = 40;
                                                        break;
                                                        case 6:
                                                                if ( (angle >= 0.25) && (angle < 0.50) ) bright = 30;
                                                                if ( (angle >= 1.75 ) && (angle < 2.0) ) bright = 30;
                                                        break;
                                                        case 7:
                                                                if ( (angle >= 0.50) && (angle < 1.75)) bright = -20;
                                                                if ( (angle >= 0.0) && (angle < 0.25) ) bright = 20;
                                                                if ( (angle >= 2.0) && (angle < 2.25) ) bright = 20;
                                                        break;
                                                        case 8:
                                                                if ( (angle >= 0.10) && (angle < 2.0) )  bright = -20;
                                                                if ( (angle >= -2.50) && (angle < -1.90) )  bright = 60;
                                                        break;
                                                        case 9:
                                                                if ( (angle >= 0.75) && (angle < 1.50) ) bright = -40;
                                                                if ( (angle >= -0.10) && (angle < 0.75) ) bright = -30;
                                                                if ( (angle >= 1.50) && (angle < 2.35)) bright = -30;
                                                        break;
                                                        case 10:
                                                                if ( (angle >= 0.0) && (angle < 2.25) ) bright = -80;
                                                                if ( (angle >= 2.25) && (angle < 2.5) ) bright = -40;
                                                                if ( (angle >= -0.25) && (angle < 0.0)) bright = -40;
                                                        break;
 
                                                }
 
                                                var pixel:int = src.getPixel(dropX + w1, dropY + h1);
                                                var r:int = (pixel >> 16 & 0xFF) + bright;
                                                var g:int = (pixel >> 8 & 0xFF) + bright;
                                                var b:int = (pixel & 0xFF) + bright;
                                                //диапазон
                                                r = ( r < 0 ) ? 0 : ( r > 0xFF ? 0xFF : r );
                                                g = ( g < 0 ) ? 0 : ( g > 0xFF ? 0xFF : g );
                                                b = ( b < 0 ) ? 0 : ( b > 0xFF ? 0xFF : b );
 
                                                res.setPixel32(blurVal + halfSize + w, blurVal + halfSize + h, (0xFF << 24 | r << 16 | g << 8 | b));
 
                                        }
                                }
 
                        }
 
                        res.applyFilter(res, res.rect, new Point(), new BlurFilter(blurVal, blurVal));
 
                        if (append)
                        {
                                var mtrx:Matrix = new Matrix();
                                mtrx.translate(dropX - res.width/2, dropY - res.height/2);
                                src.draw(res, mtrx);
                                res.dispose();
                                return null;
                        }else
                        {
                                return res;
                        }
                }
 
 
        }
 
}


alatar 25.02.2015 12:14

Капли, как правило, так не сохнут.
http://kbogdanov4.narod.ru/drying_drops.htm
http://journals.ioffe.ru/jtf/2007/02/p17-21.pdf

Добавлено через 2 минуты
http://journals.ioffe.ru/jtf/2009/08/p133-141.pdf

Добавлено через 6 минут
Т.е. такой вариант, как привел silin, возможен только на несмачиваемой поверхности. Но искажения при этом должны быть значительно большими из-за сферической формы капли. Для смачиваемых поверхностей, площадь капли будет меняться гораздо в меньших масштабах.

silin 25.02.2015 13:50

вот это по-нашему, по бразильски по флешерски, от души, что называется :)
особенно про Основы структурной эволюции, хотя и Навье−Стокс с учетом плотности потока пара тоже внушает Ж)

alatar 25.02.2015 15:20

Ну, в данном случае, больше важна визуальная составляющая. Для круглой капли, можно и градиентами обойтись.

neonoviiwolf 26.02.2015 01:54

Вложений: 1
Спасибо за ответы, буду эксперементировать
Пришёл ещё вопрос, а возможно ли спрайт скрутить программно по спирали? или есть библиотеки?

silin 26.02.2015 08:33

не уверен, что правильно понял вопрос,
есть вариант 'cкручивания' c помощью DisplacementMapFilter http://silin.su/#AS3/filters/swirl

neonoviiwolf 26.02.2015 13:29

silin спасибо - это интересно


Часовой пояс GMT +4, время: 09:19.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.