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

No hay comentarios.:

Publicar un comentario