如何在里面创建一个包含多个多边形drawable的按钮(在LibGDX中)

时间:2017-11-08 16:55:05

标签: java libgdx scene2d

是否有一些简单的方法可以在 LibGDX 中创建一个包含多个多边形drawable的Button

例如,当简单的Button可以被描绘为: simple button

和那样的高级预期按钮:

advanced button

在我的情况下,必须满足以下条件:

  1. 对象必须扩展Button类。
  2. 分隔的多边形(图中的圆和三角形)必须具有一个共同的行为 - 相同的向上,向下,悬停样式,相同的单击侦听器等。 (例如,当用户悬停圆圈时,三角形和圆圈将颜色变为绿色)
  3. 实际上它必须与具有一个多边形的按钮具有完全相同的行为,只要想象圆和三角形是一个多边形,而不是分开的多边形。

    我想出的一种方法是扩展PolygonRegionDrawable,但为了使其正确绘制,我需要覆盖DrawableTransformDrawable几乎所有方法,是否有更简单的方法那样做?

    也许可以找到一些DrawableGroup或类似的东西?

2 个答案:

答案 0 :(得分:1)

我不认为这是一种简单的方法,这里有一些选择。

ButtonTable,您可以为其添加内容。

Button button = new Button(skin);
Image img = new Image(...); // insert polygon 1 here
img.setPostion(...); // offset so its in correct position in the button
button.addActor(img);
// add more stuff

可悲的是,这并没有处理各种状态变化,比如等等。您需要跟踪添加的内容并将其更改为按钮更改。

其他选项是将多边形转换为单个图像。 这非常棘手,你可以在正确的位置将它们绘制到FrameBufferObject中并制作纹理。然后将该纹理用于Drawable按钮样式。 Reapet为您想要处理的每个州。将它们包装成和atlas将是出于性能原因的最佳选择。大量的纹理切换并不是很好。

答案 1 :(得分:0)

为了达到这样的功能,我已经实现了两个额外的类,这些类可以假定一个Drawables列表来绘制它,就像只有一个。

所以我在这里提到它,我希望它对那些想要实现相同行为的人有用。

一个抽象类,它采用格式的可绘制列表和相关坐标:

[drawable1X, drawable1Y, drawable2X, drawable2Y, ..., drawableNX, drawableNY] 

<强> BulkBaseDrawable:

abstract class BulkBaseDrawable implements Drawable {

    Array<Drawable> drawables;
    private float leftWidth, rightWidth, topHeight, bottomHeight, minWidth, minHeight, leftX, bottomY, rightX, topY;

    BulkBaseDrawable(Drawable[] drawables,
                     float... vertices) {
        this.infos = new Array<>(drawables.length);
        init(drawables, vertices);
    }

    @Override
    public float getLeftWidth() {
        return leftWidth;
    }

    @Override
    public void setLeftWidth(float leftWidth) {
        this.leftWidth = leftWidth;
    }

    @Override
    public float getRightWidth() {
        return rightWidth;
    }

    @Override
    public void setRightWidth(float rightWidth) {
        this.rightWidth = rightWidth;
    }

    @Override
    public float getTopHeight() {
        return topHeight;
    }

    @Override
    public void setTopHeight(float topHeight) {
        this.topHeight = topHeight;
    }

    @Override
    public float getBottomHeight() {
        return bottomHeight;
    }

    @Override
    public void setBottomHeight(float bottomHeight) {
        this.bottomHeight = bottomHeight;
    }

    @Override
    public float getMinWidth() {
        return minWidth;
    }

    @Override
    public void setMinWidth(float minWidth) {
        this.minWidth = minWidth;
    }

    @Override
    public float getMinHeight() {
        return minHeight;
    }

    @Override
    public void setMinHeight(float minHeight) {
        this.minHeight = minHeight;
    }

    void init(Drawable[] drawables, float[] vertices) {
        initInfo(drawables, vertices);
        initEdges();
        initSize();
    }

    private void initInfo(Drawable[] drawables, float[] vertices) {
        int i = 0;
        for (Drawable drawable : drawables) {
            infos.add(Info.builder()
                    .x(vertices[i])
                    .y(vertices[i + 1])
                    .width(drawable.getMinWidth())
                    .height(drawable.getMinHeight())
                    .drawable(drawable)
                    .build());
            i += 2;
        }
    }

    private void initSize() {
        minHeight = topY - bottomY;
        minWidth = rightX - leftX;
    }

    private void initEdges() {
        topY = Float.MIN_VALUE;
        rightX = Float.MIN_VALUE;
        bottomY = Float.MAX_VALUE;
        leftX = Float.MAX_VALUE;
        int topI = 0;
        int rightI = 0;
        int bottomI = 0;
        int leftI = 0;
        for (int i = 0; i < infos.size; i++) {
            Info info = infos.get(i);
            if (info.y + info.height > topY) {
                topY = info.y + info.height;
                topI = i;
            }
            if (info.x + info.width > rightX) {
                rightX = info.x + info.width;
                rightI = i;
            }
            if (info.y < bottomY) {
                bottomY = info.y;
                bottomI = i;
            }
            if (info.x < leftX) {
                leftX = info.x;
                leftI = i;
            }
        }
        Drawable top = infos.get(topI).drawable;
        Drawable right = infos.get(rightI).drawable;
        Drawable bottom = infos.get(bottomI).drawable;
        Drawable left = infos.get(leftI).drawable;
        leftWidth = left.getLeftWidth();
        rightWidth = right.getRightWidth();
        topHeight = top.getTopHeight();
        bottomHeight = bottom.getBottomHeight();
    }

    static class Info {

        float x, y, width, height;
        Drawable drawable;

        static InfoBuilder builder() {
            return new InfoBuilder();
        }

        static class InfoBuilder {

            float x, y, width, height;
            Drawable drawable;

            InfoBuilder x(float x) {
                this.x = x;
                return this;
            }

            InfoBuilder y(float y) {
                this.y = y;
                return this;
            }

            InfoBuilder width(float width) {
                this.width = width;
                return this;
            }

            InfoBuilder height(float height) {
                this.height = height;
                return this;
            }

            InfoBuilder drawable(Drawable drawable) {
                this.drawable = drawable;
                return this;
            }

            Info build() {
                return new Info(x, y, width, height, drawable);
            }
        }

        public Info(float x, float y, float width, float height, Drawable drawable) {
            this.x = x;
            this.y = y;
            this.width = width;
            this.height = height;
            this.drawable = drawable;
        }
    }
}

实际上实现 BulkRegionDrawable:

public class BulkRegionDrawable extends BulkBaseDrawable {

    public BulkRegionDrawable(Drawable[] drawables, float[] vertices) {
        super(drawables, vertices);
    }

    @Override
    public void draw(Batch batch,
                     float x,
                     float y,
                     float width,
                     float height) {
        for (int i = 0; i < infos.size; i++) {
            Info info = infos.get(i);
            float yK = info.height / getMinHeight();
            float xK = info.width / getMinWidth();
            info.drawable.draw(
                    batch,
                    x + (info.x * width) / getMinWidth(),
                    y + (info.y * height) / getMinHeight(),
                    width * xK,
                    height * yK);
        }
    }
}