Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





error sincronización input contra draw

Iniciado por Hechelion, 07 de Junio de 2012, 05:59:00 AM

« anterior - próximo »

Hechelion

Buenas. Como siempre, yo y mis errores raros.

Me encontré con un error muy extraño, que la verdad no tengo la menor idea de por qué se produce, así que recurro a los "gurú" del tema.

Acabo de descubrir que al ejecutar una aplicación en modo ventana (ya sea con la versión 220 o la experimental 221) se produce una dessincronización entre la posición del mouse y la posición de dibujo.


Como sé que a veces me cuesta explicarme con palabras, voy a poner el código con el cual estuve haciendo pruebas:

Antecedentes:
- Plataforma. Windows7 64 bit home premiun
- Visual Studio 2010
- probé con las versiones 220 y 221

Código (NET) [Seleccionar]

Imports dxlib32_221
Public Class Form1
   Dim oGFX As dx_GFX_Class
   Dim oInput As dx_Input_Class
   Dim MainLoop As Boolean
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       oGFX = New dx_GFX_Class
       oInput = New dx_Input_Class

       MainLoop = True

       oGFX.Init(Me.Handle.ToInt32, 1024, 768, , True)
       oInput.Init(Me.Handle.ToInt32)

       Do While MainLoop
           oInput.Update()

           If oInput.Key(dxlib32_221.Key_Const.Key_Escape) = True Then MainLoop = False
           oGFX.DRAW_Box(oInput.Mouse.X, oInput.Mouse.Y, oInput.Mouse.X + 1, oInput.Mouse.Y + 1, 0, -16711936)
           oGFX.Frame(0, 60)
       Loop

       oInput = Nothing
       oGFX = Nothing

       End

   End Sub
End Class


Como ven, estoy haciendo algo muy, muy simple, estoy dibujando un cuadrado de 2 pixel de color verde, justo en la posición donde está parado el mouse.

CitaroGFX.DRAW_Box(oInput.Mouse.X, oInput.Mouse.Y, oInput.Mouse.X + 1, oInput.Mouse.Y + 1, 0, -16711936)

En la posición (0,0) no hay problema, ahí coinciden el input con el draw, pero a medida que me alejo de ese punto la diferencia se hace cada vez más grande (el error es proporcional). En la esquina inferior-derecha se ve que el punto de dibujo no concuerda con el punto del mouse por alrededor de unos 10 a 20 pixel, como si la dimensión de la ventana tuviera diferentes valores para el input y para el dibujo.

- El error solo ocurre en modo ventana, si corro la aplicación a pantalla completa, no hay ni un solo pixel de diferencia.

- Tengo la completa seguridad, que este error no pasaba antiguamente con windowsXP.

- Ya hice la prueba de programar con vb6 y compilar desde windowsXP, pero al correr la aplicación en windows7 pasa el mismo error.


Conclusión.
Desconozco por que pasa esto, y a ver si ex3 me puede dar una mano.
Pero por experiencia personal tuve un error muy similar tiempo atrás, programando con vb6, cuando le agregaba una barra de menú al formulario, recuerdo que me pasaba exactamente lo mismo, de alguna extraña forma, los input usaban el área sin contar la barra de menú, pero el método draw si contaba la barra de menú, lo cual hacia que las dimensiones de la pantalla fueran diferentes entre los draw y los input.
¿Por qué pasa lo mismo en modo ventana bajo windows7? (sin ningún tipo de barra de menú o ningún control que modifique nada), es lo que quisiera  saber para poder solucionar.

[EX3]

Cita de: Hechelion en 07 de Junio de 2012, 05:59:00 AM
Acabo de descubrir que al ejecutar una aplicación en modo ventana (ya sea con la versión 220 o la experimental 221)
Experimental 221? Ejem, todavía no se ha liberado tal versión :..

Sobre el error en si, debería mirarlo pero nunca he tenido este problema ni en Visual Basic 6.0 ni .NET en Windows 7. Si luego tengo un hueco intento hacer una prueba rapida, pero vamos, tanto el editor de niveles como el editor de tiles/sprites que hice para la ultima versión de mi motor, que corrían en modo ventana, no sufrían tal problema ???

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

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

Hechelion

Yo tampoco lo sufría antes y es lo más extraño, ni te digo todo el rompedero de cabeza que tuve para darme cuenta del error, ya que originalmente pensaba que tenía un error en el juego (que ya es un código bastante complejo).
Me di cuenta que el error estaba en la librería cuando lo corrí  a pantalla completa y el error no se presentó.

La verdad no sé, si el error siempre se presenta y no lo habíamos notado o si yo tengo algún problema en hardware/software que genera el error.

Si tienes un tiempo para probar, el código de arriba es un proyecto completo, puedes pegar y copiar y hacer pruebas, a ver si me dices si me faltó algo o si estoy inicializando algo mal.

Thorrex

Este error me pasaba cuando dibujaba en VB6 sobre un PictureBox. Seguro que si desplazas el mouse hacia abajo, la diferencia es cada vez mayor.
Descubrí luego de renegar bastante con eso, que al iniciar el Gfx en modo ventana, lo setea y luego achica la ventana. No sé si se entiende, pero escribo un ejemplito que soluciona esto.
With frmMain.Render
    Gfx.Init(.hWnd, 512, 512, 32, True, False, False)
    .Width = 512
    .Height = 512
End With


Probalo de esa manera.
Espero que se entienda claramente.

Saludos.

[EX3]

Acabo de probar el siguiente codigo y me ha funcionado correctamente. El cuadrado se ubica en las coordenadas correctas del raton.

Public Class Form1

    Private gfx As New dx_lib32.dx_GFX_Class
    Private input As New dx_lib32.dx_Input_Class

    Private render As Boolean = True

    Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        gfx.Terminate()
        input.Terminate()
        gfx = Nothing
        input = Nothing
    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Me.Show()
        gfx.Init(Me.Handle, 800, 600, , True)
        input.Init(Me.Handle)

        Do While render
            gfx.DRAW_Box(input.Mouse.X, input.Mouse.Y, input.Mouse.X + 32, input.Mouse.Y + 32, 0, &HFFFFFFFF)
            gfx.Frame(, 60)
        Loop
    End Sub
End Class


Cita de: Hechelion en 07 de Junio de 2012, 05:59:00 AM
Conclusión.
Desconozco por que pasa esto, y a ver si ex3 me puede dar una mano.
Pero por experiencia personal tuve un error muy similar tiempo atrás, programando con vb6, cuando le agregaba una barra de menú al formulario, recuerdo que me pasaba exactamente lo mismo, de alguna extraña forma, los input usaban el área sin contar la barra de menú, pero el método draw si contaba la barra de menú, lo cual hacia que las dimensiones de la pantalla fueran diferentes entre los draw y los input.
¿Por qué pasa lo mismo en modo ventana bajo windows7? (sin ningún tipo de barra de menú o ningún control que modifique nada), es lo que quisiera  saber para poder solucionar.
Lo de que haya diferencia de valores al tener menus o demas elementos en el formulario se debe que a que la funcion de la API de Windows que devuelve las coordenadas del raton, en modo ventana, trabaja con las coordenadas logicas del formulario (por defecto la funcion siempre devuelve la posicion en coordenadas de pantalla, que asi se aplica en los modos a pantalla completa, en modo ventana se convierten a coordenadas del area de cliente de la ventana). En ese caso obiamente habria siempre una diferencia equitativa de distancia entre el cursor y lo que se dibuja en el formulario.

En tu caso dices que no usas menus ni nada en la ventana, y despues de hacer mi prueba, no entiendo por que te sucede esa desincronizacion progresiva, pero si es escalable segun la distancia de la coordenada 0,0 tiene que ser un problema de conversion de coordenadas de algun tipo (como si la escala logica del render grafico fuera distinta a la del input).

¿La ventana seguro que no tiene ninguna configuracion concreta que afecte a su diseño? ???

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

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

Hechelion

Ex3. ¿tienes activado Aero?

Estuve haciendo varias pruebas y te las resumo (también probé con tu código, tal cual lo publicaste).

-Independiente de la resolución de la pantalla, el error máximo en el eje Y era siempre de 40 pixel.
-Probé el consejo de Thorrex y no me funcionó, sin embargo si incrementaba la dimensión de la pantalla en 40 pixel en el eje Y, entonces se sincronizaba.
O sea:

Gfx.Init(.hWnd, 800, 600, 32, True, False, False)
Me.Size = New System.Drawing.Size(816, 640)


Me puse a hacer pruebas cambiando el tema del escritorio, y cuando pasaba al modo "windows classic" (y sin necesidad de usar "me.Size") funcionaba bastante mejor, por lo cual creo que el problema está en el "aero", pero no estoy seguro.

Como te decía antes, sé que este problema no lo tenía en mi antiguo PC con XP, pero este windows 7, es vanilla, es cierto que le he instalado muchos programas y algunos juegos, pero nada que cambie o modifique los gestores gráficos de windows, todo eso lo suelo usar en modo "vanilla" ya que para personalizar o sacar el máximo provecho al equipo prefiero hacerlo desde linux.

[EX3]

No deberia afectar el tema y la configuracion de estilo de las ventanas de Windows, ni en XP ni en Vista/Se7en ya que esto no afecta al area de cliente de la ventana que es lo que se gestiona para el render y las coordenadas de input en modo ventana (de hecho fue una de las tareas más "coñazo" que me toco abordar en la transicion del proyecto entre Windows98 y Windows XP por lo de la incursion de los temas de XP).

Igualmente, las pruebas las he hecho con Aero activado.

Cita de: Hechelion en 11 de Junio de 2012, 08:30:50 AM
-Independiente de la resolución de la pantalla, el error máximo en el eje Y era siempre de 40 pixel.
Vale, pensaba que la desincronizacion es progresiva. Por lo que comentas es fija, no? No me queda claro eso de error máximo.

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

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

Hechelion

Cita de: [EX3] en 11 de Junio de 2012, 08:05:53 PM
No deberia afectar el tema y la configuracion de estilo de las ventanas de Windows, ni en XP ni en Vista/Se7en ya que esto no afecta al area de cliente de la ventana que es lo que se gestiona para el render y las coordenadas de input en modo ventana (de hecho fue una de las tareas más "coñazo" que me toco abordar en la transicion del proyecto entre Windows98 y Windows XP por lo de la incursion de los temas de XP).

Igualmente, las pruebas las he hecho con Aero activado.

Cita de: Hechelion en 11 de Junio de 2012, 08:30:50 AM
-Independiente de la resolución de la pantalla, el error máximo en el eje Y era siempre de 40 pixel.
Vale, pensaba que la desincronizacion es progresiva. Por lo que comentas es fija, no? No me queda claro eso de error máximo.

Salu2...

Es progresiva, pero en la parte inferior (donde tiene el valor máximo en el eje Y (no probé el eje X)) al parecer siempre es de 40 pixel independiente de la resolución, o sea.
mouse.Y = 0 entonces error = 0
Mouse.y = screen.height entonces error = 40

Gfx.Init(.hWnd, 800, 600, 32, True, False, False)
Me.Size = New System.Drawing.Size(816, 640) <-- Con esta corrección me funciona

Gfx.Init(.hWnd, 1280, 720, 32, True, False, False)
Me.Size = New System.Drawing.Size(1296, 760) <-- Con esta corrección me funciona


Sobre el estilo de ventana, se supone que no debería afectar, pero en las pruebas que he hecho, me arroja diferentes desfases según sea el estilo y no sé si sea coincidencia o no, pero el estilo "windows classic" me arroja el menor error de desfase (casi no se nota) y es precisamente el que tiene menor margen en el decorado de la ventana.

[EX3]

Cita de: Hechelion en 11 de Junio de 2012, 08:53:42 PM
Sobre el estilo de ventana, se supone que no debería afectar, pero en las pruebas que he hecho, me arroja diferentes desfases según sea el estilo y no sé si sea coincidencia o no, pero el estilo "windows classic" me arroja el menor error de desfase (casi no se nota) y es precisamente el que tiene menor margen en el decorado de la ventana.
Pues algo raro hay de por medio por que en el estilo clasico de ventanas es donde justamente no deberia fallar. Vamos, ni idea por que estos errores las veces que los he visto en mi caso y en el de otros ha sido por meter elementos como menus y demas controles que ocupan espacio del area de cliente. De hecho, si quieres hacer pruebas más profundas, las funciones de la API de Windows que usa dx_lib32 son GetCursorPos para obtener la posicion del raton, que devuelve en coordenadas de pantalla, y ScreenToClient para transformarlas en las coordenadas de cliente, sea un formulario o cualquier contenedor con identificador Hwnd comos los PictureBox de VB6:
    Public Structure POINTAPI
        Public X As Integer
        Public Y As Integer
    End Structure

    Public Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Integer, ByRef lpPoint As POINTAPI) As Integer
    Public Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As Integer


Y aqui el ejemplo anterior modificado para que lo pruebes:
Public Class Form1

    Private gfx As New dx_lib32.dx_GFX_Class
    Private input As New dx_lib32.dx_Input_Class

    Public Structure POINTAPI
        Public X As Integer
        Public Y As Integer
    End Structure

    Public Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Integer, ByRef lpPoint As POINTAPI) As Integer
    Public Declare Function GetCursorPos Lib "user32" (ByRef lpPoint As POINTAPI) As Integer

    Private render As Boolean = True

    Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        gfx.Terminate()
        gfx = Nothing

    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Me.Show()
        gfx.Init(Me.Handle, 800, 600, , True)
        input.Init(Me.Handle)

        Dim mouse As POINTAPI

        Do While render
            GetCursorPos(mouse)
            ScreenToClient(Me.Handle, mouse)

            'gfx.DRAW_Box(input.Mouse.X, input.Mouse.Y, input.Mouse.X + 32, input.Mouse.Y + 32, 0, &HFFFFFFFF)
            gfx.DRAW_Box(mouse.X, mouse.Y, mouse.X + 32, mouse.Y + 32, 0, &HFFFFFFFF)
            gfx.Frame(, 60)
        Loop
    End Sub
End Class

Como en el caso anterior, me ha funciona correctamente. Dime si te falla también :-/

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

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

Hechelion

Pues tal como esperaba, falla.

El punto 800,600 está por afuera del área de trabajo del formulario, específicamente, ese punto está en la sombra del formulario que genera el aero.
Es como si mi formulario, contando con los margenes del windows+aero, fuera de 800,600 y el área interna fuere de menor tamaño.


Manu343726

Opino igual que EX3, el problema está en que la API de windows devuelve las coordenadas reales del ratón, y no las del area de cliene (raro, yo también pensaba que en modo ventana trabajaba en area cliente)

Además, ten en cuenta que al crear una ventana, la API crea la ventana con el tamaño que le ha dicho, así que si tu pides una de 800x600 efectivamente te la da de 800x600, con marco y todo (el marco en realidad es un dibujito monisimo encima de la ventana). Asi que si quieres que tu area de cliente sea de 800x600, deberías tener en cuenta las dimensiones de dicho marco. Por eso en pantalla completa funciona perfecamente (no hay marco)

Sobre que no nos hayamos dado cuena antes, en mi caso siempre trabajo sobre .NET,asi que uso la captura de eventos para estas cosas.

Sobre EX3 y su TLSA.Engine, no estaba programado en .NET? O usas dx_Input_class?

Manu343726

Además, todo sería más facil si pudieramos ver la implementaión de dx_Input_class  >:D

Hechelion

Pues lo que dices no es del todo cierto, si le pido una ventana de 800x600 usando la librería me la crea de 806x628, esos pixel de más deberían ser el área asignada al contorno, y el área activa debería ser de 800x600.

Respecto a no darse cuenta, es por que esto no pasa en todos los computadores ni OS, a mi, en XP NO me pasaba y a ex3 no le da error con su windows 7, por consiguiente no estamos ante un error de implementación, que si no, el error se presentaría siempre.
Acá hay un problema con un driver o configuración que está dando la coña, el problema es determinar cuál y por qué.


avalontm

De casualidad te pasa eso con modo ventana y despues de redimenciona la ventana haciendo que no cuadre la pos del mouse con el dibujo de puntero en Dxlib32?????

por que ami me pasa lo mismo solo haciendo eso

[EX3]

Cita de: Manu343726 en 12 de Junio de 2012, 08:35:19 AM
Además, todo sería más facil si pudieramos ver la implementaión de dx_Input_class  >:D
Paciencia :P Salvo más detalles sobre eventos de teclado y gamepad, el codigo que os he puesto arriba es lo que hace dx_lib32 para devolver la lectura del raton en modo ventana. Vamos, no tiene más, obtener las coordenadas del raton y pasarlas a escala del cliente.

La pregunta es, a alguien más le falla lo que comenta Hechelion o el ejemplo que he puesto arriba? ???

Cita de: Manu343726 en 12 de Junio de 2012, 08:25:45 AM
Opino igual que EX3, el problema está en que la API de windows devuelve las coordenadas reales del ratón, y no las del area de cliene (raro, yo también pensaba que en modo ventana trabajaba en area cliente)
No exactamente, lo que yo comento es que la funcion que devuelve las coordenadas del raton siempre las devuelve en coordenadas de pantalla (con origen 0,0 del escritorio) y para obtenerlas con el area de cliente de la ventana se usa la otra funcion que he mostrado arriba que toma el controlador de la ventana que se le indique. Lo que hace dx_lib32 es lo que hace el ultimo ejemplo de arriba.

Cita de: Manu343726 en 12 de Junio de 2012, 08:25:45 AM
Además, ten en cuenta que al crear una ventana, la API crea la ventana con el tamaño que le ha dicho, así que si tu pides una de 800x600 efectivamente te la da de 800x600, con marco y todo (el marco en realidad es un dibujito monisimo encima de la ventana). Asi que si quieres que tu area de cliente sea de 800x600, deberías tener en cuenta las dimensiones de dicho marco. Por eso en pantalla completa funciona perfecamente (no hay marco)
dx_lib32 crea la ventana con el área de cliente acorde a la resolución de vídeo que le indicais. Si tuvierais que andar indicando los pixeles extra os volveriais locos ya que segun configuracion del usuario y versión de Windows el estilo de las ventanas es totalmente distinto, los tamaños cambian. Esto lo gestiona dx_lib32 interna mediante varias llamadas a la API de Windows para estudiar la base de la ventana y el estilo aplicado por el sistema operativo (tamaños de los bordes, barra de titulo, etc...). Eso si, esta preparado para trabajar correctamente con ventanas de borde fijo y sin añadidos como menús o controles contenedores.

Cita de: Manu343726 en 12 de Junio de 2012, 08:25:45 AMSobre EX3 y su TLSA.Engine, no estaba programado en .NET? O usas dx_Input_class?
Salvo la version que llevo programando en C# con XNA desde hace año y medio las anteriores versiones de mi motor estan en Visual Basic 6.0 con dx_lib32 (incluso un experimento en su día entre VB.NET+C# y dx_lib32 hace unos años).

Cita de: Hechelion en 12 de Junio de 2012, 09:42:08 AM
Respecto a no darse cuenta, es por que esto no pasa en todos los computadores ni OS, a mi, en XP NO me pasaba y a ex3 no le da error con su windows 7, por consiguiente no estamos ante un error de implementación, que si no, el error se presentaría siempre.
Acá hay un problema con un driver o configuración que está dando la coña, el problema es determinar cuál y por qué.
Hechelion, una pregunta, que no me ha quedado claro. ¿Estas trabajando con Windows nativamente o desde una maquina virtual? Lo digo por que algo me suena que comentastes que trabajabas desde Linux. Si es el caso puede ser la clave de donde esta el problema. Cuando me compre hace unos años mi Macbook decidi trabajar con XP desde Mac OS con VMware y tuve problemas tanto con funciones gráficas como en otras áreas (de hecho perdí tiempo intentando arreglar bugs que no eran tal).

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.