Archive for the ‘Reflección’ Category

Un generador de juegos

Esta idea es algo que cae en la categoría de ideas locas, debido a la cantidad(muchos) de programas que permiten crear juegos y el costo de desarrollar un programa como estos es alto. Sin embargo yo no voy apostar por crear algo bonito como Unity, UDK, etc… si no por un generador de código a partir de un lenguaje(o intento) desarrollado para este objetivo.

De primera pensaba que este lenguaje debería poder desarrollar un juego completo, sin embargo era demasiado para mí y aunque tuviese ayuda solo seria un castillo más en el aire.  Entonces si no podía hacerlo completo puedo hacerlo incompleto o prototiparlos, pero lo más rápido posible para que valga la pena usarlo.

Para poder crear este lenguaje que por ahora llamo Fast Prototyping for Games (FP4G) y utilizare tecnologías como JavaCC y JCodeModel los cuales me permiten hacer un parser para el lenguaje y generar código en java. El resultado será codigo compilable en java con el esqueleto del juego y usando la biblioteca libGDX.
El lenguaje sera simple, de hecho me base en el objeto json de javascript aunque, con ligeras modificaciones.

[
valor = 1,
valorA = "hola",

etc...
]

No es algo muy complejo, solo hay que definir cosas y mágicamente el generador crea todas las clases por ti listas para que tu agregues los comportamientos necesarios para definir ciertos objetos, pero todo lo demás estará listo. La idea es que uno define que va tener y va definiendo sus propiedades. Nada más.

Y lo que tengo ya hecho.

DEFINE GAME
[
name = "Prueba",
DEFINE STATE GameLoop
[
  ADD SYSTEM SceneSystem,
  ADD SYSTEM PhysicsSystem,
  ADD SYSTEM EntitySystem,
  DEFINE ENTITY Coin
  [
     position = [ x = 10, y = 10]
  ],
  ADD ENTITY Coin,
  ADD ENTITY Coin
  ],
  START GameLoop
]

Y genera esto
(Main) http://pastebin.com/L3EaMLec
(GameLoop) http://pastebin.com/BJvDWKrR
(CoinEntity) http://pastebin.com/e193m8hu
Que con las bibliotecas correctas va compilar y mostrar una moneda en pantalla.

Usando un poco de reflección con Java

Hola, hace tiempo que no escribiá un articulo en mi blog y bueno hoy les mostraré como crear un objeto en Java.
Alguién: Pero si yo ya sé eso, es facil:

[java]MiClase m = new MiClase();[/java]

Yo: Si, pero yo crearé un objeto y además llamaré un metodo usando Reflexión

Para este tutorial omitiremos ciertas cosas, para dar un primer paso con la reflexión y sea más fácil su compresión.

Para empezar necesitaremos una clase para probar la reflexión

[java]
public class MiClase{
public MiClase(){
System.out.println(“Objeto contruido”);
}
public void funcionSimple(){
System.out.println(“Funcion Simple”);
}
}
[/java]

Empecemos entonces, como ya todos saben en Java casi todo es una clase (excepto los tipos primitivos, pero tienen una clase para convertir un int en Integer), entonces para nuestro caso necestaremos el objeto del tipo Class de MiClase

[java]Class<?> clase = MiClase.class;[/java]

Notese que este metodo no es el unico para obtener la clase de un objeto, existen más que no describire aqui.

[java]Object objecto = clase.newInstance();[/java]

Este metodo crea una nueva instancia de la clase que esta contenida en el objeto clase. Seguramente al ejecutar todo hasta aqui se daran cuenta que en la salida estandar dira:

Objeto contruido

que significa que todo esta bien.
Notar que: Esta función solo crea objetos si la clase tiene un contructor por defecto (sin parametros)

Ahora si deseamos llamar a una función sin parametros, la cual debemos obtenerla (todo esto ya se esta volviendo algo complejo)

[java]Method m = clase.getMethod(“funcionSimple”);[/java]

La clase Method es una clase especial que nos permitira llamar a cualquier función definida en una clase, en este caso estamos obteniendo la funcion “funcionSimple” de MiClase

Y para finalizar el el tutorial

[java]m.invoke(objeto)[/java]

Que llamará la función “funcionSimple” usando el objeto objecto creado anteriormente y al llamar esta funcion nos saldra en la salida estandar

Funcion Simple

El codigo completo de la clase Main con todo seria:

[java collapse=”true”]
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Clase que realiza toda el trabajo
* @author egyware
*/
public class Main {

public static void main(String[] args) {
try {
Class<?> clase = MiClase.class;
Object objecto = clase.newInstance();
Method m = clase.getMethod(“funcionSimple”);
m.invoke(objecto);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
} catch (InvocationTargetException ex) {
ex.printStackTrace();
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
} catch (SecurityException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
}
[/java]

Como habran notado este tutorial es muy simple, pero les dara un primer acercamiento de como es la Relexión en Java.

Les dejo un link:
Un tutorial de Java: http://download.oracle.com/javase/tutorial/reflect/index.html (Sinceramente nunca lo he visto)

Update 25/07/2013:
Vi el link, y es buenisimo, se los recomiendo 😉

Programando un servidor no tan simple con conexión alternada (parte 2)

Como se mostro en el tutorial anterior se mostro como hacer una coneccion directa pero a la vez se puede alternar.  Bueno el tema anterior deja varias dudas como por ejemplo ¿si quiero montar un servidor? con coneccion alternada como lo hago.  Entonces para eso haremos usaremos reflección, aunque tambien podemos usar Interfaces si es que lo deseamos, pero con otros ajustes. Nuestro prototipo de función (Como C) será:

public static boolean createConetion(String ip,int port,boolean direct,Class<?> clase,Object args[])

Para empezar los primeros parametros se ven casi triviales pero el ultimo puede ser un poco confuso. El penultimo parametro aceptara solo la clase NetHandler que la definiremos despues, ya que si aceptaramos todas las clases seria todo un lío definiendo limites para todo tipo de clases. Con el objeto Class podremos instanciar nuevos objetos y dependiendo del objeto lo haremos ejecutar de distintas formas. Y en caso que nuestra clase que hereda de NetHanlder requiera mas parametros se los pasaremos de forma de arreglo de objetos :).

//File NetHandler.java
//package egyware.net;
import java.io.*;
import java.net.*;
/**
* Clase que permite crear un controlador de red
* @author Edgardo
*/
public abstract class NetHandler{
//Defino la E/S Raw (solo bytes) del stream
protected InputStream rawIn;
protected OutputStream rawOut;
protected Socket conex;
public NetHandler(Socket socket) throws IOException{
conex = socket;
rawIn = socket.getInputStream();
rawOut = socket.getOutputStream();
}
/**
* Desde aqui se empezara a ejecutar el hilo
* definir este metodo para controlar tu coneccion de red
*/
public abstract void run();
}

Ya perfecto tenemos definida nuestra clase que nos permetira ejecutar todo tipo controladores de conecciones, pero solo nos permitira ejecutar una conexión no más, para ese caso si deseamos más conexiones implementaremos Runnable y como el metodo que se usa es el mismo en NetHandler es el mismo entonces no habrá problemas en cambiar los metodos de lugar.
Nuestra clase EcoThread usando NetHandler

//File EcoHandler.java
//package egyware.sample
//import egyware.net
public class EcoHandler extends NetHandler implements Runnable{
public EcoHandler(Socket socket) throws IOException {
super(socket);//Contruyendo la clase madre
}
public void run(){
byte buffer[]=new byte[512];
while(true){
if(rawIn.available()>0){
int reads = rawIn.read(buffer,0,buffer.length);
if(reads>0)
rawOut.write(buffer, 0, reads);
}
}
}

Y eso es todo para nuestro EcoHandler ahora nuestra feisima función(lo llamo asi porque sera compleja)

-Importación de clases y función main.

import egyware.sample.*;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
import java.util.Arrays;
import java.util.LinkedList;
public class Server {
private static boolean stop = false;
public static void main(String args[]) throws IOException {
boolean b = createConection("localhost", 3040, true, EcoHandler.class,null);
}

-Revisar que se implemente Runnable

public static boolean createConection(String ip, int port, boolean direct,
Class<?> clase, Object args[]) {
Socket conexion = null;
// Revisamos si implementa Runable
boolean runnable = false;
Class<?> interfaces[] = clase.getInterfaces();
for (int i = 0; i < interfaces.length; i++)
if (interfaces[i] == Runnable.class) {
runnable = true;// Si lo implementa
break;// salimos del for para evitar buscar en otras interfaces
}

-Revisar que herede de NetHandler

// Ademas revisamos que la clase herede de NetHandler para eso debera
// aceptar un casting
try {
clase.asSubclass(NetHandler.class);
} catch (ClassCastException cce) {
// Si falla, retornaremos falso que no pudo
cce.printStackTrace();
return false;
}

-Buscando el constructor deseado, para esta ocasion

// buscamos el constructor que necesitamos
Constructor<?> c[] = clase.getConstructors();
Constructor<?> constructor = null;
// Debemos buscar algo que ajuste a lo que no han pasado
// debemos buscar un constructor con args.length+1 parametros
int length = (args != null) ? args.length + 1 : 1; // Minimo debe tener
// 1 constructor
for (int i = 0; i < c.length; i++) {
// Debe coincidir el largo de parametros y el primer tipo debe ser
// Socket
if (length == c[i].getParameterTypes().length && c[i].getParameterTypes()[0] == Socket.class) {
constructor = c[i];
break;// Salimos del for
}
}
// No encontramos un constructor apropiado, nos salimos
if (constructor == null)
return false;

-Preparando la lista de argumentos

// Lista de argumentos: la preparamos antes como no cambia
Object argumentos[] = null;
// Declaro un bloque para que lista, no se use mas y se valla al GC
{
LinkedList<Object> lista;
if (args != null)
lista = new LinkedList<Object>(Arrays.asList(args));
else
lista = new LinkedList<Object>();
lista.addFirst(null);// Dejamos un espacio
argumentos = lista.toArray();
// Sugerimos a la VM usar el Garbage Collector o GC
System.gc();
}

-Conexión directa y las dos formas de recibir una conexión

if (direct) {
// Nos ponemos a la escucha de todas las interfaces en el puerto
// 3040
ServerSocket server;
try {
// creamos una nueva instancia
server = new ServerSocket(port);
// bueno ahora segun si implementa o no vamos a definir una
// actitud
if (runnable) {
// un while
while (!stop) {
// Aceptamos una conección
conexion = server.accept();
// si hay una nueva coneccion crear un nuevo objeto
argumentos[0] = conexion;// para eso necesitabamos espacio en blanco
// pasamos los argumentos
Object run = constructor.newInstance(argumentos);
//Sin problemas realizamos el Casting y iniciamos el Thread
new Thread((Runnable) run).start();
}
server.close();
} else {
// Aceptamos una sola conección
conexion = server.accept();
// si hay una nueva coneccion crear un nuevo objeto
argumentos[0] = conexion;/*
* para eso necesitabamos el espacio
* en blanco
*/
Object run = constructor.newInstance(argumentos); /*
* pasamos
* los
* argumentos
*/
// Cerramos para que no acepte ninguna otra coneccion
server.close();
// Realizamos un casting sin problemas a NetHandler
((NetHandler) run).run(); // Ejecutamos
}
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
} catch (InstantiationException e) {
e.printStackTrace();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
} catch (InvocationTargetException e) {
e.printStackTrace();
return false;
}
return true; // Si llego hasta aqui no hubo ningún problema

-Conexión inversa y las dos formas de conectarnos al servidor

} else {
// Ahora que terminamos con la coneccion directa, ahora con la
// indirecta
// Notar que el comportamiento sera un tanto distinto
if (runnable) {
// Nos conectamos he iniciamos 1 solo Thread
try {
conexion = new Socket(ip, port);
argumentos[0] = conexion;
Object run = constructor.newInstance(argumentos);
// Y eso es todo
new Thread((Runnable) run).start();
} catch (UnknownHostException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
} catch (InstantiationException e) {
e.printStackTrace();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
} catch (InvocationTargetException e) {
e.printStackTrace();
return false;
}
} else {
// Ahora el otro, este caso trataremos de mantener siempre una
// coneccion activa
// Si se cierra la volvemos abrir
try {
while (!stop) {
conexion = new Socket(ip, port);
Object run = constructor.newInstance(argumentos);
// Hacemos ejecutar el NetHandler hasta que pierda la
// coneccion
((NetHandler) run).run();
}
} catch (UnknownHostException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
} catch (InstantiationException e) {
e.printStackTrace();
return false;
} catch (IllegalAccessException e) {
e.printStackTrace();
return false;
} catch (InvocationTargetException e) {
e.printStackTrace();
return false;
}
}
//Si hemos llegado aqui esque todo salio de maravilla
return true;
}
}
}

Bueno hemos terminado con esta segunda parte dejo el link para que descarguen el fuente
Fuente

PS: Me he dado cuenta que el WordPress es pesimo para mostrar fuente, asi que para la proxima colocare solo puntos claves, en este caso era la reflección.
PD: Gracias a Rodrigo por el tag sourcecode, queda mas ordenado el codigo 😉
UPDATED: He divido el codigo para una mejor entendimiento.