Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 敌人的子弹瞄准C64上的玩家_Assembly_Artificial Intelligence_6502_C64_6510 - Fatal编程技术网

Assembly 敌人的子弹瞄准C64上的玩家

Assembly 敌人的子弹瞄准C64上的玩家,assembly,artificial-intelligence,6502,c64,6510,Assembly,Artificial Intelligence,6502,C64,6510,我正在浏览互联网和旧的C64书籍来寻找这个问题,但没有找到答案,所以最后我不得不把它贴在这里。我喜欢C64编码的好时光,虽然我目前没有在这个平台上编程游戏,但我想知道当时是如何克服一些硬件限制的 在所有现代游戏编程书籍和教程中,找到向玩家发射敌人子弹的正确方向的方法是使用带浮点数的向量数学,或多或少类似于以下伪代码: bullet_velocity = (player.position - bullet.position).normalize(); 现在,考虑到C64的局限性,我在源代码中看到

我正在浏览互联网和旧的C64书籍来寻找这个问题,但没有找到答案,所以最后我不得不把它贴在这里。我喜欢C64编码的好时光,虽然我目前没有在这个平台上编程游戏,但我想知道当时是如何克服一些硬件限制的

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

bullet_velocity = (player.position - bullet.position).normalize();
现在,考虑到C64的局限性,我在源代码中看到大量使用正弦表来提高速度,也许我有点心烦意乱,但当我阅读C64的旧书或C64程序员的注释程序时,我从未见过一个关于向量数学的字,我想知道当时是如何实现同样的目标的

请回答,我有上千个这样的疑问,但回答这个问题也许我能找到自己的答案


编辑:请注意:使用子弹瞄准玩家的C64游戏的示例有蚕和赛博诺伊德。

如果您对足够少的输出方向感到满意,那么通过查找表进行操作是最简单的。例如,对于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度。

你也可以(ab)使用Bresenham的划线算法瞄准你的子弹,“线”的起始坐标是敌人的坐标,终点坐标是你船的坐标。在每次迭代中,您只需在当前位置重新添加项目符号,而不是将像素添加到直线上。

这会恢复记忆。。。根据我对大多数C64游戏的回忆,他们解决这个问题的方法很简单,就是让所有的动作都严格地在水平或垂直方向上进行,使整个点变得毫无意义。@1Garrett2010:你能举一个具体游戏/关卡的例子吗?因为不同的游戏做的事情可能不同。我认为很多老游戏只允许敌人以固定的速度在水平/垂直直线上射击。而且目标不是点大小的,所以角度上的一些不精确仍然会给你一击,而且屏幕的分辨率也没有那么大。定点数学应该可以通过一个小的ish查找表来实现。但这只是我的猜测:)@Michael:Hi,游戏蚕,第一阶段的老板(不仅是他们)向玩家开火,也向网络游戏中的一些敌人开火。但我认为游戏列表可能会更广。我不确定,但他们肯定可以使用Bresenham的算法或ROM中的浮点基本例程。谢谢,我有一些疑问:1)对于“从源到目标获取向量(x,y)”,你打算获取子弹的起始和结束位置向量吗?如果一个向量应该从源到目的地进行计算,那么就涉及到浮动数学,我看不出它有什么好处!2) 在C64源上,我通常会看到带有已计算位置(x,y)的查找表(例如正弦表),在其中移动对象/精灵。在这里,您打算存储单个浮点数对值(x,y),以便在每个移动步骤添加到子弹精灵?所以在C64游戏编程中允许进行一些浮点运算?不,不需要浮点运算。如果位置是整数,那么它们之间的向量也是整数。但是对于不只是左、右、上、下或对角线的运动,你通常使用固定点——例如X的整数部分的一个字节,分数Par的另一个字节。