Tagalong Todd Tutorial: Part 5

From Intellivision Wiki
Jump to: navigation, search

Tagalong Todd Tutorial: Part 5

In this part of the tutorial, we'll add code that will cause Todd to chase the player around the screen - and we'll be done!

The complete source for this tutorial is here. It's actually the same file that comes with the SDK.

A new value and some storage

Since our idea for moving characters on the screen (as developed in part 4) involves a velocity, we'll do the same for Todd. We'll have Todd move at a constant speed rather than speeding up to a set speed like we're doing for the player. To make things simple, we'll just define that speed using a constant.

TODD_VEL    EQU     $AA

Once that is in place, we need to add a little storage for Todd's velocity calculations.

TODD        PROC                    ; TODD's STATS
@@XP        RMB     1               ; X position
@@YP        RMB     1               ; Y position
@@XV        RMB     1               ; X velocity
@@YV        RMB     1               ; Y velocity
@@TXV       RMB     1               ; Target X velocity
@@TYV       RMB     1               ; Target Y velocity
            ENDP

We have already defined the X and Y position variables for Todd in the last part of the tutorial. Here we're adding storage for the velocities just like we did for the player.

            ;; ------------------------------------------------------------ ;;
            ;;  Set up Todd's AI.                                           ;;
            ;; ------------------------------------------------------------ ;;
            CALL    STARTTASK
            DECLE   0
            DECLE   TODDTASK
            DECLE   60, 60          ; 2Hz (twice a second)

            MVII    #1,     R0
            MVO     R0,     TSKACT

To have Todd move around, we're going to define a routine that should get called every so often via the TASKQ library. This will be defined very similarly to how we programmatically moved the player around in the second part of this tutorial when we were using a timed TASKQ task. For more detail on these definitions, you can reread that section of part 2. The only things different here is that we are defining TODDTASK which will be the routine that will calculate Todd's new velocity variables. And we'll set things up so that it gets called twice a second. The actual moving of Todd around the screen will be handed by changes to MOB_UPDATE.

TODDTASK: making Todd chase the player

Now we just need to write some code that will allow Todd to chase the player around the screen.
The "chasing" algorithm will be pretty simple: just pick a direction for the next bit of movement based on Todd's and the player's positions relative to each other.

;; ======================================================================== ;;
;;  TODDTASK   -- Todd wants to find you!                                   ;;
;; ======================================================================== ;;
TODDTASK    PROC

            ;; ------------------------------------------------------------ ;;
            ;;  This is really simple:  Todd will pick one of 8 directions  ;;
            ;;  to walk in to try to move towards you.  He picks this only  ;;
            ;;  based on whether you're left/right or above/below him.      ;;
            ;; ------------------------------------------------------------ ;;

            CLRR    R0                  ; set X vel to 0
            CLRR    R1                  ; set Y vel to 0

We'll compute Todd's X and Y velocities in R0 and R1, respectively. To start out, we'll set both of these to zero.

            MVI     PLYR.XP,    R2
            MVI     TODD.XP,    R3

Next, we'll need to compare Todd's X position with the player's to see if Todd should be heading left or right to chase the player. We'll move those values into R2 and R3.

            SLR     R2,         2
            SLR     R3,         2

            CMPR    R3,         R2
            BEQ     @@xp0               ; Equal?  X-vel stays 0
            MVII    #TODD_VEL,  R0      ; Player > Todd?  Move right
            BGT     @@xp0               ; Player < Todd?  Move left
            NEGR    R0

This just compares the two positions and sets Todd's X velocity (R0) to either zero (if Todd and the player are at the same X coordinate), TODD_VEL (if Todd is to the left of the player) or -TODD_VEL (if Todd is to the right of the player). You can see the MVII instruction putting our TODD_VEL value into R0 and then the NEGR makes it negative if required. The two SLR shifts that are done before the comparison are creating a little dead zone in the number comparison (4 units out of 256) that will show up as equal. This allows numbers that are close to be seen as equal - we don't really want the game to believe that Todd and the player have to line up on the same exact pixels.

@@xp0       

            SUBR    R3,         R2      ;\
            BPL     @@dx_pos            ; |
            NEGR    R2                  ; |__ If X coords are close enough
@@dx_pos    CMPI    #2,         R2      ; |   anyway, force target Xvel to 0
            BGE     @@xp_ok             ; |
            CLRR    R0                  ;/

This chunk of code is testing to see if the player and Todd are within 2 screen units (keeping the above discussion of the little dead zone in mind) of each other in the X direction. If they are, then we force the X velocity to be zero. First it subtracts the player's and Todd's X positions and then makes sure that the result is positive using the Branch on PLus operation to jump around the NEGR operation. CMPI compares the (now guaranteed positive) result to the number 2 and sets R0 to zero if the value is not greater. BGE jumps around the CLRR if the comparison shows the value to be greater than 2.

@@xp_ok

            MVI     PLYR.YP,    R2
            MVI     TODD.YP,    R3
            SLR     R2,         2
            SLR     R3,         2

            CMPR    R3,         R2
            BEQ     @@yp0               ; Equal?  X-vel stays 0
            MVII    #TODD_VEL,  R1      ; Player > Todd?  Move right
            BGT     @@yp0               ; Player < Todd?  Move left
            NEGR    R1
@@yp0

            SUBR    R3,         R2      ;\
            BPL     @@dy_pos            ; |
            NEGR    R2                  ; |__ If Y coords are close enough
@@dy_pos    CMPI    #2,         R2      ; |   anyway, force target Yvel to 0
            BGE     @@yp_ok             ; |
            CLRR    R1                  ;/

And all of this is identical for the Y position and velocity.

@@yp_ok
            MVO     R0,     TODD.TXV    ; Set Todd's target X velocity
            MVO     R1,     TODD.TYV    ; Set Todd's target Y velocity

Now that we have the values we need, we store them into our TODD data structure so that the MOB_UPDATE routine will have easy access to them.

            JR      R5                  ; Leave
            ENDP

Exit as per normal.

Updates to MOB_UPDATE

We need to add some code to make sure Todd moves around during MOB_UPDATE.

            MVI     TODD.TXV,   R0
            SUB     TODD.XV,    R0
            SARC    R0, 2
            ADD     TODD.XV,    R0
            MVO     R0,         TODD.XV
            ADD     TODD.XP,    R0
            MVO     R0,         TODD.XP

This code is pretty similar to what we've done for the player. It subtracts our computed target velocity from Todd's actual velocity (in the X direction), does 2 SARC shifts on it to get a 1/4 effect, then adds that result to Todd's X velocity, and then adds the calculated velocity to the actual X position.

            MVI     TODD.TYV,   R0
            SUB     TODD.YV,    R0
            SARC    R0, 2
            ADD     TODD.YV,    R0
            MVO     R0,         TODD.YV
            ADD     TODD.YP,    R0
            MVO     R0,         TODD.YP

And a nearly identical chunk of code for the Y velocity and position.

That's it!

Assemble and run it. We've gone through and built the very simplistic Tagalong Todd game from the ground up!