5.1、雨滴游戏的扩展
在本教程中我们将对雨滴游戏进行扩展。我们将尝试添加一个菜单和其他的一些功能。
(前一篇文章:点击进入)
** 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对象。
我们添加了一个Sring用来显示收集的雨滴。
(www.libgdx.cn版权所有,如需转载,注明出处)