libgdx 制作技能冷却图标

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

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

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

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

libgdx 制作技能冷却图标

 

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

 

你可能感兴趣的:(libgdx)