• libgdx 制作技能冷却图标


    本篇随笔记录如何制作一个技能冷却的图标。抛砖引玉了,如需实际应用还得好好整理代码。

    表示技能冷却,计时等无非就两种吧,一是长条状,参照/扩展progressbar即可,另外一个就是方形或者圆形的了吧。

    很多有技能条的游戏UI一般都是用的是方形技能图标,如魔兽世界,暗黑三,War3.....

    在这里我们试着做一个出来,先看看效果图吧(很次,见尿了,以后可以在指针和边框上加上动画或粒子效果)

    该组件分为4层,从下往上依次为:技能原图标ground,裁剪效果层,指针层,外边框。当然也可以加入更多,或者只有两层(ground和裁剪效果)。

    上代码:

      1 public class ColdDownIcon extends Image {
      2 
      3 
      4     private TextureRegion texture;//裁剪画的纹理
      5     private TextureRegion ground;//背景纹理,裁剪镂空后要露出来的,也就是原始技能图标
      6     private TextureRegion outerRing;//图标外圈
      7     private Image handEffect;//指针效果,本来打算使用粒子效果的
      8 
      9     private PolygonSpriteBatch polyBatch;//画多边形的
     10 
     11     private Vector2 center;
     12     private Vector2 centerTop;//从上面中间开始
     13     private Vector2 leftTop;
     14     private Vector2 leftBottom;
     15     private Vector2 rightBottom;
     16     private Vector2 rightTop;
     17     private Vector2 progressPoint;
     18     private float[] fv;//裁剪画图使用的点阵{point1.x,point1.y,point2.x,point2.y  ......}
     19     private Vector2 intersectPoint;//当前切割在边上的点
     20 
     21     //当前正在切割的位置
     22     private IntersectAt intersectAt;
     23     private float liveTime;//本次cd已执行时间
     24     private float coldDownTime;//cd一次所需时间
     25     private boolean startColdDown;
     26 
     27     //当前切割位置的枚举
     28     public enum IntersectAt {
     29         NONE, TOP, BOTTOM, LEFT, RIGHT;
     30     }
     31 
     32     public ColdDownIcon(TextureRegion ground,TextureRegion outerRing, PolygonSpriteBatch polyBatch,Image handEffect,float coldDownTime)
     33     {
     34         super(ground);
     35         this.ground = ground;
     36         this.texture = ground;
     37         this.outerRing = outerRing;
     38         this.polyBatch = polyBatch;
     39         this.handEffect = handEffect;
     40         this.handEffect.setVisible(false);
     41 
     42         handEffect.setOrigin(this.getWidth()/2,this.getHeight()/2);
     43         this.coldDownTime = coldDownTime;
     44         //计算各点内部坐标
     45         center = new Vector2(this.getWidth()/2, this.getHeight()/2);
     46         centerTop = new Vector2(this.getWidth()/2, this.getHeight());
     47         leftTop = new Vector2(0, this.getHeight());
     48         leftBottom = new Vector2(0, 0);
     49         rightBottom = new Vector2(this.getWidth(), 0);
     50         rightTop = new Vector2(this.getWidth(), this.getHeight());
     51         progressPoint = new Vector2(this.getWidth()/2, this.getHeight()/2);
     52 
     53         setColor(Color.RED);
     54 
     55         setPercentage(0);
     56     }
     57 
     58     public void startColdDown(){
     59         this.startColdDown = true;
     60         this.liveTime = 0;
     61         this.setPercentage(0);
     62         this.handEffect.setVisible(true);
     63     }
     64 
     65     public void endColdDown(){
     66         this.startColdDown = false;
     67         this.liveTime = 0;
     68         this.setPercentage(0);
     69         this.handEffect.setVisible(false);
     70     }
     71 
     72     //计算切线的最远点
     73     private Vector2 IntersectPoint(Vector2 line)
     74     {
     75         Vector2 v = new Vector2();
     76         boolean isIntersect;
     77 
     78         //check top
     79         isIntersect = Intersector.intersectSegments(leftTop, rightTop, center, line, v);//切割线和上边的交点v
     80 
     81         //check bottom
     82         if (isIntersect) { intersectAt = IntersectAt.TOP; return v; }
     83         else isIntersect = Intersector.intersectSegments(leftBottom, rightBottom, center, line, v);
     84 
     85         //check left
     86         if (isIntersect) { intersectAt = IntersectAt.BOTTOM; return v; }
     87         else isIntersect = Intersector.intersectSegments(leftTop, leftBottom, center, line, v);
     88 
     89         //check bottom
     90         if (isIntersect) { intersectAt = IntersectAt.LEFT; return v; }
     91         else isIntersect = Intersector.intersectSegments(rightTop, rightBottom, center, line, v);
     92 
     93         if (isIntersect) { intersectAt = IntersectAt.RIGHT; return v; }
     94         else
     95         {
     96             intersectAt = IntersectAt.NONE;
     97             return null;
     98         }
     99     }
    100 
    101     //设置百分比,顺时针
    102     private void setPercentage(float percent)
    103     {
    104         //100 % = 360 degree
    105         //==> percent % => (percent * 360 / 100) degree
    106 
    107         float angle = convertToRadians(90); //percent = 0 => angle = -90
    108         angle -= convertToRadians(percent * 360 / 100);
    109 
    110         float len = this.getWidth() > this.getHeight() ? this.getWidth() : this.getHeight();
    111         float dy = (float) (Math.sin(angle) * len);
    112         float dx = (float) (Math.cos(angle) * len);
    113         Vector2 line = new Vector2(center.x + dx, center.y + dy);
    114 
    115         intersectPoint = IntersectPoint(line);
    116         //
    117         float l = intersectPoint.dst(center.x,center.y);
    118         float sy = 2*l/getHeight();
    119 
    120         handEffect.setScaleY(sy);
    121 
    122 
    123         if (intersectAt == IntersectAt.TOP)
    124         {
    125             if (intersectPoint.x >= this.getWidth()/2) //
    126             {
    127                 //
    128                 fv = new float[] {
    129                         center.x,
    130                         center.y,
    131                         centerTop.x,
    132                         centerTop.y,
    133                         leftTop.x,
    134                         leftTop.y,
    135                         leftBottom.x,
    136                         leftBottom.y,
    137                         rightBottom.x,
    138                         rightBottom.y,
    139                         rightTop.x,
    140                         rightTop.y,
    141                         intersectPoint.x,
    142                         intersectPoint.y
    143                 };
    144             }
    145             else
    146             {
    147                 fv = new float[] { // cắt bên trái cạnh
    148                         center.x,
    149                         center.y,
    150                         centerTop.x,
    151                         centerTop.y,
    152                         intersectPoint.x,
    153                         intersectPoint.y
    154                 };
    155 
    156             }
    157         }
    158         else if (intersectAt == IntersectAt.BOTTOM)
    159         {
    160             fv = new float[] {
    161                     center.x,
    162                     center.y,
    163                     centerTop.x,
    164                     centerTop.y,
    165                     leftTop.x,
    166                     leftTop.y,
    167                     leftBottom.x,
    168                     leftBottom.y,
    169                     intersectPoint.x,
    170                     intersectPoint.y
    171             };
    172 
    173         }
    174         else if (intersectAt == IntersectAt.LEFT)
    175         {
    176             fv = new float[] {
    177                     center.x,
    178                     center.y,
    179                     centerTop.x,
    180                     centerTop.y,
    181                     leftTop.x,
    182                     leftTop.y,
    183                     intersectPoint.x,
    184                     intersectPoint.y
    185             };
    186 
    187         }
    188         else if (intersectAt == IntersectAt.RIGHT)
    189         {
    190             fv = new float[] {
    191                     center.x,
    192                     center.y,
    193                     centerTop.x,
    194                     centerTop.y,
    195                     leftTop.x,
    196                     leftTop.y,
    197                     leftBottom.x,
    198                     leftBottom.y,
    199                     rightBottom.x,
    200                     rightBottom.y,
    201                     intersectPoint.x,
    202                     intersectPoint.y
    203             };
    204         }
    205         else // if (intersectAt == IntersectAt.NONE)
    206         {
    207             //不绘制
    208             fv = null;
    209         }
    210     }
    211 
    212     //重新绘制函数
    213     @Override
    214     public void draw(Batch batch, float parentAlpha) {
    215 //        super.draw(batch, parentAlpha);
    216         batch.draw(ground,this.getX(),this.getY());
    217 
    218         if (fv != null&&this.startColdDown) {//画裁剪了的图
    219             batch.end(); //注意这里!!!先把原来的停掉
    220             drawMe();
    221             batch.begin(); //注意这里!!再开始!
    222         }
    223         if(handEffect.isVisible()){
    224             handEffect.setX(this.getX());
    225             handEffect.setY(this.getY());
    226             handEffect.draw(batch,parentAlpha);
    227         }
    228 
    229         batch.draw(outerRing,this.getX(),this.getY());
    230     }
    231 
    232     @Override
    233     public void act(float delta) {
    234         super.act(delta);
    235         if(this.startColdDown){//开始冷却了,计时
    236             this.liveTime = this.liveTime+delta;
    237             if(this.liveTime>this.coldDownTime){//超出停止
    238                 this.endColdDown();
    239             }else{
    240                 float percent = this.liveTime*100/this.coldDownTime;
    241                 this.setPercentage(percent);
    242                 handEffect.setVisible(true);
    243                 handEffect.setRotation(-percent * 360 / 100);
    244             }
    245         }
    246     }
    247 
    248     //按点阵列区域绘制图像
    249     public void drawMe()
    250     {
    251         //裁剪
    252         EarClippingTriangulator e = new EarClippingTriangulator();
    253         ShortArray sv = e.computeTriangles(fv);
    254 
    255         //创建 polygonRegion.
    256         PolygonRegion polyReg = new PolygonRegion( texture, fv, sv.toArray());
    257 
    258         //创建 polySprite.
    259         PolygonSprite poly = new PolygonSprite(polyReg);
    260 
    261         //(position, origin, rotation, color)
    262         poly.setOrigin(this.getOriginX(), this.getOriginY());
    263         poly.setPosition(this.getX(), this.getY());
    264         poly.setRotation(this.getRotation());
    265         poly.setColor(this.getColor());
    266 
    267         //绘制
    268         polyBatch.begin();
    269         poly.draw(polyBatch);
    270         polyBatch.end();
    271     }
    272 
    273 
    274 
    275 //-----------------------------------------------------------------
    276 
    277 
    278     float convertToDegrees(float angleInRadians)
    279     {
    280         float angleInDegrees = angleInRadians * 57.2957795f;
    281         return angleInDegrees;
    282     }
    283 
    284     float convertToRadians(float angleInDegrees)
    285     {
    286         float angleInRadians = angleInDegrees * 0.0174532925f;
    287         return angleInRadians;
    288     }
    289 
    290 }
    public class ColdDownTester2 extends ApplicationAdapter implements InputProcessor {
        private Stage stage;
        private static final Logger LOGGER = new Logger(ColdDownTester2.class.getName(),Application.LOG_DEBUG);
        private Texture ground;
        private Texture hand;
        private Texture outerRing;
        private ColdDownIcon icon;
        @Override
        public void create () {
            Gdx.app.setLogLevel(Application.LOG_DEBUG);
            stage = new Stage();
            Gdx.input.setInputProcessor(this);
    
            ground = new Texture(Gdx.files.internal("frostbolt-1.png"));
            hand = new Texture(Gdx.files.internal("frostbolt-3.png"));
            outerRing = new Texture(Gdx.files.internal("frostbolt-4.png"));
    
            icon = new ColdDownIcon(new TextureRegion(ground),new TextureRegion(outerRing),new PolygonSpriteBatch(),new Image(hand),3.0f);
            stage.addActor(icon);
        }
    
        @Override
        public void render () {
            Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            stage.act();
            stage.draw();
        }
    
        @Override
        public void dispose() {
    
            stage.dispose();
            super.dispose();
        }
    
        @Override
        public void resize(int width, int height) {
            stage.getViewport().update(width,height);
            super.resize(width, height);
        }
    
        @Override
        public boolean keyDown(int keycode) {
            if(keycode == Input.Keys.J){
                icon.startColdDown();
            }
            return false;
        }
    
        @Override
        public boolean keyUp(int keycode) {
            return false;
        }
    
        @Override
        public boolean keyTyped(char character) {
            return false;
        }
    
        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            return false;
        }
    
        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            return false;
        }
    
        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            return false;
        }
    
        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            return false;
        }
    
        @Override
        public boolean scrolled(int amount) {
            return false;
        }
    }

    裁剪计算代码参考了越南人的代码,从哪来的找不到了,官网应该也有。

    以上代码只为了显示看看效果,并未关心dispose等。icon代码仍需完善,缩放旋转现在应该是有问题的,自行解决,无关本文了。

  • 相关阅读:
    Python菜鸟之路:Django 序列化数据
    Python菜鸟之路:Django 数据验证之钩子和Form表单验证
    Python菜鸟之路:Django 路由补充1:FBV和CBV
    Python菜鸟之路:Django 文件上传的几种方式
    Python菜鸟之路:Django 分页
    Python菜鸟之路:Django 信号
    Python菜鸟之路:Django 缓存
    《将博客搬至CSDN》
    Java基础语法
    Java基础语法
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3966829.html
Copyright © 2020-2023  润新知