Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





"sistema De Luces"

Iniciado por Marcee, 14 de Enero de 2006, 01:54:27 AM

« anterior - próximo »

Marcee

 Hola, estoy trabajando con directx 7. Y hace unos dias estoy intentado algo que no me sale, ojala que uds me pueden ayudar.

Le paso a contar.

Estoy intenado hacer un sistema de noche en en mi juego 2D. Este sistema lo he realizado correctamente, la pantalla del juego se oscurese como yo quiero todo bien. Pero lo que no puedo realizar es que se oscurescan en distintas tonalidades dependiendo la parte de la pantalla. Lo que quedaria como un sistema de luces.

Osea lo que yo necesito es que se oscuresca la pantalla del juego  en diferentes tonalidades, por ejemplo que sea todo oscuro y donde se encuentra el personaje sea de un tono mas claro.

Desde ya muchas gracias, espero que me hayan entendido.

Chau.


[EX3]

 Estas desarrollando el juego en DirectDraw o en Direct3D? Si estas utilizando la fuerza del hardware mediante Direct3D te seria facil mediante un sprite aplicandole alpha aditivo poder clarecer zonas de la pantalla, tal que este ejemplo:



Con DirectDraw a secas te va a ser muy costoso tanto en cuestion de implementacion como en cuestion de rendimiento. Con D3D simplemente es montar un poligono con su textura y configurar 4 propiedades para hacer esto.

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

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

Marcee

 lo estoy haciendo en direct draw :(

Lord Trancos 2

 En un modo de 8bits (con paleta de 256 colores), este tipo de cosas se podian conseguir simplemente con varias paletas y haciendo una transicion progresiva entre ellas.

En un modo de 16 o 32 bits, lo único que se me ocurre es tener varias copias de los tiles o pantallas que forman el escenario a diferentes horas del dia e ir mezclandolas sobre la copia que se use para dibujar. El "truco" estaria en mezclar un tile  diferente cada X ms (o un cacho de imagen), ya que si intentas hacerlo todo de golpe te pegara un paron el juego.
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

nostromo

 Existe un juego con codigo fuente liberado que utilizaba ese tipo de efectos, aqui te dejo el link a un port del codigo con la libreria SDL.

Abuse-SDL

El juego original para MS-DOS se llama Abuse y se publico en 1996. Utilizaba iluminación dinamica con modos de 8bits de color. Con 8bits y por tanto una paleta de 256 colores la técnica para conseguir esto se basa en "tablas de traducción"(o look-up tables). Esta técnica es la misma que utilizaba el Doom para conseguir algo de iluminacion con 256 colores.

Con 8 bits

Digamos que tienes una paleta original de 256 colores y 32 niveles de luminosidad.
Pues necesitas una tabla de 32*256 elementos de 8bits. Llamemosla T. :-)
Cada vez que vas a pintar con luminosidad l un color c haces: nuevo_color = T[l*256+c]
l = 31 es la paleta original, l=0 es con luminosidad 0(es decir, muy oscuro :) )

Es decir esta tabla traduce colores de iluminación normal(paleta original) a colores con iluminación más oscura, y estos colores más oscuros estan todos en la misma paleta original.

Lo "dificil" es calcular la tabla de traducción:

Para cada color c de la paleta original con su (R,G,B) tenemos 32 niveles de lum.
  Para cada nivel de lum. l de 0 a 31
       
       (R2,G2,B2) = CalculaLuminosidad(R,G,B,l)   Buscamos el valor R2,G2,B2 del nuevo color segun lum. l
                                                                              seria algo asi: R2=(R/32.)*l; G2=(G/32.)*l; .....

       c2 = BuscaColorMásParecido(R2,G2,B2)   Busca el color más parecido en la paleta original
       T[l*256+c] = c2


Una vez tienes todo esto, el hacer luces se haria con mapas de luz, es decir, Sprites cuyos pixeles son niveles de luz(las l anteriores).
Los mapas de luz los situas donde te de la gana como con los sprites. Seria algo similar a esto:


Para cada pixel
 l = MapaLuz[sx,sy]   // mapa de luz niveles de 0 a 31
 c = Sprite[ox,oy]   // nuestro bicho
 c2 = T[l*256+c]    // traducción de color
 Pantalla[ sx , sy ] = c2  // pintamos en pantalla


Con esta tecnica se pueden crear efectos de transparencias facilmente. Es más, como la tabla ocupa 32*256=8Kb y se utiliza constantemente será bastante rapido ya que estará almacenada en cache.

En 24bits:
Para el tema de 24bits de color el sistema seria similar solo que esta vez hacen falta 3 traducciones una por cada componente de color. Tendrias la tabla para R, para G y para B. Y harias la traducción de esta forma:
R2 = TR[ R + l*256 ]
G2 = TG[ G + l*256 ]
B2 = TB[ B + l*256 ]

donde R,G,B son los componentes del pixel del sprite y l como siempre el nivel de luminosidad

y donde la tabla TR se pre calcularia asi TR[R + l*256] = (R/32.) * l   y asi para la tabla de verde (TG) y la del azul( TB). asumo que l va de 0 a 31.
La tecnica para hacer luces dinamicas seria la misma que en 8 bits: mapas de luz con niveles de luminosidad.

En fin, espero que te sirvan algunas ideas ó que decidas hacerlo mediante direct3d u opengl.

Un saludo

Marcee

 pero lo que me decis funciona para windows ?:S:S

senior wapo

 Claro que funcionan, tu haces un lock de la superficie a oscurecer/iluminar, modificas los pixels y luego un unlock. Listo para copiar.

Lo suyo es que cuando cambia la iluminación de la escena modifiques las imagenes que usas para componer la escena sobre copias de dichas superficies y luego sean esas copias modificadas las que uses para la pantalla. No hagas las modificaciones cada frame, solo cuando cambie la iluminación general.

[EX3]

 Siendo con SDL hasta para linux y MacOS incluso entre otras muchas plataformas. No existen algorritmos fijos para una plataforma, solo soportes y SDL es multiplataforma e incluso podria serte mas sencillo de programar con el que con DirectDraw.

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

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

Leanz

 Hola, yo estoy trabajadno con marce...y paso a explicar mas detalladamente....


Anteayer me puso a ver este tema, y bueno logre un efecto de iluminacion, lockeando(Espero q exista:P) las surfaces, tomando el array y multiplicando el valor de los pixels selectivamente con un algoritmo q produce un degrade zonal, el tema de esta manera es la velocidad, los fps se van al tacho de basura y se tilda el juego como dijieron arriba...Mi pregunta es si ustedes conocen una manera mas eficaz.

senior wapo

 Hombre, revisa los cuellos de botella tipicos, a saber:

1. Usa superficies en memoria de sistema, no de video. Leer/escribir de memoria de video es leeeento.
2. No apliques esos calculos en cada frame. Precalcula el área una vez y luego la vuelcas en cada frame hasta que cambie (cache de imágenes, vamos).
3. Revisa esas multiplicaciones, que sea en punto fijo (enteros, no coma flotante)  y combina 2 en 1. Vamos, que estas multiplicando valores de 8 bits, el resultado no ocupará más que 16 bits en el peor de los casos. En una variable de 32bits te caben 2 multiplicaciones:

 0xFF * 0x16   y 0xE5 * 0x23 -->  0x00FF00E5 * 0x00160023 y luego desempaquetas...

4. No copies la pantalla entera en cada frame, sino solo las partes que cambian de un frame al siguiente. usa dirty rectangles o micro-tile arrays (googlea).

Marcee

 Estamos desarrollandolo en visual basic, y no somos muy expertos en el tema si pudieras darnos un tips mas claros te lo agradeceriamos.

Si hay una dll en un lenguaje mas veloz que emule esta acción nos gustaria saberlo tambien.

Muchas gracias.

[EX3]

 
Cita de: "Marcee"Estamos desarrollandolo en visual basic, y no somos muy expertos en el tema si pudieras darnos un tips mas claros te lo agradeceriamos.

Si hay una dll en un lenguaje mas veloz que emule esta acción nos gustaria saberlo tambien.
Entonces ya has dicho suficiente. Si estais programando en VB 6.0 y con DirectDraw olvidaros de calcular las iluminaciones por pixel en tiempo real por que es imposible lograr buenos resultados en cuanto a rendimiento en este lenguaje. Vuestras dos soluciones: Direct3D, ya sea el 7 o el 8 (yo os recomiendo el 8 por multiples ventajas a la hora de programar frente al 7) aprovechando la aceleracion por hardware y desarrollarlo mediante poligonos y texturas, o la dx_lib32 (mirar en mi firma), una libreria que os podria solucionar mucho la vida en VB a la hora de desarrollar un juego. El ejemplo que os plantee arriba esta desarrollado en VB 6.0 con la dx_lib32 y os aseguro que es sencillisimo de hacer. Actualmente me encuentro terminando la documentacion y los tutoriales de la nueva version de dicha libreria, la version 2.0, que sin duda esta mas optimizada y mas completa respecto a la version actual que encontrareis en la pagina, la version 1.03, pero para empezar yo creo que os basta de sobra para ver por encima las funciones y la sencillez de su uso y los resultados que ofrece ;)

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

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

Marcee

 No hay una dll para directdraw? En otro lenguaje que no sea visual?

[EX3]

 Realmente te merece la pena una dll solo para eso pudiendo tener una dll que ofrezca de todo? . . . No se tu, pero puestos a usar una dll, mejor una para todo que 20, no?

DirectDraw no esta preparado del todo para trabajar temas como iluminacion dinamica en tiempo real (juegos como el Abuse que trabajan con DDraw utilizan si no recuerdo mal graficos precalculados), y ya puestos menos a un en un lenguaje lento e interpretado como es Visual Basic. Alternativas mejores sin duda son Direct3D, sobre todo la version 8 en la que con menos codigo incluso puedes hacer las mismas cosas que en DirectDraw usando el doble de llamadas, y este (DDraw) sin aprovechar la potencia de la tarjeta grafica.

La clase grafica de la dx_lib32 esta implementada con Direct Graphics (o Direct3D8) y por medio de simples llamadas puedes hacerte ciertos efectos de iluminacion con suma facilidad ya sea pintando un poligono con degradado de blanco a negro incrementado el valor de opacidad de la figura mediante el canal alfa del color, o utilizando graficos que representen focos de luz o destellos aplicando un efecto de opacidad aditiva, que es el ejemplo que os he mostrado antes en la captura y este es todo su codigo:
Option Explicit

Dim m_GFX As dx_GFX_class 'Variable objeto que apunta a la clase grafica.
Dim m_Input As dx_Input_class 'Variable objeto que apunta a la clase de funciones de entrada.

Dim Render As Boolean 'Variable que controlara la ejecucion del bucle principal.
Dim Backg As Long, Light As Long 'Variables que almacenaran los identificadores de los graficos en memoria.

Private Sub Form_Load()
Me.Show

'Creamos la instancia de las clases de la libreria:
Set m_GFX = New dx_GFX_class
Set m_Input = New dx_Input_class

'Inicializamos la clase grafica y configuramos el modo de video a modo ventana:
Call m_GFX.Init(Me.hWnd, 640, 480, 32, True, False, False)

'Inicializamos la clase de funciones de entrada, donde se encuentran las rutinas para leer
'la entrada del teclado y el raton:
Call m_Input.Init(Me.hWnd)

'Cargamos los graficos en memoria:
Backg = m_GFX.MAP_Load(App.Path & "\abadia.jpg", 0)
Light = m_GFX.MAP_Load(App.Path & "\luz.png", 0)

Render = True

'Bucle principal del programa:
Do While Render
   'Si pulsamos la tecla escape o el boton izquierdo del raton salimos del bucle:
   If m_Input.Key(Key_Escape) Or m_Input.Mouse.Left_Button Then Render = False
   
   'Pintamos el fondo con el primer grafico con algo de oscuridad:
   Call m_GFX.DRAW_MapEx(Backg, 0, 0, 0, m_GFX.Screen.Width, m_GFX.Screen.Height, 0, Blendop_Color, m_GFX.ARGB_Set(255, 128, 128, 128), Mirror_None, Filter_Bilinear, False, 0, 0)
       
   'Pintamos el grafico que actuara como foco aplicandole la opcion de Opacidad Aditiva:
   Call m_GFX.DRAW_MapEx(Light, m_Input.Mouse.X, m_Input.Mouse.Y, 0, 0, 0, 0, Blendop_Aditive, m_GFX.ARGB_Set(255, 255, 255, 255), Mirror_None, Filter_Bilinear, True, 0, 0)
   
   'Procesamos todas las llamadas a la clase grafica y las mostramos en pantalla:
   Call m_GFX.Frame

Loop

'Destruimos las instancias de las clases de la libreria:
Call m_GFX.Terminate
Call m_Input.Terminate

'Terminamos el programa:
End

End Sub

Private Sub Form_Unload(Cancel As Integer)
'Si cerramos la ventana salimos del bucle principal:
Render = False

End Sub

Y no me digas que esto es dificil. Casi toda la forma de programar con la libreria es asi de sencilla.

En serio, no os empeñeis en hacer algo "bruto" con DDraw por que solo seran quebraderos de cabeza, y si os empeñais mejor pasaros a C++, que al menos ahi obtendreis mas rendimiento que en VB.

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

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

Loover

 ¿Usais Visual Basic y no estais usando la dx_lib32? ¡Fustigales [EX3]! O fustigate tu mismo por no hacer buena publicidad de tu peazo librería.

:D
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!






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.