GameScreen
public GameScreen (Game game) {
super(game);
state = GAME_READY; //游戏状态
guiCam = new OrthographicCamera(320, 480);
guiCam.position.set(320 / 2, 480 / 2, 0);
touchPoint = new Vector3();
batcher = new SpriteBatch();
worldListener = new WorldListener() {
@Override
public void jump () {
Assets.playSound(Assets.jumpSound);
}
@Override
public void highJump () {
Assets.playSound(Assets.highJumpSound);
}
@Override
public void hit () {
Assets.playSound(Assets.hitSound);
}
@Override
public void coin () {
Assets.playSound(Assets.coinSound);
}
};
world = new World(worldListener);
renderer = new WorldRenderer(batcher, world);
//暂停按钮
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";
}
//逻辑,不同情况通过不同的函数处理
@Override
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;
}
}
//
if (Gdx.app.getType() == Application.ApplicationType.Android) {
world.update(deltaTime, Gdx.input.getAccelerometerX());
} else {
float accel = 0;
if (Gdx.input.isKeyPressed(Keys.DPAD_LEFT)) accel = 5f;
if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT)) accel = -5f;
world.update(deltaTime, accel);
}
if (world.score != lastScore) {
lastScore = world.score;
scoreString = "SCORE: " + lastScore;
}
if (world.state == World.WORLD_STATE_NEXT_LEVEL) {
state = GAME_LEVEL_END;
}
if (world.state == World.WORLD_STATE_GAME_OVER) {
state = GAME_OVER;
if (lastScore >= Settings.highscores[4])
scoreString = "NEW HIGHSCORE: " + lastScore;
else
scoreString = "SCORE: " + lastScore;
Settings.addScore(lastScore);
Settings.save();
}
}
World
上面大量用了这个类,这个应该是游戏的逻辑中心
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;
}
}
}
这段基本没有什么,就是点击按钮的逻辑
@Override
public void present (float deltaTime) {
GLCommon gl = Gdx.gl;
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glEnable(GL10.GL_TEXTURE_2D);
renderer.render();
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();
}
这个是渲染逻辑,
renderer.render()
WorldRenderer
public void render () {
if (world.bob.position.y > cam.position.y) cam.position.y = world.bob.position.y;//一直以bob的位置为观察点
cam.update();
batch.setProjectionMatrix(cam.combined);
renderBackground();
renderObjects();
}
//很简单的贴图
public void renderBackground () {
batch.disableBlending();
batch.begin();
batch.draw(Assets.backgroundRegion, cam.position.x - FRUSTUM_WIDTH / 2, cam.position.y - FRUSTUM_HEIGHT / 2, FRUSTUM_WIDTH,
FRUSTUM_HEIGHT); //注意贴图是以观察点为中心贴图,这里不用屏幕坐标,充分考虑了手机的尺寸可能变化,
batch.end();
}
public void renderObjects () {
batch.enableBlending();
batch.begin();
renderBob();
renderPlatforms();
renderItems();
renderSquirrels();
renderCastle();
batch.end();
}
private void renderBob () {
TextureRegion keyFrame;
switch (world.bob.state) {
case Bob.BOB_STATE_FALL:
keyFrame = Assets.bobFall.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING); //掉落的状态
break;
case Bob.BOB_STATE_JUMP:
keyFrame = Assets.bobJump.getKeyFrame(world.bob.stateTime, Animation.ANIMATION_LOOPING); //跳起的状态
break;
case Bob.BOB_STATE_HIT:
default:
keyFrame = Assets.bobHit;
}
float side = world.bob.velocity.x < 0 ? -1 : 1;
if (side < 0)
batch.draw(keyFrame, world.bob.position.x + 0.5f, world.bob.position.y - 0.5f, side * 1, 1);
else
batch.draw(keyFrame, world.bob.position.x - 0.5f, world.bob.position.y - 0.5f, side * 1, 1);
}
Assets里面保存了bob的一些Animation
items = loadTexture("data/items.png");
bobJump = new Animation(0.2f, new TextureRegion(items, 0, 128, 32, 32), new TextureRegion(items, 32, 128, 32, 32));
bobFall = new Animation(0.2f, new TextureRegion(items, 64, 128, 32, 32), new TextureRegion(items, 96, 128, 32, 32));
Animation
public TextureRegion getKeyFrame (float stateTime, boolean looping) {
int frameNumber = (int)(stateTime / frameDuration);
if (!looping) {
frameNumber = Math.min(keyFrames.length - 1, frameNumber);
} else {
frameNumber = frameNumber % keyFrames.length;
}
return keyFrames[frameNumber];
}
通过上面的操作来取得一个动态的图片
下面大同小异
private void renderPlatforms () {
int len = world.platforms.size();
for (int i = 0; i < len; i++) {
Platform platform = world.platforms.get(i);
TextureRegion keyFrame = Assets.platform;
if (platform.state == Platform.PLATFORM_STATE_PULVERIZING) {
keyFrame = Assets.brakingPlatform.getKeyFrame(platform.stateTime, Animation.ANIMATION_NONLOOPING);
}
batch.draw(keyFrame, platform.position.x - 1, platform.position.y - 0.25f, 2, 0.5f);
}
}
private void renderItems () {
int len = world.springs.size();
for (int i = 0; i < len; i++) {
Spring spring = world.springs.get(i);
batch.draw(Assets.spring, spring.position.x - 0.5f, spring.position.y - 0.5f, 1, 1);
}
len = world.coins.size();
for (int i = 0; i < len; i++) {
Coin coin = world.coins.get(i);
TextureRegion keyFrame = Assets.coinAnim.getKeyFrame(coin.stateTime, Animation.ANIMATION_LOOPING);
batch.draw(keyFrame, coin.position.x - 0.5f, coin.position.y - 0.5f, 1, 1);
}
}
private void renderSquirrels () {
int len = world.squirrels.size();
for (int i = 0; i < len; i++) {
Squirrel squirrel = world.squirrels.get(i);
TextureRegion keyFrame = Assets.squirrelFly.getKeyFrame(squirrel.stateTime, Animation.ANIMATION_LOOPING);
float side = squirrel.velocity.x < 0 ? -1 : 1;
if (side < 0)
batch.draw(keyFrame, squirrel.position.x + 0.5f, squirrel.position.y - 0.5f, side * 1, 1);
else
batch.draw(keyFrame, squirrel.position.x - 0.5f, squirrel.position.y - 0.5f, side * 1, 1);
}
}
private void renderCastle () {
Castle castle = world.castle;
batch.draw(Assets.castle, castle.position.x - 1, castle.position.y - 1, 2, 2);
}
回到刚才的一段,主要画面绘制完毕,下面绘制不同状态的不同画面
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;
}
绘制一串文字
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);
}