# VBfx / Tile tutorial / Step 5

## Random movement

To bring life into the sample code I added a small function that provides random movement for the units. You don't have to understand the code but it's really easy. Basically it moves all units in their current direction and changes the direction from time to time. Here's the code:

```Public Sub MoveRandomly()
Dim A as Long

Dim MoveX as Long
Dim MoveY as Long

For A = 2 To UnitCount
'Reset
MoveX = 0
MoveY = 0

With Unit( A )
'Set random direction
If 100 * Rnd < 10 Then: .Direction = CLng( 3 * Rnd )

'Get movement
Select Case .Direction
Case 0: MoveY = -1 'Up
Case 1: MoveX = 1 'Right
Case 2: MoveY = 1 'Down
Case 3: MoveX = -1 'Left
End Select

'Set new position
MoveUnit A, ( .X + MoveX ), ( .Y + MoveY )
End With
Next
End Sub
```

## Collision checks

Now that we have some movement it's time to implement the collision checks. Since we already made a MoveUnit function we can just extend it to check the requested position before moving the unit. Note that we have to do 2 different collision checks, unit-to-map and unit-to-unit. The first one checks if the tile is walkable and the second checks if there's already a unit registered. If one of the checks fails the function simply exits without moving the unit at all.

Here again I'll first show you the code, then go through it step by step:

```Public Sub MoveUnit( Index as Long, NewX as Long, NewY as Long )
Dim TempIndex as Long

'Check boundaries
If NewX < 0 Then: NewX = 0
If NewY < 0 Then: NewY = 0
If NewX > ( ( Map.W - 1 ) * TileSize ) Then: NewX = ( ( Map.W - 1 ) * TileSize )
If NewY > ( ( Map.H - 1 ) * TileSize ) Then: NewY = ( ( Map.H - 1 ) * TileSize )

'Get new map index
TempIndex = ( CLng( NewY / TileSize ) * Map.W ) + CLng( NewX / TileSize )

With Unit( Index )
If Not TempIndex = .MapIndex Then
'Unit-to-map collision check
If Not Tile( Map.Floor( TempIndex ) ).Walkable Then: Exit Sub

'Unit-to-unit collision check
If Map.Units( TempIndex ) > 0 Then: Exit Sub
End If

'Unregister from map
If .MapIndex > -1 Then: Map.Units( .MapIndex ) = 0

'Apply new position
.X = NewX
.Y = NewY
.MapIndex = TempIndex

'Register to map
Map.Units( .MapIndex ) = Index
End With
End Sub
```

## Code discussion

Here we go.

```Public Sub MoveUnit( Index as Long, NewX as Long, NewY as Long )
Dim TempIndex as Long

'Check boundaries
If NewX < 0 Then: NewX = 0
If NewY < 0 Then: NewY = 0
If NewX > ( ( Map.W - 1 ) * TileSize ) Then: NewX = ( ( Map.W - 1 ) * TileSize )
If NewY > ( ( Map.H - 1 ) * TileSize ) Then: NewY = ( ( Map.H - 1 ) * TileSize )
```

This all stayed the same except that we need a tempoary index this time. Explanation following below.

```    'Get new map index
TempIndex = ( CLng( NewY / TileSize ) * Map.W ) + CLng( NewX / TileSize )
```

Instead of just moving the unit and setting the new index we get the requested map index here. This is because we need to check that position first before unregistering or moving anything.

```    With Unit( Index )
If Not TempIndex = .MapIndex Then
```

This line checks if the moved to another map position (tile). Othewise we don't have to double-check the tile and can skip the following collision tests.

```            'Unit-to-map collision check
If Not Tile( Map.Floor( TempIndex ) ).Walkable Then: Exit Sub
```

As the comment says this line checks the tile if it's walkable or not. If not we just exit the code without moving the unit at all.

```            'Unit-to-unit collision check
If Map.Units( TempIndex ) > 0 Then: Exit Sub
```

This second check uses the units map to see if the new position already contains another unit. This is exactly the line what we made this map for.

If the unit didn't yet leave it's current tile, this check would fail returning the unit's index because at this point it's still registered to that tile! This is another reason for checking if the unit moved on to another tile or not.

```        End If

'Unregister from map
If .MapIndex > -1 Then: Map.Units( .MapIndex ) = 0

'Apply new position
.X = NewX
.Y = NewY
.MapIndex = TempIndex
```

Now that the new position is confirmed we can unregister the unit from the current position and set the new coodinates. Also we can now store the new map index and use it in the following line to register the unit at the new position:

```        'Register to map
Map.Units( .MapIndex ) = Index
End With
End Sub
```

Finally the unit is re-registered at the new position.

## Conclusion

Now all the work gets paid and we can use only 1 line to perform the whole unit-to-unit collision check. And since the tile map has the same size as the unit map we can do the unit-to-map collision check without even re-calculating the map index. At this point your engine provides more or less all the collisions you need so run the sample code to see it working.