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代码仍需完善,缩放旋转现在应该是有问题的,自行解决,无关本文了。

 

转载于:https://www.cnblogs.com/hanhongmin/p/3966829.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值