flash与位图:woderfl 案例(一)

       woderfl 社区里面有着很多as3的制作技巧,其中有一本书里面介绍着很多相关的解说。里面大部分好的代码都是来自wonderfl里面的人通过自己业余时间编写出来的。这本书目前发现只有亚马逊才有得购买,而且国内只有外购才能买到日文版本。所以没办法看到里面的介绍和解说。不过好运的事,里面解说的代码在beautifl网站都有收录进去,所以很方便进行对里面代码阅读。因为这本书据说只是解说偏多,理论的东西不是很多。相比kp的书,这个偏案例。不过之所以有意思的是,这本书里面的代码技巧性比较强,收录的代码都是在as3方面有很深功底和创意的人。这本书编写作者是一个对as3有丰富经验的人名字叫池田泰延(ClockMaker),当中还有一些关于他的精彩实验。我们都可以在他的博客里面看到。


       


这本书的目录可以上亚马逊进行阅读,第一章节里面解说是采用HelloWorld开头进行解说。

案例一可以参考这里:http://wonderfl.net/c/nCFQ


案例中采用的技巧如下:(采用两层循环遍历位图数据,获取颜色值,并根据坐标信息产生运动效应)

过程:

创建一个文本,通过一个位图进行复制。

获取到位图对其进行遍历,获取不同的颜色。然后采用Tweener的类库对其产生不规则的运动。


本次使用的位图API 不多,获取颜色是采用getPixel 这个函数,整体看起来这个案例并不复杂,但是里面采用的技巧也是很普遍的一种手法。

如 随机位置,扫描像素值,延迟时间产生运动过程,这些手法也是在as3里面常用到。在这本书里面收录很多案例。


package{
    import flash.display.*;
    import flash.text.*;
    import flash.filters.*;
    import flash.geom.*;
    import caurina.transitions.Tweener;

    public class Foo extends Sprite{
        private var bd:BitmapData;
        public function Foo():void{
            var tf:TextField = new TextField();
            tf.textColor = 0x000000;
            tf.text = "Hello\nWorld!!!";
            tf.autoSize = "left";
            bd = new BitmapData(tf.width, tf.height, false, 0x3399ff);
            bd.draw(tf);
            bd.applyFilter(bd, bd.rect, new Point(), new BlurFilter());
            bd.draw(tf);

            for(var i:int = 0; i < bd.width; i++){
                for(var j:int = 0; j < bd.height; j++){
                    Tweener.addTween(
                        randomize(addChild(new Circle(bd.getPixel(i, j)))), 
                        {
                            x: i * 10,
                            y: j * 10,
                            alpha: 1,
                            delay: (i + j) * .2 * Math.random(),
                            time: 1
                        }
                    );
                }
            }
        }
        private function randomize(d:DisplayObject):DisplayObject{
            d.x = 400 * Math.random();
            d.y = 300 * Math.random();
            d.alpha = 0;
            return d;
        }
    }
}


import flash.display.Sprite;

class Circle extends Sprite{
    public function Circle(color:uint):void{
        graphics.beginFill(color);
        graphics.drawCircle(0, 0, 6);
        graphics.endFill();
    }
}



你可以改成其他文本,进行复制,产生的效果也会不一样。

第二案例,收录一个牛人(Saqoosha)制作飘雪字的技巧。效果看起来很漂亮


收录的地址在这里: http://wonderfl.net/c/g9s1

代码收录如下

当中采用了一个闪星的制作技巧,用法很特别。当中也比较核心的一点是采用粒子运动的方式来进行。让整个程序看起来就像一个艺术品那样子。整本书的目录里面可以看到,这些程序都是比较有技巧性而且想法比较独特。看这些代码也是一种享受。

package {
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.PixelSnapping;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.filters.BlurFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
        import net.hires.debug.Stats;

    [SWF(width=465, height=465, backgroundColor=0x0, frameRate=120)]

    public class Saq001 extends Sprite {
        
        private static const GRAVITY:Number = 20;
        private static const DRAG:Number = 0.3;
        
        private var _canvas:BitmapData;
        private var _glow:BitmapData;
        private var _glowMtx:Matrix;
        private var _forceMap:BitmapData;
        private var _snow:Array;
        
        public function Saq001() {
            this._canvas = new BitmapData(465, 465, false, 0x0); // カンバスをつくる。ここに 1 pixel ずつ描いていくよ
            this.addChild(new Bitmap(this._canvas)) as  Bitmap;  // stage に配置
            
            this._glow = new BitmapData(465 / 4, 465 / 4, false, 0x0); // キラキラを描く用のん。カンバスの 4 分の 1 のサイズ
            var bm:Bitmap = this.addChild(new Bitmap(this._glow, PixelSnapping.NEVER, true)) as Bitmap; // smoothing を true にして配置
            bm.scaleX = bm.scaleY = 4; // 4 倍にする。
            bm.blendMode = BlendMode.ADD; // 加算モードで合成
            this._glowMtx = new Matrix(0.25, 0, 0, 0.25);
            
            // 雪を積もらせるかたちを BitmapData に描く。
            var tf:TextField = new TextField();
            tf.defaultTextFormat = new TextFormat('Verdana', 64, 0xffffff, true); 
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.text = 'Wonderfl!!';
            tf.x = (465 - tf.width) / 2;
            tf.y = (465 - tf.height) / 2;
            this._forceMap = new BitmapData(465, 465, false, 0x0);
            this._forceMap.draw(tf, tf.transform.matrix);
            this._forceMap.applyFilter(this._forceMap, this._forceMap.rect, new Point(0, 0), new BlurFilter(8, 8));
            
            this._snow = []; // 雪パーティクルはここにいれておくよ。
            
                        this.addChild(new Stats());

            this.addEventListener(Event.ENTER_FRAME, this.update); // 毎フレーム update を呼ぶよ
        }
        
        // 雪を 1 粒発生させる関数
        public function emitParticle(ex:Number, ey:Number, s:Number = 1, c:int = 0xffffff, vx:Number = 0, vy:Number = 0):void {
            var p:SnowParticle = new SnowParticle(); // 作って
            // パラメータ設定して
            p.x = ex;
            p.y = ey;
            p.vx = vx;
            p.vy = vy;
            p.s = s;
            p.c = c;
            this._snow.push(p); // 保存
        }
        
        // 雪を動かすよーー
        public function update(e:Event):void {
            this._canvas.lock(); // いっぱい setPixel するときは必ず lock しよう
            this._canvas.fillRect(this._canvas.rect, 0x0); // カンバスをクリア
            var n:int = this._snow.length;
            var d:Number;
            var gravity:Number = GRAVITY / 1000; // あらかじめ計算しとく
            while (n--) {
                var p:SnowParticle = this._snow[n];
                p.vy += gravity * p.s; // まず重力を加える
                p.vx *= 0.99; // 空気抵抗
                p.vy *= 0.99; // y 方向にも
                d = 1 - (this._forceMap.getPixel(p.x, p.y) / 0xffffff) * DRAG; // forceMap にもとづいて抵抗値を計算。黒→速い、白→遅い。
                p.vx *= d; // forceMap から得た抵抗値を適用
                p.vy *= d; // y 方向にも
                p.x += p.vx; // 動かす
                p.y += p.vy;
                this._canvas.setPixel(p.x, p.y, p.c); // 雪 1 粒描く
                if (p.y > this.stage.stageHeight) { // もし画面外にでちゃったら
                    this._snow.splice(n, 1); // とりのぞく
                }
            }
            this._canvas.unlock(); // lock したやつは必ず unlock
            this._glow.draw(this._canvas, this._glowMtx); // キラキラを描く
            
            // 雪を発生させますよ
            n = 10;
            while (n--) {
                this.emitParticle(Math.random() * this.stage.stageWidth, 0, Math.random() + 0.5);
            }
        }
    }
}


class SnowParticle {
    
    public var x:Number;
    public var y:Number;
    public var vx:Number;
    public var vy:Number;
    public var s:Number;
    public var c:int;
    
    public function SnowParticle() {
        this.x = 0;
        this.y = 0;
        this.vx = 0;
        this.vy = 0;
        this.s = 1;
        this.c = 0xffffff;
    }
}



案例三:forked from: RainyDay

链接代码:http://wonderfl.net/c/mkJ9

一个非常酷as3的下雨效果,收录了Saqoosha forked的一个的代码片段。 



package {
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.PixelSnapping;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.filters.BlurFilter;
    import flash.filters.ColorMatrixFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.utils.Dictionary;
    
    import net.hires.debug.Stats;
    
    import frocessing.color.ColorHSV;

    [SWF(width=465, height=465, backgroundColor=0x0, frameRate=120)]

    public class RainyDay extends Sprite {
        
        private static const GRAVITY:Number = 20;
        private static const DRAG:Number = 0.7;
        
        private static const ZERO_POINT:Point = new Point(0, 0);
        
        private var _canvas:BitmapData;
        private var _glow:BitmapData;
        private var _glowMtx:Matrix;
        private var _forceMap:BitmapData;
//        private var _snow:Array;
        private var _snow:Dictionary;
        private var _color:ColorMatrixFilter = new ColorMatrixFilter([
            1, 0, 0, 0, -5,
            0, 1, 0, 0, -5,
            0, 0, 1, 0, -5,
            0, 0, 0, 1, 0
        ]);
        private var _hsv:ColorHSV = new ColorHSV();
        private var _blur:BlurFilter = new BlurFilter(1.5, 1.5, 1);
        
        public function RainyDay() {
            this._canvas = new BitmapData(465, 465, false, 0x0); // カンバスをつくる。ここに 1 pixel ずつ描いていくよ
            this.addChild(new Bitmap(this._canvas)) as  Bitmap;  // stage に配置
            
            /*this._glow = new BitmapData(465 / 4, 465 / 4, false, 0x0); // キラキラを描く用のん。カンバスの 4 分の 1 のサイズ
            var bm:Bitmap = this.addChild(new Bitmap(this._glow, PixelSnapping.NEVER, true)) as Bitmap; // smoothing を true にして配置
            //bm.scaleX = bm.scaleY = 4; // 4 倍にする。
            bm.blendMode = BlendMode.ADD; // 加算モードで合成
            this._glowMtx = new Matrix(0.25, 0, 0, 0.25);*/
            
            // 雪を積もらせるかたちを BitmapData に描く。
            var tf:TextField = new TextField();
            tf.defaultTextFormat = new TextFormat('Verdana', 64, 0xffffff, true); 
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.text = 'Rainyday';
            tf.x = (465 - tf.width) / 2;
            tf.y = (465 - tf.height) / 2;
            this._forceMap = new BitmapData(465, 465, false, 0x0);
            this._forceMap.draw(tf, tf.transform.matrix);
            this._forceMap.applyFilter(this._forceMap, this._forceMap.rect, new Point(0, 0), new BlurFilter(8, 8));
            
//            this._snow = []; // 雪パーティクルはここにいれておくよ。
            this._snow = new Dictionary();
            
            this.addChild(new Stats());

            this.addEventListener(Event.ENTER_FRAME, this.update); // 毎フレーム update を呼ぶよ
        }
        
        // 雪を 1 粒発生させる関数
        public function emitParticle(ex:Number, ey:Number, s:Number = 1, c:int = 0x00bfff, vx:Number = 0, vy:Number = 0):SnowParticle {
            var p:SnowParticle = new SnowParticle(); // 作って
            // パラメータ設定して
            p.x = ex;
            p.y = ey;
            p.vx = vx;
            p.vy = vy;
            p.s = s;
            p.c = c;
//            this._snow.push(p); // 保存
            this._snow[p] = true;
            return p;
        }
        
        // 雪を動かすよーー
        public function update(e:Event):void {
            this._canvas.lock(); // いっぱい setPixel するときは必ず lock しよう
            this._canvas.applyFilter(this._canvas, this._canvas.rect, ZERO_POINT, this._color);
            this._canvas.applyFilter(this._canvas, this._canvas.rect, ZERO_POINT, this._blur);
//            this._canvas.fillRect(this._canvas.rect, 0x0); // カンバスをクリア
//            var n:int = this._snow.length;
            var d:Number;
            var gravity:Number = GRAVITY / 100; // あらかじめ計算しとく
//            while (n--) {
            for (var key:* in this._snow) {
                var p:SnowParticle = SnowParticle(key);
//                var p:SnowParticle = this._snow[n];
//                p.vx += 0.02;
                p.vy += gravity * p.s; // まず重力を加える
                p.vx *= 0.99; // 空気抵抗
                p.vy *= 0.99; // y 方向にも
                d = 1 - (this._forceMap.getPixel(p.x, p.y) / 0xffffff) * DRAG; // forceMap にもとづいて抵抗値を計算。黒→速い、白→遅い。
                p.vx *= d; // forceMap から得た抵抗値を適用
                var vy:Number = p.vy;
                p.vy *= d; // y 方向にも
                if ((vy - p.vy) > 1 && Math.random() < 0.3) {
                    //p.vy = -2;
                    //p.vx = (Math.random() - 0.5) * 3;
                    this.emitParticle(p.x, p.y - 2, 1, p.c, (Math.random() - 0.5) * 6, -(Math.random() * 2 + 1));
                    this.emitParticle(p.x, p.y - 2, 1, p.c, (Math.random() - 0.5) * 6, -(Math.random() * 2 + 1));
                    this.emitParticle(p.x, p.y - 2, 1, p.c, (Math.random() - 0.5) * 6, -(Math.random() * 2 + 1));
                }
                var px:int = p.x;
                var py:int = p.y;
                p.x += p.vx; // 動かす
                p.y += p.vy;
//                this._canvas.setPixel(p.x, p.y, p.c); // 雪 1 粒描く
                _drawLine(p.x, p.y, px, py, p.c, 1);
                if (p.y > this.stage.stageHeight) { // もし画面外にでちゃったら
//                    this._snow.splice(n, 1); // とりのぞく
                    delete this._snow[p];
                }
            }
            this._canvas.unlock(); // lock したやつは必ず unlock
            //this._glow.draw(this._canvas, this._glowMtx); // キラキラを描く
            
            // 雪を発生させますよ
//            var n = 10;
//            while (n--) {
            for (var i:int = 0; i < 4; i++) {
                _hsv.h = Math.random() * 20 + 180;
                this.emitParticle(Math.random() * this.stage.stageWidth, -20, Math.random() + 0.5, _hsv.value);
            }
        }

        private function _drawLine(x0:int, y0:int, x1:int, y1:int, color:int, alpha:Number):void {
            var steep:Boolean = Math.abs(y1 - y0) > Math.abs(x1 - x0);
            var tmp:int;
            if (steep) {
                tmp = x0;
                x0 = y0;
                y0 = tmp;
                tmp = x1;
                x1 = y1;
                y1 = tmp;
            }
            if (x0 > x1) {
                tmp = x0;
                x0 = x1;
                x1 = tmp;
                tmp = y0;
                y0 = y1;
                y1 = tmp;
            }
            var deltax:int = x1 - x0;
            var deltay:int = Math.abs(y1 - y0);
            var error:int = deltax / 2;
            var ystep:int;
            var y:int = y0;
            if (y0 < y1) {
                ystep = 1;
            } else {
                ystep = -1;
            }
            for (var x:int = x0; x <= x1; x++) {
                if (steep) {
                    this._canvas.setPixel32(y, x, color | ((alpha * 0xff) << 24));
                } else {
                    this._canvas.setPixel32(x, y, color | ((alpha * 0xff) << 24));
                }
                error = error - deltay;
                if (error < 0) {
                    y = y + ystep;
                    error = error + deltax;
                }
            }
        }
    }
}


class SnowParticle {
    
    public var x:Number;
    public var y:Number;
    public var vx:Number;
    public var vy:Number;
    public var s:Number;
    public var c:int;
    
    public function SnowParticle() {
        this.x = 0;
        this.y = 0;
        this.vx = 0;
        this.vy = 0;
        this.s = 1;
        this.c = 0xffffff;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值