El Blog de Murphy

18 Febrero 2009

Pulpcore y Sax, usando XML

Archivado en: Pulpcore — Etiquetas:, , , , — Julio Cesar Cachay Pérez @ 1:41 am

Bueno estuve revisando alguna forma de leer XML en java y me di con 2 formas de hacerlo de forma nativa y algunas mas usando parsers, solo hablare de los de forma nativa que son DOM y SAX... bueno tampoco es que vaya a hablar mucho de ellos, solo les dire que la ventaja de SAX es el menor consumo de memoria que DOM pero como desventaja es su dificultad.

Tambien revise algunos parsers pero trato de mantener al minimo el tamaño de los archivos, y estar bajando (y anexando) Xerces o JDom no me convencio del todo, ademas no es que vaya a necesitar tanto de la funcionalidad de los parsers cuando solo voy a leer o escribir XML simples, como los gringos… “keep it simple” aunque SAX no lo es tanto…

Ahora porque digo que SAX es mas rapido, una buena lectura es la de esta pagina, en la parte que dice SAX vs DOM, aunque si googlean un poco pueden encontrar mas informacion. Se fijaran que usan Xerces como parser, pero eso es porque, y esto no lo tengo por seguro, usaban el jdk 1.3, ya que desde la version 1.4 se incluye un parser

Bueno tambien queria indicarles que se puede usar php ademas de java para la escritura y lectura de los archivos XML pero eso lo veremos en otro post (otro mas a la lista “prometi y no cumplo” XD )

Ahora si a lo que vamos, primero decirles que los applets tiene una seguridad propia de ellas que no permiten escribir XML y solo leer archivos desde tu propio servidor, entonces esto quiere decir que si uds corren algun applet sin usar un servidor este simplemente no leera su xml, es por eso que necesitamos primero hacer nuestro servidor y la manera mas facil es o usando apache, o el servidor tomcat de netbeans, io la verdad es que no instale tomcat con netbeans y por eso me baje el servidor apache, concretamente EasyPHP 3.0, porque tambien quiero hacer la prueba con php despues y con un par de “siguientes” tenemos corriendo el apache en 1 seg. Descarguenlo, instalenlo y en la carpeta www (C:\Archivos de programa\EasyPHP 3.0\www, si lo instalaron en esa ruta), copian toda la carpeta build generado en netbeans, en su navegador colocan 127.0.0.1 y veran correr a su applet

Sax lee los archivos XML de forma estructurada a diferencia de Dom que crea objetos, esto hace que Dom consuma mas memoria, es por eso que elegi Sax, lo que no he visto en internet son applets que usen Sax, bueno con pulcore veremos como hacer esto ahora.

Pero y ¿para qué usar XML? bueno imaginense que tenemos un juego y lo queremos tener en varios idiomas, entonces ¿no seria mejor tener toda la traduccion aparte en otro archivo y asi poder agregar varios lenguajes sin ninguna modificacion en el codigo? … yo tambien pensaba lo mismo ^^.

Ok a lo que vamos primero el XML

<?xml version="1.0" encoding="UTF-8"?>

<!--
    Document   : juego.xml
    Created on : 18 de febrero de 2009, 08:24 PM
    Author     : Julio Cachay
    Description:
        Datos del juego en español
-->

<juego>
    <nombre>Pio Pio</nombre>
    <descripcion>Juego arcade</descripcion>
<personaje-principal>
        <nombre>Pollito</nombre>
        <habilidad>Comer maiz</habilidad>
    </personaje-principal>
</juego>

Ahora el manejador SAX, cabe decirles que para hacer estas clases me base en el ejemplo de lector XML que contienen elementos anidados de Alberto Molpeceres. solo que no uso el parser de xerces sino el que te viene en el jdk

/**
 *
 * @author Julio Cachay
 */
import java.util.Vector;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

public class ManejadorSax {

    private Vector instancias = new Vector();
    private JuegoXMLHandler manejador;

    public ManejadorSax() {
        procesarFichero();
    }

    private void procesarFichero() {
        try {
            XMLReader reader = XMLReaderFactory.createXMLReader();
            manejador = new JuegoXMLHandler(reader, instancias);
            reader.setContentHandler(getManejador());
            reader.parse(new InputSource("http://127.0.0.1/juego.xml"));
            System.out.println("Juego:");
            System.out.println(getManejador().getActual().toString());
            System.out.println("Personaje Principal:");
            System.out.println(getManejador().getHandlerPersonaje().getPersonaje().toString());
        } catch (Exception e) {
            System.out.println("Error al procesar el fichero del juego: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * @return the manejador
     */
    public JuegoXMLHandler getManejador() {
        return manejador;
    }
}

Ahora los handler, primero el juego

/**
 *
 * @author Julio Cachay
 */
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import java.util.Vector;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

public class JuegoXMLHandler extends DefaultHandler {
    /* Esto no es nuevo */
    //vector de instancias
    private Vector instancias;
    //"Juego" que se esta procesando
    private Juego actual;
    //valor contenido entre las etiquetas de un elemento
    private String valor;
    /* Esto si es nuevo */
    //Como queremos pasar el control del proceso de un
    //Handler a otro, necesitamos tener el parser para
    //asignarle el Handler que necesite en cada instante.
    private XMLReader parser;
    //Este es el Handler que procesara los personajes que
    //contenga el documento
    private PersonajeXMLHandler handlerPersonaje;

    public JuegoXMLHandler(XMLReader parser, Vector v) {
        this.parser = parser;
        this.instancias = v;
    }

    public void startElement(String namespaceURI, String localName, String qName,
            Attributes attr) throws SAXException {
        //comprobamos si empezamos un elemento "juego"
        if (localName.equals("juego")) {
        //creamos la nueva instancia de Juego
            actual = new Juego();
            //y la añadimos al Vector que las almacena
            instancias.addElement(getActual());
        } else if (localName.equals("personaje-principal")) {
            //creamos una instancia de Personaje
            Personaje principal = new Personaje();
            //se la asignamos al juego actual como principal
            getActual().setPrincipal(principal);
            /*
            y pasamos el control al Handler de personaje principal
            le tenemos que pasar el parser, para que recoga
            los datos del fichero, este Handler para que luego
            nos devuelva el control, y el personaje donde meter
            los datos que procese.
             */
            handlerPersonaje = new PersonajeXMLHandler(parser, this, principal);
            parser.setContentHandler(getHandlerPersonaje());
        }
    }

    public void endElement(String namespaceURI, String localName, String rawName)
            throws SAXException {
        /*
        miramos de que elemento se trata y asignamos los atributos
        correspondientes al "Juego" actual.
         */
        if (localName.equals("nombre")) {
            getActual().setNombre(valor);
        } else if (localName.equals("descripcion")) {
            getActual().setDescripcion(valor);
        }
        valor = null;
    }
    /*
    Los parametros que recibe es la localizacion de los carateres del elemento.
     */

    public void characters(char[] ch, int start, int end) throws SAXException {
    //creamos un String con los caracteres del elemento y le quitamos
    //los espacios en blanco que pueda tener en los extremos.
        valor = new String(ch, start, end);
        valor = valor.trim();
    }

    /**
     * @return the handlerPersonaje
     */
    public PersonajeXMLHandler getHandlerPersonaje() {
        return handlerPersonaje;
    }

    /**
     * @return the actual
     */
    public Juego getActual() {
        return actual;
    }
}

Ahora el personaje

/**
 *
 * @author Julio Cachay
 */
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class PersonajeXMLHandler extends DefaultHandler {
    //valor contenido entre las etiquetas de un elemento
    private String valor;
    //El parser, para luego devolver el control al
    //Handler de juego.
    private XMLReader parser;
    //El Handler al que queremos volver
    private JuegoXMLHandler handlerJuego;
    //EL personaje donde meter los datos que leamos.
    private Personaje personaje;

    public PersonajeXMLHandler(XMLReader parser, JuegoXMLHandler handler,
            Personaje personaje) {
        this.parser = parser;
        this.handlerJuego = handler;
        this.personaje = personaje;
    }

    public void endElement(String namespaceURI, String localName, String rawName)
            throws SAXException {
        /*
        miramos de que elemento se trata y asignamos los atributos
        correspondientes a el "Personaje" actual o devolvemos el control
        al Handler de juego.
         */
        if (localName.equals("nombre")) {
            getPersonaje().setNombre(valor);
        } else if (localName.equals("habilidad")) {
            getPersonaje().setHabilidad(valor);
        } //si hemos llegado al final de la etiqueta
        else if (localName.equals("persona-contacto")) {
            parser.setContentHandler(handlerJuego);
        }
        valor = null;
    }
    /*
    Los parametros que recibe es la localizacion de los carateres del elemento.
     */

    public void characters(char[] ch, int start, int end) throws SAXException {
    //creamos un String con los caracteres del elemento y le quitamos
    //los espacios en blanco que pueda tener en los extremos.
        valor = new String(ch, start, end);
        valor = valor.trim();
    }

    /**
     * @return the personaje
     */
    public Personaje getPersonaje() {
        return personaje;
    }
}

Es hora de crear los objetos donde se almacenara la informacion correspondiente, primero Juego

/**
 *
 * @author Julio Cachay
 */
public class Juego {

    private String nombre;
    private String descripcion;
    private Personaje principal;

    public Juego() {
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }

    public void setPrincipal(Personaje principal) {
        this.principal = principal;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("   nombre: " + nombre);
        sb.append("   descripcion: " + descripcion);
        return sb.toString();
    }
}

Ahora personaje principal

/**
 *
 * @author Julio Cachay
 */
public class Personaje {

    private String nombre;
    private String habilidad;

    public Personaje() {
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public void setHabilidad(String habilidad) {
        this.habilidad = habilidad;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("   nombre: " + nombre);
        sb.append("   habilidad: " + habilidad);
        return sb.toString();
    }
}

Con todo esto somos capaces de traer el xml de la ruta 127.0.0.1 que te da apache, recuerden subir el xml a la carpeta www

Es hora de mostrarlo al publico

import pulpcore.scene.Scene2D;
import pulpcore.sprite.FilledSprite;
import pulpcore.sprite.Label;
import static pulpcore.image.Colors.*;

/**
 *
 * @author Julio Cachay
 */
public class Escena extends Scene2D {

    Label juego;
    Label personaje;

    @Override
    public void load() {
        ManejadorSax ms = new ManejadorSax();
        add(new FilledSprite(rgb(185, 209, 255)));
        juego = new Label("Juego: " + ms.getManejador().getActual().toString(), 20, 120);
        personaje = new Label("Personaje Principal: " + ms.getManejador().getHandlerPersonaje().getPersonaje().toString(), 20, 320);
        add(juego);
        add(personaje);
    }
}

Listo! ya terminamos todo, el resultado se vera asi

dibujo

Recuerden que pueden ver como quedo y bajarse el codigo desde mi pagina aqui

13 Febrero 2009

Pulpcore, alucard y su mapa

Archivado en: Pulpcore — Etiquetas:, , , , — Julio Cesar Cachay Pérez @ 11:46 pm

Bueno hasta ahora teniamos la animacion de Alucard y como crear un mapa es momento de fusionarlos y crear un juego de estilo plataforma, de los que no he visto en pulcore todavia, para esto le voy dar control a alucard mediante las flechas. Primero usaremos la clase mapa anteriormente creada


import pulpcore.Stage;
import pulpcore.animation.Fixed;
import pulpcore.image.CoreGraphics;
import pulpcore.image.CoreImage;
import pulpcore.sprite.Sprite;

/**
 *
 * @author Julio Cachay
 */
public class mapa extends Sprite {

    private CoreImage[][] MapaTile;
    private int TileWidth;
    private int TileHeight;
    private int numTilesLargo;
    private int numTilesFilas;
    public final Fixed vistaX = new Fixed(this);
    public final Fixed vistaY = new Fixed(this);

    public mapa(CoreImage[][] MapaTile, int Width, int Height) {
        //lo colocamos a la izquierda y en la parte de abajo
        super(0, Stage.getHeight() - Height, Stage.getWidth(), Stage.getHeight());
        this.MapaTile = MapaTile;
        this.TileWidth = Width;
        this.TileHeight = Height;
        numTilesLargo = MapaTile.length;
        numTilesFilas = MapaTile[0].length;
        // para manejo de posiciones exactas en píxeles.
        pixelSnapping.set(true);
    }

    //El largo del mapa
    public int getMapWidth() {
        return TileWidth * numTilesLargo;
    }

    //El alto del mapa
    public int getMapHeight() {
        return TileHeight * numTilesFilas;
    }

    //Altura de la tierra
    public int tierraFirme(){
        return Stage.getHeight() - TileHeight;
    }

    //se mueve?
    public boolean isScrolling() {
        return vistaX.isAnimating() || vistaY.isAnimating();
    }

    @Override
    public void update(int elapsedTime) {
        super.update(elapsedTime);
        vistaX.update(elapsedTime);
        vistaY.update(elapsedTime);
    }

    //sobreescribimos la funcion drawSprite para dibujar el mapa
    @Override
    protected void drawSprite(CoreGraphics g) {
        int y = vistaY.getAsIntFloor();
        for (int j = 0; j < numTilesFilas; j++) {
            int x = vistaX.getAsIntFloor();
            for (int i = 0; i < numTilesLargo; i++) {
                g.drawImage(MapaTile[i][j], x, y);
                x += TileWidth;
            }
            y += TileHeight;
        }
    }
}

Ya tenemos listo el mapa ahora el escenario

import pulpcore.Input;
import pulpcore.Stage;
import pulpcore.animation.Easing;
import pulpcore.image.BlendMode;
import pulpcore.image.CoreImage;
import pulpcore.scene.Scene2D;
import pulpcore.sprite.FilledSprite;
import pulpcore.sprite.Group;
import pulpcore.sprite.ImageSprite;
import static pulpcore.image.Colors.*;

/**
 *
 * @author Julio Cachay
 */
public class mapaAnimado extends Scene2D {

    CoreImage AlucardDer;
    CoreImage AlucardIzq;
    CoreImage AlucardPDer;
    CoreImage AlucardPIzq;
    ImageSprite jugador;
    Group grupo;
    boolean cargo = false;
    int i;
    int y;
    double velocidadJugador = 5;
// Nombre de las fotos
    String bloques[] = {"t01.png", "t02.png", "t03.png", "t04.png", "t05.png", "t06.png", "t07.png",
        "t08.png", "t09.png", "t10.png", "t11.png", "t12.png", "t13.png", "t14.png", "t15.png", "t16.png",
        "t17.png", "t18.png", "t19.png", "t20.png"};
    //este sera la forma de llenar, es la relacion de imagenes
    String mapa[] = {"t01t02t03t04t05t06t07t08t09t10t11t12t13t14t15t16t17t18t19t20" +
        "t01t02t03t04t05t06t07t08t09t10t11t12t13t14t15t16t17t18t19t20"};
    mapa mapaTile;

    @Override
    public void load() {
        // agregamos un cielo azul
        add(new FilledSprite(rgb(185, 209, 255)));
        // creamos el mapa
        mapaTile = crearMapa(bloques, mapa, 24, 72);
        //adherimos el mapa
        add(mapaTile);
        // agregamos a Alucard
        AlucardPDer = CoreImage.load("res/alucardfrenada.png");
        AlucardPIzq = AlucardPDer.mirror();
        AlucardDer = CoreImage.load("res/alucard.png");
        AlucardIzq = AlucardDer.mirror();
        jugador = new ImageSprite(AlucardDer, Stage.getWidth() / 2, mapaTile.tierraFirme());
        //para que el jugador se conviene bien con el mapa, lean las tecnicas RGB que se usan en el API
        jugador.setBlendMode(BlendMode.SrcOver());
        grupo = new Group();
        grupo.pixelSnapping.set(true);
        grupo.add(jugador);
        grupo.x.bindTo(mapaTile.vistaX);
        grupo.y.bindTo(mapaTile.vistaY);

        add(grupo);
    }

    @Override
    public void update(int elapsedTime) {
//Presionan el boton izquierdo
        if (Input.isDown(Input.KEY_LEFT)) {
            if (velocidadJugador > 0) {
                velocidadJugador = velocidadJugador * -1;
            }
            if (!cargo) {
                cargar();
                cargo = true;
            }
            jugador.setImage(AlucardIzq);
        }
//Presionan el boton derecho
        if (Input.isDown(Input.KEY_RIGHT)) {
            if (velocidadJugador < 0) {
                velocidadJugador = Math.abs(velocidadJugador);
            }
            if (!cargo) {
                cargar();
                cargo = true;
            }
            jugador.setImage(AlucardDer);
        }
// no presionan nada
        if (!Input.isDown(Input.KEY_LEFT) && !Input.isDown(Input.KEY_RIGHT)) {
            if (velocidadJugador > 0) {
                jugador.setImage(AlucardPDer);
            } else {
                jugador.setImage(AlucardPIzq);
            }
            cargo = false;
        } else {
            double x = jugador.x.get() + velocidadJugador;
            jugador.x.set(x);
            setDirtyRectanglesEnabled(!mapaTile.isScrolling());
            double metaX = mapaTile.vistaX.get() + velocidadJugador * -1;
            mapaTile.vistaX.animateTo(metaX, Math.abs((int) velocidadJugador), Easing.REGULAR_OUT);
        }
    }

    void cargar() {
        AlucardPDer = CoreImage.load("res/alucardfrenada.png");
        AlucardPIzq = AlucardPDer.mirror();
    }

    private mapa crearMapa(String[] bloques, String[] mapa, int Tilewidth, int Tileheight) {
        //cargar las imagenes de bloque
        CoreImage[] ImagenesBloque = new CoreImage[bloques.length];
        int i = 0;
        while (i < ImagenesBloque.length) {
            ImagenesBloque[i] = CoreImage.load("res/" + bloques[i]);
            i++;
        }
        //Creamos un mapa con los bloques
        i = 0;
        int y = 0, m = 0;
        int filMapa = mapa[0].length();
        int colMapa = mapa.length;
        CoreImage[][] mapaTile = new CoreImage[filMapa / 3][colMapa];
        while (i < filMapa - 3) {
            y = 0;
            while (y < colMapa) {
                //Comparamos las primeras letras del mapa con las del bloque
                // ejem. t01 == t01, si lo es la imagen cargada se almacena en el mapa
                String str = mapa[y].substring(i, i + 3);
                int k = 0;
                int index = 0;
                while (k < bloques.length) {
                    if (bloques[k].substring(0, 3).contentEquals(str)) {
                        index = k;
                        break;
                    }
                    k++;
                }
                mapaTile[m][y] = ImagenesBloque[index];
                y++;
            }
            m++;
            i = i + 3;
        }
        return new mapa(mapaTile, Tilewidth, Tileheight);
    }
}

Listo, terminado y finito, con eso solo hacer volar un poco la imaginacion, luego les hablare mas profundamente de colisiones, el codigo y para ver como quedo esta aqui

alucard

Saludos

5 Febrero 2009

Haciendo un mapa

Archivado en: Pulpcore — Etiquetas:, , , , — Julio Cesar Cachay Pérez @ 7:23 pm

Ya que animamos a alucard es hora de hacer un terrenito donde pueda caminar para eso utilizaremos una imagen que encontre en la web y que la rompi en varios pedacitos con gimp

Ahora renombramos las figuras para que queden con nombre de tamaño 6, ejem: t01.png, t11.png, etc

t41 = t04

Muy bien ahora el codigo de la clase principal

import pulpcore.image.CoreImage;
import pulpcore.scene.Scene2D;
import pulpcore.sprite.FilledSprite;
import static pulpcore.image.Colors.*;

/**
 *
 * @author Julio Cachay
 */
public class mapaBloque extends Scene2D {
// Nombre de las fotos
    String bloques[] = {"t01.png", "t02.png", "t03.png", "t04.png", "t05.png", "t06.png", "t07.png",
        "t08.png", "t09.png", "t10.png", "t11.png", "t12.png", "t13.png", "t14.png", "t15.png", "t16.png",
        "t17.png", "t18.png", "t19.png", "t20.png"};
    //este sera la forma de llenar, es la relacion de imagenes
    String mapa[] = {"t01t02t03t04t05t06t07t08t09t10t11t12t13t14t15t16t17t18t19t20" +
        "t01t02t03t04t05t06t07t08t09t10t11t12t13t14t15t16t17t18t19t20"};
    mapa mapaTile;

    @Override
    public void load() {
        // agregamos un cielo azul
        add(new FilledSprite(rgb(185, 209, 255)));
        // creamos el mapa
        mapaTile = crearMapa(bloques, mapa, 24, 72);
        //adherimos el mapa
        add(mapaTile);

    }

    private mapa crearMapa(String[] bloques, String[] mapa, int Tilewidth, int Tileheight) {
        //cargar las imagenes de bloque
        CoreImage[] ImagenesBloque = new CoreImage[bloques.length];
        int i = 0;
        while (i < ImagenesBloque.length) {
            ImagenesBloque[i] = CoreImage.load("res/" + bloques[i]);
            i++;
        }
        //Creamos un mapa con los bloques
        i = 0;
        int y = 0, m = 0;
        int filMapa = mapa[0].length();
        int colMapa = mapa.length;
        CoreImage[][] mapaTile = new CoreImage[filMapa / 3][colMapa];
        while (i < filMapa - 3) {
            y = 0;
            while (y < colMapa) {
                //Comparamos las primeras letras del mapa con las del bloque
                // ejem. t01 == t01, si lo es la imagen cargada se almacena en el mapa
                String str = mapa[y].substring(i, i + 3);
                int k = 0;
                int index = 0;
                while (k < bloques.length) {
                    if (bloques[k].substring(0, 3).contentEquals(str)) {
                        index = k;
                        break;
                    }
                    k++;
                }
                mapaTile[m][y] = ImagenesBloque[index];
                y++;
            }
            m++;
            i = i + 3;
        }
        return new mapa(mapaTile, Tilewidth, Tileheight);
    }

    @Override
    public void update(int elapTime) {
    }
}

Ahora el codigo del mapa

import pulpcore.Stage;
import pulpcore.animation.Fixed;
import pulpcore.image.CoreGraphics;
import pulpcore.image.CoreImage;
import pulpcore.sprite.Sprite;

/**
 *
 * @author Julio Cachay
 */
public class mapa extends Sprite {

    private CoreImage[][] MapaTile;
    private int TileWidth;
    private int TileHeight;
    private int numTilesLargo;
    private int numTilesFilas;
    public final Fixed vistaX = new Fixed(this);
    public final Fixed vistaY = new Fixed(this);

    public mapa(CoreImage[][] MapaTile, int Width, int Height) {
        //lo colocamos a la izquierda y en la parte de abajo
        super(0, Stage.getHeight() - Height, Stage.getWidth(), Stage.getHeight());
        this.MapaTile = MapaTile;
        this.TileWidth = Width;
        this.TileHeight = Height;
        numTilesLargo = MapaTile.length;
        numTilesFilas = MapaTile[0].length;
        // para manejo de posiciones exactas en píxeles.
        pixelSnapping.set(true);
    }

    //El largo del mapa
    public int getMapWidth() {
        return TileWidth * numTilesLargo;
    }

    //El alto del mapa
    public int getMapHeight() {
        return TileHeight * numTilesFilas;
    }

    //se mueve?
    public boolean isScrolling() {
        return vistaX.isAnimating() || vistaY.isAnimating();
    }

    @Override
    public void update(int elapsedTime) {
        super.update(elapsedTime);
        vistaX.update(elapsedTime);
        vistaY.update(elapsedTime);
    }

    //sobreescribimos la funcion drawSprite para dibujar el mapa
    @Override
    protected void drawSprite(CoreGraphics g) {
        int y = vistaY.getAsIntFloor();
        for (int j = 0; j < numTilesFilas; j++) {
            int x = vistaX.getAsIntFloor();
            for (int i = 0; i < numTilesLargo; i++) {
                g.drawImage(MapaTile[i][j], x, y);
                x += TileWidth;
            }
            y += TileHeight;
        }
    }
}

Con este codigo tendremos esto:

mapa

le baje la calidad para que pese menos, pueden ver como quedo y bajar el codigo aqui

Nos vemos

24 Enero 2009

PulpCore y Gimp – Dandole vida a Alucard

Archivado en: Pulpcore — Etiquetas:, , , , — Julio Cesar Cachay Pérez @ 6:19 am

Ha sido casi un mes o mas desde mi ultimo post, lo que pasa es que estuve desarrollando un modulo de logica difusa y me tomo casi 3 semanas acabarlo, y solo me concentre en eso, ahora que de nuevo hje regresado a pulpcore, se me dio por animar a Alucard del juego Castlevania para ps (Castlevania: Symphony of the Night) para esto primero busque imagenes animadas en internet y encontre estas:

alurun_prf y alucard_walk_start_and_stopaqui.

Es hora de utilizar el gimp, primero lo bajan de aca

Luego abren las imagenes, por ejemplo el primero y se daran cuenta que se deforma, es oprque todas las imagenes son superpuestas, si quieren saber como se anima aqui.

Se dieron cuenta que al abrir el gimp tienen 2 ventanas , un de ellas es la que maneja las capas. al abrir la imagen se veria asi

capas

Entonces le comenzamos a dar click en todos los ojos que parecen, estos son los visores de la imagen, son 16 en total hasta que nuestra imagen ya no tenga nada, luego de esto seleccionamos la primera capa y le damos al ojo, entonces en la imagen aparecera solo el primer movimiento de alucard

Antes

antes

Despues

despues

Para hacer zoom, solo deben darle click derecho en la imagen y zoom, o mas practico, ctrl+la rueda del mouse

Ahora creamos una nueva imagen, esta imagen tiene la misma altura, pero el ancho ahora va albergar a todas las imagenes, en este caso io eligo 8 capas, salteadas: 1, 3, 4, etc.

nuevo

Vamos activando cada capa (click en el ojo)y la copiamos a esta nueva imagen, despues de copiarlas las desactivamos

Cuando hayan acabado no olviden guardarlo como alucard.png

Quedaria asi:

alucard1

Y la frenada comenzamos a partir de la capa 24 hacia el 36 de 2 en 2 y quedaria asi:

alucardfrenada

Si lo desean pueden pintarlos porque como io toy ocioso y se los dejo a uds XD

Bueno ahora que tenemos las 2 imagenes es hora de darle sus propiedades para esto creamos un archivo llamado alucard.properties y llenamos con estas caracteristicas:

# Numero de frames fisicos (figuras)
frames.across = 8

# Punto Central (De cada frame)
hotspot.x = 25
hotspot.y = 25

#Secuencia de frames. Comienza desde 0 hasta el nro de frames -1
frame.sequence =   0,  1,  2,  3,   4,  5,  6, 7

# Duracion de cada frame en milisegundos (puede ser diferente para cada frame)
frame.duration = 100, 100, 100, 100, 100, 100, 100, 100
#Repite?
loop = true

y alucardFrenada.properties

# Numero de frames fisicos (figuras)
frames.across = 7

# Punto Central (De cada frame)
hotspot.x = 25
hotspot.y = 25

#Secuencia de frames. Comienza desde 0 hasta el nro de frames -1
frame.sequence =   0,  1,  2,  3,   4,  5,  6

# Duracion de cada frame en milisegundos (puede ser diferente para cada frame)
frame.duration = 100, 100, 100, 100, 100, 100, 100
#Repite?
loop = false

Ahora que ya tenemos todo listo pasamos a programar, haremos una animacion que vaya de izquierda a derecha por 5 seg, y se frene por 3 seg.

import pulpcore.Stage;
import pulpcore.image.CoreImage;
import pulpcore.scene.Scene2D;
import pulpcore.sprite.FilledSprite;
import pulpcore.sprite.ImageSprite;
import static pulpcore.image.Colors.WHITE;

/**
 *
 * @author Julio Cachay
 */
public class animacion extends Scene2D {

    CoreImage AlucardDer;
    CoreImage AlucardIzq;
    CoreImage AlucardPDer;
    CoreImage AlucardPIzq;
    ImageSprite jugador;
    int i;
    int y;
    double velocidadJugador = 5;

    @Override
    public void load() {
        add(new FilledSprite(WHITE));
        AlucardPDer = CoreImage.load("res/alucardFrenada.png");//Cargamos las imagenes de frenada
        AlucardPIzq = AlucardPDer.mirror();//La imagen de frenada hacia la izquierda
        AlucardDer = CoreImage.load("res/alucard.png");//la imagen de la corrida de alucard
        AlucardIzq = AlucardDer.mirror();
        jugador = new ImageSprite(AlucardDer, 5, Stage.getHeight() / 2);//al medio
        add(jugador);
    }

    @Override
    public void update(int elapsedTime) {
        i = i + elapsedTime; // i se incrementa en el numero de milisegundas despues del ultimo update
        if (i < 5000) {//si no llega a 5 seg
            if (jugador.x.get() >= Stage.getWidth()) {
                velocidadJugador = -velocidadJugador; //da la vuelta
                jugador.setImage(AlucardIzq);
            }
            if (jugador.x.get() <= 0) {
                velocidadJugador = -velocidadJugador;
                jugador.setImage(AlucardDer);
            }
            jugador.x.set(jugador.x.get() + velocidadJugador);
        } else { //si llego a 5 seg
            if (y < 3000) { // si no llega a 3 seg
                y = y + elapsedTime; // y comienza a incrementar
                if (velocidadJugador > 0) {
                    jugador.setImage(AlucardPDer);
                } else {
                    jugador.setImage(AlucardPIzq);
                }
            } else {
                if (velocidadJugador > 0) {
                    jugador.setImage(AlucardDer);
                } else {
                    jugador.setImage(AlucardIzq);
                }
                cargar();// recargamos las imagenes de freno porque el loop es false
                i = 0;
                y = 0;
            }
        }
    }
    void cargar(){//cuando el loop es false la imagen se queda en el ultimo frame, tenemos que recargarlo
        AlucardPDer = CoreImage.load("res/alucardFrenada.png");
        AlucardPIzq = AlucardPDer.mirror();
    }
}

final

Con esto terminamos, si quieren ver como quedo, o bajarse el codigo aca

Me voy a a ver el partido del Rafa Nadal, Alaoz!!!

20 Diciembre 2008

PulpCore – 3

Archivado en: Pulpcore — Etiquetas:, , , , , — Julio Cesar Cachay Pérez @ 4:59 am

Bueno ia me mude, en la mayoria, y ya me pusieron internet :D .. y esto que tiene que ver con pulpcore, ni mela, pero pa que vean que he estado ocupado a horrores. Bueno prosiguiendo, estuve revisando el codigo del post anterior, y se nota que lo hize a la volada, pero lo he mejorado y ahora ademas he agregado un obstaculo en la pantalla, primero el principal:

import pulpcore.Stage;
import pulpcore.scene.Scene2D;
import pulpcore.sprite.FilledSprite;
import pulpcore.sprite.ImageSprite;
import pulpcore.sprite.Label;
import static pulpcore.image.Colors.WHITE;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Julio Cesar Cachay Perez
 */
public class pelotaobstaculo extends Scene2D{

    private ImageSprite pelota;
    private ImageSprite cuadrados;
    private double velocidad = 5;
    private nuevaruta NRPelota;
    Label infoText;
    Label tema;
    Label velo;
    int i =0;

    @Override
    public void load() {
        add(new FilledSprite(WHITE));// primero agregamos el background
        NRPelota = new nuevaruta(Stage.getWidth(), Stage.getHeight(), velocidad);
        pelota = new ImageSprite("res/pelota.png", 140, 240);//cargamos la pelota
        cuadrados = new ImageSprite("res/Block2.png", 300, 300);//cargamos los cuadrados
        NRPelota.setAnchoSprite(pelota.width.get());
        NRPelota.setLargoSprite(pelota.height.get());
        NRPelota.almedio();

        pelota.x.set(NRPelota.getX());//lo ponemos al centro
        pelota.y.set(NRPelota.getY());

        add(pelota);//ahora la pelota
        add(cuadrados);
        tema = new Label(String.valueOf(Stage.getWidth()) + " , " + String.valueOf(Stage.getHeight()), 320, 20);
        velo = new Label("", 20, 320);
        infoText = new Label("", Stage.getWidth() / 4, Stage.getHeight() / 2);
        add(velo);
        add(tema);
        add(infoText);
    }

    @Override
    public void update(int elapsedTime) {
        mover();
        if(pelota.intersects(cuadrados)){
                choco(cuadrados);
        }

    }

    private void mover() {
        NRPelota.nuevaruta();
        pelota.x.set(NRPelota.getX());
        pelota.y.set(NRPelota.getY());
        String ex = String.valueOf(pelota.x.get());
        String ey = String.valueOf(pelota.y.get());
        infoText.setText(ex + " , " + ey);
        velo.setText(String.valueOf(NRPelota.velocidadX)+" , "+ String.valueOf(NRPelota.velocidadY));
    }
    private void choco(ImageSprite cua){
        NRPelota.cambioDireccionXchoque(cua.x.get(),cua.y.get(),cua.width.get(),cua.height.get());
        pelota.x.set(NRPelota.getX());
        pelota.y.set(NRPelota.getY());

    }
}

Ahora el codigo que hace que cuando la pelota choque tenga un comportamiento al azar de rebote

import java.util.Random;

/**
 *
 * @author Julio Cesar Cachay Perez
 */
public class nuevaruta {

    private double x = 0;
    private double y = 0;
    private int width;
    private int height;
    private double velocidad;
    public double velocidadX;
    public double velocidadY;
    private double anchoSprite = 0;
    private double largoSprite = 0;

    public nuevaruta(int width, int height, double velocidad) {
        this.width = width;
        this.height = height;
        this.velocidad = velocidad;
        velocidadX = velocidad;
        velocidadY = velocidad;
    }

    public double Xmedio() {
        //calculamos la posicion x media, a partir del ancho del objeto a poner en ese lugar
        return ((width / 2) - (anchoSprite / 2));
    }

    public double Ymedio() {
        //calculamos la posicion y media, a partir del largo del objeto a poner en ese lugar
        return ((height / 2) - (largoSprite / 2));
    }

    private void RutaX() {
        setX(getX() + velocidadX);
    }

    private void RutaY() {
        setY(getY() + velocidadY);
    }

    private boolean chocaX() {
        if (getX() <= 0 | getX() + anchoSprite >= width) {
            return true;
        } else {
            return false;
        }
    }

    private boolean chocaY() {
        if (getY() + largoSprite >= height | getY() <= 0) {
            return true;
        } else {
            return false;
        }
    }

    public void almedio() {
        x = Xmedio();
        y = Ymedio();
    }

    public void nuevaruta() {
        if (chocaX() & chocaY()) {
            if (x <= 0) {
                velocidadX = Math.abs(velocidadX);
            }
            if (y <= 0) {
                velocidadY = Math.abs(velocidadY);
            }
            if (x + anchoSprite >= width) {
                velocidadX = Math.abs(velocidadX) * -1;
            }
            if (y + largoSprite >= height) {
                velocidadY = Math.abs(velocidadY) * -1;
            }
            x = x + velocidadX * new Random().nextDouble();
            y = y + velocidadY * new Random().nextDouble();

        } else {
            if (chocaX()) {
                nuevarutaX();
            } else {
                if (chocaY()) {
                    nuevarutaY();
                }
            }
        }
        RutaX();
        RutaY();
    }

    private void nuevarutaX() {
        velocidadX = velocidadX * -1;
        RutaX();
        alazarY();
        RutaY();
        if (chocaY()) {
            velocidadY = velocidadY * -1;
            RutaY();
        }
    }

    private void nuevarutaY() {
        velocidadY = velocidadY * -1;
        RutaY();
        alazarX();
        RutaX();
        if (chocaX()) {
            velocidadX = velocidadX * -1;
            RutaX();
        }
    }

    private void alazarY() {
        Random random = new Random();
        if (random.nextDouble() > 0.5) {
            velocidadY = velocidadY * -1;
        }
        y = y + velocidadY * random.nextDouble();
    }

    private void alazarX() {
        Random random = new Random();
        if (random.nextDouble() > 0.5) {
            velocidadX = velocidadX * -1;
        }
        x = x + velocidadX * random.nextDouble();
    }

    /**
     * @param x the x to set
     */
    public void setX(double x) {
        this.x = x;
    }

    /**
     * @param y the y to set
     */
    public void setY(double y) {
        this.y = y;
    }

    /**
     * @param anchoSprite the anchoSprite to set
     */
    public void setAnchoSprite(double anchoSprite) {
        this.anchoSprite = anchoSprite;
    }

    /**
     * @param largoSprite the largoSprite to set
     */
    public void setLargoSprite(double largoSprite) {
        this.largoSprite = largoSprite;
    }

    /**
     * @return the x
     */
    public double getX() {
        return x;
    }

    /**
     * @return the y
     */
    public double getY() {
        return y;
    }

    public void cambioDireccionXchoque(double xO, double yO, double anchoO, double largoO) {

        if (y - velocidadY > yO & y + velocidadY < yO + largoO) {
            alazarY();
            velocidadX = velocidadX * -1;
        } else {
            if (x - velocidadX > yO & x + velocidadX < xO + anchoO) {
                alazarX();
                velocidadY = velocidadY * -1;

            } else {
                velocidadY = velocidadY * -1;
                y = y + velocidadY * new Random().nextDouble();
                velocidadX = velocidadX * -1;
                x = x + velocidadX * new Random().nextDouble();

            }
        }
    }
}

block2

Bueno he pulido el codigo, aunque me ha flatado explicarlo un poco, pero es que he tenido sueño, cuando termine la version final prometo subirlo explicado o con su javadoc respectivo.

Alaoz

Entradas más antiguas »

Blog de WordPress.com.