Tagalong Todd Tutorial: Part 2
From Intellivision Wiki
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.
;; ======================================================================== ;; ;; 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.
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.