VBfx / Tile tutorial / Step 3

Start and stop

Whenever a unit moves over the map we have to activate the walk, fly or drive animation. As soon as it stops the animation also has to be stopped and reset to the original state displaying the standing position. We can't just set .Animated to true in the MoveUnit function because there's a chance of the movement being rejected because of collisions. Also we need to check in each frame if the animation needs to be stopped or not.

In the Animate function we already added a short piece of code that resets the animation when it's stopped so there's no need to care about that. But we still have to check in each frame if the unit moved or not. We can't just add this to the MoveUnit function because this is exactly the function that isn't called when there's no more movement.

So the system works like this:

1) MoveUnit

2) UpdateUnits

3) Animate

Theory discussion

Hopefully that wasn't too hard to understand. Note that step 2) and 3) are frequent calls while step 1) only applies when the unit is moved. This is the reason why we have to use Moved as a temporary indicator.

Following the points you can say that Moved only gets true when the unit really moved. Animate then gets also true while Moved is set back to false in case the movement stops at this point. If not it will be automatically set to true again when calling MoveUnit the next time.

In the end the animation keeps running as long as the unit moves in each frame without interruption. If there's a short break between the animation will be reset and starts over from the beginning (but we don't care).

To the code

The only thing that changed was setting Moved back to false and to true when movement is done. Added lines are marked as usual so skip the rest:

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 )
        'Reset movement indicator
        .Moved = False
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 'We moved
        .Moved = True
'Register to map Map.Units( .MapIndex ) = Index End With End Sub

UpdateUnits

As mentioned before we need another function that is called frequently. It sets Animate to true if Moved is true and in any case it sets back Moved to false. Here's the full code:

Public Sub UpdateUnits()
    Dim A as Long
    
    'Frequently update
    For A = 0 To UnitCount
        With Unit( A )
            'Animate if moved
            .Animated = .Moved
            .Moved = False
        End With
    Next
End Sub

Conclusion

Now that's it already. Before running your engine again you'll have to add the calls for the new functions in your Main function and change the AddUnit calls as done in the sample code below. If everything worked right you can now watch the animated units walking around randomly.

Navigation