Como sabemos, em todos os jogos as telas de menu são muito importantes, pois ajudam na orientação e facilidade na hora de jogar ou escolher uma outra opção.
No nosso jogo(criado no tutorial anterior) não é diferente.
Neste tutorial iremos adicionar uma tela de menu ao nosso jogo, e para isso precisaremos do projeto do jogo criado no tutorial anterior.
Antes de começarmos, será preciso criar 2 interfaces dentro do package com.badlogic.drop com os nomes: MainMenuScreen, GameScreen.
Feito isso, vamos para o código.
A classe mais abstrata do jogo fornece uma implementação de AplicationListener juntamente com alguns outros métodos para lidar com o processamento de tela, sendo que tela e jogo são objetos que juntos formam uma estrutura simples mas precisa.Agora vamos começar com a criação d u jogo de objeto, que será o ponto de entrada para o nosso jogo.
O seguinte código deve ficar em Drop.java:
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(); //A fonte usada será Arial(padrão da LibGDX) font = new BitmapFont();
this.setScreen(new MainMenuScreen(this)); } public void render() { super.render();
}
public void dispose() { batch.dispose(); font.dispose(); } }Um erro comum é esquecer de chamar
super.render()
com uma implementação do jogo. Sem esta chamada, a tela que você definir no método create()
não será processada.No código acima, a linha this.setScreen(new MainMenuScreen(this)); tem a função de chamar para dentro do corpo do código a interface MainMenuScreen que será vista a seguir.
O código a seguir deve ficar em MainMenuScreen.java:
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); } //...resto do código após explicação... }Neste trecho de código, nós fazemos o construtor para a classe
MainMenuScreen
, que implementa a interface de tela. A interface de tela não fornece nenhum tipo do método create()
, por isso, criamos um construtor. O único parâmetro usado para o construtor neste jogo é a instância Drop
, de modo que podemos invocar seus métodos e campos dentro do código do jogo em Drop.java como dito mais acima.public class MainMenuScreen implements Screen { //public class MainMenuScreen.... @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(); } } //código completo após a explicação...
}Precisamos chamar instâncias SpriteBatch e BitmapFont, para que o texto seja inicializado e depois impresso na tela, onde
game.font.draw(SpriteBatch, String, float,float)
, representa a forma como o texto é renderizado na tela. A LibGDX vem com uma fonte pré-fabricada(Arial), de modo que você pode utilizar o construtor padrão e ainda utilizar sua fonte.OBS:
if (Gdx.input.isTouched()) { game.setScreen(new GameScreen(game)); dispose();As linhas acima irão verificar se houve alguma ação do mouse sobre a tela do jogo e se houver, a interface GameScreen será chamada e iniciará o jogo.
Código completo MainMenuScreen.java:
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); } @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(); } } @Override public void resize(int width, int height) { } @Override public void show() { } @Override public void hide() { } @Override public void pause() { } @Override public void resume() { } @Override public void dispose() { } }
Agora vamos para a interface GameScreen.
Agora que temos o nosso menu principal já pronto, é hora de começar a fazer o jogo.
Estaremos levantando a maior parte do código do jogo original , para evitar ter que pensar em uma ideia de jogo diferente para implementar.
O código abaixo deve ficar em GameScreen.java:
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; //carregamento das imagens do balde e da gota dropImage = new Texture(Gdx.files.internal("droplet.png")); bucketImage = new Texture(Gdx.files.internal("bucket.png")); //carregamento dos efeitos sonoros da chuva e dos pingos dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav")); rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3")); rainMusic.setLooping(true); //cria a camera de visão do jogador e o sprite batch camera = new OrthographicCamera(); camera.setToOrtho(false, 800, 480); //aqui é criado o "retangulo" onde o sprite do balde ficará localizado bucket = new Rectangle(); bucket.x = 800 / 2 - 64 / 2; //aqui o balde é colocado centralizado na horizontal bucket.y = 20; //aqui defini-se a posição do balde sendo no canto inferior //da tela 20 pixels acima da borda. bucket.width = 64; bucket.height = 64; //aqui é criada a matriz que irá gerar os pingos de chuva 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) { //Limpa a tela com um azul escuro. // Os argumentos para glClearColor sâo vermelho , verde // azul e o componente alpha na posição [0,1] // da cor a ser usada para limpar a tela. Gdx.gl.glClearColor(0, 0, 0.2f, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // aqui o programa diz a camera para atualizar suas // matrizes. camera.update(); //aqui o spritebatch recebe ordens para renderizar no // sistema nas coordenadas definidas pela camera. game.batch.setProjectionMatrix(camera.combined); //aqui o balde e as gotas são desenhados novamente game.batch.begin(); game.font.draw(game.batch, "Drops Collected: " + dropsGathered, 0, 480); game.batch.draw(bucketImage, bucket.x, bucket.y, bucket.width, bucket.height); for (Rectangle raindrop : raindrops) { game.batch.draw(dropImage, raindrop.x, raindrop.y); } game.batch.end(); //processo de entrada por parte do usuário através // do mouse ou teclado(setas). 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(); //aqui o programa se certifica de que o balde está // dentro dos limites da tela. if (bucket.x < 0) bucket.x = 0; if (bucket.x > 800 - 64) bucket.x = 800 - 64; //aqui é verificado se é necessário criar novos pingos // de chuva. if (TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop(); //aqui são movidas as gotas de chuva, removendo as que estão abaixo // da borda inferior da tela ou as que atingiram o balde, na qual // será executado um efeito sonoro caso atinja o balde. 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() { //iniciar a reprodução da música de //fundo assim que a tela é mostrada 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(); }// aqui todos os recursos usados serão descartados após // seu uso. }
O código acima é quase idêntico ao original, exceto pelo fato de que agora usamos um construtor em vez do método
create()
do ApplicationListener
, e transformamos Drop em um
objeto, como feito na MainMenuScreen
. Nós também começamos a tocar a música assim que a tela é definida para GameScreen
, além de colocar uma string para contar a quantidade de gotas coletadas, localizada no canto superior esquerdo da tela.
Após a conclusão, seu jogo deve ficar mais ou menos assim:
É isso, agora você tem o jogo completo terminado, e aqui acaba o tutorial .
Bom trabalho!
REFERÊNCIAS:
- GITHUB: Extending the simple game. Extending the simple game. 2016. Disponível em: <https://github.com/libgdx/libgdx/wiki/Extending-the-simple-game>. Acesso em: 23 set. 2016.
- GITHUB: A simple game. A simple game. 2016. Disponível em: <https://github.com/libgdx/libgdx/wiki/A-simple-game>. Acesso em: 23 set. 2016.
- SANTOS, Bruno. Gpjecc: TUTORIAL MY SIMPLE GAME LIBGDX. 2016. Disponível em: <https://gpjecc.blogspot.com/b/post-preview?token=bRwgWlcBAAA.vOB-Xwz8MROwQNIgXAAmTwbhc0rti45PqyWik83FR-pjmdRW_6mH5D9-DtDwCfGzfp2FnEczOFRr8bdqoOmsXw.fdQx1bxA2q0vG1gUwM7IuA&postId=8945204288171025357&type=POST>. Acesso em: 23 set. 2016.
- STACK Overflow: the import com.badlogic.gdx.graphics.gl10 cannot be resolved. the import com.badlogic.gdx.graphics.gl10 cannot be resolved. 2016. Disponível em: <http://stackoverflow.com/questions/23691868/the-import-com-badlogic-gdx-graphics-gl10-cannot-be-resolved>. Acesso em: 28 set. 2016.
1 Comentários
Galera, se vocês quiserem aprender a utilizar fontes com efeitos no LibGDX vocês podem seguir este tutorial https://www.programandojogosandroid.top/como-mostrar-texto-limpo-sem-borroes-com-efeito-stroke-libgdx
ResponderExcluir