Tagalong Todd Tutorial: Part 2

From Intellivision Wiki
Revision as of 13:35, 18 November 2011 by Rickreynolds (talk | contribs) (Another way to call MOVE_PLAYER)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

In this part of the tutorial, we'll just add enough code to move our player figure around the screen a bit.

The complete source for this tutorial (it's a subset of the full tagalong.asm found in the SDK) is here.

A new periodic task

In order to move our player figure around the screen, we just need a task that will run periodically and adjust the X and Y position variables for our player. This is pretty simple to do because we already have included the taskq library.

By the way, this is an intermediate piece of code that is not in the final tagalong.asm code listing. This seems to me to be a nice intermediate step towards updating the position of the player via hand controller input, so I'm including it as a step in the tutorial.

Moving the player

We'll write a procedure that will adjust the PLYR.XP and PLYR.YP locations programatically. Then we'll rely on the taskq library to update the player on the screen by executing the MOB_UPDATE routine we have already written.

The procedure:

;; ======================================================================== ;;
;;  MOVE_PLAYER -- Just programatically move the player around a bit.       ;;
;; ======================================================================== ;;
            PSHR    R5

            ; Just for something to do we'll move across the screen, then 
            ; down a row and back across, again and again until we get to the 
            ; bottom at which time we'll start over

            MVI     PLYR.XP,    R0      ;\
            SWAP    R0                  ; >-- Get player X position
            ANDI    #$00FF,     R0      ;/

This should look familiar. We're using the same method to grab the X position as we did in the MOB_UPDATE routine.

            ADDI    #8,         R0      ; move 8 X positions to the right

This just adds 8 pixels to the X position.

            MVII    #159,       R1      ;\__ compare X against the right edge of the screen
            CMPR    R0,         R1      ;/
            BLT     @@fixx

            SWAP    R0                  ; put the integer part back into the upper byte
            MVO     R0,    PLYR.XP      ; update the X position
            B       @@done              ; we're done

This code compares our X coordinate with 159. 159 is the rightmost pixel that can be displayed on the Intellivision. So when we get to this spot, it is time to move the player character down a row.

We compare the X position with 159 via the 'CMPR R0, R1' instruction. Then BLT will branch if R1 is less than R0, which would mean that 159 is less than our X coordinate, which means that our X coordinate is now off the right edge of the screen. We branch to @@fixx, where we'll fix the X coordinate.

If 159 is greater than or equal to our X coordinate, our X coordinate is still within the screen resolution. The code falls through and SWAPs the bytes again so that the integer part is in the upper byte of the register and puts that value back into PLYR.XP. When this happens, we're all done - no adjustment to the Y coordinate is necessary.

            ; here we've hit the right edge of the screen and should move down a row
@@fixx      MVII    #0,         R0      ;\__ set X position back to zero
            MVO     R0,    PLYR.XP      ;/

            MVI     PLYR.YP,    R0      ;\
            SWAP    R0                  ; >-- Get player Y position
            ANDI    #$007F,     R0      ;/

            ADDI    #8,         R0      ;  move 8 Y positions down

We reset X to 0, and we also need to move down a row. So we add 8 pixels to our Y coordinate.

            MVII    #96,        R1      ;\__ compare Y against the bottom edge of the screen
            CMPR    R0,         R1      ;/
            BLT     @@fixy

            SWAP    R0                  ; put the integer part back into the upper byte
            MVO     R0,    PLYR.YP      ; update the Y position
            B       @@done

We're doing a similar comparison to that above by checking the bottom of the screen. If we hit the bottom, we'll fix the Y coordinate at @@fixy. If not, we can put the Y coordinate back into PLYR.YP, and we're done.

            ; here we've hit the bottom edge of the screen and should move to the top
@@fixy      MVII    #0,         R0      ;\__ set Y position back to zero
            MVO     R0,    PLYR.YP      ;/

@@done      PULR    PC

To fix the Y coordinate, we'll set it to zero, effectively jumping back to the top of the screen.

I'm sure this isn't the most efficient way to do things, but it works and is simple.

Yes, this is slightly wrong...

The above code checking against the borders is actually wrong. The coordinate system for MOBs is a bit different. You can check the STIC documentation for the actual details. It doesn't actually affect our tutorial very much, so I'm not getting into the intricacies of how the MOBs relate to the actual screen resolution in this tutorial.

Calling our new routine

As mentioned at the top of this tutorial, we'll use the taskq library to call our new routine. There are probably several ways of doing it, and we'll try two.

A first, very simple method

The first is just to put a call to our new movement routine into the queue alongside of where we are putting our MOB_UPDATE routine into the queue. That will look like this:

            MVII    #MOB_UPDATE, R0
            JSRD    R5,   QTASK

            MVII    #MOVE_PLAYER, R0
            JSRD    R5,   QTASK

Just place those second two lines into the ISR from our last tutorial, and the taskq library will get a request to move the player over and over again.

Build it and try it!

This is enough to move our player around. He'll move pretty quickly, because a request to move the player is going into the task queue during every ISR. But it illustrates the point.

Another way to call MOVE_PLAYER

We can insert the call to MOVE_PLAYER into the task queue in a different manner. Specifically, the task queue allows for timer based tasks. We can tell the task queue to process a MOVE_PLAYER every N seconds. For our next example, we'll have it move the player every 1/4 second.

We'll tell the task queue about the timer task back in main during our initial setup code.

                ;; ------------------------------------------------------------ ;;
                ;;  Set up character movement task                              ;;
                ;; ------------------------------------------------------------ ;;
                CALL    STARTTASK
                DECLE   0
                DECLE   MOVE_PLAYER
                DECLE   30, 30          ; 4Hz

                MVII    #1,     R0
                MVO     R0,     TSKACT

The STARTTASK call is what sets up a timer based task in the queue. You can read the comments in timer.asm to get all the details, but this call works by defining the task number (0), then providing the procedure to call (MOVE_PLAYER), then providing details about how often the task should be run (the 30, 30 pair).

After telling the task queue about our new task, we set TSKACT to 1 to tell the task queue library that 1 task has been defined.

Build it and try it!

When this version is built and run, the player graphic will move across the screen at a much more reasonable pace.

That's it!

We now have a player graphic moving around. And it didn't take too much additional code after we laid all the groundwork in part 1.

Back to Programming Tutorials