2

Working on some C64 intro ideas. I move sprites based on pre-generated sinus tables using below code and a sinus table.

subroutine

        ldx counter
        cmx #100
        jmp +

        ldx #00
        stx counter

+       lda sprite_sinus,x

        inc counter

        rts

Sinus table

sprite_sinus   
    !by 25,23,21,20,18,17,15,14,12,11,10,8,7,6,5,4
    !by 3,2,2,1,1,0,0,0,0,0,0,0,0,0,1,1
    !by 2,3,4,5,6,7,8,9,10,12,13,14,16,17,19,21
    !by 22,24,25,27,28,30,32,33,35,36,37,39,40,41,42,43
    !by 44,45,46,47,48,48,49,49,49,49,49,49,49,49,49,48
    !by 48,47,47,46,45,44,43,42,41,39,38,37,35,34,32,31
    !by 29,28,26,25

But I need something different. To move sprites both x and y direction in a looping path. What other functions i can use?

wizofwor
  • 917
  • 8
  • 25
  • Different how? You could play around with [combining multiple sine waves](http://www.pouet.net/prod.php?which=14754) to create more varied waveforms. Another possibility would be to place points "randomly" across the screen and run a spline function to interpolate between them. It depends on how much computational power you can spare. – Michael Nov 26 '14 at 14:20
  • Saying different, I mean something like [Lissajous Curves](http://en.wikipedia.org/wiki/Lissajous_curve). – wizofwor Nov 26 '14 at 14:33
  • 3
    This question isn't about 6502, 6510, assembly or (aside from a textual reference) specifically the C64 either. Also, it's a 'recommendation' question, so off-topic for SO. Perhaps MathOverflow or Programmers might be a viable place to ask for waveform interpolation advice? – Eight-Bit Guru Nov 26 '14 at 15:19
  • 1
    I am well aware that the sinus waweforms are not only used in C64. I may edit the question and add some asm codes to make it more relevant. But seriously why MathOverflow or Programmers? My question is about an function to create a sprite path on C64 hardware. It is not about recommandation of a tool or it is not about mathematics only. – wizofwor Nov 26 '14 at 16:45
  • 1
    How about [Bézier curves](http://en.wikipedia.org/wiki/B%C3%A9zier_curve)? – nrz Nov 27 '14 at 07:00
  • @wizofwor OK, you've added some 6502 code now (although you have a typo in it). It's still a 'recommend me a...' question though, so off-topic for SO. I suggested the other two SE sites because they're more likely to entertain opinion-based questions about mathematical functions. – Eight-Bit Guru Nov 27 '14 at 10:02

1 Answers1

5

Coming across this question, I could not resist taking a walk down memory lane, thinking about how this might have been achieved in all those demos that once seemed so amazing to me... Here's what I came up with:

What you want to do to get somewhat complex looking sine-table based 2-D motion, is to combine multiple sine waves to build up each coordinate. At a minimum, you will want to use one sine-wave for the x-coordinate, and another for the y-coordinate. Using your trivial algorithm, which, during each iteration, just increments a table index by one, both sine-waves will be limited to loop through at the same frequency. The result will be either movement along a diagonal line, or, with appropriate phase shift between the two sines, perhaps along a circle or ellipse. These are, by the way, already proper Lissajous figures; just not the most exciting.

To make this more interesting looking, you need to loop through your different sine-waves at different frequencies. As a simple test, try incrementing the table index by two instead of one per iteration in just one of the two coordinates, and observe what happens. For a more general solution, you will need to implement an "oscillator" for each table index: a variable, in this case perhaps 16-bit wide, that will be incremented according to a "frequency" value stored in another variable (simply by adding the latter during each iteration, and letting the oscillator overflow to loop around). You can then take just a few of the higher bits of that oscillator to use as your table index. To make things simple, your table should have a power-of-two size.

To get even more complex figures, try adding two (or more) sine-waves oscillating at different frequencies to build up each coordinate component. Perhaps you could scale the sine-waves differently, for example by dividing one's values by two before adding. It's been a while (like over two decades), since I last watched a demo based on Lissajous sprite motion, but if my memory is correct, this was exactly the kind of combination used.

Following are some code snippets, which I have just written up, not tested yet. Nevertheless, their analysis should hopefully make clear, what I was trying to express in this ramble.

; Routine for advancing a 16-bit oscillator depending on a 16-bit frequency
;
; Upon entry, x must hold offset to oscillator data. (So that this
; routine can be reused with multiple oscillators. x not preserved)
; Returns sine-table value for next oscillator step in a.
advance_osc:
    clc            ; increment 16-bit oscillator by 16-bit frequency
    lda osc_lo,x
    adc frq_lo,x
    sta osc_lo,x
    lda osc_hi,x
    adc frq_hi,x
    sta osc_hi,x
                   ; get table index (osc_hi still in a)
    and #$3f       ; mask for 6-bit table size
    tax            ; x now holds 6-bit table index
    lda table,x    ; a holds value from table
    rts

; Snippet for building sprite coordinate from multiple sine-table values

; Step 1: use one sine wave to start building x coordinate
    ldx #osc_offset
    jsr advance_osc   ; returns next table value for that osc
    sta x_coord
; Step 2: add another sine wave to x coordinate
    ldx #next_osc_offset
    jsr advance_osc
    lsr               ; optional: scale down result by two
    clc
    adc x_coord       ; add sine-waves
                      ; (may want to rework this to handle 9-bit x_coord)
    sta x_coord
; Step 3..4: now, repeat the above steps for y_coord
    ...
; Step 5: once done, copy coordinates into VIC registers...
    ...
; repeat for next sprite (may be reworked into a loop)