我在没有找到答案的情况下扫描互联网和旧C64书籍的问题,所以最后我不得不在这里发布。我喜欢C64编码的美好时光,虽然我目前还没有在这个平台上编写游戏,但我想知道当时是如何克服某些硬件限制的。
在所有现代游戏编程书籍和教程中,找到向玩家发射敌人子弹的正确方向的方法是使用带浮动的向量数学,或多或少像这个伪代码:
bullet_velocity = (player.position - bullet.position).normalize();
现在,考虑到C64的限制,我在源代码中大量使用正弦表来提高速度,也许我分心了,但在阅读旧的C64书籍时,我从未见过关于矢量数学的一个词。来自C64程序员的评论程序,我想知道当时是如何获得同样的目标。
请回答,我有这样的一千个疑问,但回答这个问题也许我可以发现自己对其余的回应! : - )
编辑:请注意:C64游戏的例子包括针对玩家的子弹,是蚕和Cybernoid。
答案 0 :(得分:5)
假设您对足够少的输出方向感到满意,最容易通过查找表来完成。例如。对于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 / 256th。以子像素精度移动子弹的所有成本都是每个矢量额外几个字节的存储空间和额外的几个ADC。
根据上述建议,您可以通过从另一个字节中减去一个字节来获得从源到目标的向量。结果将是两个单个字节,这两个字节都是输出的小数部分。所以例如你可能决定用(87 / 256,239 / 256)矢量(即20度角)发射子弹。
答案 1 :(得分:1)
你也可以(ab)使用Bresenham的线条绘制算法来瞄准你的子弹,“线”的起始坐标是敌人的坐标,而末端则是你的船的坐标。不是在行中添加像素,而是在每次迭代时在当前位置重新绘制项目符号。