D-Bug & Automation Forum
D-Bug & Automation Forum >> Coding >> Sauron's homework! (assignment #1 - bouncy)
https://d-bug.mooo.com/dbugforums/cgi-bin/yabb2/YaBB.pl?num=1304238634

Message started by ggn on 01.05.11 at 08:30:33

Title: Re: Sauron's homework! (assignment #1 - bouncy)
Post by ggn on 07.05.11 at 17:16:47
Right, while I'm on the subject, I thought I'd make a quick point about abstraction as well. It may be more advanced for a simple first exercise, so you might want to skip reading it and come back later when we've done more assignments :).

So, say we want to control 10 bouncy balls like this. How would we do it with the code we have so far? Well, one solution would be to copy/paste the code 10 times and change labels, and it would work. But... what about if we found a bug? We'd then have to change it to 10 points in the code! And then maybe we'll need a change later on. 10 changes again! Etc, etc. Soon it becomes ultra tedious to say the least!

What could we do then? Well...


Code (]

the_balls:
     rept 10
     dc.l      160            ; ball x position
     dc.l      120            ; ball y position
     dc.l      1            ; vertical direction of ball
     dc.l      1            ; horizontal direction of ball
     endr

topborder      dc.l      0            ; sets top border
bottomborder      dc.l      240            ; sets bottom border
leftborder      dc.l      0            ; sets left border
rightborder      dc.l      320            ; sets right border

mainloop
     move.l      #the_balls,a0
     bsr.s      bouncy
     bra.s      mainloop

bouncy:

     movem.l (a0),d0-d3      ;load ball_x in d0, ball_y in d1, x_direction in d2 and y_direction in d3

     sub.l      d2,d0            ; moves ball left by one pixel
     add.l      d3,d1            ; moves ball down by one pixel


moveball:

     move.l      d0,ball_x            ; updates ball_x variable
     move.l      d1,ball_y            ; updates ball_y variable

     cmp.l      leftborder,d0      ; compares left border to x position
     bne.s      .check_right      ; branches if not equal to left border
     moveq      #1,d2            ; then starts moving the ball right
     bra.s      .check_top      ; now go check for top/bottom

.check_right:
     cmp.l      rightborder,d0      ; compares right border to x position
     bne.s      .check_top      ; branches if not equal to right border
     moveq      #-1,d2            ; then starts moving the ball left

.check_top:
     cmp.l      topborder,d1      ; compares top border to y position
     bne.s      .check_bottom      ; branches if not equal to top border
     moveq      #1,d3            ; then moves the ball down
     bra.s      .check_done

.check_bottom:
     cmp.l      bottomborder,d1      ; compares bottom border to y position
     beq.s      .move_up      ; branches if equal to bottom border
     moveq      #-1,d3            ; then moves the ball up

.check_done:
     movem.l d0-d3,(a0)
     rts                  ;all done, thank you, drive thru![/code):




Eh what?

Firstly, I've defined 10 balls. They're set up at the top. rept and endr define a block to be repeated as many times as we want. Saves some typing :). As a consequence, each ball's values are directly after the previous one. So what, you'll ask. We still have to reference them somehow, right?

What I basically did there was to use pointers. Registers a0 to a7, as we all know, are called address registers. In addition to just holding numbers, they have some extra functionality. For example, if an address register holds a valid address, then we can access the memory in that address by the use of parentheses. So, if a0 is loaded with the value $10000, then executing

[code]move.l (a0),d0


will fetch the longword that a0 points to and load it in a0. Cool huh? :) Of course there are limits to what one can do, but most of the 68000 instruction set is very flexible and we can use pointer logic in lots of places.

So, how does this help in our case? Simple. To control the first ball, I just load the address of the first element of the first ball, its ball_x to be precise, to a0. I then call the subroutine bouncy. Assuming that a0 contains the address of the ball's structure we want to check, I just go ahead and read all variables with the movem, but instead of a fixed address I use the one stored in a0!


Code (]      movem.l (a0),d0-d3      ;load ball_x in d0, ball_y in d1, x_direction in d2 and y_direction in d3[/code):


After all processing is done, I simply write it back to the address of a0:

[code]      movem.l d0-d3,(a0)


So, can you guess how to process the 2nd bacll? Quite simply, we can load the address of the 2nd ball's structure. We can calculate that quite easily; since each ball uses 4 longwords to store its data, the 2nd ball is located at 4bytes*4longwords=16 bytes after the first one. So,

[code]      move.l      #the_balls+4*4,a0[/code]

will point to our 2nd ball! (yes, arithmetic expressions are allowed as long as they're not too complex)



And that's it really, as you see turning an ordinary routine to a more generic one isn't as difficult as you might first think :)

D-Bug & Automation Forum » Powered by YaBB 2.6.0!
YaBB Forum Software © 2000-2022. All Rights Reserved.