在完成前面的基础性工作之后,接下来就到了重头戏:游戏主界面和游戏逻辑的搭建。
1.游戏主界面的搭建
今天我们要完成的工作是:点击play进入游戏界面,对应的在游戏界面显示一些东西.
效果:
看到以上四张图相信大家应该很明白要干什么了,下面我们上代码
GameScreen类:
package com.zhf.mylibgdx;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GLCommon;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
/**
* 游戏主界面
* @author ZHF
*
*/
public class GameScreen implements Screen {
//状态
static final int GAME_READY = 0; //准备
static final int GAME_RUNNING = 1; //运行
static final int GAME_PAUSED = 2; //暂停
static final int GAME_LEVEL_END = 3; //本关结束
static final int GAME_OVER = 4; //游戏结束
Game game;
int state; //状态
OrthographicCamera guiCam; //相机
Vector3 touchPoint; //触点
SpriteBatch batcher; //用于绘画的
Rectangle pauseBounds; //暂停按钮
Rectangle resumeBounds; //继续游戏按钮
Rectangle quitBounds; //离开按钮
int lastScore; //最后得分
String scoreString; //显示分数
public GameScreen(Game game) {
this.game = game;
//初始化工作
state = GAME_READY;
guiCam = new OrthographicCamera(320, 480);
guiCam.position.set(320 / 2, 480 / 2, 0); //将相机的视角设为中间
touchPoint = new Vector3();
batcher = new SpriteBatch();
pauseBounds = new Rectangle(320 - 64, 480 - 64, 64, 64);
resumeBounds = new Rectangle(160 - 96, 240, 192, 36);
quitBounds = new Rectangle(160 - 96, 240 - 36, 192, 36);
lastScore = 0;
scoreString = "SCORE: 0";
}
/**刷新状态**/
public void update (float deltaTime) {
if (deltaTime > 0.1f) deltaTime = 0.1f;
//根据游戏动向,刷新状态
switch (state) {
case GAME_READY:
updateReady(); //准备状态
break;
case GAME_RUNNING:
updateRunning(deltaTime); //游戏运行状态
break;
case GAME_PAUSED:
updatePaused(); //游戏暂停状态
break;
case GAME_LEVEL_END: //本关结束
updateLevelEnd();
break;
case GAME_OVER:
updateGameOver(); //游戏结束
break;
}
}
/**准备状态**/
private void updateReady () {
if (Gdx.input.justTouched()) {
state = GAME_RUNNING;
}
}
/**游戏运行状态**/
private void updateRunning (float deltaTime) {
if (Gdx.input.justTouched()) {
guiCam.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
//点击暂停
if (OverlapTester.pointInRectangle(pauseBounds, touchPoint.x, touchPoint.y)) {
Assets.playSound(Assets.clickSound);
state = GAME_PAUSED;
return;
}
}
}
/**游戏暂停状态**/
private void updatePaused () {
if (Gdx.input.justTouched()) {
guiCam.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0));
//点击继续游戏
if (OverlapTester.pointInRectangle(resumeBounds, touchPoint.x, touchPoint.y)) {
Assets.playSound(Assets.clickSound);
state = GAME_RUNNING;
return;
}
//点击离开,返回到主菜单界面
if (OverlapTester.pointInRectangle(quitBounds, touchPoint.x, touchPoint.y)) {
Assets.playSound(Assets.clickSound);
game.setScreen(new MainMenuScreen(game));
return;
}
}
}
/**本关结束**/
private void updateLevelEnd () {
if (Gdx.input.justTouched()) {
state = GAME_READY;
}
}
/**游戏结束**/
private void updateGameOver () {
if (Gdx.input.justTouched()) {
game.setScreen(new MainMenuScreen(game));
}
}
/**绘画**/
public void draw (float deltaTime) {
GLCommon gl = Gdx.gl;
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glClearColor(0f, 0f, 0f, 0f);
guiCam.update();
batcher.setProjectionMatrix(guiCam.combined);
batcher.enableBlending();
batcher.begin();
//根据游戏状态刷新界面
switch (state) {
case GAME_READY:
presentReady(); //绘制准备界面
break;
case GAME_RUNNING:
presentRunning(); //绘制暂停和分数显示
break;
case GAME_PAUSED:
presentPaused(); //绘制暂停菜单和分数显示
break;
case GAME_LEVEL_END:
presentLevelEnd(); //绘制本关结束
break;
case GAME_OVER:
presentGameOver(); //绘制游戏结束
break;
}
batcher.end();
}
/**绘制准备**/
private void presentReady () {
batcher.draw(Assets.ready, 160 - 192 / 2, 240 - 32 / 2, 192, 32);
}
/**绘制暂停和分数显示**/
private void presentRunning () {
batcher.draw(Assets.pause, 320 - 64, 480 - 64, 64, 64);
Assets.font.draw(batcher, scoreString, 16, 480 - 20);
}
/**绘制暂停菜单和分数显示**/
private void presentPaused () {
batcher.draw(Assets.pauseMenu, 160 - 192 / 2, 240 - 96 / 2, 192, 96);
Assets.font.draw(batcher, scoreString, 16, 480 - 20);
}
/**绘制本关结束**/
private void presentLevelEnd () {
String topText = "the princess is ...";
String bottomText = "in another castle!";
float topWidth = Assets.font.getBounds(topText).width;
float bottomWidth = Assets.font.getBounds(bottomText).width;
Assets.font.draw(batcher, topText, 160 - topWidth / 2, 480 - 40);
Assets.font.draw(batcher, bottomText, 160 - bottomWidth / 2, 40);
}
/**绘制游戏结束**/
private void presentGameOver () {
batcher.draw(Assets.gameOver, 160 - 160 / 2, 240 - 96 / 2, 160, 96);
float scoreWidth = Assets.font.getBounds(scoreString).width;
Assets.font.draw(batcher, scoreString, 160 - scoreWidth / 2, 480 - 20);
}
@Override
public void render(float delta) {
update(delta);
draw(delta);
}
@Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void show() {
// TODO Auto-generated method stub
}
@Override
public void hide() {
// TODO Auto-generated method stub
}
@Override
public void pause() {
if (state == GAME_RUNNING) state = GAME_PAUSED;
}
@Override
public void resume() {
// TODO Auto-generated method stub
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
}
分析:
这里代码里的注释已经写得很清楚,这里我再讲一下框架,方便初学者学习,在构造方法里我们初始化了一些变量,接下来很重要的一步就是在render()方法里写了两个重要的方法:update() 和 draw(); 即:游戏的逻辑
update(floatdeltaTime): 根据游戏动向不断地刷新状态(准备状态、游戏运行状态、游戏暂停状态、本关结束、本关结束)
draw(floatdeltaTime): 根据游戏状态刷新界面(
presentReady();//绘制准备界面
presentRunning();//绘制暂停和分数显示
presentPaused();//绘制暂停菜单和分数显示
presentLevelEnd();//绘制本关结束
presentGameOver();//绘制游戏结束)
我们别忘了和前面一样,在MainMneuScreen中将条状那行注释去掉:
game.setScreen(new GameScreen(game));
同样,游戏界面中包含一些元素(如暂停按钮,菜单等),自然要在Asset类中对应的加载资源进去。
声明:
//游戏界面
public static TextureRegion pause;//暂停按钮
public static TextureRegion pauseMenu; //暂停弹出菜单
public static TextureRegion ready; //准备
public static TextureRegion gameOver; //游戏结束
实例化:
//游戏界面界面
pause = new TextureRegion(items, 64, 64, 64, 64);
pauseMenu = new TextureRegion(items, 224, 128, 192, 96);
ready = new TextureRegion(items, 320, 224, 192, 32);
gameOver = new TextureRegion(items, 352, 256, 160, 96);
ok!这一讲可能代码比较少,这里我们主要先将框架搭建起来,下一讲我们我涉及到游戏场景中各个元素以及世界的编写。