```Welcome again.  In this episode, we will be dealing with functions.  First on our agenda is how to make our editor a
little more refined.  Up until now, the editor makes it hard to make nice-looking maps.  So, to remedy this problem,
we will make all of our points follow a snap-to-grid, which means that all of our points will snap to the closest of
some certain values.
In this demonstration, we will snap all of our points to the closest multiple of 8.
So, sounds easy right?  All we need to do is take all of the points that we get in the MouseUp event and round them
to the closest 8.  This will be made easier by making a function that will round any integer we pass it to the
nearest 8.

Rounding to the nearest 8 *sounds* easy: 0->0, 1->0, 2->0, 3->0, 4->8, 5->8, 6->8, 7->8
And there are a lot of ways to do it.  Since this functionality is only for the editor, we really don't *need* it to
be as fast as possible, although, it wouldn't hurt for it to be fast.
Private Function RoundTo8(ByVal Number As Integer) As Integer
Return 8 * Convert.ToInt32(Math.Round(Number / 8, 0))
End Function
Surely, this is a valid solution as well, and probably the first one that comes to mind if you are used to it.
My version would be below, however , but it would barely make a difference in which function
you use, since it will only be called four times.
Private Function Nearest8(ByVal Number As Integer) As Integer
Return (Number + 4) And (Not &O7)
End Function
Now, we have to apply this function.
We could just round the points in the MouseUp event so only our final result is on the grid.
We can also round the points in the Artwork sub so that our selection rectangle snaps to the grid as well.
First, let's do the MouseUp snapping.
In the MouseUp event, we can (actually we could have long ago) have the rectangle that represents where the new
object will go.  The 'Placed' Rectangle variable can do this for us.
So, before we even enter the Select Case block, we can set up the Placed Rectangle.
Placed = Rectangle.FromLTRB(Math.Min(InitialPt.X, Mu.X) + ScreenLeft, Math.Min(InitialPt.Y, Mu.Y) + ScreenTop, Math.Max(InitialPt.X, Mu.X) + ScreenLeft, Math.Max(InitialPt.Y, Mu.Y) + ScreenTop)
This is how it would have been before.  Now:
Placed = Rectangle.FromLTRB(Nearest8(Math.Min(InitialPt.X, Mu.X) + ScreenLeft), Nearest8(Math.Min(InitialPt.Y, Mu.Y) + ScreenTop), _
Nearest8(Math.Max(InitialPt.X, Mu.X) + ScreenLeft), Nearest8(Math.Max(InitialPt.Y, Mu.Y) + ScreenTop))
'Our completed selection rectangle.

And we no longer have to assign Placed right before we use it for the Platforms, Walls, and Lava.
Coins and Floaters are another matter, but you can leave those out of the rounding operation.
Private Sub PFMain_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
Dim Placed As Rectangle
'This is the rectangle that we have drawn.
Dim Mu As Point = New Point(e.X, e.Y)
'Convert the mouseeventargs's .X and .Y into a Point structure.
IsMouseDown = False

Placed = Rectangle.FromLTRB(Nearest8(Math.Min(InitialPt.X, Mu.X) + ScreenLeft), Nearest8(Math.Min(InitialPt.Y, Mu.Y) + ScreenTop), _
Nearest8(Math.Max(InitialPt.X, Mu.X) + ScreenLeft), Nearest8(Math.Max(InitialPt.Y, Mu.Y) + ScreenTop))
'Our completed selection rectangle.

Select Case MDObject
Case "P"c
'For platforms.
Platforms.Insert(0, Placed)
Case "W"c
'For walls.
Walls.Insert(0, Placed)
Case "L"c
'For lava.
Lavas.Insert(0, Placed)
Case "C"c
Coins.Insert(0, New Rectangle(Nearest8(Mu.X + ScreenLeft), Nearest8(Mu.Y + ScreenTop), COINSIZE, COINSIZE))
'Place a coin at the point where the mouse was released.
Case "F"c
Clock.Enabled = False
'Lighten the processing load while we set up our floater.
Dim Fm As FloaterEd = New FloaterEd
Fm.ShowDialog()
'After the showdialog, the floater's final six properties will be set.
'But, the rectangle will be empty.
Dim Fltr As LevFloater = Fm.Floater
'Copy the floater to our variable.
Fltr.Loc = New Rectangle(Nearest8(Mu.X + ScreenLeft), Nearest8(Mu.Y + ScreenTop), FLOATERSIZE, FLOATERSIZE)
'For the floater...
'Set the rectangle.  The size is fixed, so we just make the rectangle like we did for the coin.
Floaters.Insert(0, Fltr)
'And this final floater will be added.
'The movement of the floater after it is added to the form is not the exact movement that it will have
'when it is loaded from file, because the value of FloatTick is not always 0 when the floater is created, and its
'movement depends on the value of floattick with the periodic function.
Clock.Enabled = True
'Continue game.
End Select
End Sub
And then, for the Artwork subroutine and drawing the selection rectangle.

Outline = Rectangle.FromLTRB(Math.Min(Nearest8(InitialPt.X + ScreenLeft) - ScreenLeft, Nearest8(Curse.X + ScreenLeft) - ScreenLeft), _
Math.Min(Nearest8(InitialPt.Y + ScreenTop) - ScreenTop, Nearest8(Curse.Y + ScreenTop) - ScreenTop), _
Math.Max(Nearest8(InitialPt.X + ScreenLeft) - ScreenLeft, Nearest8(Curse.X + ScreenLeft) - ScreenLeft), _
Math.Max(Nearest8(InitialPt.Y + ScreenTop) - ScreenTop, Nearest8(Curse.Y + ScreenTop) - ScreenTop))
Now, the snapping process is complete.

If you happened to be following the periodic section, you'll find my formulas for squares, triangles, and etc.
These same formulas can be ported over to .NET as well, with a few modifications, of course.
Private Function Fmd(ByVal Nume As Single, ByVal Denom As Single) As Single
Dim ItE As Double = Math.IEEERemainder(Nume, Denom)
'Finally figured out how this function works.
If ItE < 0 Then
ItE = Denom + ItE
End If
Return Convert.ToSingle(ItE)
End Function
And then, there's the actual functions.
Private Function Fmd(ByVal Nume As Single, ByVal Denom As Single) As Single
Dim ItE As Double = Math.IEEERemainder(Nume, Denom)
'Finally figured out how this IEEERemainder function works.
If ItE < 0 Then
ItE = Denom - ItE
End If
End Function
Private Function TrglDif(ByVal N As Single) As Single   'Squarewave used for generating the trianglewave.
Dim Res As Single = Fmd(N, 2)  'Fmd now takes a numerator and a denominator.
If Res >= 0 AndAlso Res < 1 Then
Return 1
Else
Return -1
End If
End Function
Private Function HxgnDif(ByVal N As Single) As Single
Dim Res As Single = Fmd(N, 4)
If Res >= 0 AndAlso Res < 1 Then
Return 2
ElseIf Res >= 1 AndAlso Res < 2 Then
Return 0
ElseIf Res >= 2 AndAlso Res < 3 Then
Return -2
Else
Return 0
End If
End Function
Private Function TrpzDif(ByVal N As Single) As Single
Dim Res As Single = Fmd(N, 3)
If Res >= 0 AndAlso Res < 1 Then
Return 0
ElseIf Res >= 1 AndAlso Res < 2 Then
Return 2
Else
Return -2
End If
End Function
Private Function SclnDif(ByVal N As Single) As Single
Dim Res As Single = Fmd(N, 3)
If Res >= 0 AndAlso Res < 1 Then
Return 2
Else
Return -1
End If
End Function

Our enumeration will also have to be changed.
Public Enum PeriodicDesignation
Stable = 0  'Denotes that the object will not move in this direction.
CosineFxn   'Moves using the cosine function.
SineFxn     'Moves using the sine function.
Triangle
Hexagon
Trapezoid
Scalene
End Enum

And integrating these functions with our existing floaters.

Dim LP As Integer
For LP = 0 To Floaters.Count - 1
Floater = DirectCast(Floaters(LP), LevFloater)
'Since we are changing properties of the floater, and since floater is a structure, we have to reassign the
'newly modified floater back to the array.

Select Case Floater.FunctionHorizontal
'Looking at the function that we have designated, we choose the proper periodic function for setting to dX and dY.
Case PeriodicDesignation.CosineFxn
dX = Convert.ToInt32(Floater.RadispeedX * Math.Cos(Convert.ToDouble(FloatTick) * Floater.FrequencyX / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.SineFxn
dX = Convert.ToInt32(Floater.RadispeedX * Math.Sin(Convert.ToDouble(FloatTick) * Floater.FrequencyX / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Stable
dX = 0
Case PeriodicDesignation.Triangle
dX = Convert.ToInt32(Floater.RadispeedX * TrglDif(Convert.ToSingle(FloatTick) * Floater.FrequencyX / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Hexagon
dX = Convert.ToInt32(Floater.RadispeedX * HxgnDif(Convert.ToSingle(FloatTick) * Floater.FrequencyX / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Trapezoid
dX = Convert.ToInt32(Floater.RadispeedX * TrpzDif(Convert.ToSingle(FloatTick) * Floater.FrequencyX / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Scalene
dX = Convert.ToInt32(Floater.RadispeedX * SclnDif(Convert.ToSingle(FloatTick) * Floater.FrequencyX / Me.FREQUENCYDIVIDER))
End Select
Select Case Floater.FunctionVertical
'Looking at the function that we have designated, we choose the proper periodic function for setting to dX and dY.
Case PeriodicDesignation.CosineFxn
dY = Convert.ToInt32(Floater.RadispeedY * Math.Cos(Convert.ToDouble(FloatTick) * Floater.FrequencyY / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.SineFxn
dY = Convert.ToInt32(Floater.RadispeedY * Math.Sin(Convert.ToDouble(FloatTick) * Floater.FrequencyY / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Stable
dY = 0
Case PeriodicDesignation.Triangle
dY = Convert.ToInt32(Floater.RadispeedY * TrglDif(Convert.ToSingle(FloatTick) * Floater.FrequencyY / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Hexagon
dY = Convert.ToInt32(Floater.RadispeedY * HxgnDif(Convert.ToSingle(FloatTick) * Floater.FrequencyY / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Trapezoid
dY = Convert.ToInt32(Floater.RadispeedY * TrpzDif(Convert.ToSingle(FloatTick) * Floater.FrequencyY / Me.FREQUENCYDIVIDER))
Case PeriodicDesignation.Scalene
dY = Convert.ToInt32(Floater.RadispeedY * SclnDif(Convert.ToSingle(FloatTick) * Floater.FrequencyY / Me.FREQUENCYDIVIDER))
End Select

Floater.Offset(dX, dY)
'Move the floater using our offset subroutine.
Floaters(LP) = Floater
'Return the floater that we've modified to the array.
Next

```