在本教程中我们将对雨滴游戏进行扩展。我们将尝试加入一个菜单和其它的一些功能。

 

** Screen接口**

Screen对于不论什么游戏都是主要的,Screen包括非常多来自ApplicationListener对象的方法,但包括两个新的方法:show和hide。用来获得或失去焦点。

** Game类**

Game类提供来继承自ApplicationListener的接口供使用,同一时候提供了一些方法用来设置和控制Screen渲染。

通过使用Screen和Game对象,能够创建一个简单而结构健壮的游戏。

接下来创建一个Game对象,作为游戏的入口。

代码例如以下:

package cn.libgdx.drop;

import com.badlogic.gdx.Game;

import com.badlogic.gdx.graphics.g2d.BitmapFont;

import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class Drop extends Game {

public SpriteBatch batch;

public BitmapFont font;

public void create() {

batch = new SpriteBatch();

//使用Libgdx默认的字体

font = new BitmapFont();

this.setScreen(new MainMenuScreen(this));

}

public void render() {

super.render(); //这个很重要!

}

public void dispose() {

batch.dispose();

font.dispose();

}

}

我们启动应用时实例化一个SpriteBatch和BitmapFont。SpriteBatch对象用来渲染屏幕的对象,像texture;BitmapFont对象与SpriteBatch一起使用,用来设置渲染字体。

接下来,我们设置MainMenuScreen对象,用来在首次执行时设置參数。

通常的错误是忘记在render()方法中调用super.render()方法,否则Screen类中的create()方法将不会被渲染。

最后,不要忘记消除全部对象!

主菜单

代码例如以下:

package cn.libgdx.drop;

import com.badlogic.gdx.Gdx;

import com.badlogic.gdx.Screen;

import com.badlogic.gdx.graphics.GL20;

import com.badlogic.gdx.graphics.OrthographicCamera;

public class MainMenuScreen implements Screen {

final Drop game;

OrthographicCamera camera;

public MainMenuScreen(final Drop gam) {

game = gam;

camera = new OrthographicCamera();

camera.setToOrtho(false, 800, 480);

}

}

在代码中,我们加入继承自Screen接口的构造方法,Screen接口不提供不论什么create()方法,所以我们使用构造方法。构造方法唯一必须的參数是一个实例化的Drop。接下来是render()方法:

public class MainMenuScreen implements Screen {

@Override

public void render(float delta) {

Gdx.gl.glClearColor(0, 0, 0.2f, 1);

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

camera.update();

game.batch.setProjectionMatrix(camera.combined);

game.batch.begin();

game.font.draw(game.batch, "Welcome to Drop!!! ", 100, 150);

game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);

game.batch.end();

if (Gdx.input.isTouched()) {

game.setScreen(new GameScreen(game));

dispose();

}

}

}

我们调用之前创建的SpriteBatch和BitmapFont。接下来检測屏幕是否被触摸,假设为true则将游戏设置为一个GameScreen实例而且销毁当前实例。

游戏屏幕

接下来我们制作我们的游戏,代码例如以下:

package cn.libgdx.drop;

import java.util.Iterator;

import com.badlogic.gdx.Gdx;

import com.badlogic.gdx.Input.Keys;

import com.badlogic.gdx.Screen;

import com.badlogic.gdx.audio.Music;

import com.badlogic.gdx.audio.Sound;

import com.badlogic.gdx.graphics.GL20;

import com.badlogic.gdx.graphics.OrthographicCamera;

import com.badlogic.gdx.graphics.Texture;

import com.badlogic.gdx.math.MathUtils;

import com.badlogic.gdx.math.Rectangle;

import com.badlogic.gdx.math.Vector3;

import com.badlogic.gdx.utils.Array;

import com.badlogic.gdx.utils.TimeUtils;

public class GameScreen implements Screen {

final Drop game;

Texture dropImage;

Texture bucketImage;

Sound dropSound;

Music rainMusic;

OrthographicCamera camera;

Rectangle bucket;

Array raindrops;

long lastDropTime;

int dropsGathered;

public GameScreen(final Drop gam) {

this.game = gam;

// 加载图片

dropImage = new Texture(Gdx.files.internal("droplet.png"));

bucketImage = new Texture(Gdx.files.internal("bucket.png"));

// 加载音乐

dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));

rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

rainMusic.setLooping(true);

//创建相机和SpriteBatch

camera = new OrthographicCamera();

camera.setToOrtho(false, 800, 480);

// 创建Rectangle

bucket = new Rectangle();

bucket.x = 800 / 2 - 64 / 2;

bucket.y = 20;

bucket.width = 64;

bucket.height = 64;

raindrops = new Array();

spawnRaindrop();

}

private void spawnRaindrop() {

Rectangle raindrop = new Rectangle();

raindrop.x = MathUtils.random(0, 800 - 64);

raindrop.y = 480;

raindrop.width = 64;

raindrop.height = 64;

raindrops.add(raindrop);

lastDropTime = TimeUtils.nanoTime();

}

@Override

public void render(float delta) {

Gdx.gl.glClearColor(0, 0, 0.2f, 1);

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

camera.update();

game.batch.setProjectionMatrix(camera.combined);

game.batch.begin();

game.font.draw(game.batch, "Drops Collected: " + dropsGathered, 0, 480);

game.batch.draw(bucketImage, bucket.x, bucket.y);

for (Rectangle raindrop : raindrops) {

game.batch.draw(dropImage, raindrop.x, raindrop.y);

}

game.batch.end();

if (Gdx.input.isTouched()) {

Vector3 touchPos = new Vector3();

touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);

camera.unproject(touchPos);

bucket.x = touchPos.x - 64 / 2;

}

if (Gdx.input.isKeyPressed(Keys.LEFT))

bucket.x -= 200 * Gdx.graphics.getDeltaTime();

if (Gdx.input.isKeyPressed(Keys.RIGHT))

bucket.x += 200 * Gdx.graphics.getDeltaTime();

if (bucket.x < 0)

bucket.x = 0;

if (bucket.x > 800 - 64)

bucket.x = 800 - 64;

if (TimeUtils.nanoTime() - lastDropTime > 1000000000)

spawnRaindrop();

Iterator iter = raindrops.iterator();

while (iter.hasNext()) {

Rectangle raindrop = iter.next();

raindrop.y -= 200 * Gdx.graphics.getDeltaTime();

if (raindrop.y + 64 < 0)

iter.remove();

if (raindrop.overlaps(bucket)) {

dropsGathered++;

dropSound.play();

iter.remove();

}

}

}

@Override

public void resize(int width, int height) {

}

@Override

public void show() {

rainMusic.play();

}

@Override

public void hide() {

}

@Override

public void pause() {

}

@Override

public void resume() {

}

@Override

public void dispose() {

dropImage.dispose();

bucketImage.dispose();

dropSound.dispose();

rainMusic.dispose();

}

}

这里我们使用了构造方法来取代继承自ApplicationListener的create()方法,传递一个Drop对象。