标签:style blog http color io os 使用 ar 2014
本篇随笔记录如何制作一个技能冷却的图标。抛砖引玉了,如需实际应用还得好好整理代码。
表示技能冷却,计时等无非就两种吧,一是长条状,参照/扩展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代码仍需完善,缩放旋转现在应该是有问题的,自行解决,无关本文了。
标签:style blog http color io os 使用 ar 2014
原文地址:http://www.cnblogs.com/hanhongmin/p/3966829.html