假设您对足够少的输出方向感到满意,那么通过查找表最容易做到这一点。例如,对于 64 个输出方向,抓取(x, y)
从源到目标的向量,如果两者都是正数,则将两者都左移直到其中一个填充符号位,然后从每个的前两位形成一个四位表索引并查看输出向量。
假设您的分辨率为 160x200,那么我想您在进入之前需要丢掉一些精度。
适当地镜像以处理其他象限。假设对象位置的固定点为 8.8,子弹速度为 1,那么这是一个 32 字节的查找表。
所以,天真地,像:
xPosYPos:
; assuming ($00) has the positive x difference
; and ($01) has the positive y difference
lda $00
ora $01
shiftLoop:
asl $00
asl $01
asl a
bpl shiftLoop
; load A with table index
lda #$00
rol $00
rol a
rol $00
rol a
rol $01
rol a
rol $01
rol a
; look up vector
tax
lda xVec, x
; ... put somewhere ...
lda yVec, x
; ... put somewhere ...
...使用更智能的解决方案可能涉及更多类似的东西:
lda $00
ora $01
asl a
bmi shift1
asl a
bmi shift2
... etc ...
shift1:
... etc, but you can shift directly to form
the table index rather than going to all the work
of shifting the vector then piecing together from
the top bits ...
或者,您可以创建一个 256 字节的查找表来查找基于的例程地址x|y
(由于它们都是正数,因此最多始终为 127)并直接跳转到移位而不计算位。
物体位置和固定点的入门:
假设您处于 160x200 模式,那么您可以将对象位置的每个组件存储为单个字节。所以 x 一个字节,y 一个字节。许多游戏所做的是将每个位置存储为两个字节。所以 x 和 y 总共有四个字节。
其中一个字节与单字节格式相同——它是整数位置。另一个是小数部分。因此,如果您有一个位置和一个速度(以及欧拉积分),那么您可以对位置进行 16 位速度加法。然后你只需使用最高字节作为位置。
这通常称为定点算术。与浮点不同,整数中小数点所在的位置是固定的。在此处描述的方案中,它始终是 8 位。
因此,例如添加仅字节数量的偏移量:
clc
lda xPosition
adc xVelocity
sta xPosition
sta SomeHardwareRegisterForSpritePosition
要使用定点方案添加偏移量:
clc
lda xFractionalPosition
adc xFractionalVelocity
sta xFractionalPosition
lda xPosition
adc xVelocity
sta xPosition
sta SomeHardwareRegisterForSpritePosition
优点是您的速度矢量现在可以在任何方向上小至像素的 1/256。因此,例如,您可以存储一个速度,表示您的子弹每一帧都会向左移动一个像素,向下移动 32/256 个像素。以亚像素精度移动子弹的所有成本是每个向量额外的几个字节存储空间和额外的几个 ADC。
使用上述建议,您可以通过从另一个字节中减去一个字节中的一个字节来获得从源到目标的向量。结果将是两个单字节,这两个字节都是输出的小数部分。因此,例如,您可能决定用 (87/256, 239/256) 的矢量(即 20 度角)发射子弹。