assembly 如何在6502组件(内斯)中进行平滑的水平/垂直移动?

xt0899hw  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(110)

我目前正在为一个大学项目做一个6502程序集的平台游戏演示,我不明白如何在这个项目中实现平滑的水平/垂直移动和加速。基本上,每个移动都包含以下代码的一个稍微不同的版本:

READ_RIGHT:
  LDA JOYPAD1
  AND #%00000001
  BNE DO_RIGHT
  JMP READ_RIGHT_DONE

DO_RIGHT:
  JSR HandleAcceleration
  JSR UpdatePlayerPosition

READ_RIGHT_DONE:

  RTI

HandleAcceleration:
  LDA ACCEL + 1
  CLC
  ADC #$01
  STA ACCEL + 1

  BCC @ON_CARRY

  LDA ACCEL + 0
  CMP MAX_ACCEL
  BCC @NOT_MAX_ACCEL
  LDA MAX_ACCEL
  STA ACCEL

@ON_CARRY:
  INC ACCEL
  INC MOV_FLAG

@NOT_MAX_ACCEL:
  RTS

UpdatePlayerPosition:
  LDA PLAYER_X
  STA $0203
  STA $020B
  TAX
  CLC
  ADC #$08
  STA $0207
  STA $020F
  ADC SPEED
  STA PLAYER_X

  RTS

字符串
我想我应该用定点算法来做这个,但是每次我试过,程序都不像预期的那样工作。如果有人知道我应该做什么或者我做错了什么,请帮助我。
我尝试将以下逻辑应用于代码:

READ_RIGHT:
  LDA JOYPAD1
  AND #%00000001
  BNE DO_RIGHT
  JMP READ_RIGHT_DONE

DO_RIGHT:
  JSR HandleAcceleration
  JSR UpdatePlayerPosition

READ_RIGHT_DONE:

  RTI

HandleAcceleration:
  LDA ACCEL + 1
  CLC
  ADC #$01
  STA ACCEL + 1

  BCC @ON_CARRY

  LDA ACCEL + 0
  CMP MAX_ACCEL
  BCC @NOT_MAX_ACCEL
  LDA MAX_ACCEL
  STA ACCEL

@ON_CARRY:
  INC ACCEL
  INC MOV_FLAG

@NOT_MAX_ACCEL:
  RTS

UpdatePlayerPosition:
  LDA PLAYER_X
  STA $0203
  STA $020B
  TAX
  CLC
  ADC #$08
  STA $0207
  STA $020F
  ADC SPEED
  STA PLAYER_X

  RTS


并没有给精灵平稳的加速度,只是让它瞬间加速了很多,没有其他作用。

1qczuiv0

1qczuiv01#

你的问题是由于没有注意垂直回扫引起的。当你没有捕捉到光束或没有正确设置IRQ时,CPU会连续运行你的代码。你需要的是以恒定的速度/FPS运行你的代码。我不是内斯硬件Maven,但从文档来看,$2002地址似乎是主循环结构的答案。尝试添加;

Main:
    // Wait for vertical retrace here
    lda $2002
    bit 7
    bne Main

    // Do your stuff here
    jmp Main

字符串
或者通过使用IRQ,尝试正确设置IRQ进入参数,同时考虑到垂直回扫。每个基于6502的8位机器都有一种方法来捕获屏幕顶部的光束。您只需要为内斯研究“垂直回扫”,“捕获光束”科目。

kmbjn2e3

kmbjn2e32#

这是一个轻微的猜测,因为我从来没有做过任何内斯编程,但6502是一个little endian机器。传统上,16位值存储在低地址的最低有效字节和高地址的最高有效字节。
在你的代码中,你首先在高位字节加1,然后做了一些我不完全理解的奇怪的事情,很可能是错误的,如下所示:
如果ACCEL是一个16位的值,要向它添加1,我会期望这样的结果:

lda accel
clc
adc #1
sta accel
lda accel+1
adc #0
sta accel+1

字符串
另一个问题是bcc @on_carry之后的代码。紧接着的代码只有在设置了进位时才会执行。如果你加1,那么只有在加法结果为零时才会设置进位(从$ff开始循环)。
因此,大多数情况下,您最终会同时递增accelaccel+1
如果加法后accel+1为零,则将accelmax_accel进行比较。如果累加器小于操作数,则cmp * 清除 * 进位标志。因此,如果A < max_accel
如果accel小于max_accel,你什么都不做(直接进入rts),但是如果它大于max_accel,你设置accelmax_accel,然后你通过增加accel

相关问题