绝代码农 发表于 2021-7-17 22:00:06

第一个libgdx程序--仿别踩白块

学libgdx有一段时间了,有一个星期了吧,边做边学,选的是别踩白块。

   libgdx总体思想可以用下面这张图来表示

   

   总体可分为两层吧,入口不算,Screen+Actor. 这个很好理解啊,你去看话剧表演,得有屏幕吧,屏幕上面有英雄,有坏蛋,还有道具吧,
所以,简单来说暂且就看作两层。


   下面看看具体项目:


      首先跑起来是这样的:
   
                                 


      代码是这样的:


      1. 入口类 FirstGame
         
      既然是入口,主要做一些初始化操作


public class FirstGame extends Game
{

private MenuScreen menuScreen;

@Override
public void create()
{
Const.WIDTH = Gdx.graphics.getWidth();
Const.HEIGHT = Gdx.graphics.getHeight();
menuScreen = new MenuScreen(this);
setScreen(menuScreen);
}

@Override
public void render()
{
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
super.render();
}

}

   2. 游戏选择界面 MenuScreen

      这里真正开始libgdx部分了,主要是图片按钮TextButton控件的使用及两个动画特效的实现。根据界面显示,用了6个主菜单TextButton和3个子菜单TextButton,代码如下:

public class MenuScreen implements Screen
{

private TextButtonStyle whiteStyle, blackStyle;
/** 6个主菜单 */
private TextButton classicBtn, arcadeBtn, zenBtn, speedBtn, relayBtn, moreBtn;
/** 3个子菜单 */
private TextButton mode1Btn, mode2Btn, mode3Btn;
private Texture texture;
private Stage stage;
/** 这里用集合来存放所有点击过的菜单的位置,用来得到哪一个需要收缩,哪一个需要弹出 */
private List<Integer> idList;
/** 是否播放动画 */
private boolean isrun;
private FirstGame game;

public MenuScreen(FirstGame game)
{
this.game = game;
}

@Override
public void render(float delta)
{
/** 收缩菜单与弹出菜单动画特效。这里开始逻辑有点乱,耐心看看吧,一时间没想到更好的办法,唉 ==||*/
if (isrun)
{
int len = idList.size();
if (len > 0)
{
if (len > 1)
{
if (idList.get(len - 2) % 2 == 1)
{
if (inx > -240)
{
modeBtnMoveIn();
}
} else
{
if (inx < 480)
{
modeBtnMoveIn();
}
}
}

if (idList.get(len - 1) % 2 == 1)
{
if (outx < 0)
{
modeBtnMoveOut();
} else
{
isrun = false;
}
} else
{
if (outx > 240)
{
modeBtnMoveOut();
} else
{
isrun = false;
}
}
}
}
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
}

@Override
public void resize(int width, int height)
{
}

@Override
public void show()
{
stage = new Stage(new StretchViewport(Const.WIDTH, Const.HEIGHT));
initBtnStyle();
initBtn();
Gdx.input.setInputProcessor(stage);
idList = new ArrayList<Integer>();
}

/** 初始化按钮背景颜色 */
private void initBtnStyle()
{
texture = new Texture(Gdx.files.internal("data/whitebg.png"));
Sprite sprite = new Sprite(texture);
SpriteDrawable whiteSpriteDrawable = new SpriteDrawable(sprite);

whiteStyle = new TextButtonStyle();
whiteStyle.down = whiteSpriteDrawable;
whiteStyle.up = whiteSpriteDrawable;
whiteStyle.font = new BitmapFont();
whiteStyle.fontColor = Color.BLACK;

texture = new Texture(Gdx.files.internal("data/black.png"));
sprite = new Sprite(texture);
SpriteDrawable blackSpriteDrawable = new SpriteDrawable(sprite);

blackStyle = new TextButtonStyle();
blackStyle.down = blackSpriteDrawable;
blackStyle.up = blackSpriteDrawable;
blackStyle.font = new BitmapFont();
blackStyle.fontColor = Color.WHITE;
}

/** 实例化按钮 */
private void initBtn()
{
classicBtn = new TextButton("Classic", whiteStyle);
classicBtn.setPosition(0, Const.HEIGHT * 2 / 3);
classicBtn.setSize(Const.WIDTH / 2, Const.HEIGHT / 3);
classicBtn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
initmodeBtn("25", "50", "Discontinuous", 1);
idList.add(1);
setInitX();
isrun = true;
return super.touchDown(event, x, y, pointer, button);
}
});

arcadeBtn = new TextButton("Arcade", blackStyle);
arcadeBtn.setPosition(Const.WIDTH / 2, Const.HEIGHT * 2 / 3);
arcadeBtn.setSize(Const.WIDTH / 2, Const.HEIGHT / 3);
arcadeBtn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
initmodeBtn("Normal", "Faster", "Retrograde", 0);
idList.add(2);
setInitX();
isrun = true;
return super.touchDown(event, x, y, pointer, button);
}
});

zenBtn = new TextButton("Zen", blackStyle);
zenBtn.setPosition(0, Const.HEIGHT / 3);
zenBtn.setSize(Const.WIDTH / 2, Const.HEIGHT / 3);
zenBtn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
initmodeBtn("15\"", "30\"", "Discontinuous", 1);
idList.add(3);
setInitX();
isrun = true;
return super.touchDown(event, x, y, pointer, button);
}
});

speedBtn = new TextButton("Speed", whiteStyle);
speedBtn.setPosition(Const.WIDTH / 2, Const.HEIGHT / 3);
speedBtn.setSize(Const.WIDTH / 2, Const.HEIGHT / 3);
speedBtn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
initmodeBtn("Slow", "Normal", "Retrograde", 0);
idList.add(4);
setInitX();
isrun = true;
return super.touchDown(event, x, y, pointer, button);
}
});

relayBtn = new TextButton("Relay", whiteStyle);
relayBtn.setPosition(0, 0);
relayBtn.setSize(Const.WIDTH / 2, Const.HEIGHT / 3);
relayBtn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
initmodeBtn("8\"", "10\"", "12\"", 1);
idList.add(5);
setInitX();
isrun = true;
return super.touchDown(event, x, y, pointer, button);
}
});

moreBtn = new TextButton("More", blackStyle);
moreBtn.setPosition(Const.WIDTH / 2, 0);
moreBtn.setSize(Const.WIDTH / 2, Const.HEIGHT / 3);
moreBtn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
initmodeBtn("1", "2", "3", 0);
idList.add(6);
setInitX();
isrun = true;
return super.touchDown(event, x, y, pointer, button);
}
});

stage.addActor(classicBtn);
stage.addActor(arcadeBtn);
stage.addActor(zenBtn);
stage.addActor(speedBtn);
stage.addActor(relayBtn);
stage.addActor(moreBtn);

/** 在这里实例化并注册监听事件,不能去到initmodeBtn再做操作 */
mode1Btn = new TextButton("", whiteStyle);
mode2Btn = new TextButton("", blackStyle);
mode3Btn = new TextButton("", whiteStyle);
mode1Btn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
setScreen(1);
return super.touchDown(event, x, y, pointer, button);
}
});
mode2Btn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
setScreen(2);
return super.touchDown(event, x, y, pointer, button);
}
});
mode3Btn.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
setScreen(3);
return super.touchDown(event, x, y, pointer, button);
}
});
}

/** 页面跳转 */
private void setScreen(int mode)
{
switch (idList.get(idList.size() - 1))
{
case 1:
switch (mode)
{
case 1:
game.setScreen(new GameScreen(game, Const.GameModeOne.CLASSIC, Const.GameModeTwo.MODE1));
break;
case 2:
game.setScreen(new GameScreen(game, Const.GameModeOne.CLASSIC, Const.GameModeTwo.MODE2));
break;
case 3:
game.setScreen(new GameScreen(game, Const.GameModeOne.CLASSIC, Const.GameModeTwo.MODE3));
break;
default:
break;
}
break;
case 2:
switch (mode)
{
case 1:
game.setScreen(new GameScreen(game, Const.GameModeOne.ARCADE, Const.GameModeTwo.MODE1));
break;
case 2:
game.setScreen(new GameScreen(game, Const.GameModeOne.ARCADE, Const.GameModeTwo.MODE2));
break;
case 3:
game.setScreen(new GameScreen(game, Const.GameModeOne.ARCADE, Const.GameModeTwo.MODE3));
break;
default:
break;
}
break;
case 3:
switch (mode)
{
case 1:
game.setScreen(new GameScreen(game, Const.GameModeOne.ZEN, Const.GameModeTwo.MODE1));
break;
case 2:
game.setScreen(new GameScreen(game, Const.GameModeOne.ZEN, Const.GameModeTwo.MODE2));
break;
case 3:
game.setScreen(new GameScreen(game, Const.GameModeOne.ZEN, Const.GameModeTwo.MODE3));
break;
default:
break;
}
break;
case 4:
switch (mode)
{
case 1:
game.setScreen(new GameScreen(game, Const.GameModeOne.SPEED, Const.GameModeTwo.MODE1));
break;
case 2:
game.setScreen(new GameScreen(game, Const.GameModeOne.SPEED, Const.GameModeTwo.MODE2));
break;
case 3:
game.setScreen(new GameScreen(game, Const.GameModeOne.SPEED, Const.GameModeTwo.MODE3));
break;
default:
break;
}
break;
case 5:
switch (mode)
{
case 1:
game.setScreen(new GameScreen(game, Const.GameModeOne.RELAY, Const.GameModeTwo.MODE1));
break;
case 2:
game.setScreen(new GameScreen(game, Const.GameModeOne.RELAY, Const.GameModeTwo.MODE2));
break;
case 3:
game.setScreen(new GameScreen(game, Const.GameModeOne.RELAY, Const.GameModeTwo.MODE3));
break;
default:
break;
}
break;
case 6:
break;
default:
break;
}
}

/** 初始化不同游戏模式按钮 */
private void initmodeBtn(String s1, String s2, String s3, int flag)
{
mode1Btn.setText(s1);
mode2Btn.setText(s2);
mode3Btn.setText(s3);
/** 背景色分了两种情况 */
if (flag == 1)
{
mode1Btn.setStyle(whiteStyle);
mode2Btn.setStyle(blackStyle);
mode3Btn.setStyle(whiteStyle);
} else
{
mode1Btn.setStyle(blackStyle);
mode2Btn.setStyle(whiteStyle);
mode3Btn.setStyle(blackStyle);
}
stage.addActor(mode1Btn);
stage.addActor(mode2Btn);
stage.addActor(mode3Btn);
}

/** 收缩菜单的x坐标需要平移到哪里为止,弹出菜单的x坐标需要平移到哪里为止 */
private float inx, outx;
/** 这两个值分别用来计算弹出菜单的高度和y坐标 */
private float moveh, moveYEnd;

/** 按钮收缩动画效果 */
private void modeBtnMoveIn()
{
int len = idList.size();
if (len > 1)
{
switch (idList.get(len - 2))
{
case 1:
moveYEnd = 800 * 2 / 3;
moveh = 800 / 3;
inx -= 20;
mode1Btn.setPosition(inx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(inx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(inx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 2:
moveYEnd = 800 * 2 / 3;
moveh = 800 / 3;
inx += 20;
mode1Btn.setPosition(inx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(inx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(inx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 3:
moveYEnd = 800 / 3;
moveh = 800 / 3;
inx -= 20;
mode1Btn.setPosition(inx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(inx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(inx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 4:
moveYEnd = 800 / 3;
moveh = 800 / 3;
inx += 20;
mode1Btn.setPosition(inx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(inx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(inx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 5:
moveYEnd = 0;
moveh = 800 / 3;
inx -= 20;
mode1Btn.setPosition(inx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(inx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(inx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 6:
moveYEnd = 0;
moveh = 800 / 3;
inx += 20;
mode1Btn.setPosition(inx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(inx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(inx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
default:
break;
}
}
}

/** 按钮弹出动画效果 */
private void modeBtnMoveOut()
{
switch (idList.get(idList.size() - 1))
{
case 1:
moveYEnd = 800 * 2 / 3;
moveh = 800 / 3;
outx += 15;
mode1Btn.setPosition(outx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(outx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(outx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 2:
moveYEnd = 800 * 2 / 3;
moveh = 800 / 3;
outx -= 15;
mode1Btn.setPosition(outx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(outx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(outx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 3:
moveYEnd = 800 / 3;
moveh = 800 / 3;
outx += 15;
mode1Btn.setPosition(outx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(outx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(outx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 4:
moveYEnd = 800 / 3;
moveh = 800 / 3;
outx -= 15;
mode1Btn.setPosition(outx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(outx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(outx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 5:
moveYEnd = 0;
moveh = 800 / 3;
outx += 15;
mode1Btn.setPosition(outx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(outx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(outx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
case 6:
moveYEnd = 0;
moveh = 800 / 3;
outx -= 15;
mode1Btn.setPosition(outx, moveYEnd + moveh * 2 / 3);
mode1Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode2Btn.setPosition(outx, moveYEnd + moveh / 3);
mode2Btn.setSize(Const.WIDTH / 2, moveh / 3);
mode3Btn.setPosition(outx, moveYEnd);
mode3Btn.setSize(Const.WIDTH / 2, moveh / 3);
break;
}
}

/** 获得收缩菜单和弹出菜单平移的目标位置 */
private void setInitX()
{
int len = idList.size();
if (len > 1)
{
if (idList.get(len - 2) % 2 == 1)
{
inx = 0;
} else
{
inx = 240;
}
}
if (idList.get(len - 1) % 2 == 1)
{
outx = -240;
} else
{
outx = 480;
}
}

@Override
public void hide()
{
}

@Override
public void pause()
{
}

@Override
public void resume()
{
}

@Override
public void dispose()
{
}

}



   如果看上面代码毫无压力的话(是指基本用法方面,本人代码比较乱++|| ),libgdx的基本用法差不多了。

      3. 演员类 BlockActor
      
      参考OOP里一切皆对象的说法。libgdx里所有用户能看到能动的东西基本都能作为演员,类似你去看话剧,舞台上能动的是不是基本都是演员(可能不是很恰当,初学的话暂时先这么理解吧)。演员有自己的属性,事件,动作等,可以在这里定义。

public class BlockActor extends Actor
{
private GameScreen screen;
public ImageButton mImageButton;
private TextureRegionDrawable startRegionDrawable, blackRegionDrawable, whiteRegionDrawable, greyRegionDrawable, redRegionDrawable;
private TextureRegion startRegion, blackRegion, whiteRegion, greyRegion, redRegion;
private Texture startTexture, blackTexture, whiteTexture, greyTexture, redTexture;

public BlockActor(GameScreen screen, BlockColor blockColor, float x, float y, int nameIndex)
{
this.screen = screen;
startTexture = new Texture(Gdx.files.internal("data/start.png"));
startRegion = new TextureRegion(startTexture);
startRegionDrawable = new TextureRegionDrawable(startRegion);
blackTexture = new Texture(Gdx.files.internal("data/black.png"));
whiteTexture = new Texture(Gdx.files.internal("data/white.png"));
greyTexture = new Texture(Gdx.files.internal("data/grey.png"));
redTexture = new Texture(Gdx.files.internal("data/red.png"));
whiteRegion = new TextureRegion(whiteTexture, 120, 200);
whiteRegionDrawable = new TextureRegionDrawable(whiteRegion);
redRegion = new TextureRegion(redTexture, 120, 200);
redRegionDrawable = new TextureRegionDrawable(redRegion);
blackRegion = new TextureRegion(blackTexture, 120, 200);
blackRegionDrawable = new TextureRegionDrawable(blackRegion);
greyRegion = new TextureRegion(greyTexture, 120, 200);
greyRegionDrawable = new TextureRegionDrawable(greyRegion);

if (nameIndex == 1 && blockColor == Const.BlockColor.BLACKBLOCK)
{
mImageButton = new ImageButton(startRegionDrawable, greyRegionDrawable);
mImageButton.setName(nameIndex + "");
} else if (blockColor == Const.BlockColor.BLACKBLOCK)
{
mImageButton = new ImageButton(blackRegionDrawable, greyRegionDrawable);
mImageButton.setName(nameIndex + "");
} else
{
mImageButton = new ImageButton(whiteRegionDrawable, redRegionDrawable);
mImageButton.setName("-1");
}
mImageButton.setSize(120, 200);
mImageButton.setPosition(x, y);
mImageButton.addListener(new InputListener()
{
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
return true;
}

@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
int position = Integer.parseInt(mImageButton.getName() + "");
if (position == 1)
{
BlockActor.this.screen.prerowpostion = position;
BlockActor.this.screen.isStart = true;
BlockActor.this.screen.blockState = Const.BlockState.MOVEING;
} else
{
if (BlockActor.this.screen.gameModeOne == Const.GameModeOne.CLASSIC && position == Const.BLOCKCOUNT)
{
BlockActor.this.screen.isSuc = true;
BlockActor.this.screen.blockState = Const.BlockState.IDLE;
BlockActor.this.screen.game.setScreen(new DeadScreen(BlockActor.this.screen));
} else
{
if (position == BlockActor.this.screen.prerowpostion + 1)
{
BlockActor.this.screen.prerowpostion = position;
BlockActor.this.screen.blockState = Const.BlockState.MOVEING;
} else
{
BlockActor.this.screen.blockState = Const.BlockState.IDLE;
BlockActor.this.screen.game.setScreen(new DeadScreen(BlockActor.this.screen));
}
}
}
super.touchUp(event, x, y, pointer, button);
}
});
}

@Override
public void draw(Batch batch, float parentAlpha)
{
super.draw(batch, parentAlpha);
}

}




    我的博客其他文章列表
    http://my.oschina.net/helu

文档来源:开源中国社区https://my.oschina.net/helu/blog/291297
页: [1]
查看完整版本: 第一个libgdx程序--仿别踩白块