Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Identificadores únicos Gestor de Recursos

Iniciado por adrigm, 04 de Enero de 2013, 09:21:09 PM

« anterior - próximo »

adrigm

Vamos a ver, planteo mi problema.

Estoy creando un gestor de recursos para mi proyecto. Este consiste en "añadir" unas rutas relativas a la ruta del ejecutable donde cargar recursos, algo así.

sm->AddDirectory("Data");

esto agregaria la siguiente ruta de búsqueda de recursos: "ruta/del/ejecutable/Data/"

si ahora hago


sm->AddDirectory("Data/a");
sm->AddDirectory("Data/b");


Tengo 3 rutas donde buscar recursos:


  • "ruta/del/ejecutable/Data/"
  • "ruta/del/ejecutable/Data/a/"
  • "ruta/del/ejecutable/Data/b/"

Bien ahora pongamos que quiero cargar una imagen. usaría lo siguiente:

sm->GetImage("sprite.png");

Esto lo que haría primero buscar si el recurso "sprite.png" está ya cargado, en cuyo caso simplemente devuelve una referencia a él. En el caso de que no lo esté "busca" en los directorios establecidos, lo carga y devuelve la referencia.

Bien el problema es cuando yo tengo lo siguiente:

  • "ruta/del/ejecutable/Data/a/sprite.png"
  • "ruta/del/ejecutable/Data/b/sprite.png"

Como vemos al "buscar" no sabemos a cual se está refiriendo el usuario de los dos. Una solución sería que en caso de ambigüedad el usuario pudiera especificar el directorio en el que buscar, algo así:

sm->GetImage("sprite.png", "Data/a");

Pero entonces, ya el identificador único no podría ser "sprite.png" porque sería ambiguo, tendría que ser la ruta comleta:

"ruta/del/ejecutable/Data/a/sprite.png"

con unos identificadores únicos tan largos que son cadenas de caracteres sería ineficiente ya que sabemos que la comparación de cadenas no es algo muy eficiente.

Se admiten propuestas y soluciones.
http://razonartificial.com/ - Blog personal sobre desarrollo de videojuegos

AgeR

Hola!

Supongo que cada uno te dará una solución, porque hay muchas, unas más complejas que otras.

Yendo a lo sencillo: "ruta/del/ejecutable/" te lo puedes ahorrar de la cadena identificadora del recurso, porque por lo que dices va a ser igual en todos.

Otra combinación sería tener todas las texturas por ejemplo en un mismo directorio, y jugar con sus nombres: "sprite_a.png", "sprite_b.png". Al cargar una textura sabes en qué directorio buscar y sabes que dentro del directorio los nombres serán únicos.

Hay soluciones mucho más elaboradas, pero si no vas a cargar recursos dinámicamente durante el gameplay por ejemplo, es más que suficiente.

Si quieres algo más elaborado, puedes montarte un script que te recorra todos los directorios de datos y te genere un archivo de cabecera con pares (ID, recurso) a partir de la ruta del archivo, y luego en código referenciarlos por el ID en vez de por el nombre.

Pero vamos, yo no añadiría directorios genéricos de datos, sino más bien cosas como sm->AddTexturePath("Textures"); sm->AddMusicPath("Music"); etc...

Si después haces sm->GetTexture("sprite_a.png"); ya sabe en qué ruta ha de buscarlo al ser una textura.

No sé si he aclarado algo o te he liado más...  |:|

adrigm

Me has aclarado, me has aclarado.

El problema viene de que no es un Juego sino un pequeño framework genérico lo que estoy realizando y no quería imponer nada a la hora de gestionar los directorios de los diferentes proyectos puede que a unos les convenga una estructura de directorios y a otros otra.

Por eso no puedo tener un método de carga de recursos específicos porque hay algunos generales, pero se pueden extender otros mediante plugins. Todo esto se podría implementar en un Asset Manager mediantes plantillas y programación genérica, pero no quiero enredarlo tanto.

Creo que voy a optar por que se defina un directorio donde buscar recursos y luego cada recurso deba buscarse por su ruta relativa, algo así:

sm->ResourcesDirectory("Data");

sm->GetTexture("textures/sprite.png");




http://razonartificial.com/ - Blog personal sobre desarrollo de videojuegos

AgeR

Ah vale, jeje

Siendo un framework que van a usar terceros, lo mejor es siempre lo más sencillo para el usuario. La opción que propones es simple y clara, aunque nada impide al usuario hacer

sm->GetTexture("textures/bichos/futuristas/metalicos/armados/peligrosos/terminator.png");

con lo que tendrías el mismo problema del principio. Pero como dices, si no quieres complicarlo, la solución está bien. Si el usuario busca recursos ya precargados masivamente durante el gameplay sí que podría ser un problema el tiempo de búsqueda.

adrigm

Se me ocurre que con este método definir un sistema antiusariospuñeteros (por definirlos xD) podría ser creando un hash de cadenas, así las comparaciones serían más rápidas.
http://razonartificial.com/ - Blog personal sobre desarrollo de videojuegos

FANatiko

Creo que estás intentando solucionar un problema que, en la práctica, no existe.

El identificador "global" de una textura en tu asset manager, yo creo que debería ser la ruta de la textura (aunque, como dice AgeR, el path del .exe no es necesario). Pero, hay una diferencia entre el identificador "interno" que usa el AssetManager para saber si tiene que cargar o no una textura y el "identificador" que usan los usuarios para cargar una textura.

Si tienes un sistema donde "montas" carpetas como lo que cuentas. Lo normal es que buscando "sprite.png" obtengas el primero que encuentres. Por este motivo, en este tipo de sistemas es bastante comun que el orden de montado importe. Vas a tener que tratar, eso sí, el caso de referencias entre ficheros. Cuando cargues un fichero de "Data/b", las referencias siempre las deberías considerar "relativas" y, si no lo encuentras, ya dejar que busque.

De todas formas, si quieres montar un sistema como este, te recomiendo que o bien coges PhysicsFS (si programas en C/C++) o bien te programas la posibilidad de montar todo en uno (o varios) .zip (de forma que puedes tener toda la lista de ficheros cacheada, porque los FileExists al FS suelen ser caros).

julen26

Cita de: adrigm en 04 de Enero de 2013, 09:21:09 PM

Pero entonces, ya el identificador único no podría ser "sprite.png" porque sería ambiguo, tendría que ser la ruta comleta:

"ruta/del/ejecutable/Data/a/sprite.png"

con unos identificadores únicos tan largos que son cadenas de caracteres sería ineficiente ya que sabemos que la comparación de cadenas no es algo muy eficiente.

Yo optaría por esta opción más simple por razones que ya han comentado. Yo uso este método.
Además si para guardar los recursos usas por ejemplo una tabla hash o similar, al guardar valores hash de la clave (en este caso la ruta), no se hará la comparación de caracteres que te preocupa.

[EX3]

#7
Cita de: FANatiko en 05 de Enero de 2013, 12:10:23 PM
Si tienes un sistema donde "montas" carpetas como lo que cuentas. Lo normal es que buscando "sprite.png" obtengas el primero que encuentres. Por este motivo, en este tipo de sistemas es bastante comun que el orden de montado importe. Vas a tener que tratar, eso sí, el caso de referencias entre ficheros. Cuando cargues un fichero de "Data/b", las referencias siempre las deberías considerar "relativas" y, si no lo encuentras, ya dejar que busque.
Me acabas de recordar justo el sistema que usan los motores de id software (los de Quake en concreto) y Valve (Gold y Source, si no me equivoco con este ultimo no ha cambiado). En estos tu tenias digamos paquetes de archivos (piensa en ZIPs para que te sea más sencillo verlo, y de hecho asi lo hacian los de id a partir del Quake 3). Este sitema te permitia tener varios paquetes de archivos con estructuras iguales o distintas.

Si usabas estructuras iguales podias añadir actualizaciones facilmente de assets ya existentes sin perder los anteriores, ya que a la hora de buscar un asset concreto, si este estaba repetido siempre se devolvia el correspondiente, por orden alfabetico, del paquete más nuevo (aqui los paquetes se solian llamar pak0, pak1, pak2, siendo pak2 en la practica, el que deberia ser más reciente).

Si usabas estructuras distintas simplemente añadias nuevos assets a la estructura del gestor de assets. La idea siempre era que el gestor de assets se montaba la estructura con los assets unicos teniendo en cuenta lo que te comentaba en caso de encontrar assets con el mismo nombre y ruta en distintos paquetes. Sobre el id unico, en este sistema no se complicaron demasiado la cabeza, el id del assets siempre era su path + nombre en los paquetes ("textures/walls/rocktile.jpg" por ejemplo).

Cita de: adrigm en 04 de Enero de 2013, 09:21:09 PM
con unos identificadores únicos tan largos que son cadenas de caracteres sería ineficiente ya que sabemos que la comparación de cadenas no es algo muy eficiente.
Sinceramente, salvo que vayas a gestionar millones de assets, piensa que en la practica, la busqueda y carga de un asset en el gestor la haras en un punto concreto de carga del juego o seleccion puntual en un editor, despues ya tendras ese asset procesado en un objeto instanciado al que haras referencia directa para trabajar con el. Yo no me complicaria la vida y tiraria de comparacion de cadenas de toda la vida.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt






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.