saratogacoach 0 Newbie Poster

Hi,

I am a newbie (retired social worker) using Visual Basic 2010 Express edition and need some help with an animation for an eLearning lesson. The animation illustrates a type of white noise (like TV static) called dynamic visual noise. I've got much of the code worked out (with a lot of help) but I discovered that the speed of the animation, using this code is wrong and need some help to fix the code, get it working correctly.

You can view a Flash demo of this noise animation at http://elearningprojects.com/WN5.swf

More info here about the visual noise animation (even a Delphi source code and Windows demo): http://www.st-andrews.ac.uk/~www_sp/people/personal/jgq/

The animation has a 640 X 640 canvas, with 8 X 8 white and black dots filling it using 80 across and 80 down, for a total of 6400 dots. Some of these (approximately 400) change every second (1000 Ms) from white to black or black to white. These 400 dots need to be selected randomly every second.

The VB code I am using is missing the ability to randomly select the 400 dots per second which are the dots to be changed (white to black or black to white).

Here's the current (commented) code that needs an addition of a random generator for the 400 dots every second that will be changed:

Option Strict On
Public Class Form1
    Private gDotSize As Integer = 8
    Private gCanvasSize As Integer = 640
    Private gDelay As Integer = 100 'ms
    Private gProceed As Boolean = False
    Private gImage As New System.Drawing.Bitmap(gCanvasSize, gCanvasSize)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.SetClientSizeCore(gCanvasSize, gCanvasSize)
        Me.Text = "Click the form to start and stop"

        'Set double-buffering so that graphics may be invalidated without causing flickering.
        SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.DoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
    End Sub

    Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        If gProceed Then
            gProceed = False
        Else
            gProceed = True
            Dim vThread As New System.Threading.Thread(AddressOf GenerateStatic_Background)
            With vThread
                .IsBackground = True
                .Name = "Thread for generating static"
            End With
            vThread.Start(New Object) 'You could pass an object into the thread here if you wanted.
        End If
    End Sub

    Private Sub GenerateStatic_Background(ByVal Arg As System.Object)

        'The canvas is square, so how many rows and columns will there be?
        Dim vRows As Integer = Convert.ToInt32(gCanvasSize / gDotSize)
        Dim vCols As Integer = Convert.ToInt32(gCanvasSize / gDotSize)

        'How many dots will there be total?
        Dim vTotalDots As Integer = Convert.ToInt32(vRows * vCols)

        'Create blank image to draw on.
        Dim vImg As New System.Drawing.Bitmap(gCanvasSize, gCanvasSize)
        Using vGr As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(vImg)

            'Instance random generator object and seed data.
            Dim vGen As New System.Security.Cryptography.RNGCryptoServiceProvider

            'Prepare an empty array of bytes which will be used to store random seed data.
            'These random bytes will be converted to a 32-bit integer.  Int32's are 4 bytes
            'in length; therefore the array will be 4 bytes in size.  Remember, when
            'dimensioning static arrays, we do not specify the "length" of the array like
            'in C++, but instead we specify the "upper bounds" a.k.a. the last index of
            'the array, which would be 3 (0-3).
            Dim vSeed(3) As Byte

            'Fill the empty array with a cryptographically strong sequence of random values.
            vGen.GetBytes(vSeed)

            'Instance a Random object using the random bytes (converted to an integer) as a seed.
            Dim vRand As Random = New Random(BitConverter.ToInt32(vSeed, 0))

            'Variables for choosing the color.
            Dim vCurrentRand As Integer = 0 'Black is 0; white is 1
            Dim vCurrentColor As System.Drawing.Color = System.Drawing.Color.Black

            'Do until told to stop by the user.
            While gProceed

                'Wait the desired period.
                System.Threading.Thread.Sleep(gDelay)

                'We will start on the first row on the left, work right across the columns, then drop
                'down to the second next row (back to the left), and again work right across the
                'columns, and so on...
                Dim vCurrentDot As New System.Drawing.Rectangle(0, 0, gDotSize, gDotSize)
                Dim vCurrentRow As Integer = 0
                Dim vCurrentCol As Integer = 0

                'Iterate each dot... come up with a random black or white state, and draw it to the image.
                For i As Integer = 0 To vTotalDots - 1

                    'Generate random black or white state for this dot.
                    vCurrentRand = vRand.Next(0, 2) 'Either 0 or 1
                    If vCurrentRand = 0 Then vCurrentColor = System.Drawing.Color.Black Else vCurrentColor = System.Drawing.Color.White

                    'Draw this dot.
                    vGr.FillRectangle(New System.Drawing.SolidBrush(vCurrentColor), vCurrentDot)

                    'Increment the current dot for the next iteration.
                    vCurrentCol += 1 : vCurrentDot.X += gDotSize
                    If vCurrentCol = vCols Then
                        vCurrentCol = 0 : vCurrentDot.X = 0
                        vCurrentRow += 1 : vCurrentDot.Y += gDotSize
                    End If
                Next

                'Update the UI.
                If Me.InvokeRequired Then
                    Try
                        Me.Invoke(New DrawUpdate_Delegate(AddressOf DrawUpdate), CType(vImg, System.Object))
                    Catch ex As Exception
                        'Error cuz you ended the program without allowing the thread to stop.
                        'To prevent this error, you could set gProceed = False in the Form_Closing event so the thread can end naturally.
                        'This Try block just prevents the error message.
                    End Try
                Else
                    DrawUpdate(CType(vImg, System.Object))
                End If
            End While
        End Using
    End Sub

    Private Delegate Sub DrawUpdate_Delegate(ByVal Arg As System.Object)
    Private Sub DrawUpdate(ByVal Arg As System.Object)
        gImage = DirectCast(Arg, System.Drawing.Bitmap)
        Me.Invalidate()
    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        e.Graphics.DrawImageUnscaled(gImage, 0, 0)
    End Sub
End Class

I would appreciate any code suggestions to add the random generator (described above) and where to add it in the above code. It would also be a huge help if I can change the specific number of random dots so I can try values ranging from 390-400 dots per second to see which value best replicates the precise animation speed needed.

Thanks very much for your help.

Kind Regards,
saratogacoach

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.