Hola a todos,
Mi problema es el siguiente, he creado unas clases para manejar sprites y otras para manejar eventos del teclado, hasta aqui todo bien, dado que considero terminada la primera parte de mi mini proyecto. Asi que me he puesto a cronometrar tiempos para ver como va el tema y...
Mi bucle principal de momento solo dibuja y maneja dos sprites con sus animaciones , los eventos de teclado para manejarlos y un fondo de pantalla, q de momento se dibuja entero a cada iteraccion. Pues de media tarda 60 milisegundos en completar una vuelta !!!
Desearia que me dijerais que en el fondo las operaciones graficas son las que mas tiempo consumen, porque ahora deberia implementar:
-El detector de colisiones, con multirectangulos.
-La IA, que tengo pensada con maquinas de estados y unos pocos arbolillos.
-El subsitema de sonido....
Tras implementar esto imagino que mi bucle se ira facilmente a los 100-150 milisegundos no??
Mi pregunta es cual debe ser el tiempo medio por cada iteraccion de un bucle principal en un juego normalillo ?
Porque, si tenemos en cuenta esto de que el ojo humano ve 25 imagenes por segundo, el tiempo optimo del bucle sería 40 ms. Esto seria pedir demasiado?
El hecho de dibujar todo el fondo en vez de solo la parte que cambia pesa mucho en tiempo??
BUeno, gracias anticipadas. TOY HUNDIO
Te iba a responder antes de que desapareciera tu anterior post :P
Deberias realizar las mediciones en cuadros por segundo y no por milisegundos, la idea es llegar a una media de 30 a 60 fps para mostrar un renderizado suave a la vista. Haciendo una prueba rapida en la tostadora que tengo por PC en la oficina, en una prueba con dx_lib32, a 640x480, dibujando el fondo por duplicado (para implementar un efecto) con una textura de 640x480 con TripleBuffer, sin espera de refresco vertical y sin limitacion de fps, 5 sprites con rotaciones (uno de ellos por duplicado tambien para otro efecto implementado), aplicando efectos a las texturas de los sprites y el fondo y dibujar quads con degradados me da una media de 62 fps y una media de 10/5 milisegundos por bucle (la maquina como digo es una autentica tostadora de oficina de hace 4 o 6 años). En casa con el MacBook con una integrada intel 950 y el AMD con la GeForce3 supera los los 90 fps de sobra, por lo que el tiempo de ciclo seguro se rebaja a mucho menos de 3 milisegundos.
Si expones el como estas implementando las llamadas quizas sepamos ayudarte. Me huele a que estas recargando texturas en el propio bucle o realizando algun paso que te puedes ahorrar perfectamente.
CitarDesearia que me dijerais que en el fondo las operaciones graficas son las que mas tiempo consumen, porque ahora deberia implementar:
-El detector de colisiones, con multirectangulos.
-La IA, que tengo pensada con maquinas de estados y unos pocos arbolillos.
-El subsitema de sonido....
De las que has mencionado, las colisiones y la IA, pero claro, dependiendo de como de complejas sean ya que no existe una implementacion unica de estos modulos. El sistema de audio generalmente suele correr siempre en un hilo independiente por lo que no demorara el hilo principal del programa (esto lo gestionan las propias librerias como DirectSound y similares).
CitarTras implementar esto imagino que mi bucle se ira facilmente a los 100-150 milisegundos no??
Mi pregunta es cual debe ser el tiempo medio por cada iteraccion de un bucle principal en un juego normalillo ?
Centrate en que el programa mantenga una media de 30 a 60 fps, no busques un tiempo fijo en milisegundos por esto varia segun la carga de datos a procesar en el bucle.
Lo principal que debes tener en cuenta a la hora de optimizar los modulos es intentar evitar llamadas en los momentos que no sean necesarios, por ejemplo dibujar sprites fuera de pantalla (descarta todo lo que no sea visible) o calcular toda la fisica de golpe (esto cuando profundices un poco veras que se divide la escena de forma que calcules solo lo necesario). La IA ya es mas compleja de optimizar pero igualmente hay formas de agilizarla, segun veo se esta poniendo de moda el procesar la IA entre otras cosas en un hilo independiente al principal, pero claro, segun casos, en un PacMan no te merece la pena mientras que en un Quake quizas si.
Ve por partes. Yo no me comeria la cabeza con colisiones y maquinas de estados hasta no tener asegurado el modulo grafico.
Salu2...
JAjaj , te has dado cuenta.
Este foro es mortal o te publica por duplicado o no te publica.
Agradezco tu respuesta fuenlabreño.
A que te refieres exactamente con frames?, se que es una pregunta tonta pero esque tiene tantas acepciones.
A las veces que llamo a mi funcion Pantalla.Actualizar? esta funcion blitea a la pantalla lo que hay en memoria de video, digamos, se que sabes lo q quiero decir, primero hago todas las animaciones los cambios de posicion y luego llamo a Pantalla.Actualizar que lo blitea todo a pantalla. Cuando hablas de frame te refieres a las veces que flasheo la pantalla?
Si es asi, no llego a 30 por segundo ni de coña. Cuando este en casa lo mido y t lo digo.
Antes se me olvidó dar un dato muy importante que me has recordado al hablar de la tostadora de tu oficina, mi programa de momento esta corriendo en mi ordenador personal, y le llamo personal porque hace tanto tiempo que lo tengo que ya le he cogido cariño....
PIII 800, XDDD en su defensa he de decir que la grafica es una Geforce4MX4000, tiene 1 Gb de memoria y El gestor de escritorio de Ubuntu, BERYL realiza todos los efectos a la perfeccion, por no hablar del Warcraft III que puede correr con todas las opciones graficas al maximo con una suavidad q ya la querrian muchos PIV XDD.
En las pruebas que estoy haciendo todo es optimo, dibujo los sprites justos y lo unico que podria mejorar es dibujar solo la parte del fondo que cambia y no todo como hago ahora.
Mierda, escribí un post en el otro hilo que hiciste pero lo han debido borrar, seguramente lo eliminaron justo después de haber publicado yo y no lo vieron.
Uuuuf q pereza volver a escribir, bueno no pasa na.
Ahí va otra vez:
1) Mide en frames por segundo mejor, es decir, número de veces que presentas en pantalla todos los gráficos en un segundo.
2) Si usas SDL y quieres que el dibujado vaya más rápido, tendrás q meterte con mierdas de dirty rectangles, etc, es decir, dibujar solo las zonas que cambian. Si usaras aceleración por hardware podrías olvidarte de eso y ganar mucha velocidad.
3) Los fps de tu juego, visto el tipo de juego que es, no se te van a ir en la lógica o las colisiones, ahí como mucho se te irán 2 o 3 fps. Tu cuello de botella por frame, como casi siempre, es dibujar todo, y más si es por bliteado por software como es tu caso.
4) Vigila que no estés haciendo alguna burrada, como hacer new/delete en cada iteración del bucle o algún "sleep" olvidado por ahí.
5) Yo no he usado SDL directamente nunca, pero indirectamente, usando Fenix (que usa SDL internamente), los juegos me iban a 30 o 40 fps en un pentium 200Mhz.
6) Ahora mismo, con la IndieLib y aceleración por hardware... bueno, prueba tu mismo los ejemplos, puedes tener 2000 sprites en pantalla rotándose, escalándose y cambiando su entintado a unos 30fps más o menos. Y un escenario con un fondo y tan solo 3 sprites, a 1024x768, en un ordenador de gama media, no debería bajar de los 300fps (con aceleración hardware). Depende, claro del tamaño de los sprites.
7) Si tienes bien separada la lógica del juego de la de dibujado, siempre puedes terminarlo ahora dibujando por fuerza bruta (sin usar dirty rectangles) y más tarde usar Direct3d, Ogl a pelo, o alguna api de dibujado de más alto nivel, para ganar velocidad. Pero entonces deberías tener cuidado y crear solo sprites potencia de dos (o más tarde usar un engine que te permita usar sprites que no sean potencia de dos).
Perdón por la confusión de los posts desaparecidos, es que justo ha publicado [EX3] la repuesta al duplicado que estaba eliminando :(
sync
Ale ale, tan pronto desaparecen mensajes como de pronto posteamos todos a la vez :D Este foro es unico :lol:
Cita de: "trutoman"A que te refieres exactamente con frames?, se que es una pregunta tonta pero esque tiene tantas acepciones.
A las veces que llamo a mi funcion Pantalla.Actualizar? esta funcion blitea a la pantalla lo que hay en memoria de video, digamos, se que sabes lo q quiero decir, primero hago todas las animaciones los cambios de posicion y luego llamo a Pantalla.Actualizar que lo blitea todo a pantalla. Cuando hablas de frame te refieres a las veces que flasheo la pantalla?
Caliente caliente, tambien engloba calculos de fisica e IA. En verdad, para ser mas concretos, seria el numero de vueltas que ejecutas el bucle principal en un segundo. La tasa optima suele ser 60 veces pero hasta 30 la frecuencia es aceptable. Por eso te decia que no midas en milisegundos ya que nunca obtendras un valor fijo debido a las variantes de procesos. Mide solo en milisegundos para testear individualmente una funcion concreta para depurar posibles demoras localizadas en tu codigo.
No estoy puesto para nada en SDL pero se que han comentado alguna vez que las conversiones de tipo de pixel (entre superficies por ejemplo) puede bajar notoriamente el rendimiento. Recuerda que SDL ejecuta por software y no por hardware como si lo hace OpenGL y Direct3D.
Salu2...
Vaya esto se complica, no tenia ni idea que opengl iba directo al hardware, para q veais la idea que tengo XD...
Ahora mismo mido los fps.
Buena idea esa de medir cada funcion por separado para ir optimizando las mas lentas, me pongo a ello.
He depurado un poco y no hago nada raro;
*Cargo sprite
*Lo bliteo en la surface temporal
*Lo elimino
*Y cuando todos los sprites estan dibujados, flasheo a la pantalla fisica.
Lo habitual imagino...
No puede ser!!
Hago lo siguiente:
Inicializo todo, sprites, pantalla, animaciones.
while (!fin)
uint32 start = 0
Dibujarsprite(1)
Dibujarsprite(2)
Animar(1)
Animar(2)
start = sdl_getticks
if (start>1000)
fin = true
Pues bien, da una vuelta y tarda 3700 milisegundos????
Si pongo el limite a 10000, por si me equivoco con las unidades de medida, aunque pensaba que daba milisegundos da 111 vueltas
Cita de: "trutoman"He depurado un poco y no hago nada raro;
*Cargo sprite
*Lo bliteo en la surface temporal
*Lo elimino
*Y cuando todos los sprites estan dibujados, flasheo a la pantalla fisica.
Lo habitual imagino...
Error como una catedral! Los recursos como las texturas se cargan al principio o antes de la escena y se mantienen en memoria hasta la finalizacion del programa o hasta que tengas que cargar, por ejemplo, un nuevo nivel. Cargar desde disco, crear y eliminar en memoria es un proceso muy muy costoso. No te obsesiones con lo que ocuparas en memoria cargando todas las texturas ni resto de recrusos, que no estamos hablando de programar un Spectrum 48k :D Lo que se suele hacer es tener un "pool" de recursos (como un almacen mas o menos organizado segun necesidad) por ejemplo, un array/coleccion/lista donde almacenas las texturas que necesitas y a donde accederas para leerlas. Esto es mil veces mas rapido ya que estas leyendo en la RAM o en la memoria de la grafica, mas rapido que acceder a disco.
Salu2...
Tienes razon, pero la verdad es que me he explicado mal.
Yo cargo el fichero de imagen entero y creo unos vectores con las coordenadas para hacer los recortes de todos los sprites.
Esto antes de empezar el bucle de juego.
Luego la funcion dibujarsprite simplemente coge del vector de coordenadas las que le toquen y corta del fichero la imagen adecuada.
Ambos vector de coordenadas y fichero de imagen estan en memoria.
Se que un acceso a disco es del orden de 100000 mas lento que un acceso a memoria;
se puede hacer mas rapido?
Por carga de sprite te referias pues a seleccionar la superficie a dibujar y su region definida. Hasta ahi bien supongo. Lo costoso seria realizar duplicados de texturas en tiempo de ejecucion y demas historias semejantes.
Sobre el calculo de fps, el primer ciclo del bucle no siempre es el mas fiable, realmente deberias tener en cuenta la media que te durante la ejecucion. Para realizar el calculo deberias hacer algo como esto:
int last, framesDrawn;
int frameRate; // Este es valor que representa los cuadros por segundo.
if(sdl_GetTick() - last >= 1000)
{
last = sdl_GetTick();
frameRate = framesDrawn
framesDrawn = 0
}
Esto lo ejecutas justo de despues de pintar la escena, al final de bucle. Con esto obtendras la cuenta fiable de cuadros por segundo.
Salu2...
Citar
Yo cargo el fichero de imagen entero y creo unos vectores con las coordenadas para hacer los recortes de todos los sprites.
Esto antes de empezar el bucle de juego.
Luego la funcion dibujarsprite simplemente coge del vector de coordenadas las que le toquen y corta del fichero la imagen adecuada.
Ambos vector de coordenadas y fichero de imagen estan en memoria.
Se que un acceso a disco es del orden de 100000 mas lento que un acceso a memoria;
se puede hacer mas rapido?
A ver si me queda claro.
Cuando accedes a la imagen en memoria no accedes a disco, solo lo haces una vez al cargar, eso está bien.
Al dibujar, bliteas (dibujas) una región en concreto de la imagen grande. Eso está bien.
Lo que estaría mal es si para dibujar dicha region, la recortas y la pegas en otra dirección de memoria tuya, eso estaría muy muy mal :D El único copiado de dicha región debe hacerse al buffer de dibujo, y en este caso SDL se ocupará de eso con su función pertinente de bliteado.
Mira a ver si haces algo de esto
dentro del bucle principal del juego (olvidate de la parte en la que cargas y la parte en la que liberas memoria fuera de dicho bucle):
¿Haces algún new/delete?
¿Haces algún copiado/pegado de memoria?
¿Haces algún acceso a disco?
Si la respuesta es sí a alguna de esas, pues ya tendrás algo que podrás evitar y ganar muchos fps.
Bueno ya he conseguido medir las fps, y no paso el corte, lo he hecho mil y una veces y no paso de -17- siempre 17 vueltas da en un segundo.
En cuanto a las preguntas de loover si, tienes razon, cargo la imagen en memoria, y luego interiormente la clase CSprite copia su parte de la imagen a una surface suya que hace de buffer, y de ahi cuando sea requerido lo copia a memoria., es decir hago una copia intermedia que me puedo quitar.
Si no he entendido mal te refieres a pasar del fichero cargado en memoria directamente a pantalla el sprite adecuado verdad.
Ahora hare ese cambio a ver si me llega a 30 fps.
Citarla imagen en memoria, y luego interiormente la clase CSprite copia su parte de la imagen a una surface suya que hace de buffer, y de ahi cuando sea requerido lo copia a memoria., es decir hago una copia intermedia que me puedo quitar.
Si no he entendido mal te refieres a pasar del fichero cargado en memoria directamente a pantalla el sprite adecuado verdad.
En memoria lo que debes evitar es crear superifcies en tiempo de ejecucion. Doy por hecho que SDL tendra una funcion para seleccionar una superficie para realizar las operaciones de dibujo y que esta funcion tendra sus parametros para poder definir que region de la superficie dibujar, llamemosla SDL_SetSurface(). Tu tendrias tus imagenes almacenadas como superficies en una lista cuando las cargas desde disco al cargar la escena y esas seran las unicas superficies que tendras a parte del backbuffer, por ende tus llamadas al bucle quedarian similar a estoi:
SDL_Rect region;
Do While (fin)
{
region.x = 0; region.y = 0; region.width = arrSuperficies[0].width; region.height = arrSuperficies[0].height;
SDL_SetSurface(arrSuperficies[0], region);
SDL_Blit(0, 0, 32, 32);
region.x = 32; region.y = 32; region.width = 32; region.height = 32;
SDL_SetSurface(arrSuperficies[1], region);
SDL_Blit(128, 64, 32, 32);
SDL_Flip();
}
Esta al menos seria la forma de hacerlo en Direct3D. Ahi no realizas ninguna copia ni generas nuevas instancias de objetos lo que te ahorra carga al procesador y por ende ganas velocidad. Ten siempre en cuenta que la carga y creacion de texturas y superficies es un proceso costoso, y mas por software por lo que debes evitarlas. Leer de la memoria siempre sera mas rapido que copiarla a otra seccion y leerla despues.
Salu2...
Pues si asi lo voy a hacer.
He medido el tiempo individual de cada funcion.
El dibujar los dos sprite me da 0 ó 1 milisegundos, mientras que dibujar el fondo de pantalla consume 40 milisegundos, si cogemos que doy 17 vueltas, 17*40 = 680, es decir el 68% del tiempo lo gasto en pintar el fondo, esto me lleva a una conclusion obvia -> DirtyRectangles.
Estoy pensando como hacerlo y el problema primero que me ha llamado la atencion es que antes de dibujar cualquier cosa tengo que conocer las coordenadas de todo lo que he dibujado en la iteraccion anterior...OMG creo que abrire otro post para esto XDD. Perdón, antes me documentare y si no me sale bien a la primera entonces abrire post.
Probando el programa de prueba sin pintar el fondo me daba 58 fps. Thats GOOD
Cita de: "trutoman"Estoy pensando como hacerlo y el problema primero que me ha llamado la atencion es que antes de dibujar cualquier cosa tengo que conocer las coordenadas de todo lo que he dibujado en la iteraccion anterior...OMG creo que abrire otro post para esto XDD. Perdón, antes me documentare y si no me sale bien a la primera entonces abrire post.
http://dr0id.homepage.bluewin.ch/pygame_tutorial01.html
Estuve buscando hace poco para intentar implementarlo tambien en mi libreria y encontre algunas webs interesantes, una la del enlace, donde no solo te explican como implementarlo si no los pros y contras de implementar esta tecnica, por ejemplo, que los dirty rects no te haran efecto alguno en scrolls al estar obligado a redibujar todo cuando muevas el scroll. Esta tecnica esta bien si la vas a usar en escenas estaticas.
Salu2...
[Ex3] los dirty rectangles solo tienen sentido en render por software, olvidate de ganar algo con eso usando direct3d.
Trutoman te recomiendo que no entres en cosas obsoletas como dirty rectangles, a día de hoy entrar en algo así cuando todo se hace por hardware no te va a aportar nada interesante para aprender. Sería más interesante aprender a abstraer la lógica del juego del sistema de render, etc. Cosas bastante más útiles (a mi forma de ver, claro).
Sino quieres entrar en temas de opengl/direct3d podrías utilizar alguna librería que te permita al menos blitear los sprites directamente, usando aceleración hardware. Vuelvo a invitarte a que pruebes IndieLib. Pero tienes otras opciones como HGE engine o PTK o las otras dos librerías del foro, aunque la de EX3 es para visual basic (de momento, jeje).
Dibujar un fondo, y 3 sprites del tamaño de los que enseñaste, en un ordenador gama media usando Indielib no bajaría de los 400 fps. Aparte que luego podrías meterte en temas muy interesantes como efectos de partículas y tal, que en software... pues como que no chutan muy bien :)
Un saludo.
Al final loover me vas a convencer.
Dado que opengl y direct3d ataca directamente a la tarjeta grafica y a su memoria, digamos que usar tu librería seria lo mismo que lo que estoy haciendo ahora con SDL.
La unica pega es que yo suelo programar en linux (ubuntu) creo que tu libreria no esta disponible para linux o si?
CitarDado que opengl y direct3d ataca directamente a la tarjeta grafica y a su memoria, digamos que usar tu librería seria lo mismo que lo que estoy haciendo ahora con SDL.
Yep, en vez de dibujar con SDL, dibujarías con las funciones que vienen con IndieLib. Y si quieres usar el sistema de animaciones y de colisiones que ya lleva bien, si prefieres usar uno propio, tambien bien :)
La verdad es que me gustaría mucho verte usándola, porque apenas tiene 2 semanas y solo he visto dos prototipos de juegos. Y veo que tu le echas muchas ganas y que sin duda te va a salir algo guapo. Por falta de tiempo no puedo hacer yo mismo un juego tipo street fighter, pero es que viendo lo que necesitas (colisiones por frame, sistema de animaciones, etc) es que te vendría perfecto, vamos, lo diseñé así pensando en eso.
Citar
La unica pega es que yo suelo programar en linux (ubuntu) creo que tu libreria no esta disponible para linux o si?
Touche! Al usar Direct3d de momento solo está disponible para windows. Me gustaría hacer un port a mac/linux en un futuro próximo, pero esto no va a ser así en menos de 6 meses como mínimo, o puede que nunca.
Venga, echale aunque sea un vistazo :), ve a windows, bajate de la web la SDK y dentro tienes 19 ejecutables, listos para que cliquees y veas lo que se puede hacer con la librería.
Cita de: "Loover"[Ex3] los dirty rectangles solo tienen sentido en render por software, olvidate de ganar algo con eso usando direct3d.
Si te dijera que dx_lib32 no es capaz de mover los mil conejos de tu pueba a mas de 17fps entenderias el por que ando mirando cosas como los dirty rects :P Mi libreria esta respondiendo bien para trabajar con composiciones grandes de graficos (composiciones grandes = menos graficos) pero si quiero implementar composiciones con tiles de 32x32 o 64x64 para implementar efectillos de vertices como tu sprite maya esto penaliza mucho el rendimiento, y como ya hablamos en las otras ocasiones, me merece mas la pena implementar una chorrada como los dirtyRects o similar, aunque sea de forma opcional, que hacer lo mas correcto que seria reescribir de nuevo el render grafico (eso mas adelante cuando toque portar el TLSA.Engine .NET a Mono y TAO Framework :))
Sobre el uso de librerias en Linux, mirate la de TheAzazel, CRM32Pro, que tambien esta basada en SDL y es la mas completa que vas a encontrar en el foro en cuanto a funcionalidades y herramientas (la mas simple es la mia que te ayuda lo justo y da gracias :P)
Salu2...
He descubierto porque tardaba tanto :D :D
Estaba haciendo el blitsurface de una superficie a la que aun no habia aplicado SDL_DisplayFormat, esta funcion convierte una surface al "formato" de la pantalla, es decir cada vez que dibujaba un sprite el ordenador tenia que "convertir" la surface a otra surface con la profundidad de color y todas esas caracteristicas raras de las pantallas.
Ahora dibujando el fondo (sin dirtyrect) y los sprites animados 58 fps... XDDD YES!!
Por cierto loover, despues de haberme convencido a utilizar tu libreria, me doy cuenta que visual c++ 2008 necesita un procesador con 1.6 Ghz para corre, todo son pegas, de todas maneras antes de Julio pienso gastarme pasta y pillar un QuadDumped con su Nvidia 8000series GT. La utilizare porque sino nadie podra ver mi juegillo , todo el mundo usa güindous.!!! :cry:
CitarPor cierto loover, despues de haberme convencido a utilizar tu libreria, me doy cuenta que visual c++ 2008 necesita un procesador con 1.6 Ghz para corre, todo son pegas, de todas maneras antes de Julio pienso gastarme pasta y pillar un QuadDumped con su Nvidia 8000series GT. La utilizare porque sino nadie podra ver mi juegillo , todo el mundo usa güindous.!!!
Pruebalo, igual no te va tan lento :D. Y prueba las demos de IndieLib, aunque sea por gusto de verlas. Hay cosillas curiosas.
De todos modos SDL es multiplataforma, irá en windows, linux, mac y lo que le eches.