Difference between revisions of "Tagalong Todd Tutorial: Part 2"

From Intellivision Wiki
Jump to: navigation, search
(Moving the player)
(Another way to call MOVE_PLAYER)
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
[[Category: Programming]][[Category: Tutorial]]
 
In this part of the tutorial, we'll just add enough code to move our player  
 
In this part of the tutorial, we'll just add enough code to move our player  
 
figure around the screen a bit.
 
figure around the screen a bit.
Line 25: Line 26:
 
The procedure:
 
The procedure:
  
    ;; ======================================================================== ;;
+
;; ======================================================================== ;;
    ;;  MOVE_PLAYER -- Just programatically move the player around a bit.      ;;
+
;;  MOVE_PLAYER -- Just programatically move the player around a bit.      ;;
    ;; ======================================================================== ;;
+
;; ======================================================================== ;;
    MOVE_PLAYER PROC
+
MOVE_PLAYER PROC
                PSHR    R5
+
            PSHR    R5
   
+
                ; Just for something to do we'll move across the screen, then  
+
            ; 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  
+
            ; down a row and back across, again and again until we get to the  
                ; bottom at which time we'll start over
+
            ; bottom at which time we'll start over
   
+
                MVI    PLYR.XP,    R0      ;\
+
            MVI    PLYR.XP,    R0      ;\
                SWAP    R0                  ; >-- Get player X position
+
            SWAP    R0                  ; >-- Get player X position
                ANDI    #$00FF,    R0      ;/
+
            ANDI    #$00FF,    R0      ;/
  
 
This should look familiar.  We're using the same method to grab the X  
 
This should look familiar.  We're using the same method to grab the X  
 
position as we did in the MOB_UPDATE routine.
 
position as we did in the MOB_UPDATE routine.
 
      
 
      
                ADDI    #8,        R0      ; move 8 X positions to the right
+
            ADDI    #8,        R0      ; move 8 X positions to the right
  
 
This just adds 8 pixels to the X position.
 
This just adds 8 pixels to the X position.
  
 
      
 
      
                MVII    #159,      R1      ;\__ compare X against the right edge of the screen
+
            MVII    #159,      R1      ;\__ compare X against the right edge of the screen
                CMPR    R0,        R1      ;/
+
            CMPR    R0,        R1      ;/
                BLT    @@fixx
+
            BLT    @@fixx
   
+
                SWAP    R0                  ; put the integer part back into the upper byte
+
            SWAP    R0                  ; put the integer part back into the upper byte
                MVO    R0,    PLYR.XP      ; update the X position
+
            MVO    R0,    PLYR.XP      ; update the X position
                B      @@done              ; we're done
+
            B      @@done              ; we're done
  
 
This code compares our X coordinate with 159.  159 is the rightmost pixel  
 
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  
 
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.  This really means that we
+
is time to move the player character down a row.
won't actually draw the figure when it is at 159, but that's going to be fine
 
for the purposes of this demo.  We just want something to illustrate movement.
 
  
 
We compare the X position with 159 via the 'CMPR R0, R1' instruction.  Then  
 
We compare the X position with 159 via the 'CMPR R0, R1' instruction.  Then  
Line 72: Line 71:
 
adjustment to the Y coordinate is necessary.
 
adjustment to the Y coordinate is necessary.
 
      
 
      
                ; here we've hit the right edge of the screen and should move down a row
+
            ; 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
+
@@fixx      MVII    #0,        R0      ;\__ set X position back to zero
                MVO    R0,    PLYR.XP      ;/
+
            MVO    R0,    PLYR.XP      ;/
   
+
                MVI    PLYR.YP,    R0      ;\
+
            MVI    PLYR.YP,    R0      ;\
                SWAP    R0                  ; >-- Get player Y position
+
            SWAP    R0                  ; >-- Get player Y position
                ANDI    #$007F,    R0      ;/
+
            ANDI    #$007F,    R0      ;/
   
+
                ADDI    #8,        R0      ;  move 8 Y positions down
+
            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  
 
We reset X to 0, and we also need to move down a row.  So we add 8 pixels to  
 
our Y coordinate.
 
our Y coordinate.
 
      
 
      
                MVII    #96,        R1      ;\__ compare Y against the bottom edge of the screen
+
            MVII    #96,        R1      ;\__ compare Y against the bottom edge of the screen
                CMPR    R0,        R1      ;/
+
            CMPR    R0,        R1      ;/
                BLT    @@fixy
+
            BLT    @@fixy
   
+
                SWAP    R0                  ; put the integer part back into the upper byte
+
            SWAP    R0                  ; put the integer part back into the upper byte
                MVO    R0,    PLYR.YP      ; update the Y position
+
            MVO    R0,    PLYR.YP      ; update the Y position
                B      @@done
+
            B      @@done
  
 
We're doing a similar comparison to that above by checking the bottom of the  
 
We're doing a similar comparison to that above by checking the bottom of the  
Line 97: Line 96:
 
we can put the Y coordinate back into PLYR.YP, and we're done.
 
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
+
            ; 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
+
@@fixy      MVII    #0,        R0      ;\__ set Y position back to zero
                MVO    R0,    PLYR.YP      ;/
+
            MVO    R0,    PLYR.YP      ;/
   
+
    @@done      PULR    PC
+
@@done      PULR    PC
                ENDP
+
            ENDP
 
                  
 
                  
 
To fix the Y coordinate, we'll set it to zero, effectively jumping back to  
 
To fix the Y coordinate, we'll set it to zero, effectively jumping back to  
Line 130: Line 129:
 
That will look like this:
 
That will look like this:
  
                MVII    #MOB_UPDATE, R0
+
            MVII    #MOB_UPDATE, R0
                JSRD    R5,  QTASK
+
            JSRD    R5,  QTASK
   
+
                MVII    #MOVE_PLAYER, R0
+
            MVII    #MOVE_PLAYER, R0
                JSRD    R5,  QTASK
+
            JSRD    R5,  QTASK
  
Just place those two lines into the ISR from our last tutorial, and the taskq  
+
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.
 
library will get a request to move the player over and over again.
  
Line 155: Line 154:
 
initial setup code.
 
initial setup code.
  
                    ;; ------------------------------------------------------------ ;;
+
                ;; ------------------------------------------------------------ ;;
                    ;;  Set up character movement task                              ;;
+
                ;;  Set up character movement task                              ;;
                    ;; ------------------------------------------------------------ ;;
+
                ;; ------------------------------------------------------------ ;;
                    CALL    STARTTASK
+
                CALL    STARTTASK
                    DECLE  0
+
                DECLE  0
                    DECLE  MOVE_PLAYER
+
                DECLE  MOVE_PLAYER
                    DECLE  30, 30          ; 4Hz
+
                DECLE  30, 30          ; 4Hz
   
+
                    MVII    #1,    R0
+
                MVII    #1,    R0
                    MVO    R0,    TSKACT
+
                MVO    R0,    TSKACT
  
 
The STARTTASK call is what sets up a timer based task in the queue.  You can  
 
The STARTTASK call is what sets up a timer based task in the queue.  You can  
Line 184: Line 183:
 
We now have a player graphic moving around.  And it didn't take too much  
 
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.
 
additional code after we laid all the groundwork in part 1.
 +
 +
[[Programming Tutorials|Back to Programming Tutorials]]

Latest revision as of 13:35, 18 November 2011

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.       ;;
;; ======================================================================== ;;
MOVE_PLAYER PROC
            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
            ENDP
               

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