先上效果:
准备素材:
素材准备好,使用GDX Texture Packer打包
整体布局采用Stack + Table,每层都使用Table来绘制不同的元素
package com.mygdx.game.ui;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Button;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Stack;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.viewport.FitViewport;
public class GameHUD implements Disposable {
private static final String TAG = GameHUD.class.getSimpleName();
private GameUIDemo game;
private Stage stage;
private OrthographicCamera camera;
private FitViewport viewport;
private TextureAtlas atlas;
private BitmapFont font;
public GameHUD(GameUIDemo game){
this.game = game;
//加载资源
atlas = new TextureAtlas(Gdx.files.internal("ui/gameui.atlas"));
font = new BitmapFont();
font.setColor(Color.WHITE);
//创建舞台
camera = new OrthographicCamera();
viewport = new FitViewport(GameUIDemo.V_WIDTH, GameUIDemo.V_HEIGHT, camera);
stage = new Stage(viewport, game.batch);
//创建多层布局框架
Stack layout = new Stack();
layout.setFillParent(true);
//绘制头像、等级部分外框层
Table headTable = new Table();
headTable.setFillParent(true);
headTable.left().top();
headTable.add(new Image(atlas.findRegion("bottom_bg"))).colspan(3).left().width(GameUIDemo.V_WIDTH).height(30);
headTable.row();
Image headImg = new Image(atlas.findRegion("head"));
float hw = GameUIDemo.V_WIDTH * 0.20f;
float headScale = hw / headImg.getWidth();
headTable.add(headImg).width(hw).height(headImg.getHeight() * headScale).left().top();
Image headInner = new Image(atlas.findRegion("head_inner"));
headTable.add(headInner).width(GameUIDemo.V_WIDTH - hw - 10).height(headInner.getHeight() * headScale - 1).padRight(-15f).left().top();
Image headCorner = new Image(atlas.findRegion("head_corner"));
headTable.add(headCorner).width(30).height(headCorner.getHeight() * headScale - 1).padLeft(-5f).left().top();
headTable.row();
layout.add(headTable);
//头部名称、金币和钻石等显示框层
Table textTable = new Table();
textTable.setFillParent(true);
textTable.left().top().padTop(30);
TextureAtlas.AtlasRegion textInnerRegion = atlas.findRegion("text_inner");
TextureAtlas.AtlasRegion textCornerRegion = atlas.findRegion("text_corner");
Image textInner = new Image(textInnerRegion);
Image textCorner = new Image(textCornerRegion);
float cornerWidth = textCorner.getWidth() * headScale;
float offsetLeft = headImg.getWidth() * headScale - 10;
float innerWidth = GameUIDemo.V_WIDTH - offsetLeft - cornerWidth * 3 - 40;
float innerHeight = textInner.getHeight() * headScale;
float innerTop = (headInner.getHeight() - textInner.getHeight()) * headScale / 2;
textTable.add(textInner).width(innerWidth / 3).height(innerHeight).padTop(innerTop - 1).padLeft(offsetLeft);
textTable.add(textCorner).width(textCorner.getWidth() * headScale).height(innerHeight).padTop(innerTop - 1).left();
textInner = new Image(textInnerRegion);
textTable.add(textInner).width(innerWidth / 3).height(innerHeight).padTop(innerTop - 1).padLeft(20);
textInner = new Image(textInnerRegion);
textTable.add(textInner).width(innerWidth / 3).height(innerHeight).padTop(innerTop - 1).padLeft(20);
layout.add(textTable);
//金币、钻石图标层
Table infoTable = new Table();
infoTable.setFillParent(true);
infoTable.left().top().padTop(30).padLeft(headImg.getWidth() * headScale - 30);
Image levelImg = new Image(atlas.findRegion("level_bg"));
infoTable.add(levelImg).width(levelImg.getWidth() * headScale).height(levelImg.getHeight() * headScale).left().top();
Image goldenImg = new Image(atlas.findRegion("golden"));
float goldenOffsetLeft = innerWidth / 3 + 20 - goldenImg.getWidth() * headScale / 2;
infoTable.add(goldenImg).width(goldenImg.getWidth() * headScale).height(goldenImg.getHeight() * headScale).padLeft(goldenOffsetLeft).padTop(innerTop).left().top();
TextureAtlas.AtlasRegion plusRegion = atlas.findRegion("plus");
Image plusImg = new Image(plusRegion);
float plusOffsetLeft = innerWidth / 3 - plusImg.getWidth() * headScale - 5;
infoTable.add(plusImg).width(plusImg.getWidth() * headScale).height(plusImg.getHeight() * headScale).padLeft(plusOffsetLeft).padTop(innerTop + 1).left().top();
Image dimondImg = new Image(atlas.findRegion("dimond"));
infoTable.add(dimondImg).width(dimondImg.getWidth() * headScale).height(dimondImg.getHeight() * headScale).padLeft(10).padTop(innerTop + 1).left().top();
plusImg = new Image(plusRegion);
plusOffsetLeft = innerWidth / 3 - plusImg.getWidth() * headScale - 10;
infoTable.add(plusImg).width(plusImg.getWidth() * headScale).height(plusImg.getHeight() * headScale).padLeft(plusOffsetLeft).padTop(innerTop + 1).left().top();
layout.add(infoTable);
//底部面板、底部背景层
Table bottomTable = new Table();
bottomTable.setFillParent(true);
bottomTable.bottom();
bottomTable.add(new Image(atlas.findRegion("bar_corner"))).left().width(30).height(60);
bottomTable.add(new Image(atlas.findRegion("bar_inner"))).left().width(GameUIDemo.V_WIDTH - 60).height(60);
Image rightCorner = new Image(atlas.findRegion("bar_corner"));
rightCorner.setOriginX(15);
rightCorner.setScaleX(-1);
bottomTable.add(rightCorner).right().width(30).height(60);
bottomTable.row();
bottomTable.add(new Image(atlas.findRegion("bottom_bg"))).colspan(3).left().width(GameUIDemo.V_WIDTH).height(30);
bottomTable.row();
layout.add(bottomTable);
//底部菜单图标层
Table iconTable = new Table();
float iconScaleX = 0.45f, iconScaleY = 0.4f;
iconTable.setFillParent(true);
iconTable.center().bottom().padBottom(50);
Button iconHome = new Button(new TextureRegionDrawable(atlas.findRegion("icon_home")));
iconTable.add(iconHome).bottom().width(iconScaleX * iconHome.getWidth()).height(iconScaleX * iconHome.getHeight()).pad(0, 5, 0, 10);
Button iconHero = new Button(new TextureRegionDrawable(atlas.findRegion("icon_hero")));
iconTable.add(iconHero).bottom().width(iconScaleX * iconHero.getWidth()).height(iconScaleX * iconHero.getHeight()).pad(0, 10, 0, 10);
Button iconAdventure = new Button(new TextureRegionDrawable(atlas.findRegion("icon_adventure")));
iconTable.add(iconAdventure).bottom().width(iconAdventure.getWidth() * iconScaleX).height(iconAdventure.getHeight() * iconScaleX).pad(0, 10, 0, 10);
Button iconBag = new Button(new TextureRegionDrawable(atlas.findRegion("icon_bag")));
iconTable.add(iconBag).bottom().width(iconScaleX * iconBag.getWidth()).height(iconScaleX * iconBag.getHeight()).pad(0, 10, 0, 10);
Button iconUnit = new Button(new TextureRegionDrawable(atlas.findRegion("icon_unit")));
iconTable.add(iconUnit).bottom().width(iconScaleX * iconUnit.getWidth()).height(iconScaleX * iconUnit.getHeight()).pad(0, 10, 0, 5);
layout.add(iconTable);
stage.addActor(layout);
Gdx.input.setInputProcessor(stage);
}
public void draw(float dt){
stage.draw();
stage.act(dt);
}
@Override
public void dispose() {
stage.dispose();
}
}
启动入口类
package com.mygdx.game.ui;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.ScreenUtils;
public class GameUIDemo extends Game {
public static final float V_WIDTH = 480;
public static final float V_HEIGHT = 800;
public SpriteBatch batch;
public Skin skin;
public BitmapFont font;
private GameHUD gameHUD;
@Override
public void create() {
skin = new Skin(Gdx.files.internal("ui/uiskin.json"));
font = new BitmapFont(Gdx.files.internal("bitmapfont_big.fnt"));
batch = new SpriteBatch();
gameHUD = new GameHUD(this);
}
@Override
public void render() {
super.render();
ScreenUtils.clear(Color.WHITE);
gameHUD.draw(Gdx.graphics.getDeltaTime());
}
@Override
public void resize(int width, int height) {
super.resize(width, height);
}
@Override
public void dispose() {
super.dispose();
}
}