Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Menu

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menu

Mensajes - TrOnTxU

#121
Programación gráfica / Re: qué librería uso?
27 de Noviembre de 2010, 05:49:34 PM
Si quieres hacer un editor, y tienes poco tiempo: C# WinForms
Es rápido de desarrollar, y bastante sencillo y potente. Puedes gastar GDI+ o Managed DX para dibujar. El primero solo 2D, en un principio.

El tema es que puedas editar gráficos "vectoriales" en 2D que seria la representacion con la que trabajarias ¿no?
Luego debes covertir los datos "vectoriales 2D" a datos "vectoriales 3D" y dibujarlos en un visualizador ¿me equivoco?

No sé como va el tema XNA ahora, ya hace tiempo que no lo toco. Pero hacerte un visualizador 3D en un Componente o Control de Winforms, es realmente sencillo.
El problema vendria si quieres hacer varias ventanas de visualización. Sigue siendo tan facil como arrastrar tu Control al formulario que quieras, pero creo que no puedes configurar las chains de directX, y tendrias que tner un device para cada ventana (lo único en lo que puede influir es en el rendimiento del dibujado, pero para lo que quieres hacer no debe ser un problema).

Bueno, espero haber sido de alguna utilidad,
un saludo y suerte.

PS: por cierto Mortdegana, come algo que te se ve flacucho :P
#122
Hola,
siguiendo el consejo de Hechelion estoy investigando la forma de "romper" yo mismo la protección de mi software para poder mejorarla.

Lo primero que he encontrado es el Reflector y el FileDisassembler. Con el que puedes ver e incluso trazar en el visual studio cualquier .NET, .exe o .dll, a nivel de código fuente (C# en este caso). Lo único que no se todavia como hacer es modificar el ensamblado, pero darme un dia más que esto parece (y ojala me equivoque) que coser y cantar  >:(

Si no seria muy complicado sustituir un "jne" por un "je" en ensamblador ni te cuento como de facil es leer o trazar el codigo fuente C# y encontrar lo que buscas, sobretodo si se trata de modificar un par de comparaciones.

Lo primero que tengo en mente es utilizar ofuscadores de código, ya lo utilizaba bastante cuando haciamos juegos de moviles en java, e incluso a veces desensamblabamos el propio código ofuscado, ya que algunos parches para algun movil especifico como meter una llamada a un clase unica de ese modelo, sin tener la libreria y cosas de ese estilo.
La verdad es que funcionan de una forma muy parecida a los que utilizaba para java, pero con la diferencia aquel código ofuscado y decompilado, raramente podia compilarse de nuevo otra vez como java, y tenias que modificar y "reconstruir" parte del código, y si no estabas muy relacionado el byte-code de java, puede que no supierascomo hacerlo o las pasaras canutas (como yo).
Esto parece, sin embargo, y a mi pesar, mucho más fácil  :grrr:

Tambien he leido que hay una manera de que visual studio encripte tus dlls, y que solo con una clave puedas decriptarla, pero una vez el usuario final tenga la clave, no se que le impediria utilizar reflector, por ejemplo.

Por último, el tema de comprimir o encriptar parte del código ... no se me ocurre como, no se si el código CLI o como se llame se puede encriptar/comprimir, y luego hacer el procedimiento inverso y ejecutarlo.
Lo único que posiblemente se pueda hacer, o pueda funcionar, es tener código "crítico" para la ejecución del programa en C# en un archivo encriptado y en tiempo de ejecución desencriptarlo y compilarlo / ejecutarlo JIT. Pero no se donde meter la clave, si la pongo en código se puede trazar, si la pongo el registro tambien, si la pongo en un archivo por supuesto, y si la encripto necesito otra clave para desencriptarla (nananana, arrrrggg!)  |:|


La verdad es que me asusta bastante esta "desproteción" del software, que para mi parece demasiado flagrante, y aunque sé que todos los lenguajes se pueden "crackear" esto me parece excesivo. El coste de la versatilidad y potencia de la reflexión en .NET aqui parece una de las mayores amenazas para la seguridad de tu producto.
Pero bueno, tengo la mayor parte de la funcionalidad del editor en C#, y la verdad es que me ha costado menos de la mitad que si la tuviera que haber hecho en C++, asi que no voy a cambiar a estas alturas de lenguaje.

Si alguien puesto en .NET me pudiera tranquilizar (aunque solo fueran un par de mentiras piadosas) quizás acabará antes de "rallarme" con todo este tema, y vuelva al código de funcionalidad del programa. (please)


Bueno, un saludo y gracias.

EDIT: otra cosa que estoy pensando es realizar crc o hash de los assemblies que contienen la proteccion, y comprobarlos en otras partes del programa, o utilizar el resultado como clave asimetrica para encriptar algo, todavia estoy cociendo la idea. No es un obstaculo insuperable, pero puede dar bastantes dolores de cabeza al que intente modificar un assembly. ¿alguna opinión al respecto?
#123
Muchas gracia por la explicación :)

Por ahora solo tengo en mente un par de posibles clientes para un par de proyectos.
Asi que la aplicación no deberia ir de manos en manos, y seguramente serian los mismos clientes los que se asegurarian de que la aplicacion por la que pagan la licencia no sale a terceras personas que pudieran aprovecharse de algo que solo ellos deberian tener.

Asi que solo me preocupan los "clientes", que, como es habitual, si pueden pagar 10 en vez de 20 no se lo piensan, aunque esos 10 fueran a parar a alguien contratado para "modificar ilegalmente" el programa, en vez de al desarrollador original del software. Y que quede claro que siempre he defendido compartir código y el open source, pero depués de ver como diferentes empresas hacian grandes cantidades de dinero a costa del trabajo y esfuerzos de "asalariados", no tengo ninguna gana de lo que sigan haciendolo a la mia, puesto que aqui ya no cumplo el papel de "asalariado".

Mi intención (y espero que asi sea, o muy mal me irá) es que el "engine" en si, vaya creciendo y evolucionando en cuanto a plataformas destino y features, de manera que puedo controlar que sean "necesarias" ciertas actualizaciones, y que las versiones anteriores del software queden, por necesidad, obsoletas. Lo cual me puede ayudar a ir integrando un sistema de proteccion cada vez más complejo, o, al menos, ligeramente modificado, por si la versión anterior ya ha sido reventada.

Por supuesto no pienso dedicarme al software antipirateria ya que ni siquiera me considero experto en lo que hago (y eso que cada dia se me hace más dificil recordar cuantos años llevo ya en esto), asi que ni decir tengo de meterme en algo en lo que estoy completamente pez (ahora mismo no veo capaz ni de desbordar un buffer).

El tipo de aplicación que estoy realizando no creo que sea la indicada para un público extenso, y, en caso de que compañias más "importantes" quisieran utilizar mi producto, he de decir que me fio más de ellas (por irónico que parezca), que algunas de las más "pequeñas" que ahora mismo puedan estar interesadas en mi producto. Simplemente por el echo de que el dinero de las licencias "se la pela" literalmente.
Cuando he currado en una empresa "multinacional" o una empresa "grande" hemos tenido licencias legales de todo el software, incluso licencias de sobra guardadas en un cajón y cogiendo polvo. Más tarde he llegado a una empresa más "modesta" como Lead Programmer y me han tenido con un portatil basura durante dos o tres semanas (perdiendo tiempo de productividad) por no gastarse el dinero en un PC (entre otras muchas barbaridades).

Asi que lo que me preocupa, una vez más, es que alguien pueda gastarse dinero en saltarse el if, con tal de salirse con la suya y no pagar el mismo dinero o un poco más a mi, que al fin y al cabo, soy el que ha perdido montones de horas de sueño y vida social.

En cuanto al tema se los serials / bulk, las fechas de activación, etc lo he implementado como técnica disuasoria. Primero, es fácil de implementar, simplemente se basa en encryptar/desencryptar texto con la informacion de la licencia, comprobar las fechas y las features de la version activada.
Si alguien no versado en el tema ve los cuadros de dialogo y que no puede iniciar la aplicacion, puede frenarle la idea, antes incluso de intentar averiguar realmente como esta implementada la protección. Por supuesto, alguien que tenga idea tardaria 0'01 seg en reventarlo.

Como tengo mucho más que implementar de la parte funcional del software, no puedo dedicarle mucho más tiempo a esto, pero aun asi Hechelion me ha interesado mucho el tema de la protección que implementas tú cifrando parte del código necesario, si fueras tan amable de recomendarme un par de enlaces donde pueda intentar ilustrarme sobre el tema te estaria muy agracedio, más que nada por intentar mejorar un poco (solo lo suficiente) el sistema de protección.

Y por cierto, y ya que veo que estas muy puesto en el tema, también me suelo preguntar como se puede demostrar que una aplicación (pongamos un juego de ps3,  por ejemplo) ha sido realizado con tu sdk o engine. ¿Analizando los binarios para encontrar los patrones de tus librerias por ejemplo?
Es otra cosa que me ronda la cabeza, como ves últimamente me estoy volviendo un poco paranoico, XD

Bueno, muchas gracias de nuevo.
Adew!

EDIT:
en cuanto a crear varios timers me parece una idea estupenda, asi que voy a intentar ponerme con ello cuando antes,  :D thank you!
Por cierto, cuando hablas de no utilizar una única función, ¿te refieres que seria mejor tener varias funciones que hagan lo mismo o algo parecido y cada vez que "salta" un timer llamar a una de ellas?
Bien pensado tiene sentido que si averiguas la dirrecion de la funcion que hace el check, te seria, más o menos sencillo, buscar las zonas donde se llama a la misma direccion, ¿no?
#124
General Programadores / Proteccion de Licencia para Software .NET
26 de Noviembre de 2010, 07:35:26 PM
Wenas.

Puede que hace unos años no me imaginara nunca haciendo esta pregunta, pero después de haber pasado por diferentes y variadas empresas (siempre que hicieran juegos, si es que eso se puede considerar variación XD), y haber visto lo que se cuece ...

El tema es que estoy desarrollando en casa un frame-work multiplataforma para PC y consolas next-gen (si, ya se que soy muy original). Basicamente se compone de una aplicacion/editor con soporte para plug-ins (de echo la mayoria de la funcionalidad está alojada en las .dll de los plugins) en C# (winforms/.NET), una serie de wrappers C++/CLR, y un player en C++ (bueno, uno para cada plataforma).

Mi problema ahora es como licenciarlo (entregar el software) y no arriesgarme a que me hagan la 3-14 (tb conocida en mi pueblo como: "la jugada fosca").

Para simplificarlo he decidido varias cosas:

* No distribuir el source de nada.
* Se podrian seguir desarrollando plug-ins para ampliar el editor.
* La "programación" seria completamente en script (de momento soporto Lua, aunque estoy pensando en integrar Python y Squirrell)
* El player siempre tiene la pantalla de splash, de modo que solo sirva de visualizador (tanto en el PC de desarrollo, como en la consola target)
* El editor no permita realizar el "empaquetado final" de los assets
* Para los masters o candidates versions que se deban enviar para checking a la compañia de la consola seria imprescindible que realizara yo la build final.
* El sistema de control de licencia solo esta instalado en el editor (desarrollarlo en C# es muchisimo más comodo).


El problema es que por mucho que le meto (y se me ocurre poner) al control de licencia:
* Guardado de datos sensibles encriptados
* Creación de Bulk Keys y License Keys
* Trial versions
* Caducidad de la licencia
* Control de cambio de fechas
* Verificación de licencia por servidor
* Grabacion y comprobacion de datos en registro de windows.

No me quito la sensacion que todo parece resumirse en que como alguien se salte el "if (LicenseManager.ChekValid())" que hay cuando arranca el editor todo esfuerzo es inutil.

He estado indagando en programas comerciales que te ofrecen soluciones en apariencia muy completas, pero a la hora de integrar (por los ejemplos que he visto) en tu programa es lo mismo, si alguien se salta el if ... hasta luego lucas.

He pensado en poner mas comprobaciones de licencia durante la ejecución de la aplicación, pero poca cosa más se me ocurre.

¿ Alguien está más familiarizado con esto?

Se que Vicente tiene idea (por no decir que es Dios) de todo el tema del .NET, el codigo que se produce al compilar, como decompilarlo, que si CLR, que si CLI, y todo eso que practicamente desconozco.
Mi pregunta tb seria como de facil es "reventar" una aplicacion de .NET para saltarse el if, o intentar trazar el comportamiento de la aplicacion, para descifrar  los algoritmos, claves y procedimientos del sistema de licencia. Sobretodo comparado con c++, porque tb habia pensado en hacer el sistema en c++ y ponerlo tanto en el player como en el editor (para lo que seguramente haria un wrapper C++/CLR y una bonita .dll).

Gracias de antemano a todos y un saludo.
#125
Cita de: Buffon en 21 de Junio de 2010, 09:04:16 AM
Si no recuerdo mal, en comandos1 no habían pisos, pero en el 2 sí.

En el uno podias ir navegando por el agua con la barca justo debajo de un puente por el que podias ir andando si no recuerdo mal. Esto serian "pisos", pero se podria solucionar si un bit indica si es "walkable", y otro si es "navegable". El dibujar el puente por encima o no se solucionaria con la info de z(orden de dibujado).
Con más información se podria indicar un rango de altura actual en la posicion en el mapa de durezas, y limitar el paso de una altura a otra, etc.
Tambien se podrian tener mapas de "sectores" para diferentes pisos y zonas del mapa, y hacer "links" entre ellos.

No sé, son ideas.

Salu2
#126
Cita de: tamat en 20 de Junio de 2010, 11:08:15 AM
...
ademas el sistema tenía información 3d muy simplificada de la geometria de la escena, y es la que utilizaba para temas de colisiones, campo de vision de las entidades, etc.

...

¿Estas seguro? A mi me suena que en el Comandos se pintaban las colisiones, sectores, etc en photoshop en una capa encima de la imagen ya renderizada, esta capa se exportaba aparte y se utilizaba como mapa  de "durezas" (como lo llamaban en el Div). Digo me suena, por que me lo contaran asi, yo NO he currado en Pyro.

De este modo las coordenadas del personaje se pueden mantener 2D(x,y) y no hace falta tener la representacion 3D(x,y,z) y tener que ir pasandola a 2D para situar el sprite a renderizar (esto quizas seria mejor para un estilo Marble Madness en "isometrico puro").

El mapa de durezas (MD) puede tener cualquier representacion parecida a una imagen (matriz NxM), aunque al no tener que dibujarse (excepto por casos de depuración) deberia estar en RAM de CPU para realizar las comprobaciones (aunque actualmente se podrian trabajar con modelos de shader > 3 y con las texturas en memoria de tarjeta).
En un ejemplo de color indexado a 256 colores tenemos un byte para cada pixel del MD, del que podemos utilizar por ejemplo 3 bits(8valores) para indicar el nivel de z (como orden de dibujado respecto a otros elementos), tres mas para el tipo de terreno (bloqueado, hierba, nieve, agua,  ...) y nos quedan dos bits que podemos utilizar para cualquier flag.

Otra cosa es que tampoco necesitas la resolución de la imagen de visualizacion, asi que podemos tener un mapa un 25% más pequeño(por ejemplo), y para encontrar la correspondencia del mapa de render con el de durezas solo tenemos que dividir por cuatro: // (suponiendo que utilizamos valores enteros como coord 2D)
xdurezas = (xscreen + xscroll) >> 2; ydurezas = (yscreen + yscroll)>> 2;


Tambien debes tener en cuenta que los sprites que esten dentro del mismo z (orden de dibujado) se deben dibujar segun su coordenada Y (que deberia de estar en el "bottom" o pies del objeto/sprite), de modo que el "personaje" que tenga los pies con mayor Y (más abajo) se pintará después que el que los tenga más "alto".

Por ultimo opino que los pathfinding (A*, crash&turn, etc) pueden funcionar mejor (mejor tiempos de ejecución, y mayor facilidad de implementación)  con esta representación que con representación 3D.

Pero es solo una opinión.
¿Alguien se le ocurren otras implementaciones o porque seria mejor utilizar representacion interna 3D de las coordenadas y pasarlas a 2D solo al dibujar?

Salu2
#127
Hay una relación entre el tipo de pipeline de contenido que utilices y el formato al que debes exportar.

Ante todo (como dice tamat) lo mejor es cargar un formato directo (lo más semejante a un Load-InPlace será lo más efectivo para los tiempos de carga). Diseñado especificamente para las necesidades de tu motor.

Si utilizas una pipeline basado en exportación (como Ogre por ejemplo), deberias exportar desde tu programa de edición directamente tu propio formato (mediante un plug-in como dice tamat).

Si utilizas pipeline basado en importación (como Unity, Phyre, XNA, ...) lo normal es exportar Collada o FBX. Puedes tener funciones de carga directa desde el FBX o Collada (que permiten rapida visualización, trabajo colaborativo en el caso de collada, etc), y funciones de conversion a formato propio, que es el asset final que incluirias en la build de juego.


Las ventajas del pipeline de contenido basado en importacion para mi son bastante claras. De todas formas dejo un link a un buen articulo de gamasutra: http://www.gamasutra.com/view/feature/4085/sponsored_feature_the_.php, y cada uno que decida su camino  :)


Salu2
#128
General Programadores / Re: Imprimir ListView
03 de Mayo de 2010, 11:29:43 PM
Ese tipo de desorden a mi me suena a que la base de datos esta indexando, y los ordena conforme le viene.
O que al hacer la consulta llegan de forma diferente cada vez, no sé.

Pero creo recordar que las listViews se podian ordenar por campo. Creo que se podia setear desde código y desde el editor de forms (me parece).
Aunque no suelo usar listView con "binding" a una base de datos, las utilizo para mostrar estructuras de datos internas, y modificarlas.


EDIT: Nada, me he rallao, creia que decias una DataGridView  ::)

^^

adew!
#129
Hola,

al final conseguí que rulara en la máquina Mono. Cuando obtenia el assembly con getExecuting solo me devolvia las clases que tenia registradas en el editor, pero al final pude obtenerlo a partir de la clase ArbolCompo y con un par de cambios más funciona bien :)

Por desgracia la maquina mono que utilizo no soporta LINQ y no puedo utilizar esos filtros  :( . Aunque la verdad me molan mucho, y para los editores en .NET la verdad es que es una caña (assetdb, busquedas sobre la jerarquia de escena, etc)  :D

Y ya puestos me molaria hacerte otra pregunta Vicente (si te viene bien claro :)).
Tu que sabes de IA y de C#.
Cuando comencé el diseño de los arboles estos, tenia pensado utilizar un objeto que fuera el Conocimiento del Agente, y que cuando se cambiara algo de él se marcara un flag de modificación, para que el árbol supiera que tenia que reevaluarse.

De forma automática en Lua lo que haria seria utilizar __newindex en la metatabla del objeto para indicar que todo cambio sobre ese objeto, activara el flag de modificado, y cuando acabara de evaluar el arbol deshabilitaria el flag manualmente.

En C# lo único que se me habia ocurrido era utilizar propiedades para cada variable del conocimiento, y cada set modificar el flag.
¿Se te ocurre una forma mejor? (la verdad es que no estoy muy puesto en c#)  ::)

Gracias nuevamente :)

ta luego
#130
Al final me autocensto yo mismo   |:|

Con esto tengo automatizado la lista de strings de las clases derivadas de ArbolCompo y sus acciones y condiciones.
Eso si, los enums se tienen que llamar de una forma determinada (TipoDeAccion, TipoDeCondicion).
El truco esta en hacer el Init solo al crear la ventana del editor, cerrarla para modificar los enums o el numero de clases derivadas de ArbolCompo, y volver a abrir la ventana más tarde (con lo que recarga los cambios por reflexion).

Aqui funciona, lo probaré en el curro con la maquina Mono. Ya digo algo.

La verdad es que ha sido más sencillo de lo que esperaba.

class ArbolCompoHelper
{
    public static void Init()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();

        // Obtenemos todos los types del assembly (igual un poco basto, pero weno)
        Type[] myTypes = assembly.GetTypes();
        List<Type> enemyBTs = new List<Type>();

        // Filtramos por los que sean subclase de ArbolCompo
        foreach (Type t in myTypes)
            if (t.IsSubclassOf(typeof(ArbolCompo)))
                enemyBTs.Add(t);

        // Creamos array de nombres de enemigos:
        int n = enemyBTs.Count;
        tiposDeEnemigos = new string[n];
        acciones = new string[n][];
        condiciones = new string[n][];
        // recorremos los tipos de los enemigos
        for (int i = 0; i < n; i++)
        {
            // seteamos el nombre
            tiposDeEnemigos[i] = enemyBTs[i].Name;
            // Buscamos y listamos los enums
            acciones[i] = ListaEnum(myTypes, enemyBTs[i].FullName + "+TipoDeAccion");
            condiciones[i] = ListaEnum(myTypes, enemyBTs[i].FullName + "+TipoDeCondicion");
        }
    }

    public static string [] ListaEnum(Type [] types, string nombre)
    {
        foreach (Type t in types)
            if (t.FullName == nombre)
                return Enum.GetNames(t);
        return null;
    }


    protected static string[] tiposDeEnemigos = null;
    public static string[] ObtenerTiposEnemigos()
    {
        return tiposDeEnemigos;
    }

    static string[][] acciones = null;
    static string[][] condiciones = null;

    static string[] ObtenerAcciones(int tipo)
    {
        return acciones[tipo];
    }

    static string[] ObtenerCondiciones(int tipo)
    {
        return condiciones[tipo];
    }
}


Espero que alguien le sirva de algo ^^

adew!
#131
Cita de: Vicente en 26 de Abril de 2010, 09:58:17 PM
Lo he leído dos veces y debo estar super espeso, porque no lo entiendo :(
Pues si tú no lo entiendes mal vamos ... XD

El post en si es espeso. Además no sé si me explicado bien y el tema igual es un poco complejo.
Bueno, voy a intentarme explicar un poco mejor. El código está en el curro, pero pongo algo de ejemplo.
Es como un arbol de comportamiento (aunque más bien es un arbol de decision). Lo que pasa es que he simplificado algunas cosas ya que no dispongo de mucho tiempo para invertir en esto.
Actualmente tengo en el runtime algo parecido a estos scripts de c# (funcionan en Wii bajo la vm mono de Novell):

// Nodos del arbol
class NodoArbolCompo
{
    List<NodoArbolCompo> hijos;

    public void EjecutarNodo(ArbolCompo arbol)
    {
        // Evaluamos condicion
        if (arbol.EvaluarCondicion(this.condicion))
        {
            // Ejecutamos Acción
            arbol.EjecutarAccion(accion);
            // Recorremos hijos ...
            foreach (NodoArbolCompo nodo in hijos)
                nodo.EjecutarNodo(arbol);
        }
    }

    string condicion;
    string accion;
}

// Agente / gestion del conocimiento del agente
class IAAgent
{
    // ... esto es otra historia
};

// Arbol de comportamiento (más bien de decisión)
class ArbolCompo
{
    NodoArbolCompo raiz;
    protected IAAgent iaAgent;

    public ArbolCompo(IAAgent agent)
    {
        iaAgent = agent;
        // ....
    }

    public void EjecutarArbol()
    {
        raiz.EjecutarNodo(this);
    }

    public void CargarArbol(string resourceName)
    {
        // ...
    }

    public void SalvarArbol(string resourceName)
    {
        // ...
    }


    // Para sobreescribir por las clases derivadas
    public virtual void EjecutarAccion(string accion)
    {
        // NOTHING
    }

    public virtual bool EvaluarCondicion(string condicion)
    {
        return false;
    }
}

// Acciones y Condiciones especificas del malo1
class ArbolMalo1 : ArbolCompo
{

    public ArbolMalo1(IAAgent agent) : base(agent)
    {
        // ...
    }

    public override bool EvaluarCondicion(string condicion)
    {
        bool b = false;
        // ...
        return b;
    }

    public override void EjecutarAccion(string accion)
    {
        // ...
    }
}


Se que es un tostón pero he intentado simplificarlo al máximo  ^_^'
El rollo es que cada nodo del arbol tiene dos strings (accion y condicion), la funcion ejecutarNodo y una lista de hijos.
Y ArbolCompo tiene el nodo raiz, una refencia al agente, metodos para cargar/salvar el arbol y dos metodos para sobreescribir por las clases derivadas: EjecutarAccion y EvaluarCondicion. (como he dicho esta muy simplificado).

Bien ahora tengo el editor:


En el editor mantengo una copia de un objeto generico ArbolCompo, y utilizo los metodos de cargar y salvar. Las acciones y condiciones se editan en una textBox.
En runtime cargo el archivo en cualquiera de los derivados de arbolCompo y a funcionar.

Todo esto surgio en una versión de prueba, pero ha funcionado bien y tenemos que iterar y mejorarlo.
La primera cosa que pensé es que cada vez que evaluo el arbol debo comprobar los strings (lo hice asi es su momento para simplificar y de prueba) y es mas caro que comprobar enteros. Además del problema de equivocarte al escribir alguna cadena.
La solución es bastante clara, voy a sustiuir los strings de condicion y accion por un int en las funciones, y a a crear enums dentro de cada clase que derive de el arbol generico para las condiciones y las acciones.

El problema lo tengo en el editor.
Como solución rápida seria sustuir el string por el un id de un numero con la acción a realizar. Pero seria poco informativo ver el árbol de esa forma. Asi que me molaria tener una lista desplegable de opciones para cada acción y condición de cada nodo.
Además tengo que poner otra lista en de seleccion del tipo de arbol que estamos editando (cada uno puede tener unas acciones y condiciones diferentes).
Y de momento la interfaz de mi editor que tengo para llenar ese tipo de lista son un array de strings.

Editor deseado:


Entonces, primera solución para obtener los [] string de tipo de arbol, condicion y accion:
class ArbolCompoHelper
{
    static string[] tiposDeEnemigos = { "Malo1", "Malo2" };
    static string[] ObtenerTiposEnemigos()
    {
        return tiposDeEnemigos;
    }

    static string[] accionesMalo1 = { "Dispara", "SalCorriendo", "Pasea", "UrgarNariz" };
    static string[] condicionesMalo1 = { "VesEnemigo", "EnemigoCerca" }; // ...

    static string[] accionesMalo2 = { "LanzaGranada", "EchateAlSuelo", "Rascate", "DaOrdenes" };
    static string[] condicionesMalo2 = { "EnemigoATiro", "EstasCansado", "PocaVida" };

    static string[] ObtenerAcciones(string tipo)
    {
        switch (tipo)
        {
            case "Malo1": return accionesMalo1;
            case "Malo2": return accionesMalo2;
        }
        return null;
    }

    static string[] ObtenerCondiciones(string tipo)
    {
        switch (tipo)
        {
            case "Malo1": return condicionesMalo1;
            case "Malo2": return condicionesMalo2;
        }
        return null;
    }
}


Y en cada derivada de CompoArbol queria poner estos enums:
enum TipoDeAccion
    {
        Dispara = 0,
        SalCorriendo,
        Pasea,
        UrgarNariz
    }

    enum TipoDeCondicion
    {
        VesEnemigo = 0,
        EnemigoCerca
    }

   // Para poder hacer:

    public override bool EvaluarCondicion(int condicion)
    {
        bool b = false;

        switch ((TipoDeCondicion)condicion)
        {
            case TipoDeCondicion.EnemigoCerca:
                // ... return iaAgent.dist2Player < 1.0f;
                break;
            case TipoDeCondicion.VesEnemigo:
                // ...
                break;
        }

        return b;
    }


El problema es que para añadir una nueva acción (por ejemplo) tengo que añadir el enum y la lógica de EvaluarCondición en la derivada del ArbolCompo, y añadir por otra parte el nombre de la condicion en el array correspondiente de ArbolCompoHelper. (Y ambos estarán en .cs diferentes). Además no me puedo descuidar los indices ya que el nombre del array se tiene que corresponder con el indice que marca el enum correspondiente de cada clase.
Y la cosa es peor para añadir un nuevo enemigo, ya que tengo que definir en el heper sus arrays, llamarlos desde el case, etc.
Con lo que se me antoja complicado de mantener, y muy susceptible a errores (ahora tb lo es, pero se supone que lo tengo que mejorar).

Y después de todo este infierno de post  :-[ tengo solo 4 preguntas para usted señor Vicente  :-[ :-[ :-[ :-[
1) Puedo obtener al abrir el editor (y solo desde él) con reflexión un [] string con el nombre de todas las clases derivadas de ArbolCompo ??? Como?
2) Puedo obtener un array con los nombres de un enum ordenados segun su indice ??? (supongo que si xo ...) Como?
3) Puedo utilizar la info que he sacado del punto 1, para de alguna extraña forma acceder a un desglose (p.2) de un enum de esa clase selccionada? Comoooor?
4) ¿Alguna solución mejor?

Bueno, gracias y perdon por el peñazo, pero ya viene siendo habitual en mi estos post moliticos  0:-)

como dijo el sabio: Buenas noches y buena suerte
voy a dormiiiiiillll por hora
#132
Hola, me encontrao con un problemilla scriptando algunas cosas del editor de arboles de comportamiento de nuestro ultimo juego.
Espero que alguien con más conocimientos de c# que yo me pueda decir si lo que quiero se puedo hacer.

Tengo una jerarquia de clases parecida a esta:
BehaivourTree (arbol generico)
-> Malo1BT ( deriva de BehaivourTree )
-> Malo2BT ( deriva de BehaivourTree )
-> ...

En mi editor por cada nodo me tienen que salir una lista de acciones y condiciones disponibles.
El problema viene cuando cada clase derivada (Malo1BT, Malo2BT, ...) tiene una lista de acciones y condiciones diferente.

En un principio (en teoria) tendria que tener el objeto final (Malo1BT, ...), entonces bastaria con que esta clase tuviera implementado un metodo ObtenAcciones/Condiciones que fuera abstracto (preferiblemente) enla clase genérica BehaivourTree.

Pues bien, el tema es que he implementado que cualquier clase derivada pueda cargar cualquier tipo de arbol. Por tanto en mi editor tengo un BehaivourTree genérico (no puedo hacerlo abstract), luego el arbol se graba como una serie de indices (int) en disco, y se carga en tiempo de ejcución ( ... y si, funciona bastante, bastante bien  ;) )

Pues bien, para que en el editor se sustituyan los indices por los nombres de las acciones y condiciones disponibles he pensao en obtener dos arrays de strings (1 x acciones y otro para condiciones). En el editor (parte superior izq) debe haber una lista con los tipos de arboles (por enemigo), y que indique que arrays de strings tenemos que obtener.

Por tanto para cada TIPO clase (Malo1BT, MaloBT2, ...) tengo dos arrays de strings ( acciones / condiciones ). Que se corresponden con los indices de un enum que tiene cada clase con sus acciones/condiciones.

Como obtenerlos:
1) Clase estatica "BehaivourTreeHelper" que contiene métodos estaticos para listar los tipos de enemigos ( string [] ObtenerTiposEnemigos() ). Y metodos para obtener acciones/condiciones por tipo de clase ( string [] ObtenerAcciones(Type p) o ObtenerAcciones(string nombreClase) ).

2) Mi problema es que defino enums con las acciones dentro de cada clase derivada (Malo1BT por ejemplo).
Y mantener los indices del array de strings en una clase diferente me parece un poco lioso.
Asi que preferiria escribir un método estático en cada clase que obtenga el array. Pero al ser estatico no puedo aplicar ningun tipo de polimorfismo (creo) para decir: todas las clases q derivan de BehaivourTree tiene ue tener un metodo ObtenAcciones, y luego obtener estas acciones dependiendo del tipo.

3) Lo cojonudo del todo seria poder además utilizar Reflexion (pensar que el coste me la suda un poco, porque estoy en el editor, no en el runtime del juego ni en el engine) y obtener las listas de strings a partir de los enums. Pero no tengo mucha idea. Quizás alguien (seguro) ha echo algo parecido y me puede dar una idea de como abordarlo.


Bueno, que opinais al respecto, ¿a alguien se le ocurre una solución?
Pues nada gracias a todos de antemano.

Nos vemos!!!
#133
Cita de: [EX3] en 17 de Marzo de 2010, 02:18:13 PM
En DirectX se supone que eso *creo* se podia hacer mediante los SwapBuffers o SwapChains, creo que era algo como separar o tener dos buffers de renderizado que podias asociar a diferentes ventanas. Si le sirve a alguien entendido en materia como referencia para aconsejarte con algo mas detalle...

Las Swap de dx valen para no tener que crearte varios devices si quieres renderizar en varias ventanas, y no perder mucho rendimiento (ejemplo claro: world editor con varias ventanas de vista: front/top/left/perspective). Aunque si te creas varios devices con una swapChain por cada device también funciona. (lo he probao :) )
Pero en un principio (y remarco lo de "en un principio") no te dan información sobre el monitor que estas utilizando.
Hay samples en el DX_SDK de multiple monitor, y creo que es de donde más info se puede sacar (si vas a estar usando DX, claro).

Cita de: ZüNdFoLGe en 17 de Marzo de 2010, 01:47:24 PM
No veo diferencia entre usar swing o un terminal de consola (eso depende de lo que tu estes imaginandote, cosa que no sé), la pregunta es clara, nunca mencioné la palabra 'juego'. ...

??? No hay diferencia? Bueno, creo que dejaré esto de programar, ... creo que vi unas opos por ahi para barrendero, igual ...
La palabra "juego" raramente deberia darse por sentada en un foro como este, de claro matiz taurino.

LA PREGUNTA DEL MILLÓN (lo que todos estabais deseando preguntar):
+ Porque no te creas dos ventanas. Colocas cada una en un monitor y en cada una pintas lo que te salga de los h****s quieras?????
+ Lo que quieres es una ventana que cuando la cambies de monitor cambie de color lo que estas renderizando en él?

Dios mio estoy perdido!! Menos mal que la pregunta estaba clara!!


Adew
#134
General Programadores / Re: Listas de errores/todo
17 de Abril de 2010, 10:13:43 AM
Cita de: Mars Attacks en 15 de Abril de 2010, 07:54:44 PM
Mantis

Mantis poweeeer!!
jejeje

1) Para planificación usaria Merlin (para MacOs, MsProject para windows) si quieres ir en plan diagramas de gantt y tal (pero las licencias de estos progrmas no son "baratas" precisamente, además que suelen ser un poco liosos y tienen su rollo).
Hay otras "alternativas" libres y basadas en java y otras teconologias multiplataforma que tb te pueden servir.
Utilizando MsProject, en una ocasión, hice un programa en C#/WinForms cliente que "se conectaba" al un documento de project compartido en la red interna y utilizaba las interOps para ofrecer una interfaz sencilla (y controlada) para el acceso a los proyectos por parte tanto de los "trabajadores" como de los "gestores del proyecto". Los incovenietnes son que cada ordenador que se conectaba debia tener instalada una copia del MsProject, además de otras tipo de cosas que han dejado de gustarme de la "planificación tradicional" que ofrecen este tipo de programas.

2) Yo en cada empresa que he currado (exceptuando las que tenian un sistema propietario similar) he acabado instalando un apache con php y MySql y rulando un Mantis. Puedes usarlo y configurarlo como quieras, y con un poco de tiempo te puedes montar un buen servicio web para tu intranet que te lo maneje todo (docs con semaforos, tareas, bugs, svn, etc).
Hay otras aplicaciones de servicio web que estan bastante bien tb (google is your friend). Y si quieres llevar un buen control de bugs, issues y features con varios testers (sobretodo si estan en otros estudios o un poco "lejos") al final tendrás que pasar por aqui.

3) Si quieres algo más sencillo el ToDoList (busca en codeProject) esta muy bien, pero creo que no hay port para MacOs (aunque si tienes algo de tiempo podrias echarle un ojo ya que creo que distriuyen el source), y realmente es de las mejores y más sencillas aplicaciones que he visto de este tipo.

4) Si tiras más hacia el desarrollo ágil: "Everybody loves Excel". En mis últimos proyectos utilizo backLogs en excel con unos cuantos macros en VB que me permiten automatizar bastantes cosas de manejo de tareas. También es una opción si lo integras con MsProject para que te saque gantts o algún tipo especifico de informe.
No sé hasta que punto paquetes "Office abiertos" como Open o Star Office pueden rular macros ni de que tipo son, pero tb son buenas alternativas.

5) GoogleDocs está bastante bien sobre todo porque puedes utilizar los dataSheets para las tareas y los bugs. Además de que siempre que tengas conexión puedes acceder a ellos (prácticamente desde cualquier lugar). Pero que yo sepa no hay soporte para scripts o macros que te permitan automatizar la gestión de tareas en los dataSheets.


Al final hay muchas opciones, y ninguna es la mejor, depende bastante de tu tipo de proyecto, tu forma de trabajo, etc.


Espero haber servido de alguna ayuda :)

Adew!

PS: El RedMine no tiene mala pinta, igual un dia le echo un ojo (dios!, necesito tiempoooooooo)  :(

[EDIT] -> Muchos IDEs tb permiten una gestión de TODOs y otro tipo de tareas básicamente de programación, con el añadido de que puedes meterlo en el código directamente con comentarios del tipo:
// TODO implementar x
// TOFIX optimizar z

aunque supongo que ya lo sabias  ::)
#135
General Programadores / Re: PhyreEngine, se puede descargar?
17 de Abril de 2010, 08:57:07 AM
Hola,

el Phyre rula en PC con DX o OpenGl (win/linux), pero la verdad es que hay motores más "completos" y más fáciles de conseguir (y de usar) si lo que estás pensando es en hacer algo para PC.
Además Phyre esta optimizado para Cell y para utilizar las SPUs, y es donde le sacarás más partido (aunque solo sea para desmenuzarlo y cogerte lo que más te interese como manejo de jobs, código de SPU, etc.).
La compatibilidad con PC creo que realmente solo viene bien para las tools, y para previsualizar pequeños cambios (sobretodo afinación de gameplay y estas cosas) sin tener que estar mandando cosas al devKit (además chungo que todos los developers de una empresa tengan un devkit con lo "baratos" que son  ::)).

Si lo que quieres es hacer algo para PS3 tranqui que lo puedes tener nada más ingreses en la scedev(si tienes que hacer algo para ps3 tu empresa deberá estar registrada como desarrolladora autorizada) y te bajes todo el mogollonazo de gigas entre sdks y cosas.

No te puedo decir mucho más (NDA), pero yo que tú miraria otras opciones :)

Un saludo!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.