Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





botones, timer...

Iniciado por divmas, 05 de Marzo de 2011, 06:23:54 PM

« anterior - próximo »

divmas

Muy buenas,

antes de nada felicitar a EX3 por esta gran libreria.

Os explico mi problema. Estoy desarrolando una aplicación en vb .net, tengo una clase boton que detecta los hits del raton y llama:

    Public Event click_derecho()
    Public Event click_izquierdo()

pues bien, en el form principal es donde defino los eventos cuando se clica pero me he encontrado con el problema (despues de leer varios mensajes) que si no es con un timer los clicks no los detecta correctamente.

Entonces mi pregunta es:

como hago para enlazar esa clase boton con el timer para que los hits los detecte correctamente.

No sé si me he explicado bien.

Gracias de antemano



[EX3]

Wenas :)

Disculpame por que quizas ando algo espeso pero no he entendido bien el problema que tienes. Que es lo que buscas hacer exactamente? Lanzar los eventos de tu clase boton a haber un click?

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

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

divmas

si, mira dentro del loop cargo los botones que a su vez tienen eventos (al hacer click) pero claro como cada boton tiene un evento distinto lo he de declarar en el form_load

Do
   cargo botones con el adreesof correspondiente
Loop

sub botonizquierdoclick
evento
end sub

pero no responde bien a los clicks... a veces si a veces no...

si estuviera dentro de un timer los clicks se harian bien por lo que he podido comprobar pero no puede meter el sub botonizquierdoclick dentro del timer como es logico por lo tanto que debo hacer?

Gracias

Hechelion

Qué estás usando para detectar el clic del mouse?

El evento HIT de la librería?. Si es ese, entonces la solución pasa por usar el Press y agrear una variable que recuerde el estado anterior del press y luego simulas el hit on un if
If ClicAnterior = false and Clic = true Then EventoHIT

El problema se genera en un timer interno que usa la librería para disparar el HIT y según la velocidad del equipo y la cantidad de FPS del juego ese timer no anda muy bien y hace que el HIT salte o no.

[EX3]

Vale, ahora entiendo a que te referias con los timers :P

Como te comenta el compañero Hechelion, es un bug de la libreria el que las funciones _Hit no funcionen correctamente. Tenia por ahi una clase que solventaba este error adjuntada en un par de respuestas del foro pero parece ser que estan inaccesibles por que no soy capaz de descargarlas y por aqui en casa no la encuentro :-/

La idea de esta clase es que te ofrecia una version propia de las funciones _HIT y un metodo de actualizacion que deberia llamarse al principio de cada ciclo del bucle principal de tu juego y este metodo seria quien controlaria los estados de pulsacion y no el cronometro interno de dx_lib32 pero si te lo estudias un poco no te seria compliacado hacerlo tu mismo, como te comenta Hechelion, meter una variable para controlar si se ha pulsado el boton del raton y en cada ciclo controlar si sigue pulsada o no para cambiar el estado.

do
    estado = mouse.LeftButton
   
    if (estado = false and mouse.LeftButton = true) then hit = true else hit = false

    (...)
loop


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

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

divmas

Primero de todo gracias a los dos por la rápida respuesta, pero sigo sin dar en el clavo... os explico:

tengo en el principal:

Código (vbnet) [Seleccionar]


do

estado=m_input.Mouse_Press

loop

sub click_izquierdo
...
end sub



en la clase boton cuando detecto la zona de impacto:

Código (vbnet) [Seleccionar]


If estado = 0 And m_input.Mouse_Press = Mouse_Button.Left_Button Then

    RaiseEvent click_izquierdo()

End If




esto seria según me habeis dicho...    pero no funciona...

que hago mal?

Gracias

Ubermann

No sé si he entendido bién lo que quieres hacer, pero ¿por qué no pones en los botones un método al cual se accede a través de la detección del click dentro del timer?

Ejemplo:

Dentro de tu clase botón:
Public Sub myMetodo()
    MsgBox "Hola Mundo"
end Sub


y en el timer llamas a dicho método cuando se haga clic.

No sé si es eso lo que quieres llegar a conseguir.

divmas

En el timer puedo controlar cuando se clica pero no "donde" se clica... dentro del boton tengo la zona de impacto...  se podria llegar a hacer lo que dices calculando la zona de impacto en el mismo timer pero tengo muchos "botones"...

Gracias por tu sugerencia de todos modos

Ubermann

Cita de: divmas en 06 de Marzo de 2011, 04:06:48 PM
En el timer puedo controlar cuando se clica pero no "donde" se clica... dentro del boton tengo la zona de impacto...  se podria llegar a hacer lo que dices calculando la zona de impacto en el mismo timer pero tengo muchos "botones"...

Gracias por tu sugerencia de todos modos

Ah vale, ya entiendo lo que quieres hacer...

También puedes intentar lo siguiente, que a narices tiene que funcionar, y es muy sencillo.

Primero necesitarás que los objetos botón que has creado pertenezcan a una matriz de objetos, como seguramente ya habrás hecho. De esta manera todos los ellos tienen un índice único y puedes acceder a sus propiedades y métodos fácilmente.

En segundo lugar, en el Timer pones lo que es el control de clicks, para saber si el usuario a presionado click derecho o izquierdo.
Cuando alguno de estos botones sea pulsado, llamas a otro método que con un bucle (for...next es lo que necesitas) compruebe si el puntero está encima de alguno de los botones. En caso afirmativo, ya tendrás exactamente qué botón se ha pulsado, y en consecuencia podrás llamar a la función o sub que necesites.

El procedimiento para comprobar si el ratón está encima de algún botón podría ser algo así (pseudocódigo más o menos)

for i = 0 to maxButtons - 1
    if (ratonX > boton(i).left AND ratonX < boton(i).left + boton(i).width) AND _
       (ratonY > boton(i).top AND ratonY < boton(i).Y + boton(i).height) then
        'es decir, si la coordenada X del ratón está entre los límites horizontales del botón, y
        'la coordenada Y entre los límites verticales, entonces el ratón está sobre el botón número "i"
       
        MsgBox "¡¡¡He pulsado sobre el botón con índice igual a " & str(i) & "!!!"
    endif
next


No sé si eso te podría servir.

divmas

Ese codigo si funciona sin duda en un "código normal" pero en el mio harto complejo todo se dificulta mucho al tener muchos objetos y tener que pasarle parametros, etc...

Ando buscando esa clase que EX3 hizo un dia para resolver el bug de los hit.... Gameeventhitclass.cls  creo que se llamaba o bien una solucion rapida... sin tener que recurrir al timer... es decir lo que propusieron EX3 y Hexelion pero con más detalle porque como ellos me dijeron no anda.

Muchas gracias por la molestia que te has tomado pero voy buscando el otro camino que explicaron ellos dos y estoy desesperado porque me hace mucha falta tenerlo.

Hechelion

#10
Cita de: divmas en 06 de Marzo de 2011, 02:47:49 AM
Primero de todo gracias a los dos por la rápida respuesta, pero sigo sin dar en el clavo... os explico:

tengo en el principal:

Código (vbnet) [Seleccionar]


do

estado=m_input.Mouse_Press

loop

sub click_izquierdo
...
end sub



en la clase boton cuando detecto la zona de impacto:

Código (vbnet) [Seleccionar]


If estado = 0 And m_input.Mouse_Press = Mouse_Button.Left_Button Then

   RaiseEvent click_izquierdo()

End If




esto seria según me habeis dicho...    pero no funciona...

que hago mal?

Gracias

La pregunta del millón.  el "estado" lo estás actualizando antes o después de usarlo en los IF?

Edit:
En este caso debes actualizar el estado después de ejecutar los IF, si lo usas antes, entonces jamas se dará la situación estado = 0 y clic = 1.

[EX3]

Esta es la clase que decia:
' GameInputHitEvent.cls
' Version 1.0
' Clase complemento para la clase dx_Input_Class de dx_lib32 2.2.0 para lectura de eventos de pulsaciones.
' José Miguel Sánchez Fernández - 09/02/2009 (actualizado 07/02/2011)

Option Explicit

Private refGameInput As dx_Input_Class  ' Referencia a la instacia de dx_Input_Class del programa.

Private keybHitState(255) As Boolean    ' Estados de las teclas del teclado.
Private mouseHitState As Mouse_Data     ' Estados de los botones del raton.
Private joyHitState(1 To 4, 1 To 16) As Boolean

' Inicializa la clase obteniendo la referencia a la instancia de la clase dx_Input_Class del programa:
Public Sub Initialize(GameInput As dx_Input_Class)
    Set refGameInput = GameInput
End Sub

' Evalua si la tecla del teclado ha sido presionada:
Public Function Key_Hit(key As Key_Const) As Boolean
    If refGameInput.key(key) And Not keybHitState(key) Then
        keybHitState(key) = True
        Key_Hit = True
    End If
End Function

' Evalua si el boton del raton ha sido presionado:
Public Function Mouse_Hit(Button As Mouse_Button) As Boolean
    If (Button = Left_Button And refGameInput.Mouse.Left_Button) And Not mouseHitState.Left_Button Then
        mouseHitState.Left_Button = True
        Mouse_Hit = True
       
    ElseIf (Button = Right_Button And refGameInput.Mouse.Right_Button) And Not mouseHitState.Right_Button Then
        mouseHitState.Right_Button = True
        Mouse_Hit = True
       
    ElseIf (Button = Middle_Button And refGameInput.Mouse.Middle_Button) And Not mouseHitState.Middle_Button Then
        mouseHitState.Middle_Button = True
        Mouse_Hit = True
       
    End If
End Function

' Evalua si el boton del joystick ha sido pulsado:
Public Function Joystick_Hit(Joystick As Integer, Button As Joystick_Button) As Boolean
    Dim value As Long
    value = refGameInput.Joystick_Press(Joystick)
    If value > 0 And Not joyHitState(Joystick, value) Then
       joyHitState(Joystick, value) = True
       Joystick_Hit = True
    End If
End Function

' Actualiza los estados de la clase:
Public Sub Update()
    Call UpdateKeyb
    Call UpdateMouse
    Call UpdateJoystick
End Sub

' Codigo encargado de actualizar los estados del teclado:
Private Sub UpdateKeyb()
    Dim key As Long
    For key = 0 To 255
        If Not refGameInput.key(key) And keybHitState(key) Then keybHitState(key) = False
    Next
End Sub

' Codigo encargado de actualizar los estados del raton:
Private Sub UpdateMouse()
    If Not refGameInput.Mouse.Left_Button And mouseHitState.Left_Button Then mouseHitState.Left_Button = False
    If Not refGameInput.Mouse.Right_Button And mouseHitState.Right_Button Then mouseHitState.Right_Button = False
    If Not refGameInput.Mouse.Middle_Button And mouseHitState.Middle_Button Then mouseHitState.Middle_Button = False
End Sub

' Codigo encargado de actualizar los estados de los joysticks:
Private Sub UpdateJoystick()
    Dim i As Long, j As Long
    For i = 1 To 4
        With refGameInput.Joystick(i)
            If .X = 0 Then
                joyHitState(i, 13) = False
                joyHitState(i, 15) = False
            ElseIf .Y = 0 Then
                joyHitState(i, 14) = False
                joyHitState(i, 16) = False
            Else
                For j = 1 To 12
                    If Not .Button(i) And joyHitState(i, i) Then joyHitState(i, i) = False
                Next
            End If
        End With
    Next
End Sub

' Destructor de la clase:
Private Sub Class_Terminate()
    Set refGameInput = Nothing
End Sub


Copiar el codigo en un modulo clase y lo nombrais como "GameInputHitEventClass". Despues es tan sencillo como que lo añadais en vuestro proyecto y lo useis de la siguiente manera:

1. Crearos una instancia del objeto que sea visible desde cualquier parte del proyecto (donde tengáis instanciado dx_lib32 seria un buen lugar):
Public HitEvent As New GameInputHitEventClass

2 . Inicializar el objeto pasandole la instancia de la clase dx_Input_Class que tengais:
' Supongamos que vuestra instancia de dx_Input_Class se llame m_Input:
Call HitEvent.Initialize(m_Input)


3. Al principio de vuestro bucle principal, antes de nada, deberéis hacer la siguiente llamada para actualizar correctamente los estados de la clase, siempre antes de cualquier llamada que se vaya hacer para preguntar estados, de lo contrario no funcionara correctamente la sincronizacion:
Call HitEvent.Update()

4. Despues ya podreis llamar a las funciones de la clase para evaluar estados:
If HitEvent.Key_Hit(Key_Space) Or HitEvent.Mouse_Hit(Left_Button) Then ...

Las funciones de joystick no he podido evaluarlas (no tengo ninguno en el trabajo obviamente :P) pero las del teclado y raton si funcionan seguro por que las acabo de probar con el siguiente ejemplo:
Option Explicit

Dim GameInput As New dx_Input_Class
Dim HitEvent As New GameInputHitEventClass

Private Sub Form_Load()
    Call Me.Show
    Call GameInput.Init(Me.hWnd)
    Call HitEvent.Initialize(GameInput)
   
    Dim i As Long
   
    Do
        Call HitEvent.Update
       
        If HitEvent.Key_Hit(Key_Space) Or HitEvent.Mouse_Hit(Left_Button) Then
            Select Case i
                Case 0
                    Me.BackColor = vbRed
                    i = 1
                Case 1
                    Me.BackColor = vbYellow
                    i = 2
                Case 2
                    Me.BackColor = vbGreen
                    i = 3
                Case 3
                    Me.BackColor = vbBlue
                    i = 0
            End Select
        End If
       
        DoEvents
    Loop
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Set HitEvent = Nothing
    GameInput.Terminate
    End
End Sub


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

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

divmas


Muchísimas gracias EX3 por las molestias y poner a disposición esa clase. Funciona perfectamente.
Has hecho un grandisimo trabajo con esta libreria.

Gracias igualmente a Hechelion y Ubermann por intentar ayudarme.

Un saludo.






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.