手把手教你写蛇蛇大作战(五)
还未实现的功能有 游戏结束判断,菜单界面,机器蛇(AI) 我们先来实现游戏结束判断和游戏重开
效果图
首先还是老套路 看图。
这次就没录gif图 主要是就看个结果。毕竟录gif也挺麻烦的。>_
边界碰撞判断
在这里我们判断上下左右 4个边界判断碰撞,当蛇头(即Snake 的位置 position)
右边界 position.x >=MAP_WIDTH/2
左边界 position.x <= -MAP_WIDTH/2
上边界 position.y>=MAP_HEIGHT/2
下边界 position.y <=-MAP_HEIGHT/2
代码修改
修改 WorldController.java
添加属性
private boolean gameOver;//游戏结束
1
2
3
privatebooleangameOver;//游戏结束
添加方法
private void checkGameOver() {
float radius = snake.bounds.width / 2;
if (snake.position.x + radius >= Constants.MAP_WIDTH / 2
|| snake.position.x <= -Constants.MAP_WIDTH / 2
|| snake.position.y + radius >= Constants.MAP_HEIGHT / 2
|| snake.position.y <= -Constants.MAP_WIDTH / 2) {//判断边界
gameOver = true;
AudioManager.instance.stopMusic();//停止播放音乐
AudioManager.instance.play(Assets.instance.sounds.liveLost);//播放dead sound
}
}
public boolean isGameOver() {
return gameOver;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
privatevoidcheckGameOver(){
floatradius=snake.bounds.width/2;
if(snake.position.x+radius>=Constants.MAP_WIDTH/2
||snake.position.x<=-Constants.MAP_WIDTH/2
||snake.position.y+radius>=Constants.MAP_HEIGHT/2
||snake.position.y<=-Constants.MAP_WIDTH/2){//判断边界
gameOver=true;
AudioManager.instance.stopMusic();//停止播放音乐
AudioManager.instance.play(Assets.instance.sounds.liveLost);//播放dead sound
}
}
publicbooleanisGameOver(){
returngameOver;
}
在update() 方法改为如下
public void update(float deltaTime) {
if (isGameOver()) return;
handleInput(deltaTime);
snake.update(deltaTime);
testCollision();
cameraHelper.update(deltaTime);
for (Food food : foods) {
food.update(deltaTime);
}
checkGameOver();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
publicvoidupdate(floatdeltaTime){
if(isGameOver())return;
handleInput(deltaTime);
snake.update(deltaTime);
testCollision();
cameraHelper.update(deltaTime);
for(Foodfood:foods){
food.update(deltaTime);
}
checkGameOver();
}
我们看到的效果图用到的是LibGdx 默认的皮肤 可以从LibGdx 找到也可以去我的github
将uiskin.atlas ,uiskin.json 和uiskin.png 拷贝到assets 目录下面 然后开始写代码了。
修改WorldRenderer.java
添加下面几个属性
private Skin skinLibgdx;//默认皮肤private Window winGameOver;
private TextButton btnBack;//返回按钮
private TextButton btnStart;//重新开始按钮
private Window winGameOver;//游戏结束Window
1
2
3
4
5
6
privateSkinskinLibgdx;//默认皮肤private Window winGameOver;
privateTextButtonbtnBack;//返回按钮
privateTextButtonbtnStart;//重新开始按钮
privateWindowwinGameOver;//游戏结束Window
初始化
skinLibgdx = new Skin(Gdx.files.internal(Constants.SKIN_LIBGDX_UI),new TextureAtlas(Constants.TEXTURE_ATLAS_LIBGDX_UI));
...
stage.addActor(buildGameOverDialog());
...
1
2
3
4
5
6
skinLibgdx=newSkin(Gdx.files.internal(Constants.SKIN_LIBGDX_UI),newTextureAtlas(Constants.TEXTURE_ATLAS_LIBGDX_UI));
...
stage.addActor(buildGameOverDialog());
...
Constants.java中添加
public static final String SKIN_LIBGDX_UI = "images/uiskin.json";
public static final String TEXTURE_ATLAS_LIBGDX_UI = "images/uiskin.atlas";
1
2
3
4
publicstaticfinalStringSKIN_LIBGDX_UI="images/uiskin.json";
publicstaticfinalStringTEXTURE_ATLAS_LIBGDX_UI="images/uiskin.atlas";
buildGameOverDialog() 方法
private Table buildGameOverDialog() {
winGameOver = new Window("GAME OVER", skinLibgdx);//游戏结束window
Table table = new Table();//这里的Table 表示布局方式
table.pad(10, 10, 0, 10);
table.add(new Label("GAME OVER!", skinLibgdx, "default-font", Color.ORANGE)).colspan(3);//绘制GAME OVER! Label
table.row();
btnBack = new TextButton("Back", skinLibgdx);//添加返回按钮
table.add(btnBack).padRight(30);
btnBack.addListener(new ChangeListener() {//添加监听方法
@Override
public void changed(ChangeEvent event, Actor actor) {
showOptionsWindow(false, true);//隐藏结束window
Gdx.app.exit();
}
});
btnStart = new TextButton("ReStart", skinLibgdx);//添加重新开始按钮
table.add(btnStart);
btnStart.addListener(new ChangeListener() {//添加监听
@Override
public void changed(ChangeEvent event, Actor actor) {
AudioManager.instance.play(Assets.instance.sounds.bm);
showOptionsWindow(false, true);
worldController.init();//重现开始
}
});
winGameOver.add(table).pad(10, 10, 0, 10);
winGameOver.setColor(1, 1, 1, 0.8f);
showOptionsWindow(false, false);
winGameOver.pack();
winGameOver.setPosition((Constants.VIEWPORT_GUI_WIDTH - winGameOver.getWidth()) / 2,
(Constants.VIEWPORT_GUI_HEIGHT - winGameOver.getHeight()) / 2);
return winGameOver;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
privateTablebuildGameOverDialog(){
winGameOver=newWindow("GAME OVER",skinLibgdx);//游戏结束window
Tabletable=newTable();//这里的Table 表示布局方式
table.pad(10,10,0,10);
table.add(newLabel("GAME OVER!",skinLibgdx,"default-font",Color.ORANGE)).colspan(3);//绘制GAME OVER! Label
table.row();
btnBack=newTextButton("Back",skinLibgdx);//添加返回按钮
table.add(btnBack).padRight(30);
btnBack.addListener(newChangeListener(){//添加监听方法
@Override
publicvoidchanged(ChangeEventevent,Actoractor){
showOptionsWindow(false,true);//隐藏结束window
Gdx.app.exit();
}
});
btnStart=newTextButton("ReStart",skinLibgdx);//添加重新开始按钮
table.add(btnStart);
btnStart.addListener(newChangeListener(){//添加监听
@Override
publicvoidchanged(ChangeEventevent,Actoractor){
AudioManager.instance.play(Assets.instance.sounds.bm);
showOptionsWindow(false,true);
worldController.init();//重现开始
}
});
winGameOver.add(table).pad(10,10,0,10);
winGameOver.setColor(1,1,1,0.8f);
showOptionsWindow(false,false);
winGameOver.pack();
winGameOver.setPosition((Constants.VIEWPORT_GUI_WIDTH-winGameOver.getWidth())/2,
(Constants.VIEWPORT_GUI_HEIGHT-winGameOver.getHeight())/2);
returnwinGameOver;
}
showOptionsWindow 方法
public void showOptionsWindow(boolean visible, boolean animated) {
float alphaTo = visible ? 0.8f : 0.0f;
float duration = animated ? 1.0f : 0.0f;
final Touchable touchEnable = visible ? Touchable.enabled : Touchable.disabled;
winGameOver.addAction(sequence(touchable(touchEnable), alpha(alphaTo, duration)));//然Game Over window 执行个消失动画 透明度变为0
}
1
2
3
4
5
6
7
8
publicvoidshowOptionsWindow(booleanvisible,booleananimated){
floatalphaTo=visible?0.8f:0.0f;
floatduration=animated?1.0f:0.0f;
finalTouchabletouchEnable=visible?Touchable.enabled:Touchable.disabled;
winGameOver.addAction(sequence(touchable(touchEnable),alpha(alphaTo,duration)));//然Game Over window 执行个消失动画 透明度变为0
}
在方法render()中 添加以下代码
if (worldController.isGameOver()) {//游戏结束时显示结束弹窗
showOptionsWindow(true, true);
}
1
2
3
4
5
if(worldController.isGameOver()){//游戏结束时显示结束弹窗
showOptionsWindow(true,true);
}
尝试运行下吧!
GitHub
代码已经放在GITHUB
可以切换到tag4 来查看本篇文章代码
使用 `git checkout tag4