首页 > 代码库 > libgdx 制作技能冷却图标
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 degree105 //==> percent % => (percent * 360 / 100) degree106 107 float angle = convertToRadians(90); //percent = 0 => angle = -90108 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.y143 };144 }145 else146 {147 fv = new float[] { // c?t bên trái c?nh148 center.x,149 center.y,150 centerTop.x,151 centerTop.y,152 intersectPoint.x,153 intersectPoint.y154 };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.y171 };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.y185 };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.y203 };204 }205 else // if (intersectAt == IntersectAt.NONE)206 {207 //不绘制208 fv = null;209 }210 }211 212 //重新绘制函数213 @Override214 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 @Override233 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代码仍需完善,缩放旋转现在应该是有问题的,自行解决,无关本文了。
libgdx 制作技能冷却图标
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。