Tiled based games en C++: ¿Cómo plantearlo?

Temas relacionados con la programación y la actualización audiovisual
User avatar
benway
Usuario avanzado
Posts: 172
Joined: Sun Apr 03, 2005 1:22 pm
Location: Madrid

Tiled based games en C++: ¿Cómo plantearlo?

Postby benway » Sun Jun 05, 2005 9:50 am

Hola!

Tras Horacio Esquiador y sus mil actualizaciones ;) voy a volver a la carga con otro remake. Quiero hacer un "Tiled based game" con mapeado grande, tipo "Goody" o "Phantomas", y, dado que mis conocimientos de programación son más bien escasos, pues me han surgido un par de dudillas que querría consultaros...

Programando en C++, aunque más que el código concreto lo que necesito es que me aclaréis las ideas ;) ...

-¿ Como guardo el mapa en memoria ? He pensado usar una clase "tile", y otra clase "pantalla", y asignar un número a cada "localidad" del mapa. Esa clase "pantalla" tendría o bien una lista enlazada de los tiles que tiene, o bien un puntero a punteros de int (o char) para crear una matriz dinámica con los tiles que le corresponden, y, además, los números de las localidades que se "conectan" con esta, y en que sentido cada conexión (tipo aventura conversacional). ¿Os parece buena idea? Querría, lógicamente, escribir un código que pueda re-utilizar más tarde, y, aunque no sea necesario en este juego (que todavía no voy a desvelar ;), hasta que no tenga alguna demo visible), querría que fuera compatible con pasar de una "localidad" a otra con scroll continuo (tipo Super Mario Bross o Sonic), que no se vea cual es una localidad y cual otra (Como han hecho los chicos de Coptron games con los grupos de 3 localidades horizontales en el Goody)

-Otra cosa que no se muy bien como hacer es que si planteo el mapa como un "scroll continuo"... ¿Cómo defino las posiciones de los enemigos? Lo único que se me ocurre es asignar a cada tile unas coordenadas "absolutas" dentro del mapa, y definir el movimiento de los enemigos usando esas coordenadas "absolutas" (a parte de las "relativas" o "reales" en la pantalla que tenga cada enemigo y cada tile) (Me sería fácil definirlo si cada vez que cambiamos de localidad se borra la pantalla y se redibuja sin scroll... Sería añadirlos a los datos de cada localidad, y no habría que distinguir entre coordenadas "absolutas" y "reales")

- Cuando ponéis en una "localidad" un objeto que tenga más de un tile (por ejemplo... un bloque de piedra de 4 x 4 tiles)... ¿lo partís en sus 16 tiles o lo ponéis a parte, como tal objeto? Supongo que lo partiréis, sería cuestión de que el "editor de niveles" lo haga automaticamente...

Muchas gracias por adelantado ;) (Por las sugerencias y por haber leído todo este ladrillo ;))
Un saludo.Image - Image
User avatar
Popolon
Usuario avanzado
Posts: 474
Joined: Tue May 13, 2003 2:31 pm
Location: Lloret de Mar
Contact:

Postby Popolon » Sun Jun 05, 2005 12:00 pm

hay muchísimas alternativa.

Empecemos por como guardar el mapa:

a) la opción más sencilla es considerar que todos los "tiles" son del mismo tamaño. Y por tanto, una "localidad" (habitación o como quieras llamarle) se puede definir simplemente como una matriz, donde en cada casilla guardes el tile que va en cada posición. (por supuesto, puedes tener varios niveles de profundidad, y definir cada "localidad" por varias matrices). En esta opción, el caso de la piedra de 4x4 que dices, se dividiría en sus 16 partes. Por poner un ejemplo, yo utilicé esta opción en el "Maze of Galious" y en el "Transball"

b) una opción un poco más elaborada es permitir q cada "tile" tenga un tamaño diferente. Y por tanto, una "localidad" no puede definirse con una matriz, sino con una lista de "tiles-posicionados". Un "tile-posicionado" es una tripleta: (x,y,tile). En esta opción, tu piedra de 4x4 sería un único tile más grande. Por ejemplo, yo estoy utilizando esta opción en el "F-1 Spirit", el "Magical Tree" y el "Maze of Galious 2".

Sobre el tema de coordenadas globales/locales, tambien hay muchas opciones, pero te explico la que (despues de probar unas cuantas) a mí me ha gustado más:

Divides el mapeado del juego en función a 2 conceptos:
- Mapas
- Habitaciones

El mapeado del juego está compuesto por una serie de "mapas". Un "mapa" es un conjunto de habitaciones conexas. Por ejemplo, en un juego estilo zelda, habria un "mapa" para el mundo, y un "mapa" para cada una de las cuevas, castillos, etc. Un juego como "phantomas" estaría compuesto por un único "mapa".

Dentro de cada "mapa", puedes definir unas coordenadas absolutas de mapa. Cada abitación tendrá una coordenada en el mapa también. Por tanto, la equivalencia entre coordenadas locales de "habitación" y de "mapa" es: "coordenada mapa de un objeto" = "coordenada habitación del objeto" + "coordenada mapa de la habitación en que está".

De esa manera, puedes especificar las posiciones de los enemigos tanto en coordenadas mapa como en coordenadas habitación, y es facil realizar la conversión.

Bueno, espero haberme explicado... :wink:
User avatar
benway
Usuario avanzado
Posts: 172
Joined: Sun Apr 03, 2005 1:22 pm
Location: Madrid

Postby benway » Sun Jun 05, 2005 4:25 pm

Gracias!

El sistema de "tiles posicionados" es el que usé en Horacio Esquiador para las pistas de esquís: Cada "objeto de la pista" es un tile, con una x e y absolutas. La clase "pista de esquí" ya se encarga de hacer las conversiones de globar a local. Lo que pasa es que en el Horacio... la "vista" se desplaza en una única dirección, y además a velocidad constante, así que, metiendo los datos de los tiles ordenados segun su coordenada y, puedo tener un tile "índice" (el primero que se tiene que dibujar) que irá "avanzando" consecutivamente en la lista, y en el momento que un tile tiene una coord y que lo sitúa fuera de la pantalla dar por concluido el retrazado de la pista... pero... no sé muy bien como hacerlo para no tener que intentar dibujar todos los tiles del "mundo" correspondiente y valorar individualmente si están o no dentro de la pantalla...

Muchas gracias de nuevo :oops: :)
Un saludo.Image - Image
User avatar
benway
Usuario avanzado
Posts: 172
Joined: Sun Apr 03, 2005 1:22 pm
Location: Madrid

Postby benway » Sun Jun 05, 2005 4:31 pm

Oops... si es que soy demasiado rápido y escribo antes de leer BIEN la respuesta... :oops: :oops: :oops: :roll:

Ya lo veo:
Divides el mapeado del juego en función a 2 conceptos:
- Mapas
- Habitaciones
Ok... solo hay que dibujar las habitaciones que estén en ese momento en la pantalla :)

Así, a priori, este sistema de los tiles posicionados me parece más indicado para usar el scroll del que hablábamos antes, y el de las matrices de tiles para pantallas fijas tipo "abu simbel"... pero supongo que es solo una "primera impresión"
Un saludo.Image - Image
User avatar
na_th_an
Usuario avanzado
Posts: 66
Joined: Wed Mar 10, 2004 2:01 pm
Location: Sevilla
Contact:

Postby na_th_an » Mon Jun 20, 2005 2:25 pm

Sí, de hecho es mucho más fácil (y rápido) hacer Scroll con un mapa de grid (matriz 2D de tiles). No toma más de 10 lineas de código :)
La misión ha fracasado:
Has perdido tus efectivos.
User avatar
benway
Usuario avanzado
Posts: 172
Joined: Sun Apr 03, 2005 1:22 pm
Location: Madrid

Postby benway » Sun Jun 26, 2005 10:15 pm

Sí, es que como en Horacio hice algo parecido a "tiles posicionados", y un scroll... pues me pareció más fácil por eso, pero para un mapa grande, la cosa cambia.

Luego tb. me imagino que dependiendo de la cantidad de "tiles" por pantalla será más eficiente una u otra forma.

Otra preguntilla que me ha surgido (a todo esto, todavía no he empezado ni una sola línea de código :? )... ¿Cómo tratáis los objetos y enemigos? ¿Hago una lista enlazada con todos los objetos y enemigos del juego (Weno, 2 listas, una para cada cosa)? Esto lo veo más fácil, pero menos eficiente... habría que actualizar el movimiento de todos los enemigos, y chequear la colisión contra todos los enemigos y todos los objetos en cada ciclo del juego... ¿O 2 listas enlazadas por cada habitación? Entonces... ¿Cómo hacer para que cuando matas un enemigo / coges un objeto no vuelva a aparecer? La única solución que se me ocurre es crear las 2 listas por cada habitación al ppio del juego, es decir, las 2 listas de todas las habitaciones... y luego usar punteros para direccionar la "lista activa" a la lista de la habitación correspondiente, pero seguro que hay soluciones más fáciles y eficientes...

Muchas gracias :) Seguro q luego cuando me ponga a programar me surgen la "inspiración" más fácilmente, pero quiero, aunq solo sea x una vez, tener un planteamiento previo del programa que me sirva para no encontrarme sorpresas luego... y además, creo que mis neuronas se han ido ya de vacaciones ( o q por el calor están poco activas)... de ahí q necesite tanta ayuda :wink:
Un saludo.Image - Image
User avatar
Popolon
Usuario avanzado
Posts: 474
Joined: Tue May 13, 2003 2:31 pm
Location: Lloret de Mar
Contact:

Postby Popolon » Mon Jun 27, 2005 12:07 am

Para ahorrarte comparar todos con todos, puedes dividir el mapa según una parrilla, y para cada cuadrado de la parrilla tienes una lista de objetos. Entonces, solo debes comprobar colisiones entre objetos que estén dentro del mismo cuadrado (o que estén en los cuadrados adyacentes).

Sobre lo de hacer que los objetos y enemigos no reaparezcan. Yo como lo hice es así:
- cada enemigo y objeto tiene un identificador único (un entero) (todos menos los objetos sin importancia, como las monedas que sueltan los bichos al matarlos, etc, que tienen identificador = -1 )
- existe una lista objetos prohibidos (es decir, monstruos u objetos que no tienen que volver a reaparecer), que guarda parejas <T,ID>
- cuando un enemigo muere o un objeto es cogido, se añade una pareja <T,ID> de la lista de objetos prohibidos
- si se quiere que un objeto no reaparezca nunca más, se añade la pareja <-1,ID>
- si se quiere que un objeto no reaparezca durante los próximos X ciclos de juego, se añade <X,ID>
- a cada ciclo, se le resta uno a los contadores de tiempo de cada pareja de la lista de objetos prohibidos (excepto los que tengan contador de tiempo = -1). Cuando los contadores llegan a cero quiere decir que los objetos/enemigos pueden volver a reaparecer, y se eliminan de la lista de objetos prohibidos.

Bueno, no sé si es una buena solución. Pero después de pensar unos dias, es la que más me convenció. :wink:
User avatar
na_th_an
Usuario avanzado
Posts: 66
Joined: Wed Mar 10, 2004 2:01 pm
Location: Sevilla
Contact:

Postby na_th_an » Mon Jun 27, 2005 11:46 am

Dios, me pierdo entre tanto objeto :D no sabéis lo que os admiro a los programadores de lenguaje OO. Con lo contento que estoy yo con mis arrays de estructuras y mis punteros a función :D
La misión ha fracasado:
Has perdido tus efectivos.
User avatar
benway
Usuario avanzado
Posts: 172
Joined: Sun Apr 03, 2005 1:22 pm
Location: Madrid

Postby benway » Mon Jun 27, 2005 12:20 pm

Muchas gracias, popolon :) :) :) Es que hasta ahora, los programas que he hecho (tanto en el Spectrum / en el 486, como ahora el "Columns" y el "Horacio..." los he hecho prácticamente sobre la marcha... Pensaba un poco antes de empezar como resolver determinados problemillas, pero tampoco demasiado. De hecho, la segunda fase del Horacio la programé totalmente sobre la marcha. Y así me pasó, tardé como 2 semanas en implementar el detector de colisiones "pixel perfect", de las cuales la primera me la pasé pensando "Cómo cXXX hacerlo" hasta que se me ocurrió lo de las máscaras de bits y el hacer un & entre ellas. Ahora, el problema es que al plantearse hacer un juego "grande", pues surgen más problemas y, sobre todo, más complejos, y lo que me da miedo (aunque se que hasta cierto punto es inevitable) es empezar a hacer las cosas de una manera que luego resulte inútil, y tenga que volver a empezar :(

Jajajaja, na_th_an ... A mí me costó un poco el cogerle el punto a la POO, pero luego es muchísimo más cómoda. Todo el rollo ese que cuentan en las "introducciones" de libros / cursos / apuntes sobre POO de que "... se resuelven los problemas en base a como son en el mundo real, donde hay objetos que interaccionan entre sí, en lugar de como son en el ordenador, que tiene que recibir una lista secuencial de órdenes..." o algo así :wink: es cierto, y me resulta más fácil de plantear... es como más real.

Aunque supongo que será una cuestión de costumbres :), porque cuando empecé a mirar esto de la POO no me entraba en la cabeza: Al fin y al cabo, toda mi "experiencia previa" se basaba en PASCAL y BASIC.

Otra vez más, muchas gracias... :)
Un saludo.Image - Image
User avatar
na_th_an
Usuario avanzado
Posts: 66
Joined: Wed Mar 10, 2004 2:01 pm
Location: Sevilla
Contact:

Postby na_th_an » Mon Jun 27, 2005 2:30 pm

No, si en realidad a simple vista parece mejor para ciertas cosas, como por ejemplo para manejar distintos tipos de enemigos cada uno con una AI diferente. Lo que yo hago es poner un puntero a función dentro de la estructura, lo cual, conceptualmente, es exactamente lo mismo que hacerlo orientado a objetos, pero con distinta sintaxis.

Mucha suerte en tu nuevo proyecto :) Además, somos "compañeros de Allegro", así que seguiremos hablando.
La misión ha fracasado:
Has perdido tus efectivos.

Return to “Desarrollo”

Who is online

Users browsing this forum: No registered users and 5 guests