[ActionScript 3.0] 模拟win7彩色气泡屏保效果

主文件:

package
{
    import com.views.BubbleView;
    import com.views.ColorfulBubble;
    
    import flash.display.Sprite;
    import flash.display.StageDisplayState;
    import flash.events.Event;
    
    /**
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2016-12-28 下午2:08:51
     *
     */
    [SWF(width="1920",height="1080",backgroundColor="0x000000")]
    public class BubbleCollision extends Sprite
    {
        
        private var _bubbleView:BubbleView;
        public function BubbleCollision()
        {
            if(stage){
                init(null);
            }else{
                addEventListener(Event.ADDED_TO_STAGE,init);
            }
        }
        private function init(e:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE,init);
            stage.displayState = StageDisplayState.FULL_SCREEN;
            _bubbleView = new BubbleView();
            this.addChild(_bubbleView);
            _bubbleView.start();
        }
        
    }
}

气泡运动控制类:

package com.views
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.events.Event;
    
    /**
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2016-12-28 下午3:01:15
     *
     */
    public class BubbleView extends Sprite
    {
        
        private var _bubbles:Array=[];
        private var _checkBubbles:Array=[];
        public var viewWidth:Number = 1920;
        public var viewHeight:Number = 1080;
        //弹性
        public var bo:Number = -0.6;
        public var len:int = 16;
        public function BubbleView()
        {
            super();
        }
        private function initBubbles():void
        {
            for (var i:int = 0; i < len; i++)
            {
                var bubble:ColorfulBubble = new ColorfulBubble();
                bubble.name = "bubble_" + i;
                bubble.color = rgb();
                bubble.radius = 129*0.5;
                this.addChild(bubble);
                _bubbles.push(bubble);
            }
            
        }
        /**
         * 开始运动
         */
        public function start():void
        {
            initBubbles();
            rank(this);
            addEventListener(Event.ENTER_FRAME, enterFrame);
        }
        /**
         * 随机排列,不重叠
         * @param parent 父容器 
         */
        private function rank(parent:Sprite):void{
            for(var j:int = 0;j<parent.numChildren;j++){
                setPosition(parent.getChildAt(j),parent);
            }
        }
        
        /**
         * 递归调用,设置对象随机排列不重叠
         * @param obj 显示对象
         * @param parent 父级
         * @param 对象之间的间距
         */
        private function setPosition(obj:DisplayObject,parent:Sprite,dis:Number = 20):void
        {
            obj.x = Math.random()*(viewWidth-obj.width) ;
            obj.y = Math.random()*(viewHeight-obj.height) ;
            for(var i:int = 0;i<parent.numChildren;i++){
                if(obj != parent.getChildAt(i)){
                    //不重叠,没有间距
                    /*if(obj.hitTestObject(parent.getChildAt(i))){
                    setPosition(obj);
                    return;
                    }*/
                    //不重叠,并有一定间距dis,间距为0效果同上
                    if(Math.abs(obj.x-parent.getChildAt(i).x)<obj.width+dis&&Math.abs(obj.y-parent.getChildAt(i).y)<obj.height+dis){
                        setPosition(obj,parent);
                        return;
                    }
                }
            }
        }
        private function enterFrame(evt:Event):void
        {
            var c:int = _bubbles.length;
            for (var i:int = 0; i < c; i++)
            {
                var bubble:ColorfulBubble = _bubbles[i];
                
                move(bubble);
                
                if (bubble.isHold)
                {
                    var res:Boolean = false;
                    for (var j:int = i+1; j < c; j++)
                    {
                        var bubble1:ColorfulBubble = _bubbles[j];
                        var dx:Number = bubble1.x - bubble.x;
                        var dy:Number = bubble1.y - bubble.y;
                        var dis:Number = Math.sqrt(dx * dx + dy * dy);
                        if (dis < bubble.radius + bubble1.radius)
                        {    
                            res = true;
                            break;
                        }
                    }
                    bubble.isHold = res;
                }
                else
                {
                    for (j = i + 1; j < c; j++)
                    {
                        checkTouch(_bubbles[i], _bubbles[j]);
                    }
                }    
                bubble.addEventListener(Event.CONNECT,onConnect);
            }
            
        }
        private function onConnect(event:Event):void
        {
            var num:int = event.target.name.split("_")[1];
            this.dispatchEvent(new Event(Event.CONNECT));
        }
        /**
         * 泡泡运动边界控制
         */
        private function move(bubble:ColorfulBubble):void
        {
            
            var radius:Number = bubble.radius;
            
            if (bubble.x + radius > viewWidth)
            {
                bubble.dragStop();
                bubble.x = viewWidth - radius;
                bubble.vx *= bo;
            }
            else if (bubble.x - radius < 0)
            {
                bubble.dragStop();
                bubble.x = radius;
                bubble.vx *= bo;
            }
            
            
            if (bubble.y + radius > viewHeight)
            {
                bubble.dragStop();
                bubble.y = viewHeight - radius;
                bubble.vy *= bo;
            }
            else if (bubble.y - radius < 0)
            {
                bubble.dragStop();
                bubble.y = radius;
                bubble.vy *= bo;
            }            
        }
        /**
         * 检测两个彩色泡泡是否有碰撞
         */
        private function checkTouch(bubble0:ColorfulBubble, bubble1:ColorfulBubble):void
        {
            
            var dx:Number = bubble1.x - bubble0.x;
            var dy:Number = bubble1.y - bubble0.y;
            var dis:Number = Math.sqrt(dx * dx + dy * dy);
            if (dis < bubble0.radius + bubble1.radius)
            {                
                var angle:Number = Math.atan2(dy, dx);
                var sin:Number = Math.sin(angle);
                var cos:Number = Math.cos(angle);
                
                var x0:Number = 0;
                var y0:Number = 0;
                
                var x1:Number = dx * cos + dy * sin;
                var y1:Number = dy * cos - dx * sin;
                
                var vx0:Number = bubble0.vx * cos + bubble0.vy * sin;
                var vy0:Number = bubble0.vy * cos - bubble0.vx * sin;
                
                var vx1:Number = bubble1.vx * cos + bubble1.vy * sin;
                var vy1:Number = bubble1.vy * cos - bubble1.vx * sin;
                
                var vxTotal:Number = vx0 - vx1;
                vx0 = ((bubble0.mass - bubble1.mass) + vx0 + 2 * bubble1.mass * vx1) / (bubble0.mass + bubble1.mass);
                vx1 = vxTotal + vx0;
                
                ////////////
                //x0 += vx0;
                //x1 += vx1;
                var absV:Number = (vx0 < 0? -vx0 : vx0) + (vx1 < 0? -vx1 : vx1);
                
                var xd:Number = x0 - x1;
                xd = xd < 0? -xd : xd;
                
                var overlap:Number = (bubble0.radius + bubble1.radius) - xd;
                
                x0 += vx0 / absV * overlap;
                x1 += vx1 / absV * overlap;                
                
                ////////////
                
                var x0F:Number = x0 * cos - y0 * sin;
                var y0F:Number = y0 * cos + x0 * sin;
                
                var x1F:Number = x1 * cos - y1 * sin;
                var y1F:Number = y1 * cos + x1 * sin;
                
                bubble1.x = bubble0.x + x1F;
                bubble1.y = bubble0.y + y1F;
                bubble0.x = bubble0.x + x0F;
                bubble0.y = bubble0.y + y0F;
                
                bubble0.vx = vx0 * cos - vy0 * sin;
                bubble0.vy = vy0 * cos + vx0 * sin;
                bubble1.vx = vx1 * cos - vy1 * sin;
                bubble1.vy = vy1 * cos + vx1 * sin;
                
                bubble0.dragStop();
                bubble1.dragStop();
            }
        }
        private function rgb():uint {
            return (Math.random() * 0xffffff);
        }
    }
}

单个气泡控制类

package com.views
{
    import com.res.BubbleRes;
    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.ColorTransform;
    
    /**
     * @author Frost.Yen
     * @E-mail 871979853@qq.com
     * @create 2016-12-28 下午2:12:09
     *
     */
    public class ColorfulBubble extends Sprite
    {
        private var _bubble:BubbleRes;//彩色泡泡元件
        private var _downX:Number;
        private var _downY:Number;
        /**
         * 摩擦力
         */
        private var _fr:Number = 0.99;
        private var _radius:Number = 129;
        private var _tmpx:Number;
        private var _tmpy:Number;
        private var _ct:ColorTransform = new ColorTransform();
        private var _color:uint = 0xff00ff;
        public var vx:Number = 0;
        public var vy:Number = 0;
        public var ax:Number = 0;
        public var ay:Number = 0;
        public var max_speed:Number = 1;
        /**
         * 质量
         */
        public var mass:Number = 50;
        public var isHold:Boolean = true;
        public var move:Function;
        public function ColorfulBubble()
        {
            initViews();
            initEventListeners();
            
        }
        private function initViews():void
        {
            _bubble = new BubbleRes();
            this.addChild(_bubble);
            ax = getRandom();
            ay = getRandom();
            move = usualMove;
            
        }
        private function initEventListeners():void
        {
            _bubble.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
            addEventListener(Event.ENTER_FRAME, enterFrame);
        }
        private function enterFrame(evt:Event):void
        {
            move();
        }
        
        private function onStartDrag(evt:MouseEvent):void
        {        
            _downX=mouseX;
            _downY=mouseY;
            stage.addEventListener(MouseEvent.MOUSE_UP, onStageUp);
            
            vx = vy = 0;
            ax = ay = 0;
            
            _tmpx = stage.mouseX;
            _tmpy = stage.mouseY;
            
            move = dragMove;
            
            //this.startDrag();
        }
        private function onStageUp(evt:MouseEvent):void
        {
            if(Math.sqrt((mouseX-_downX)*(mouseX-_downX)+(mouseY-_downY)*(mouseY-_downY))<10)
            {
                this.dispatchEvent(new Event(Event.CONNECT));
            }else
            {
                
            }
            dragStop();
        }
        public function dragStop():void
        {        
            if(stage)
            {
                stage.removeEventListener(MouseEvent.MOUSE_UP, onStageUp);
            }            
            
            move = usualMove;        
        }    
        private function usualMove():void
        {
            var box:Boolean = vx < 0;
            var boy:Boolean = vy < 0;                
            
            vx = box ? -vx : vx;
            vy = boy ? -vy : vy;
            
            vx *= _fr;
            vy *= _fr;
            
            //bubble.ax *= fr;
            //bubble.ay *= fr;
            
            if (vx < .1)
            {
                //vx = Math.random() * 8 - 4;
                ax = getRandom();
            }
            else if (vx > max_speed)
            {
                ax = 0;
            }
            
            if (vy < .1)
            {
                //vy = Math.random() * 8 - 4;
                ay = getRandom();
            }
            else if (vy > max_speed)
            {
                ay = 0;
            }                
            
            vx = (box ? -vx : vx) + ax;
            vy = (boy ? -vy : vy) + ay;    
            
            this.x += vx;
            this.y += vy;            
        }
        private function dragMove():void
        {
            vx = stage.mouseX - _tmpx;
            vy = stage.mouseY - _tmpy;    
            
            _tmpx = stage.mouseX;
            _tmpy = stage.mouseY;
            
            this.x += vx;
            this.y += vy;
            
            vx *= .5;
            vy *= .5;
        }
        private function getRandom():Number
        {
            return Math.random() / (Math.random()*3-3) - .05;
        }
        
        public function set radius(r:Number):void
        {        
            var scale:Number = r * 2 / _bubble.width;    
            this.width *= scale;
            this.height *= scale;    
            _radius = this.width / 2;
            this.cacheAsBitmap = true;
        }
        
        public function get radius():Number
        {
            return _radius;
        }
        private function rgb():uint {
            return (Math.random() * 0xffffff);
        }

        public function get color():uint
        {
            return _color;
        }

        public function set color(value:uint):void
        {
            _ct.color = value;
            _bubble.transform.colorTransform = _ct;
            _color = value;
        }

    }
}

 

posted on 2017-02-23 14:07  晏过留痕  阅读(328)  评论(0编辑  收藏