用于精灵运动的窦功能的替代品

时间:2014-11-26 13:24:28

标签: assembly 6502 c64 6510

处理一些C64介绍的想法。我使用下面的代码和一个正弦表,根据预先生成的正弦表移动精灵。

子程序

        ldx counter
        cmx #100
        jmp +

        ldx #00
        stx counter

+       lda sprite_sinus,x

        inc counter

        rts

Sinus表

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

但我需要不同的东西。在循环路径中向x和y方向移动精灵。我可以使用哪些其他功能?

1 个答案:

答案 0 :(得分:4)

来到这个问题,我无法抗拒走在记忆的道路上,思考如何在所有曾经让我感到惊讶的演示中实现这一点......这就是我想出的:

为了获得有些复杂的基于正弦表的二维运动,您想要做的是组合多个正弦波来构建每个坐标。至少,您需要为x坐标使用一个正弦波,为y坐标使用另一个正弦波。使用您的平凡算法,在每次迭代期间,只需将表索引递增1,两个正弦波将被限制为以相同的频率循环。结果将是沿对角线移动,或者在两个正弦之间具有适当的相移,可能沿着圆形或椭圆形。顺便说一下,这些已经是适当的利萨茹形象;只是不是最令人兴奋的。

为了使这看起来更有趣,你需要以不同的频率循环你不同的正弦波。作为一个简单的测试,尝试在两个坐标之一中将表索引递增2而不是每次迭代一次,并观察发生的情况。对于更通用的解决方案,您需要为每个表索引实现一个“振荡器”:一个变量,在这种情况下可能是16位宽,将根据存储在另一个变量中的“频率”值递增(简单地通过在每次迭代期间添加后者,并让振荡器溢出循环)。然后,您可以将该振荡器的一些较高位用作表索引。为简单起见,您的桌子应具有两个幂的大小。

要获得更复杂的数字,请尝试添加两个(或更多)以不同频率振荡的正弦波,以构建每个坐标分量。也许您可以以不同方式缩放正弦波,例如在添加之前将一个值除以二。已经有一段时间了(比如二十多年),因为我上次观看了一个基于Lissajous精灵运动的演示,但如果我的记忆是正确的,这正是所使用的那种组合。

以下是一些代码片段,我刚刚编写过,尚未测试过。然而,他们的分析应该有希望说清楚,我试图在这漫游中表达的内容。

; 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)