我想使用LibGDX编写一个棋盘游戏,在游戏中我希望能够在该棋盘上添加或删除行/列。首先,我做了一些测试,为此做好准备。这是代码:
public class Test extends Game {
Skin skin;
Stage stage;
Texture texture1;
static int columns = 7;
static int rows = 12;
Window window2;
Table table2;
ArrayList<ArrayList<TextButton>> buttons;
@Override
public void create () {
skin = new Skin(Gdx.files.internal("data/uiskin.json"));
buttons = new ArrayList<ArrayList<TextButton>>();
for(int i = 0 ; i< rows; ++i)
{
buttons.add(new ArrayList<TextButton>());
for( int k = 0; k < columns; ++k)
{
buttons.get(i).add(new TextButton(("ASD" + i + k), skin));
}
}
texture1 = new Texture(Gdx.files.internal("data/badlogicsmall.jpg"));
TextureRegion image = new TextureRegion(texture1);
stage = new Stage(new ScreenViewport());
Gdx.input.setInputProcessor(stage);
ImageButtonStyle style = new ImageButtonStyle(skin.get(ButtonStyle.class));
style.imageUp = new TextureRegionDrawable(image);
ImageButton iconButton = new ImageButton(style);
window2 = new Window("Dialog2", skin);
window2.getTitleTable().add(new TextButton("X", skin)).height(window2.getPadTop());
window2.setSize(300, 400);
table2 = new Table();
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
table2.row();
}
ScrollPane pane= new ScrollPane(table2,skin);
pane.setScrollbarsOnTop(false);
pane.setFadeScrollBars(false);
window2.add(iconButton).row();
window2.add(pane);
stage.addActor(window2);
iconButton.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
new Dialog("Some Dialog", skin, "dialog") {
protected void result (Object object) {
System.out.println("Chosen: " + object);
if((Boolean) object )
{
for(int i = 0 ; i <columns; ++i){
table2.getCells().removeIndex(0).getActor().remove();}
}
}
}.text("Are you enjoying this demo?").button("Yes", true).button("No", false).key(Keys.ENTER, true)
.key(Keys.ESCAPE, false).show(stage);
}
});
}
@Override
public void render () {
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
stage.draw();
}
正如您在此处所见,我创建了一个独立按钮和一个表格,并用按钮填充它。然后在单击按钮后,我想删除该表的第一行,并将其余行向上移动。它只能工作一次(第一行),然后(第二次点击)我得到了这个例外:
Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: index can't be >= size: 70 >= 70
不知道该怎么做以及如何解决它。希望你能帮助我。
更新
感谢您的回复;我的代码现在看起来像这样:
// initialization
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(new TextButton(("ASD" + i + k), skin));
}
table2.row();
}
// sample operation - remove left column
for(int i = 0 ; i <rows; ++i){
table2.removeActor( table2.getChildren().get(i*columns-i) );
}
columns--;
另外,我在逻辑模型中得到了类似的Array,并希望根据该数组更改UI表的状态。那么这种方法是正确的还是应该改变一些东西?
答案 0 :(得分:0)
以这种方式使用桌子有点麻烦,至少我不知道更好。您的代码的快速修复将是:
// Global field
int removedRows = 0;
// In your listener
System.out.println("Chosen: " + object);
if ((Boolean) object)
{
for (int i = 0; i < columns; ++i)
{
table2.getCells().get(i + columns * removedRows).clearActor();
}
removedRows++;
}
但是如果你想删除完整的行,我会使用VerticalGroup并在那里添加每一行,这样你就可以直接访问一行并从VerticalGroup中删除它。如果按钮使用固定尺寸,那么它也会正确对齐。
table2.getCells()
返回一个数组,这意味着我们现在对该数组进行操作而不再对table2进行操作!
这意味着如果执行此操作: table2.getCells()removeIndex(0)。 它只会从数组中删除该单元格。这不会将table2更新为完整对象,只更新该表的单元格数组(因为没有返回该数组的副本)
换句话说,你这样做:
Array<Cell> table2Cells = table2.getCells();
Cell tableCell = table2Cells.removeIndex(0);
tableCell.clearActor();
因此,您从table2单元格数组中删除单元格,然后清除单元格内容(在本例中为actor)。但是你没有更新表来反映删除的单元格的变化,table2仍然&#34;认为&#34;单元格在那里,但你删除了它。
因此你得到索引错误,因为舞台绘制了表格,而表格想要绘制一个不再存在的单元格。
因此,如果您想为游戏创建某种类型的棋盘,最好的方法是编写您自己的类,提供您想要的功能。
解决方法是重置表格并重新填写:
int table2Rows = table2.getRows();
table2.reset();
// Omit the first row
for (int i = rows - table2Rows + 1; i < rows; ++i)
{
for (int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
table2.row();
}
table2.layout();
因此第一个单元格将包含第一个按钮,依此类推,因为表格内部值已正确更新。
答案 1 :(得分:0)
问题是关于你正在使用的 row() - 在第一行之前没有行单元格(用row()方法标记),这就是它的原因不会导致错误,但在删除第二个时会发生错误。
与 table2 比较,没有任何行进行测试:
for(int i = 0 ; i< rows; ++i)
{
for( int k = 0; k < columns; ++k)
{
table2.add(buttons.get(i).get(k));
}
//table2.row(); - we don't want any rows!
}
好的,我们知道问题在哪里,但它不是解决方案(好吧可能是一些解决方案:))。您应该使用以下代码操作表的Actors,而不是硬删除表格单元格的索引:
for(int i = 0 ; i <columns; ++i){
table2.removeActor( table2.getChildren().first() );
}