繁体   English   中英

敌人的子弹针对C64上的玩家

[英]Enemy bullets targeting player on a C64

我在没有找到答案的情况下扫描互联网和旧的C64书籍,所以最后我不得不在这里发布。 我喜欢C64编码的美好时光,虽然我目前还没有在这个平台上编写游戏,但我想知道当时是如何克服某些硬件限制的。

在所有现代游戏编程书籍和教程中,找到向玩家发射敌人子弹的正确方向的方法是使用向量数学与浮点数,或多或少像这个伪代码:

bullet_velocity = (player.position - bullet.position).normalize();

现在,考虑到C64的限制,我在源代码中大量使用正弦表来提高速度,也许我分心了,但是当我从C64程序员那里阅读旧的C64书籍或评论程序时,我从未见过关于矢量数学的一个词,我想知道如何在同一时间获得同样的目标。

请回答,我有这样的一千个疑问,但回答这个问题也许我可以发现自己对其余的回应! :-)

编辑:只是一个注释:用针对玩家的子弹的C64游戏的例子是Silkworm和Cyber​​noid。

假设您对足够少的输出方向感到满意,最容易通过查找表来完成。 例如,对于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度角)发射子弹。

你也可以(ab)使用Bresenham的线条绘制算法来瞄准你的子弹,“线”的起始坐标是敌人的坐标,而末端则是你的船的坐标。 不是在行中添加像素,而是在每次迭代时在当前位置重新绘制项目符号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM