jueves, 16 de marzo de 2017

SpaceInvaderClon - Paso 2

SpaceInvaderClon - Paso 2

Hola buenas, 
Seguiremos en nuestro afán xD
En esta ocasión, haremos que nuestro nave espacial, se mueva, y dispare xD
Tanto para nuestro Escritorio(por medio de las flechas cursoras) y Android(por medio del acelerómetro).
Tambien cambiare un poco la metodología, porque creo que se entiende más ver el código fuentes, que tratar de explicar en texto xD
Si tienen alguna duda, pueden dejarla en los comentarios, inclusive puedo hacer otro post mas explicativo de los puntos que no entiendan.
Mano a la obra. Comencemos con la clase Asset, por el momento solo tendrá los nombre de nuestros sprites:
package sv.com.chuckle.game.spaceinvaderclon.utils;

public class Asset {
    public static String nombSpriteHero = "Starfighter.png";
    public static String nombSpriteMisil = "missile.png";
    public static String nombSpriteAlien = "alien.png";

}

En este momento, vamos a utilizar un patrón de diseño que LibGdx no proporciona. Es sencillo y muy útil. Es crear un Escenario y este contiene Actores, los cuales actúan es nuestro Escenario, esto es representado:
Stage stage = new Stage();
Actor hero = new Actor();
stage.addActor(hero);
Ya en nuestro render, llamar:
stage.act();
stage.draw();
Claro, falta la parte donde el hero, debe de tener su actuacion, el metodo act() llama a todos los act de todos los actores.
Entonces creamos la clase GameObject que extiende de la clase Image(esta clase extiende de Actor), y va hacer nuestro clase común, donde se crearán nuestros Sprites, aquí lo importante está la clase Rectangle que es una clase geométrica, la cual no es pintada en la pantalla, pero si funciona a nivel lógico, y la cual será utilizada para ver si está sobrepuesta sobre otro rectángulo, osea las COLISIONES. Este rectángulo tiene las dimensiones de la imagen del sprite y se moverá en las mismas coordenadas que el sprite.
package sv.com.chuckle.game.spaceinvaderclon.utils;

import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.scenes.scene2d.ui.Image;

public class GameObject extends Image {
    private Rectangle rectangle;

    public GameObject(String nombTexture,float x,float y){
        super(new Texture(nombTexture));
        rectangle = new Rectangle(x,y,getWidth(),getHeight());
        setPosition(x,y);
    }

    @Override    public void act(float delta) {
        super.act(delta);
        rectangle.setPosition(getX(),getY());
    }

    public Rectangle getRectangle() {
        return rectangle;
    }
}
Crearemos la clase misil:
package sv.com.chuckle.game.spaceinvaderclon.entidad;

import sv.com.chuckle.game.spaceinvaderclon.utils.Asset;
import sv.com.chuckle.game.spaceinvaderclon.utils.GameObject;
import sv.com.chuckle.game.spaceinvaderclon.utils.Utils;

public class Misil extends GameObject{
    private float vel;

    public Misil(float x, float y){
        super(Asset.nombSpriteMisil,x,y);
        vel = 300;
    }

    @Override    public void act(float delta) {
        super.act(delta);
        moveBy(0,vel*delta);

        if(getY() > Utils.ALTO)
            remove();

    }
}
Observaciones: una variable flotante vel, esta variable representa la velocidad del misil. En el método ¨act¨, vemos el método moveBy, esta acción suma un desplazamiento en x e y, si observamos en x no se moverá, solo en y; esto moverá de forma vertical el sprite, por un corto desplazamiento, pero el método act esta en nuestro render, así que se está ejecutando cada momento, así que da la impresión que es un movimiento fluido. Luego observamos que se pregunta si la posición de Y es mayor que nuestro ALTO, si es así, removemos nuestro actor de la escena, esto hace que se libere memoria.

Creamos la clase Alien, pero por el momento solo aparecera pintada en nuestra pantalla.

Continuas creando la clase Hero, aqui esta la carnita de este tutorial:
package sv.com.chuckle.game.spaceinvaderclon.entidad;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.utils.TimeUtils;

import sv.com.chuckle.game.spaceinvaderclon.utils.Asset;
import sv.com.chuckle.game.spaceinvaderclon.utils.GameObject;
import sv.com.chuckle.game.spaceinvaderclon.utils.Utils;


public class Hero extends GameObject{
    private float x;
    private float vel = 250f;
    private ESTADO estado;
    private long lastFire;

    enum ESTADO{
        nada        ,derecha        ,izquierda    }

    public Hero(float x, float y) {
        super(Asset.nombSpriteHero, x, y);
    }

    @Override    public void act(float delta) {
        super.act(delta);

        if(Gdx.input.isTouched()){
            if(TimeUtils.millis() - lastFire >= 300){
                Misil misil = new Misil(getX()+getWidth()/2-10, getY()+getHeight());
                getStage().addActor(misil);
                lastFire = TimeUtils.millis();
            }
        }

        Application.ApplicationType appType = Gdx.app.getType();
        switch (appType){
            case Desktop:
                if(Gdx.input.isKeyPressed(Input.Keys.LEFT))
                    estado = ESTADO.izquierda;
                else if(Gdx.input.isKeyPressed(Keys.RIGHT))
                    estado = ESTADO.derecha;
                else                    estado = ESTADO.nada;
                break;
            case Android:
                if(Gdx.input.getAccelerometerX() < 0)
                    estado = ESTADO.derecha;
                else if(Gdx.input.getAccelerometerX() > 0)
                    estado = ESTADO.izquierda;
                else                    estado = ESTADO.nada;
                break;
        }//fin switch
        x = getX();
        if(estado == ESTADO.derecha)
            x += delta*vel;
        if(estado == ESTADO.izquierda)
            x -= delta*vel;

        if(x<=0)
            x = 0;
        else if(x>= Utils.ANCHO-getWidth())
            x = Utils.ANCHO-getWidth();

        setPosition(x, 0);
    }
}
Observaciones: Esta parte se las dejo a ustedes que descifren que quiero decir xD.
Quiza lo unico que les puedo ayudar, es TimeUtils.millis(), con la cual obtenemos el tiempo transcurrido en milisegundos, entonces aquí estamos dando 300 milisegundos para que aparezca otro disparo.

Luego, reescribimos la clase GameScreen, la cual se debe de implementar de Screen. Ver código fuente.

Por último reescribimos la clase GameLoop:
package sv.com.chuckle.game.spaceinvaderclon;

import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;

import sv.com.chuckle.game.spaceinvaderclon.screen.MainScreen;
import sv.com.chuckle.game.spaceinvaderclon.utils.Asset;

public class GameLoop extends Game {

   public GameLoop(){

   }

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

   @Override   public void render() {
      getScreen().render(Gdx.graphics.getDeltaTime());
   }
}
Observaciones: Aqui lo importanet es el setScreen xD
Resultado:


Codigo fuente aqui

Si te gusta mi trabajo y crees que vale la pena que sigamos aprendiendo, pues dona un dólar
para esta buena causa xD

lunes, 27 de febrero de 2017

SpaceInvaderClon - Paso 1

SpaceInvaderClon - Paso 1

Hola buenas, 
Seguimos en nuestro afán, de nuestro primer juego. Aquí puedes ver la parte previa PASO 0
En este paso 1, vamos a crear la lógica entre pantalla, así seguimos avanzando.
Primero creamos la clase Utils y creamos el paquete: sv.com.chuckle.game.spaceinvaderclon.utils
Código clase Utils:
package sv.com.chuckle.game.spaceinvaderclon.utils;

import com.badlogic.gdx.Gdx;

public class Utils {
    public static int ANCHO = 480;
    public static int ALTO = 650;
    public static boolean IS_DEBUG = true;

    public static void log(String tag,String message){
        if(IS_DEBUG)
            Gdx.app.log(tag, message);
    }
}

En esta clase, hemos definido de forma estática, el ancho y alto de nuestra pantalla.
Los valores 480x650, hacen referencia una pantalla en vertical(Portrait). También hemos 
definido una variable tipo booleana llamada "IS_DEBUG", la cual será nuestra bandera 
si deseamos escribir en la consola y para dibujar los elementos geométricos, para las 
colisiones.


Modificar pantalla Desktop y Android
Para ello primero nos dirigiremos a la clase DesktopLauncher, de nuestro subproyecto 
"desktop", aqui agregamos las definiciones del ANCHO y ALTO, de la clase Utils, asi:

package sv.com.chuckle.game.spaceinvaderclon.desktop;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import sv.com.chuckle.game.spaceinvaderclon.GameLoop;
import sv.com.chuckle.game.spaceinvaderclon.utils.Utils;

public class DesktopLauncher {
   public static void main (String[] arg) {
      LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
      config.width = Utils.ANCHO;
      config.height = Utils.ALTO;
      config.resizable =  false;
      config.title = "Space Invader - CLON";
      new LwjglApplication(new GameLoop(), config);
   }
}
Creo que se entiende que se está haciendo.

Luego vamos por el archivo de configuración de android el AndroidManifest.xml 
del subproyecto "android' y cambiaremos la linea donde se encuentre la etiqueta:
android:screenOrientation, por esto: android:screenOrientation="portrait"


Crear las Pantallas
Para esto creamos el paquete: 
sv.com.chuckle.game.spaceinvaderclon.screen
Y creamos tres clases llamadas: MainScreen, GameScreen y GameOverScreen.
Estas clases deben de implementarse con la interfaz llamada: Screen
Y su constructor debe de recibir como parámetro el objeto GameLoop, que es el que extiéndete de Game(Este controla nuestro juego).
Clase MainScreen:
package sv.com.chuckle.game.spaceinvaderclon.screen;

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

import sv.com.chuckle.game.spaceinvaderclon.GameLoop;
import sv.com.chuckle.game.spaceinvaderclon.utils.Utils;

public class MainScreen implements Screen{
    private GameLoop game;
    private BitmapFont font;
    private Batch batch;

    public MainScreen(GameLoop game){
        this.game = game;
        font = new BitmapFont();
        batch = new SpriteBatch();
    }

    @Override    public void show() {

    }

    @Override    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 0);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if(Gdx.input.justTouched())
            game.setScreen(new GameScreen(game));
        batch.begin();
        font.draw(batch, "SPACE INVADER", Utils.ANCHO/2-60, Utils.ALTO/2+100);
        font.draw(batch, "Presione sobre la pantalla para iniciar el juego", Utils.ANCHO/2-150, Utils.ALTO/2+50);
        batch.end();

    }

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

    }

    @Override    public void pause() {

    }

    @Override    public void resume() {

    }

    @Override    public void hide() {

    }

    @Override    public void dispose() {
        font.dispose();
        batch.dispose();
    }
}

Las otras dos clases son iguales, solo cambian las posiciones del texto.
Clase GameScreen:
@Overridepublic void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    if(Gdx.input.justTouched())
        game.setScreen(new GameOverScreeen(game));
    batch.begin();
    font.draw(batch, "Pantalla De Juego", Utils.ANCHO/2-50, Utils.ALTO/2+100);
    font.draw(batch, "Presione sobre la pantalla para continuar", Utils.ANCHO/2-120, Utils.ALTO/2+50);
    batch.end();

}

Clase GameOverScreen:
@Overridepublic void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0, 0);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    if(Gdx.input.justTouched())
        game.setScreen(new GameScreen(game));
    batch.begin();
    font.draw(batch, "GAME OVER", Utils.ANCHO/2-50, Utils.ALTO/2+100);
    font.draw(batch, "Presione sobre la pantalla para iniciar el juego", Utils.ANCHO/2-150, Utils.ALTO/2+50);
    batch.end();

}
Para fines prácticos, el flujo por el momento es:
MainScreen->GameScreen<->GameOverScreen

Paso Final:
Para nuestro final, solo falta modificar la clase GameLoop, para que sea esta la que controle todo nuestro juego. Para ello limpiamos toda la clase y la extendemos de Game, asi:
package sv.com.chuckle.game.spaceinvaderclon;

import com.badlogic.gdx.Game;

import sv.com.chuckle.game.spaceinvaderclon.screen.MainScreen;

public class GameLoop extends Game {

   @Override   public void create() {
      setScreen(new MainScreen(this));
   }
}
Como Game, tiene la capacidad de poner que pantalla esté activa, de esta forma al iniciar
nuestro juego, la pantalla por defecto será la MainScreen.
Ya podemos ejecutar nuestro subproyectos, y veran como nos quedó.
Aquí el resultado:


Como vemos es super sencillo hacer este juego de pantallas.
Para nuestra próxima entrega,  ya pintaremos nuestra nava y haremos que se mueva y dispare xD

Codigo fuente aqui.

Saludos

Si te gusta mi trabajo y crees que vale la pena que sigamos aprendiendo, pues dona un dólar
para esta buena causa xD

domingo, 26 de febrero de 2017

SpaceInvaderClon - Paso 0

Hola Buenas.

Ahora comenzamos con nuestro primer juego pedagógico.

Claraciones:

  • He tenido varios problemas con la versión más reciente del LibGDX(1.9.5). Sospecho que es por que hace más de 4 años que tengo instalado el SDK de android. He hecho varias pruebas si casi siempre me falla cuando quiero trabajar con la librería Box2D. Pero he logrado hacer funcionar todo con la última versión de LigGDX 1.9.5 y Android Studio 2.23, así que para este proyecto utilizaremos estas versiones.
  • Los artes las buscaremos en http://opengameart.org/

Manos a la Obra:

Como ya hemos dicho antes, descargamos la versión 1.9.5 de LibGDX aquí, en teoría con esta versiones podemos modificar que version de LibGDX queremos utilizar, guia aqui.
Por cualquier cosa también podemos descargar versiones más viejas aquí.
Una vez tengamos descargado, descomprimimos estos archivos en algun de fácil acceso, de preferencia en la raíz o home, por ejemplo C:/(si estamos en Windows).

Siguiente paso, descargar los assets, para hecho nos vamos a la pagina http://opengameart.org/,
para efectos prácticos ya los tengo listo, puedes cargarlo de aquí
Recomiendo encarecidamente tener actualizado su android studio.

Nuestro juego será más o menos como el mítico Space Invader, tratara de nuestro nave estara en la base de la pantalla, y solo se movera de izquierda y derecha, y presionando sobre la pantalla disparara hacia arriba. Por otro lado los enemigos bajarán de forma constante y aparecerán de forma aleatoria en el eje X.

Creamos una carpeta donde se generarán los archivos de LibGDX, yo utilizare: C:\workspace_libgdxelsalvador\spaceInvaderClon, le damos doble click gdx-setup.jar, de los archivos recién descargados. Y colocamos los siguientes valores:
Y presionamos el Botón Generate, y damos click en "SI" o "YES" de las advertencias que nos aparezcan. Esperamos que finalice, luego ya estamos listo para importar en nuestro Android Studio:
Luego importamos nuestro proyecto, elegimos la opción: Import Project y elegimos la carpeta donde esta los archivos generados(en mi caso: C:\workspace_libgdxelsalvador\spaceInvaderClon)

Android Studio nos dará una recomendación, en este caso le diremos que si Actualice(Update):

Esperemos que finalice toodo el proceso de actualización de Gradles, una vez se finalice se debe de configurar que el Android Studio ejecute nuestro sub proyecto de Desktop, como aplicación.
Para ello elegimos el sub proyecto "desktop" y damos click sobre Edit Configuratios...

Damos click al botón "+" y elegimos la opción "Application":

Aquí hay que llenar los datos que se nos piden, podemos hacer uso de los botones que nos ayudan a buscar por medio de un explorador. Aquí podemos resaltar la opción Working directory, es donde se encuentran nuestros ASSETS:
Aplicamos los cambio y presionamos el OK.
Listo, ya podemos ejecutar nuestro subproyecto Desktop.

Haremos algo de limpieza antes de comenzar todo.
En nuestro subproyecto "android", eliminamos la imagen "badlogic.jpg" de la carpeta "assets" y luego copias todos los archivos descargados de nuestro assets_libgdxelsalvador.blogspot.com.zip, siempre en la carpeta "assets", así:

En la clase "GameLoop", del subproyecto "core", lo dejamos así:
package sv.com.chuckle.game.spaceinvaderclon;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class GameLoop extends ApplicationAdapter {
   SpriteBatch batch;
   Texture img,img2,img3;

   @Override   public void create () {
      batch = new SpriteBatch();
      img = new Texture("alien.png");
      img2 = new Texture("Starfighter.png");
      img3 = new Texture("missile.png");
   }

   @Override   public void render () {
      Gdx.gl.glClearColor(1, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      batch.begin();
      batch.draw(img, 0, 0);
      batch.draw(img2, 100, 0);
      batch.draw(img3,200,0);
      batch.end();
   }
   
   @Override   public void dispose () {
      batch.dispose();
      img.dispose();
      img2.dispose();
      img3.dispose();
   }
}

Guardamos, y ejecutamos el subproyecto desktop:

 También podemos correr el proyecto de "android", para ello tenemos que tener un dispositivo físico conectado a nuestro computador o algún emulador.
Listo ya tenemos nuestro ambiente listo para comenzar con la logica xD
En la siguiente entrega, haremos el juego entre pantallas de los juegos.
Codigo fuente aqui
Saludos

Si te gusta mi trabajo y el esfuerzo, pues puedes donar un $1, a esta causa xD

sábado, 25 de febrero de 2017

2017 - Disculpas, Continuidad y Más

Hola Buenas.
Se que no he continuado con el contenido que me había propuesto. Por eso me disculpo sinceramente.
Prometo subir material por lo menos una vez al mes en el peor de los casos.

Continuaré donde nos habíamos quedado, en seguir preparándonos para hacer un juego funcional, que ponga en práctica todo lo que hemos aprendido. La meta es hacer un mini juego que cumpla con todo el ciclo de vida de un videojuego normal, claro este juego es con fines pedagógicos.
Que incluirá este juego:

  1. Manejo de pantallas(Principal, Juego, GameOver, etc.).
  2. Manipulación de sonidos y música de fondo.
  3. Colisiones entre los diferentes objetos.
  4. Manipulación de controles para nuestro juego(Desktop: por medio de las flechas cursoras y Android: por medio del giroscopio.)
  5. Claro, manipulación de los Sprite. 
Y que viene luego de nuestro gran proyecto?
Pues existen muchas cosas un poco más avanzadas, que iremos aprendiendo de poco a poco.
Entre la cuales podemos mencionar:
  1. Editor de Mapas por medio de patrones: Tiled
  2. Cómo utilizar la librería Box2D, puedes ver algunos demos aquí.
  3. Editor de niveles como Overlap2D y VisEditor.
  4. Editor de Sistemas de Partículas.
  5. Técnicas de rendimiento(Sprite Sheet, Asset Manager y Pooling).
  6. Manipulación de GUI.
  7. Manipulación de FONT.
  8. ETC.
Como ven esto se pone SABROSO, así que pendientes xD

En diciembre del año pasado(2016), fue liberada la versión 1.9.5 de libgdx. He tratado de trabajar con él y resulta que tiene unos problemas con la sincronización de las API's de Android. Quizá sea porque tengo ratos de no actualizar mis SDK de Android, aún utilizado Eclipse.
Por esta razón, utilizaremos la versión 1.6.1 LibGdx, la cual podemos descargar de AQUI

Desde este punto esta es la versión que utilizaremos en todos los artículos del presente Blog.

Como siempre todo el contenido de este Blog, estará en GitHub y tratare de colgar un video demostrativo.

Creo que es todo xD
El siguiente post, estaremos preparando todo el ambiente, sonidos, música y sprite. Para comenzar nuestro proyecto del juego. Lo que no se, cuantas partes o tutoriales haré para terminar el juego.

Nos vemos la otras semana, ya con el inicio del juego insignia xD

Saludos.




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