Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Tazmania40

#1
Muchas gracias Elektro por todo, ya he probado la segunda opción y es la que me voy a quedar (dejo aqui el código) es justo lo que quería, por un lado con el sender obtengo las propiedades de la matriz del PictureBox donde he realizado click para cambiar y por otro lado el índice con tu función que era la pregunta principal, así conservo los datos de mi propiedad Tag que puedo modificar.

Tienes un dominio absoluto de los métodos de las clases, te envidio (sanamente) por tu facilidad sobre la programación en general, yo como ya comente en otros post programo por hobby para realizar pequeños jueguecitos principalmente con VB.NET y XNA, aunque ahora también aprendí algo de C# (traducciones  a vb.net) y GameMaker (v.1.4).

Gracias por la explicación de Friend, como suelo utilizar clases externas siempre pongo public. Siempre veo que sueles utilizar la forma correcta y de buenas prácticas para programar, aunque muchos no lo entendemos y dando consejos de que no utilizar. Miraré esa información a modo consulta. Sobre el tema de modificar un PictureBox o cualquier otro control, creo que es muy extenso y ese tercer método no utilizaré. Saludetes y que pases un buen finde

Código (vbnet) [Seleccionar]

Public Class Form1
    Private Matriz(2, 3) As PictureBox                          ' Matriz de 3x4 elementos

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ' Dibujamos matriz bidimensional de 3 filas y 4 columnas
        For F = 0 To 2                                          ' Recorre las Filas
            For C = 0 To 3                                      ' Recorre las Columnas
                Matriz(F, C) = New PictureBox
                Matriz(F, C).Size = New Size(32, 32)
                Matriz(F, C).BorderStyle = 1
                Matriz(F, C).Location = New Point(C * 32 + C, F * 32 + F + 100)
                Matriz(F, C).Tag = 0
                Me.Controls.Add(Matriz(F, C))
                AddHandler Matriz(F, C).Click, AddressOf Evento2
            Next C
        Next F
    End Sub

    Private Sub Evento2(sender As Object, e As EventArgs)
        Dim indices As Integer() = IndicesOf(Matriz, DirectCast(sender, PictureBox))
        Dim pcb As PictureBox = DirectCast(sender, PictureBox)
        pcb.BackColor = Color.Blue
        MsgBox("Valor Fila: " & indices(0) + 1 & " y Columna: " & indices(1) + 1)
    End Sub

    ' Función obtener índice de una Matriz de 2 dimensiones
    Public Shared Function IndicesOf(Of T)(ByVal [array] As T(,), ByVal value As T) As Integer()

        For i As Integer = [array].GetLowerBound(0) To [array].GetUpperBound(0)
            For j As Integer = [array].GetLowerBound(1) To [array].GetUpperBound(1)
                If [array](i, j).Equals(value) Then
                    Return {i, j}
                End If
            Next j
        Next i
        Return Nothing

    End Function
End Class
#2
Muchas gracias Elektro eres un genio, haces que lo difícil parezca fácil y encima expones muchas maneras. Voy analizarlas y te voy escribiendo en este mismo post. No tengo mucho tiempo (tengo 3 niñas y dos son bebes) y me cuesta probar y analizar.

El primero de la clase no lo había pensado de esa manera. He realizado el código y funciona. Lo pongo el pequeño ejemplo

Código (vbnet) [Seleccionar]

Public Class Form1
    Private Matriz(2, 3) As PictureBox                          ' Matriz de 3x4 elementos

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        ' Dibujamos matriz bidimensional de 3 filas y 4 columnas
        For F = 0 To 2                                         ' Recorre las Filas
            For C = 0 To 3                                     ' Recorre las Columnas
                Matriz(F, C) = New PictureBox
                Matriz(F, C).Size = New Size(32, 32)
                Matriz(F, C).BorderStyle = 1
                Matriz(F, C).Location = New Point(C * 32 + C, F * 32 + F + 100)

                Dim obj As New TestClass()
                obj.Valor = 0
                obj.F = F
                obj.C = C
                Matriz(F, C).Tag = obj

                Me.Controls.Add(Matriz(F, C))
                AddHandler Matriz(F, C).Click, AddressOf Evento2
            Next C
        Next F
    End Sub

    Private Sub Evento2(sender As Object, e As EventArgs)
        Dim pcb As PictureBox = DirectCast(sender, PictureBox)
        Dim obj As TestClass = DirectCast(pcb.Tag, TestClass)
        pcb.BackColor = Color.Blue
        MsgBox("Fila y Columna (" & obj.F + 1 & "," & obj.C + 1 & ")")
    End Sub

    ''''' CLASE PARA ASIGNAR LAS PROPIEDADES
    Friend NotInheritable Class TestClass
        Public Property Valor As Integer
        Public Property F As Integer
        Public Property C As Integer

        Public Sub New() ' Constructor vacío
        End Sub
    End Class

End Class


En este código la pega que veo es en Tag yo tengo valores que al principio valen 0 y luego les asigno otros al pulsar en cada recuadro que provienen de la propiedad Tag de un Picture principal.
Aqui lo he llamado obj.Valor, podia solucionarlo a continuación del evento
Código (vbnet) [Seleccionar]

obj.Valor = PicPrincipal.Tag
Matriz(obj.F, obj.C).Tag = obj

Vamos enredándolo un poco porque siempre tienes que pasarle todas las propiedades, pero la solución es válida para los índices de la matriz. Una pregunta para las prácticas de buena programación

Friend NotInheritable : porque empleas que la clase sea Friend y este modificador (es la clase base según he leido). He probado con Public (funciona y sin modificador) que siempre realizo cuando creo mis programas, claro dentro de una clase externa. Me imagino que Friend es para que no se pueda acceder externamente, aunque ahi yo suelo emplear Private, siempre he tenido un lio con estas cosas que son sencillas.

A ver si mañana (aunque ya es, jeje) pruebo la función para mi código y así conservo la propiedad Tag con los valores y sería más fácil.

Gracias y saludos
#3
En primer lugar muchas gracias Elektro como siempre. Efectivamente el objeto sender, me fije ayer más tarde podía asignar las propiedades en el momento de hacer clic y que ese PictureBox por ejemplo cambiara de color.

Código (vbnet) [Seleccionar]

Private Sub Evento2(sender As Object, e As EventArgs)       
        sender.BackColor = Color.Blue
        '.......
    End Sub


Aunque lo que requiero realmente es obtener el indice como en array de una dimensión. Si hay alguna forma de pasarle esas 2 coordenadas al evento o que las recoja y ponerlo en una variable matriz de 2 dimensiones
Código (vbnet) [Seleccionar]

Dim Index As Integer = Array.IndexOf(Lista, sender)
' Esto mismo con una variable matriz de mismo tipo que la principal y donde la clase Array pueda
' obtener los 2 indices al igual que hace con 1 solo. Aunque sus métodos solo dicen que es para
' 1 dimensión. Si hay algo parecido a esta clase y obtenerlo fácilmente.


Como bien dices la propiedad Tag podemos guardar esas coordenadas, pero lamentablemente la utilizo para guardar valores. Otra posibilidad es agregar otra propiedad personal al control PictureBox (Como Tag, aunque claro serían otras 2 más Matriz(F, C) guardar F y C) , pero sería muy engorroso y alargaría mucho el código, además de que no se.

No se si en los parámetros del evento click pueden recoger esas 2 coordenadas, tal y como hacemos cuando creamos un procedimiento o función, que también me valdría.

Gracias y saludos
#4
Buenas estoy realizando un programa y me veo atascado en un evento por código, de momento no encuentro nada pero sigo buscando, a ver si alguno me da la solución antes.

Pongo el siguiente ejemplo y es lo mismo que deseo que funcione con las matrices de 2 dimensiones en Visual Basic 2013.

Código (vbnet) [Seleccionar]

Private Lista(4) As PictureBox

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
       For A = 0 To 4
           Lista(A) = New PictureBox                       ' Creamos una nueva instancia
           Lista(A).Size = New Size(32, 32)                ' Tamaño PictureBox
           Lista(A).BorderStyle = 1                        ' Dibuja borde
           Lista(A).Location = New Point(A * 32 + A, 50)   ' Posicionamos PictureBox
           Me.Controls.Add(Lista(A))                       ' Añadimos al Formulario
           AddHandler Lista(A).Click, AddressOf Evento1    ' Agregamos evento Click
       Next A      
End Sub

Private Sub Evento1(sender As Object, e As EventArgs)
       Dim Index As Integer = Array.IndexOf(Lista, sender) ' Obtenemos el índice seleccionado
       MsgBox("Has pulsado " & Index + 1 & " recuadro.")
End Sub


El código de arriba muestra 5 controles de tipo PictureBox como un array, puesto que en NET no se
podía realizar mediante diseño, al hacer click en cualquiera de ellos obtenemos el índice del
que hemos pulsado y así podemos utilizar las propiedades de cada uno de ellos.

Siguiendo con el ejemplo, me gustaría lo mismo para una matriz de 2 dimensiones que la dibujo
perfectamente, pero cuando asigno el evento Click no se que emplear para obtener el índice
puesto que Array.IndexOf es para matrices unidimensionales ¿Como puedo obtener el índice de
una matriz de 2 dimensiones, (0,0) (0,1) (0,2).. (1,0)..etc, al hacer click sobre cada recuadro
PictureBox ? Muchas GRACIAS y saludos

Código (vbnet) [Seleccionar]

Private Matriz(2, 3) As PictureBox                      ' Matriz de 3x4 elementos
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load      
       
       ' Dibujamos matriz bidimensional de 3 filas y 4 columnas
       For F = 0 To 2                                         ' Recorre las Filas
           For C = 0 To 3                                     ' Recorre las Columnas
               Matriz(F, C) = New PictureBox
               Matriz(F, C).Size = New Size(32, 32)
               Matriz(F, C).BorderStyle = 1
               Matriz(F, C).Location = New Point(C * 32 + C, F * 32 + F + 100)
               Me.Controls.Add(Matriz(F, C))
               AddHandler Matriz(F, C).Click, AddressOf Evento2
           Next C
       Next F
   End Sub

   Private Sub Evento2(sender As Object, e As EventArgs)
       ' Fallo porque Array.IndexOf  es para matrices de 1 sola dimensión
       Dim Index As Integer = Array.IndexOf(Matriz, sender)
       '...
   End Sub

#5
Cita de: rulovive en 29 Enero 2018, 16:40 PM
pensé que el manejo por consola era lo mas puro para curtirse en la programacion... digo. si no lo he hecho en modo visual es precisamente porque quiero batallar... aunque ya no se XD


Buenas, según mi opinión sobre el tema, pensaba hace muchos años al inicio que estudiar ensamblador era lo más para desarrollar juegos y de hecho incluía pequeñas rutinas por aquel entonces cuando programaba en Pascal (naturalmente corrían super rápidas). Con el tiempo y pasado los años (ahora actualizandome a VB.NET (2013-1015) el querer hacer mejores juegos te lleva a utilizar el modo gráfico y no solo el GDI+ del Visual Basic, sino el aprender otras librerias, en mi caso XNA para poder realizar lo que siempre me gusto, esos jueguecillos de los años 80 o 90, puesto que en Visual Basic o C# tenemos el problema de los tiempos de refresco cuando ejecutamos nuestro programa en distintos procesadores o Sistemas Operativos. Por ejemplo en uno de mis juegos llamado "Meteoros" donde utilizaba GDI+ aunque realicé una rutina de tiempo para calcular al principio la velocidad de procesador, no era del todo exacta al probar en un Pentium IV, dual core o I5 o bien en un SO Windows 7 o Windows XP (SP3). Por ello me decante por XNA para Visual Basic 2013 que como bien sabrás esta hecho para C# donde sin problemas soluciona los tiempos y la manipulación de los gráficos.

Aunque como dice Elektro si ha ti te hace ilusión seguir programando en modo consola, pues sigue así, yo por ejemplo XNA esta obsoleto pero me soluciona lo que siempre he querido. Ahora estoy aprendiendo a realizar algun juego estilo hibrido Windows Form y XNA; así aprovecho las caracteristicas de los controles de Windows Forms con el Game Loop que se ejecuta en XNA (60 veces por segundo) para dibujar al mismo tiempo mis objetos y que se muevan a la misma velocidad aunque cambie de procesador o sistema operativo.

Saludetes
#6
Me respondo a mi mismo porque ya he encontrado la solución.
He encontrado otro traductor y aunque tampoco lo dejaba exacto, modificando ya lo solucioné
https://www.carlosag.net/tools/codetranslator

Código (vbnet) [Seleccionar]

If (((bitsA((x - texture1Rectangle.X) + (y - texture1Rectangle.Y) * texture1Rectangle.Width) And &HFF000000) >> 24) > 20 AndAlso
    ((bitsB((x - texture2Rectangle.X) + (y - texture2Rectangle.Y) * texture2Rectangle.Width) And &HFF000000) >> 24) > 20) Then
     PorColisionPixel = True
     .....
End If


El traductor te cambia el número a decimal "4278190080" (QUE TAMBIEN FUNCIONA) pero el operador de desplazamiento >> te lo cambia por +, además de varios paréntesis que no hacen falta y hay es donde fallaba en tiempo de ejecución que no hacía bien la comprobación por pixel.

Si sabéis de algún traductor de C# a VB.net y viceversa más actualizado y que sea online se agradece. Gracias y salu2
#7
Buenas, estoy con una parte de código que no consigo traducir a VB.net, en C# funciona sin problemas. He utilizado el conversor http://converter.telerik.com pero se ve que ya no funciona, también otros conversores online pero dan problemas o el código escrito no compara correctamente la colisión, ya que se trata de colisiones entre 2 objetos por pixel.

Si podéis echarme una mano tan solo con este código o bien algún conversor que funcione correctamente de C# a VB.NET

Código (csharp) [Seleccionar]

if (((bitsA[(x - texture1Rectangle.X) + (y - texture1Rectangle.Y) * texture1Rectangle.Width] & 0xFF000000) >> 24) > 20 &&
   ((bitsB[(x - texture2Rectangle.X) + (y - texture2Rectangle.Y) * texture2Rectangle.Width] & 0xFF000000) >> 24) > 20)
                    {
                        PorColisionPixel = true;
                        ...
                    }


El fallo se presenta en el operador de desplazamiento o número hexadecimal.
Como nota decir que el código lo estoy realizando con XNA 4.0 en Visual Basic 2013, donde ya realicé el programa en XNA 4.0 con C# funcionando correctamente la colisión por pixel y es ahora donde he traducido todo el programa y solo me falta esta parte de código que no consigo que funcione en VB.net.

Muchas gracias y saludos

#8
Buenas a todos/as, ya lo he conseguido también la visualización mediante animaciones con "Sprite Sheet". La instrucción que solamente cambia es GetData.

Código (csharp) [Seleccionar]

Player.GetData(0,
              new Rectangle(currentFrameX * FrameWidth, currentFrameY * FrameHeight, FrameWidth, FrameHeight),
              texturaPlayer,
              currentFrameX * currentFrameY,
              FrameWidth * FrameHeight);


Donde currentFrameX es la imagen que queremos representar en el eje X. Normalmente comenzamos por la primera y la inicializamos con 0. CurrentFrameY sería la altura de esa imagen por si tenemos imágenes de diferentes alturas (creo que esto se realiza para las escalas...). Yo en mi juego como el "Sprit Sheet" tiene la misma altura y quiero coger cada recuadro en mi caso es 0 también.

FrameWidth y FrameHeight, corresponden a la anchura y altura de una sola imagen, por ejemplo mi "Sprite Sheet" es de 670x60 (aconsejo imágenes animadas en partes iguales cada recuadro). FrameWidth sería 67 y FrameHeight sería 60.

Recordar que la imagen que capturamos de origen en el rectángulo tiene que ser el ancho y alto de 1 sola imágen y la imagen rectángulo destino es lo mismo pero cambiamos la posiciones X e Y según vamos moviendo nuestro sprite.

Saludetes y bueno ahora lo pasaré a VB.net que es lo que me gusta.
#9
Referente a las librerías de XNA y comentario de obsoleto como dices Elektro no significa que no sirva, te lo he oido decir en muchas ocasiones y no todos los programadores están a la última, incluso los que trabajan y se ganan la vida en ello.

XNA termino el soporte de Microsoft en 2014, pero como bien dije en unos post anteriores yo tenía problemas para mis juegos con el tema de los tiempos y que fueran a la misma velocidad en distintos procesadores, la clase  Stopwatch me solucionó en parte, pero todavía viejos procesadores se notaba la velocidad y fallaba dicha clase. Tenía la opción de mirar directX (más difícil) y casi toda la ayuda va para C++ que no tenía ni idea o bien elegir XNA más fácil y que el usuario al que va dirigido el juego solo tiene que instalar unas librerias de 7 Mb y ya puede correr los juegos en XNA. Con XNA el ciclo del juego se realiza en 60 veces en 1 segundo (60Hz) y se soluciona el tiempo que era mi mayor problema para distintos procesadores. Con todo lo que trae para realizar juegos 2D (incluso también tiene 3D) para mi es más que suficiente, después de realizar juegos estilo arkanoid, serpiente, meteoritos, tetris... pues ya tocaba empezar con los scroll, animaciones e intentar hacer algo de plataformas. Yo con saber eso voy más que contento, si puedo realizar algo en 3D el día de mañana pues creo que me sobra librería. Como bien dije lo hago por hobby y si bien podía pasarme a motores como 3d Unity, pues no me llama la atención de momento y eso que veo tutoriales y lo respeto a todos aquellos que hacen maravillas con Unity, pero a mi me gusta seguir programando con VB.NET y todo lo que pueda hacer con el.

Bueno voy a intentar pegarme con lo que dije "sprite sheets" para mostar la imagen que quiero comparar con el sprite en tema de colisión de pixel. Se utiliza el mismo método GetData que lleva otros parámetros. Imaginemos que mi textura tiene 6 imágenes para la animación y quiero mostrar la número 3, naturalmente GetData tiene que capturar la 3 que es distinta a la 1. Si alguien sabe se lo agradezco, aunque me pegaré con ello y sino lo consigo pondré una nueva pregunta describiendo.

Gracias Elektro, eres todo una máquina, yo es que voy muy lento y con la edad ya me conformo con practicar lo que puedo cada día que muchas veces me quita tiempo de sueño, pero siempre con ganas.

Saludetes
#10
Ya está resuelto, gracias Electro por en enlace al traductor (http://converter.telerik.com), pensaba que para XNA no valía.  Aunque no entiendo si por ejemplo en VB.net declarar un array tipo variable u objeto es

Código (vbnet) [Seleccionar]
Dim var() As Integer

su traducción en C#
Código (csharp) [Seleccionar]
int[] var; por eso me ha dado indicio a error en la traducción y lo puse en "texturaPlayer". Aqui está el código correcto.

Código (vbnet) [Seleccionar]

Private Player As Texture2D                         ' Sprite del Jugador1
Private rectPlayer As Rectangle                     ' Rectángulo Jugador1 (colisión)
Private texturaPlayer As Color()                    ' Colores Jugador1

Protected Overrides Sub LoadContent()
        spriteBatch = New SpriteBatch(GraphicsDevice)
       ' Carga textura Jugador 1 y copia el total número colores
        Player = Content.Load(Of Texture2D)("Imagenes\Sprite1")
        texturaPlayer = New Color(Player.Width * Player.Height - 1) {}
        Player.GetData(texturaPlayer)
        .....
End Sub


Veo que el GetData también permite para tira de imágenes, en el argot llamado "sprite sheets" ya que utilizo animaciones y naturalmente la imagen de "Player" cambia cada cierto tiempo y tiene que evaluar esa imagen. Si alguien ya lo ha realizado se agradece, yo empezaré a intentarlo con C# y luego en VB.NET.

Saludetes