游戏里冷却时间效果 cool down (CD) 扇形

发表评论 阅读评论

非常抱歉,这个只想到效果,忘记了CPU,我又重新写了个,请看 冷却时间(CD,cool down) 效果更新,优化CPU
左边是一个冷却时间效果,右边是一个扇形

这是一个冷却效果cd的演示demo,如果你看不到这个flash,请到文章页面查看!

这里是一个游戏里常用到的冷却时间效果。
先是在 这里 看到 wizim 写的这个效果没有完工,又看到有好多人回帖说想要这样的效果,然后我就把它写成类,写的更通用些。

可以附加到任意显示对象上,只需目标显示对象在显示列表里。
当然,要是flex里用,则需继承UIComponent。
废话就不多说了,直接上代码。

Sector 这是一个扇形类:

package com.litefeel.display
{
    import flash.display.Sprite;
    /**
     * 一个扇形类
     *
     * www.litefeel.com
     * @author lite3
     */
    public class Sector extends Sprite
    {
        private var _radius:Number;
        private var _angle:Number;
        private var _startFrom:Number;
        private var _fullColor:uint;
        private var _lineColor:uint;
        private var _lineThickness:Number;
        private var _showTieLine:Boolean;

        public function get showTieLine():Boolean { return _showTieLine; }
        public function get lineColor():uint { return _lineColor; }
        public function get lineThickness():uint { return _lineThickness; }
        public function get fullColor():uint { return _fullColor; }
        public function get startFrom():Number { return _startFrom; }
        public function get angle():Number { return _angle; }
        public function get radius():Number { return _radius; }

        /**
         * 实例化一个扇形
         * @param   radius
         * @param   angle
         * @param   startFrom
         * @param   fullColor
         * @param   lineColor
         * @param   lineThickness
         * @param   showTieLine
         */
        public function Sector(radius:Number, angle:Number, startFrom:Number = 270,
            fullColor:uint = 0xFF00FFFF, lineColor:uint = 0xFF000000,
            lineThickness:Number = 1, showTieLine:Boolean = true)
        {
            drawSector(radius, angle, startFrom, fullColor, lineColor,lineThickness, showTieLine);
        }

        /**
         * 画扇形
         * @param   radius      半径
         * @param   angle       扇形的角度 >= 0  , if > 360 ,则 = 360
         * @param   startFrom   开始角度        无效值则为0
         * @param   fullColor   填充颜色 ARGB 格式的
         * @param   lineColor   线条颜色 ARGB 格式的
         * @param   showTieLine 是否显示原点到弧线的连线
         */
        public function drawSector(radius:Number, angle:Number, startFrom:Number = 270,
            fullColor:uint = 0xFF00FFFF, lineColor:uint = 0xFF000000,
            lineThickness:Number = 1, showTieLine:Boolean = true):void
        {
            if (isNaN(radius) || radius < 0) radius = 0;

            if (isNaN(angle) || angle < 0) angle = 0;
            if (angle > 360) angle = 360;

            if (isNaN(startFrom)) startFrom = 0;

            _radius = radius;
            _angle = angle;
            _startFrom = startFrom;
            _fullColor = fullColor;
            _lineColor = lineColor;
            _lineThickness = lineThickness;
            _showTieLine = showTieLine;

            // 清除以前的
            graphics.clear();

            if (angle >> 24) / 0xFF);
            graphics.beginFill(fullColor &amp; 0xFFFFFF, (fullColor >>> 24) / 0xFF);

            var radian:Number = startFrom / 180 * Math.PI;  // 弧度,临时替换用的
            var px:Number = Math.cos(radian) * radius;      // 划线的坐标点
            var py:Number = Math.sin(radian) * radius;
            graphics.lineTo(px, py);

            if (!showTieLine) graphics.lineStyle(lineThickness, lineColor &amp; 0xFFFFFF, (lineColor >>> 24) / 0xFF);
            // 画圆弧
            while (angle > 0)
            {
                var tempAngle:Number = (angle >= 45) ? 45 : angle;
                // 控制点坐标
                radian = (startFrom + tempAngle * 0.5) / 180 * Math.PI;
                var cx:Number = radius / Math.cos(tempAngle / 360 * Math.PI) * Math.cos(radian);
                var cy:Number = radius / Math.cos(tempAngle / 360 * Math.PI) * Math.sin(radian);
                // 更新角度
                startFrom += tempAngle;
                angle -= tempAngle;
                // 计算划线末点坐标
                radian = startFrom / 180 * Math.PI;
                px = Math.cos(radian) * radius;
                py = Math.sin(radian) * radius;
                // 画线
                graphics.curveTo(cx, cy, px, py);
            }
            // 连接到结束点
            if (!showTieLine) graphics.lineStyle(0, 0, 0);
            graphics.lineTo(0, 0);
            graphics.endFill();
        }
    }
}

MovableSector 这是实现冷却时间效果的类:

package com.litefeel.display
{
    import flash.display.DisplayObject;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.getTimer;

    /**
     * 在一周结束后,触发 flash.events.Event.COMPLETE 事件
     */
    [Event(name="complete", type="flash.events.Event")]

    /**
     * 一个可转动的扇形,就像游戏里的冷却时间一样
     * 可以附加到任意显示对象,也不用理会目标是否缩放,注册点位置
     * 只需要目标在现实列表里
     *
     * www.litefeel.com
     * @author lite3
     */
    public class MovableSector extends Sprite
    {
        private var _running:Boolean = false;
        private var _color:uint;

        private var beginTime:Number;   // 开始的时间
        private var totalTime:Number;   // 总时间
        private var startFrom:Number;   // 开始的角度

        private var sector:Sector;
        private var maskShape:Shape;

        public function MovableSector(display:DisplayObject)
        {
            mouseChildren = false;
            mouseEnabled = false;

            if (display) setTarget(display);
        }

        /**
         * 是否在转动
         */
        public function get running():Boolean { return _running; }

        /**
         * 颜色 不包括 alpha通道
         */
        public function get color():uint { return _color; }
        public function set color(value:uint):void
        {
            if (_color != value)
            {
                _color = value;
                if (maskShape)
                {
                    var r:Number = (value &amp; 0xFF0000) >>> 16;
                    var g:Number = (value &amp; 0x00FF00) >>> 8;
                    var b:Number = value &amp; 0x0000FF;
                    trace(r, g, b);
                    maskShape.transform.colorTransform = new ColorTransform(0, 0, 0, 1, r, g, b);
                }
            }

        }

        /**
         * 设置目标,并添加到目标上层
         * 目标必须在现实列表里
         * 转动结束后出发complete事件
         *
         * @param   display
         * @eventType   flash.events.Event
         */
        public function setTarget(display:DisplayObject):void
        {
            // init UI
            if (sector) removeChild(sector);
            if (!maskShape) maskShape = new Shape();

            var radius:Number = Math.sqrt(display.width * display.width + display.height * display.height) * 0.5;
            sector = new Sector(radius, 0, -90, 0xFFFFFFFF, 0, 0, false);
            addChild(sector);

            var rect:Rectangle = display.getBounds(display.parent);
            var stageP:Point = display.localToGlobal(new Point(rect.x, rect.y));

            var halfW:Number = rect.width * 0.5;
            var halfH:Number = rect.height * 0.5;
            maskShape.graphics.clear();
            maskShape.graphics.beginFill(_color);
            for (var i:int = 0; i < rect.width; i++)
            {
                for (var j:int = 0; j < rect.height; j++)
                {
                    if (display.hitTestPoint(rect.x + i, rect.y + j, true))
                        maskShape.graphics.drawRect(i - halfW, j - halfH, 1, 1);
                }
            }
            addChild(maskShape);
            maskShape.cacheAsBitmap = true;
            maskShape.mask = sector;

            this.x = rect.x + halfW;
            this.y = rect.y + halfH;

            // 添加到显示列表
            display.parent.addChildAt(this, display.parent.getChildIndex(display) + 1);
        }

        /**
         * 从某个角度开始转一周
         * @param   startFrom   开始转动的角度
         * @param   totalTime   转一圈所用的时间(单位:毫秒)
         */
        public function start(startFrom:Number, totalTime:Number):void
        {
            if (sector)
            {
                this.startFrom = startFrom;
                this.totalTime = totalTime;
                beginTime = getTimer();
                _running = true;

                // 先画一个圆
                sector.drawSector(sector.radius, 360, startFrom, 0xCC000000, 0x00000000, 0, false);

                if (!sector.hasEventListener(Event.ENTER_FRAME))
                    sector.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
            }
        }

        private function enterFrameHandler(e:Event):void
        {
            var postTime:Number = getTimer() - beginTime;

            // 时间到了
            if (postTime >= totalTime)
            {
                sector.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
                sector.drawSector(sector.radius, 0);
                _running = false;
                dispatchEvent(new Event(Event.COMPLETE));
            }
            // 时间还没到
            else
            {
                var postAngle:Number = 360 * postTime / totalTime;
                sector.drawSector(sector.radius, 360 - postAngle, startFrom + postAngle, 0x0, 0x0, 0, false);
            }
        }
    }
}

完整源码下载☞

  1. lite3 | | #1

    @foxlively
    O(∩_∩)O~,这个倒是忘记了,没注意CPU,想到好方法了再改 :grin:

  2. foxlively | #2

    效果好
    但CPU占用率太高了
    WOW里应该不是用这种原理实现的吧,否则全都是这个cooldown机器死定了

  3. jack_ni | #3

    哈哈 不错

  1. 本文目前尚无任何 trackbacks 和 pingbacks.
回到顶部