jueves, 14 de abril de 2016

Tutorial 8: Manejo de Pantallas

Hola buenas.
Es de mi agrado informarle que solo faltan dos tutoriales(incluyendo este), para el gran proyecto del blog. Es correcto haremos un juego completo xD

El presente tutorial tratare de explicar cómo interactuan las diferentes pantallas de nuestros juegos.
Por ejemplo:

  1. El juego inicia y presenta la pantalla del logo(SplashScreen).
  2. Luego se presenta la pantalla principal(MainScreen o MenuScreen).
  3. Dependiendo de la acción del jugador, puede dirigirse a otras pantallas, para nuestro ejemplo el usuario presiona jugar y se carga la pantalla del juego(GameScreen).
  4. Estando en la pantalla del juego pueden suceder que perdamos(GameoverScreen) o pausemos nuestro juego(PauseScreen).
En los numerales anteriores hemos visto más o menos como fluyen las iteraciones entre las pantallas.


El diagrama anterior ejemplifica la iteraciones del ejemplo que narre.
Después de un poco de teoriza vamos a nuestro amado libgdx.
Estrategia: Nuestro ejemplo tendrá dos pantallas, la primera que indicara que presionando sobre la pantalla, nos llevará a la segunda pantalla. Estando en la segunda pantalla un mensaje nos indicara que presionando sobre la pantalla, nos llevara a la pantalla anterior. Una vez estemos de vuelta en la pantalla primera, cambiara el mensaje y dirá que si presionamos en la pantalla el programa cerra.

Preparamos nuestro proyecto:

Importamos nuestro proyecto. Y nos dirigimos a la clase: "Tuto6",y hacemos:

package sv.chuckles.tuto6;

import com.badlogic.gdx.Game;

public class Tuto6 extends Game {

@Override
public void create() {
setScreen(new GameScreen(this));
}
}

Limpiamos nuestra clase y extendemos de la clase Game, la cual nos pedirá, implementar un método llamado create. Libgdx nos proporciona esta clase, para controlar las pantallas, aqui lo importante es la setScreeen, la cual iremos poniendo la pantalla que se ira presentando.
Para este caso estamos creando la pantalla GameScreen.

La clase GameScreen es implementada de la clase Screeen:

package sv.chuckles.tuto6;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class GameScreen implements Screen{
private Tuto6 game;
private BitmapFont bitmapFont;
private SpriteBatch batch;
private String texto;
private boolean isRetorno;
public GameScreen(Tuto6 game){
this.game = game;
batch = new SpriteBatch();
bitmapFont = new BitmapFont();
isRetorno = false;
}

@Override
public void show() {
bitmapFont.setColor(Color.GOLD);
if(!isRetorno)
texto = "Presione sobre la pantalla";
else
texto = "Presione sobre la pantalla, para salir";
}

@Override
public void render(float delta) {
Gdx.gl.glClearColor(0.4f, 0.4f, 0.4f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
bitmapFont.draw(batch, 
"Pantalla: GameScreen\n"+texto, 
Gdx.graphics.getWidth()/2-90, 
Gdx.graphics.getHeight()/2+50);
batch.end();
if(Gdx.input.justTouched()){
if(!isRetorno){
game.setScreen(new SecondScreen(game,this));
isRetorno = true;
}else
Gdx.app.exit();
}
}

@Override
public void resize(int width, int height) {
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public void hide() {
if(isRetorno)
dispose();
}

@Override
public void dispose() {
Gdx.app.log("GameScreen", "Entra al dispose");
batch.dispose();
bitmapFont.dispose();
}
}
Explicacion: 
  • En el constructor GameScreen, recibimos de parámetro la clase que hereda de Game, esta clase hay que llevarla por todas las pantallas, puesto es el que controla que pantalla esta ejecutándose.
  • Hemos creado BitmapFont bitmapFont, para pintar mensajes en nuestras pantallas, con esta clase podemos escribir nuestros mensajes con Font, que podemos diseñar o descargar; para efectos de pruebas, vamos a utilizar el default.
  • He creado una variable tipo boolean isRetorno, para controlar si ya fue visitada la segunda pantalla.
  • Después del create, se ejecuta el show, y luego el render. En el método render, escribimos el mensaje: "Pantalla: GameScreen\nPresione sobre la pantalla" y luego observamos que se espera que solo se presione sobre la pantalla. Si cumple con la condición primera hacemos uso otra vez del setScreeen, veremos que en el constructor de la segunda pantalla, se envia otro parametro(this), este parametro es la GameScreen.
La segunda escena es igual que la GameScreen, a difetencia que en el render solo esta: game.setScreen(gameScreen):
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
bitmapFont.draw(batch, 
"Pantalla: SecondScreen\nPresione sobre la pantalla,\npara regresar a la pantalla anterior", 
Gdx.graphics.getWidth()/2-90, 
Gdx.graphics.getHeight()/2+50);
batch.end();
if(Gdx.input.justTouched()){
game.setScreen(gameScreen);
}
}

Ya podemos ejecutar nuestro proyecto, tanto en el proyecto de android o el del escritorio.
Ejecutando en sub proyecto Desktop:


Al presionar en la pantalla, nos llevara a la segunda pantalla:

Si volvemos a presionar sobre la pantalla, nos llevara a la primera pantalla, esto es una forma de implementar la acción de Pausa en nuestros juegos.

Listo, ya podemos interactuar con muchas pantallas, según sean nuestras necesidades.
Un Saludo

Si te gusta mi trabajo y quisieras ver mas y mas rápido, puedes donar $1.00 vía donación paypal:




lunes, 11 de abril de 2016

Nuestro Primer Juego para Android

Hola buenas.
Este post lo he escrito con la intensión de compartirles un poco nuestra experiencia en el diseño y desarrollo de nuestro primer juego para android al estilo de Aero Fighters
Lo llamamos Panic Invasion, por votación a personas allegadas.
El juego consta de scroll vertical, y auto disparo. Con el control, se puede poner el dedo sobre cualquier punto de la pantalla y la nave se moverá en el sentido que arrastremos nuestro dedo.
Después de alcanzar el final de la escena, se presentara un enemigo mas grande a vencer(boss), como es típico en estos juegos. Ademas consta de 6 niveles a superar y algunos efectos de sistemas de partículas.

Screenshots:




Aqui esta la app: Panic Invasion

Objetivo:
Nuestro principal objetivo era terminar un juego completo, 100% funcional. Y dejar a un lado las pruebas de conceptos(Hacer tutoriales y ejemplos). 

Un problema grande que nos encontramos fue, que no poseemos algún diseñador para realizar artes.
Tuvimos que buscar artes gratis y descargar casi todo lo que veíamos, este fue nuestro repositorio http://opengameart.org/ 

Otro problema fue el rendimiento del juego en el dispositivo real. Esto pasaba porque cada vez que aparecía un enemigo, este era cargado en ese momento. Lo cual implicaba que el juego fuera al disco y luego cargara las texturas en la memoria del dispositivo. Pidiendo ayuda en los foros http://www.badlogicgames.com/forum/, la solución fue simple: Cargar todos los assets al inicio del juego o escena.

Luego de haber recorrido las tres faces del desarrollo de juego(Pre producción, Producción y Post producción), concluyo, que la etapa mas subestimada es la pre producción(etapa donde se planea todo el juego) y la mas difícil es la post producción(etapa de comercialización de nuestro juego).

Cloclusión:
El desarrollo de videojuegos es difícil y mas difícil es hacer buenos juegos. Aquí lo importante es la perseverancia y querer sacar un juego del cual estar orgullosos.

En pleno año 2016, existen muchas comunidades que ayudan a programadores/diseñadores que recién comienzan sus aventuras, así que animo y adelante.

Juego en google play: Panic Invasion

Sígueme en Twiter: https://twitter.com/libgdxESA

Un saludo








martes, 5 de abril de 2016

Tutorial 7.5: Tomando un Screenshot

Hola buenas.
Les quería compartir como obtener un Screenshot, es muy fácil.
Este es un agregado al tutorial anterior Tutorial 7, agregaremos un bloque de código para tomar nuestra foto en el método "longPress"; este método funciona teniendo presionado sobre la pantalla el puntero del ratón o el dedo en nuestro dispositivo.
Agregamos el siguiente bloque de instrucciones en el método longPress:

Gdx.app.log("longPress", "Screenshot inicia proceso"); byte[] pixels = ScreenUtils.getFrameBufferPixels(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight(), true); Pixmap pixmap = new Pixmap(Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight(), Pixmap.Format.RGBA8888); BufferUtils.copy(pixels, 0, pixmap.getPixels(), pixels.length); PixmapIO.writePNG(Gdx.files.external("miPantallazo.png"), pixmap); pixmap.dispose(); Gdx.input.vibrate(1000); Gdx.app.log("longPress", "Screenshot tomada");

Bueno no hay mucho que decir, lo importante es que escribe una imagen en formato PNG, ya sea en nuestro home, carpeta personal(c:/users/miPersona), en la raiz de nuestra SD si estamos en dispositivo mobil.

Para que funcione en nuestro sub proyecto de antroid, debemos de ingresar los permisos, para escritura de archivos y permisos de vibración.

Abrimos el archivo: AndroidManifest.xml
Y agregamos:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.VIBRATE"/>

Listo, ya podemos probar nuestra toma de pantalla, tanto en el proyecto desktop y android

Sígueme en Twiter: https://twitter.com/libgdxESA

Un Saludo

Si te gusta mi trabajo y quisieras ver mas y mas rápido, puedes donar $1.00 vía donación paypal:

lunes, 4 de abril de 2016

Tutorial 7: Cámara y Gestos

Hola buenas.
En el presente tutorial, veremos como manipular un poco la cámara y unos conceptos de captura de gestos.
Es sabido que en los diversos juegos, existe un objeto fundamental, este objeto es la cámara, la cual se encarga de observar en un recuadro llamado vista, que elementos existen en ella.
En nuestro caso la cámara tiene varias propiedades:

  1. Mover y rotar la cámara en nuestras escenas.
  2. Hacer zoom in o zoom out(acercar o alejar los elementos de nuestro escena).
  3. Cambiar las relaciones de aspectos.
Aquí esta la documentación: Camara
También veremos la interfaz GestureListener, para detectar que gestos estamos haciendo en la pantalla.
Para nuestro caso de estudio, utilizaremos la funcion de "pan", la cual lee los estados cuando un dedo en la pantalla es esta siendo arrastrado. Excelente para hacer los desplazamientos entre escenas grandes. En adicion la funcion "fling" es perfecto para hacer el Swipe.

Estrategia:
Utilizaremos una imagen de 2048x1152, y nuestra pantalla tendrá 800x400, es esta pantalla centraremos la imagen, para poder visualizarla solo ese segmento. 

Luego por medio del  arrastre del mouse/dedo, desplazaremos la camera en ese sentido.
Manos a la obra:
Para comenzar, creamos nuestro proyecto, así:
Importamos en eclipse, la imagen que utilizaremos es: dbs_2048x1152.jpg, esta se debe colocar en la carpeta de assets del proyecto de android, y borrar la otra que se encuentra ahí.
Nuestro código quedaría así:
Clase Tuto5:
package sv.chuckles.tuto5;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Vector2;

public class Tuto5 extends ApplicationAdapter implements GestureListener {
SpriteBatch batch;
Sprite sprite;
OrthographicCamera camera;
@Override
public void create () {
batch = new SpriteBatch();
sprite = new Sprite(new Texture("dbs_2048x1152.jpg"));
sprite.setPosition(-sprite.getWidth()/2,-sprite.getHeight()/2);
camera = new OrthographicCamera(800, 400);
Gdx.input.setInputProcessor(new GestureDetector(this));
}

@Override
public void render () {
camera.update();
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
   
batch.setProjectionMatrix(camera.combined);
batch.begin();
sprite.draw(batch);
batch.end();
if (Gdx.input.isKeyPressed(Input.Keys.A)) {
camera.zoom += 0.02;
        }
if (Gdx.input.isKeyPressed(Input.Keys.Q)) {
camera.zoom -= 0.02;
        }
}
@Override
public void dispose() {
batch.dispose();
}

@Override
public boolean touchDown(float x, float y, int pointer, int button) {
return false;
}

@Override
public boolean tap(float x, float y, int count, int button) {
return false;
}

@Override
public boolean longPress(float x, float y) {
return false;
}

@Override
public boolean fling(float velocityX, float velocityY, int button) {
return false;
}

@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
camera.translate(-deltaX,deltaY);
return false;
}

@Override
public boolean panStop(float x, float y, int pointer, int button) {
return false;
}

@Override
public boolean zoom(float initialDistance, float distance) {
return false;
}

@Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
return false;
}
}

Explicación:
  • Linea 15: ahí esta la implementacion de la interfaz "GestureListener", que nos ayuda a capturar los gestos. Cuando se implementa, a la clase se le agregan los métodos sobrescritos: touchDown, tap, longPress, fling, pan, panStop, zoom y pinch.
  • Linea 18: Creamos la variable camera.
  • Linea 26: Instanciamos el objeto camera y pasamos de parametro 800x400 que tendra de vista nuestra ventana.
  • Linea 28: Esta instrucción es muy importante, es aquí donde se le dice a LibGdx que nuestra clase implementada es la que se utilizara para la lectura de los gestos. Si somos observadores vemos que la clase GestureDetector recibe de parámetro "this", que no es nada mas que nuestra clase implementada.
  • Linea 33: Esta instrucción actualiza la vista de la cámara, es decir actualiza las coordenadas para pintarlas en nuestra ventana.
  • Linea 37: Esta instrucción convierte las coordenadas de la cámara a coordenadas naturales para el batch, porque esto, es donde escalamos las pantallas, por ejemplo nuestra escena es de 1024x768, pero nuestra ventana tiene 800x400. Entonces con esto la resolución alta se ajusta a la pequeña.
  • Linea 42 a la 47: Si presionamos la tecla A, hará un zoom in y la tecla Q, hará un zoom out, esto solo funciona en el proyecto de Desktop.
  • Linea 77: la instrucción translate, mueve la cámara, después de la acción del pan.
Ya puedes probar vía Desktop y con tu dispositivo mobil xD

Espero que les ayude y un saludo.


Sígueme en Twiter: https://twitter.com/libgdxESA

Si te gusta mi trabajo y quisieras ver mas y mas rápido, puedes donar $1.00 vía donación paypal: