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

时间: 2024-10-04 11:03:12

libgdx 制作技能冷却图标的相关文章

使用NGUI制作技能冷却图标

最近在学习NGUI,有些小的知识点,个人觉得很不错,就记录下来了,毕竟好记性不如烂笔头,温故知新. 首先导入NGUI插件,插件我会在文章下面给出链接. 导入NGUI后,会在菜单栏,看到NGUI的按钮,我们首先创建一个Sprite,重命名为Skill,为其选择图集和精灵,调整Skill的大小和位置,我这里Size 为200*200. 在Hierarchy面板中选中Skill,然后再Scene面板中,右键创建一个Sprite,重命名为Filled,为其选择图集和精灵,最好选择一个单色的精灵,然后,T

纯css3样式属性制作各种图形图标

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="

NGUI的技能冷却实现

使用NGUI实现技能冷却的原理是这样的:在表示技能的Sprite上加一个半透明的Sprite,将类型设置为filled类型,Fill Dir设置为Radial360,通过程序调节Fill Amount就可以模拟技能从冷却到被活的一段时间内渐变的效果.如下图所示: 代码中一个标志位isCooling表示是否正在冷却,只有当按下释放技能的按键并且该标志位为false时才可以释放技能,释放完成后isCooling立即变为true,然后冷却的部分在每帧都会减少,直至完全消失.代码如下: 1 using

SkillButton 技能冷却

#pragma once #include "cocos2d.h" USING_NS_CC; class SkillButton :public Node { public:  SkillButton();  ~SkillButton();                            //技能标记  static SkillButton * createSkillButton(float skillCD,const char* normalImage,const char* 

让你的Photoshop编辑制作ICO格式图标文件(ICOFormat支持图标文件插件)

相信很多制图的朋友都喜欢用PS,但是你能用Photoshop保存为ICO格式图标文件吗?默认肯定不行,不知道是什么原因,大名鼎鼎的图像编辑软件Adobe Photoshop一直不支持导入导出ico格式图标文件. 不过还好,ps支持插件,有了一个名为ICOFormat的插件,IcoFormat是一款可以让Photoshop支持ICO和CUR格式的PS插件,有了它就可以直接从ps里打开.保存ico和cur格式文件了. 一起来看看ICOFormat:让Photoshop支持导入导出ico和cur格式文

Cocos2d-x技能冷却还要等多久?---之游戏开发《赵云要格斗》(9)

这里是Evankaka的博客,欢迎大家前来讨论与交流------      转载请注明出处http://blog.csdn.net/evankaka/article/details/42747719 本文将主要来实现游戏开发过程中,技能冷却的实现,一个按钮点一次后,就会有一个冷却时间,得等冷却时间过了之后,你才能再次点击,一般这是实现特殊技能的.在这里,我也自己写了一个类,非常方便,只要把这个类加到你的工程中,加两张图片,就可以实现功能了. cocos2d-x版本:2.2.5 工程环境:wind

网站如何添加和制作favicon.ico图标教程

经常看到有部分网站没有 favicon.ico 图标,所以今天打算普及一下相关知识,希望还没有 favicon.ico 图标的站长们,能够制作出自己独特的图标. 那么到底什么是favicon.ico? 好搜百科给出的解释:所谓 favicon,即 Favorites Icon 的缩写,顾名思义,便是其可以让浏览器的收藏夹中除显示相应的标题外,还以图标的方式区别不同的网站.当然,这不仅仅是 Favicon 的全部,根据浏览器的不同,Favicon 显示也有所区别:在大多数主流浏览器如 FireFo

NGUI技能冷却CD特效制作

其实蛮简单的今天紫龙感觉萌萌哒就详详细细地记录一下把: 首先在制作一个sprite命名为skill加一个背景图片,然后再建立一个sprite,选择一个可以挡住skill的背景的图片,然后选择Filled属性(如下图).然后在Sprite下面建立一个Label用来表示技能的按键快捷键,本例用的是R键...如下图                  因为sprite的图片挡住了skill的图片,所以给sprite的Alpha值调整到半透明,调整在color里面的属性如图(图的左边已经看到了效果):在c

使用NGUI来制作技能的CD冷却效果

using System.Collections; using System.Collections.Generic; using UnityEngine; public class CDScripts : MonoBehaviour { public int cd_time = 2; //技能的冷却速度 public bool cd_isCan = false; //是否可以释放技能的标志位 private UISprite cd_sprite; private void Awake() {