Extendiendo del juego sencillo - jackgris/wikiLibGDX_es GitHub Wiki
En este tutorial vamos a ampliar el juego simple "Drop", realizado en el tutorial anterior. Vamos a añadir una pantalla de menú, y un par de características que hacen de este juego un poco más completo con otras funciones.
Vamos a empezar con una introducción a algunas clases más avanzadas en nuestro juego.
Las pantallas son fundamentales para cualquier juego con múltiples componentes. Las pantallas contienen muchos de los métodos que se utilizan a partir del objeto ApplicationListener, e incluyen un par de nuevos métodos: show
y hide
, que se llaman cuando la pantalla obtiene o pierde el foco, respectivamente.
La clase abstracta Game proporciona una implementación de ApplicationListener para su uso, junto con algunos métodos de ayuda para configurar y gestionar el dibujo de la pantalla.
Juntos, los objetos Screen y Game crean una estructura simple y de gran alcance para los juegos.
Vamos a empezar con la creación de un objeto Game, que será el punto de entrada a nuestro juego.
Vamos a mostrar algo de código y a recorrer a través de él:
package com.badlogic.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();
//Use LibGDX's default Arial font.
font = new BitmapFont();
this.setScreen(new MainMenuScreen(this));
}
public void render() {
super.render(); //important!
}
public void dispose() {
batch.dispose();
font.dispose();
}
}
Comenzamos la aplicación con las instancias de un SpriteBatch y un BitmapFont. Es una mala práctica crear varios objetos que se pueden compartir en su lugar (ver DRY). El objeto SpriteBatch se utiliza para representar los objetos en la pantalla, como las texturas; y el obteto BitmapFont se utiliza, junto con un SpriteBatch, para representar texto en la pantalla. Tocaremos más sobre esto en las clase Screen.
A continuación, configuramos el Screen de Game a un objeto MainMenuScreen
, con una instancia de Drop como su primer y único parámetro.
Un error común es olvidarse de llamar super.render()
con una implementación de Game. Sin esta llamada, el Screen que se establece en el método create()
no se dibujara!
Por último, otro recordatorio, el limpiar los objetos! Otras lecturas.
Ahora, vamos a entrar en el meollo de la cuestión de la clase MainMenuScreen.
package com.badlogic.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);
}
//...Rest of class omitted for succinctness.
}
En este fragmento de código, hacemos que el constructor de la clase MainMenuScreen
, que implementa la interfaz Screen. La interfaz Screen no proporciona ningún tipo de método create()
, por lo que en su lugar utilizamos un constructor. El único parámetro para el constructor es necesario para este juego es una instancia de Drop
, por lo que podemos pedir sus métodos y campos si es necesario.
A continuación, el método final "meaty" en la clase MainMenuScreen
: render(float)
public class MainMenuScreen implements Screen {
//public MainMenuScreen(final Drop gam)....
@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();
}
}
//Rest of class still omitted...
}
El código aquí es bastante sencillo, excepto por el hecho de que tenemos que llamar a las instancias de SpriteBatch y BitmapFont de juego en lugar de crear una nuestra. game.font.draw(SpriteBatch, String, float, float)
, es cómo es presentado el texto en la pantalla. LibGDX viene con una fuente pre-hecha, Arial, de modo que usted puede utilizarla en el constructor por defecto y aún así obtener una fuente.
Entonces para ver si se ha tocado la pantalla, si es así, entonces comprobamos para ajustar la pantalla de juegos a una instancia de GameScreen, y luego deshacemos la instancia actual de MainMenuScreen. El resto de los métodos que se necesitan para poner en práctica en el MainMenuScreen se deja en blanco, así que voy a seguir omitiendolas (no hay nada que se elimine en esta clase).
Ahora que hemos terminado nuestro menú principal, es el momento para que finalmente lleguemos a hacer nuestro juego. Estaremos levantando la mayor parte del código del juego original como para evitar la redundancia, y no tener que pensar en una idea de juego diferente para implementar la forma más simple de lo que es Drop.
package com.badlogic.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<Rectangle> raindrops;
long lastDropTime;
int dropsGathered;
public GameScreen(final Drop gam) {
this.game = gam;
// load the images for the droplet and the bucket, 64x64 pixels each
dropImage = new Texture(Gdx.files.internal("droplet.png"));
bucketImage = new Texture(Gdx.files.internal("bucket.png"));
// load the drop sound effect and the rain background "music"
dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
rainMusic.setLooping(true);
// create the camera and the SpriteBatch
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
// create a Rectangle to logically represent the bucket
bucket = new Rectangle();
bucket.x = 800 / 2 - 64 / 2; // center the bucket horizontally
bucket.y = 20; // bottom left corner of the bucket is 20 pixels above
// the bottom screen edge
bucket.width = 64;
bucket.height = 64;
// create the raindrops array and spawn the first raindrop
raindrops = new Array<Rectangle>();
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) {
// clear the screen with a dark blue color. The
// arguments to glClearColor are the red, green
// blue and alpha component in the range [0,1]
// of the color to be used to clear the screen.
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// tell the camera to update its matrices.
camera.update();
// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
game.batch.setProjectionMatrix(camera.combined);
// begin a new batch and draw the bucket and
// all drops
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();
// process user input
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();
// make sure the bucket stays within the screen bounds
if (bucket.x < 0)
bucket.x = 0;
if (bucket.x > 800 - 64)
bucket.x = 800 - 64;
// check if we need to create a new raindrop
if (TimeUtils.nanoTime() - lastDropTime > 1000000000)
spawnRaindrop();
// move the raindrops, remove any that are beneath the bottom edge of
// the screen or that hit the bucket. In the later case we increase the
// value our drops counter and add a sound effect.
Iterator<Rectangle> 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() {
// start the playback of the background music
// when the screen is shown
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();
}
}
Este código es casi el 95% igual que al de la aplicación original, excepto que ahora se utiliza un constructor en lugar de el método create()
de ApplicationListener
, y pase un objeto Drop
, como en la clase MainMenuScreen
. También empezamos a reproducir la música tan pronto como la pantalla se ajusta a GameScreen
.
También hemos añadido un string en la esquina superior izquierda del juego, que hace un seguimiento de la cantidad de gotas de lluvia recogidas.
Eso es todo, usted tiene el juego completo terminado. Eso es todo lo que hay que saber acerca de la interfaz Screen y de la clase abstracta Game, y todo lo que hay para la creación de juegos con múltiples facetas y estados.
Para obtener el código completo, visite est git de Github
Ahora que usted tiene una comprensión de lo que son múltiples pantallas, es el momento de aprovechar la oportunidad. Aprenda sobre Scene2d, Scene2D.ui y Skins para hacer su menú principal mas hermoso, y tal vez añadir explosiones en el juego de las gotas, por el realismo, por supuesto.
Si también ha leído los pasos siguientes del tutorial anterior de Drop, usted debe estar listo para hacer su propio juego. Lo más recomendable es salir y hacerlo, así que vayan y hagan la próxima gran cosa!
- Indice
- Sección anterior: Un juego sencillo
- Siguiente sección: Manejo de archivos