wiz*_*wor 2 assembly c64 6502 6510
致力于一些 C64 介绍性想法。我使用下面的代码和正弦表根据预先生成的正弦表移动精灵。
子程序
ldx counter
cmx #100
jmp +
ldx #00
stx counter
+ lda sprite_sinus,x
inc counter
rts
Run Code Online (Sandbox Code Playgroud)
窦表
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
Run Code Online (Sandbox Code Playgroud)
但我需要一些不同的东西。在循环路径中移动精灵的 x 和 y 方向。我还可以使用哪些其他功能?
小智 5
遇到这个问题时,我忍不住回忆起来,思考如何在所有那些曾经对我来说如此神奇的演示中实现这一点......这就是我想到的:
为了获得看起来有些复杂的基于正弦表的二维运动,您想要做的是组合多个正弦波来构建每个坐标。至少,您需要使用一个正弦波作为 x 坐标,使用另一个正弦波作为 y 坐标。使用您的简单算法(在每次迭代期间,仅将表索引增加一),两个正弦波将被限制以相同的频率循环。结果将是沿着对角线移动,或者在两个正弦之间有适当的相移,可能沿着圆形或椭圆形移动。顺便说一句,这些已经是正确的利萨如图形;只是不是最令人兴奋的。
为了使这个看起来更有趣,您需要以不同的频率循环不同的正弦波。作为一个简单的测试,尝试将表索引增加 2,而不是每次迭代仅在两个坐标之一中增加 1,并观察会发生什么。对于更通用的解决方案,您需要为每个表索引实现一个“振荡器”:一个变量,在本例中可能是 16 位宽,它将根据存储在另一个变量中的“频率”值递增(简单地通过在每次迭代期间添加后者,并让振荡器溢出循环)。然后,您可以仅采用该振荡器的一些较高位来用作表索引。为简单起见,您的表格大小应为 2 的幂。
要获得更复杂的图形,请尝试添加两个(或更多)以不同频率振荡的正弦波来构建每个坐标分量。也许您可以以不同的方式缩放正弦波,例如在相加之前将一个值除以二。自从我上次观看基于利萨如精灵运动的演示以来,已经有一段时间了(大约二十多年),但如果我没记错的话,这正是所使用的组合。
以下是我刚刚写的一些代码片段,尚未测试。尽管如此,他们的分析有望澄清我在这篇闲言中试图表达的内容。
; 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)
Run Code Online (Sandbox Code Playgroud)