Moving with Fixed-Point Numbers
Gives coordinates and velocities a fractional part so characters can move with sub-pixel precision.
Why a fractional part is needed
If coordinates are kept only in whole pixels, velocity can only take discrete steps such as “1 pixel per frame” or “2 pixels per frame.” To create motion such as slow acceleration or gradually falling under gravity, you need a unit finer than one pixel (a subpixel).
Here we use a unit that divides one pixel into 256 parts.
| Variable | Size | Contents |
|---|---|---|
| $10 | 1 byte | Fractional part of the X coordinate (in units of 1/256 pixel) |
| $11/$12 | 2 bytes | Integer part of the X coordinate (pixels) |
| $14/$15 | 2 bytes | Velocity in the X direction (signed, in units of 1/256 pixel) |
$10-$12 is treated as a 24-bit value in units of 1/256 pixel.
Adding velocity to the coordinate
The velocity is a signed 16-bit value, so when adding it to the 24-bit coordinate, fill the high byte with the sign (sign-extend it) before adding.
; add the velocity to the X coordinate
REP #$20
CLC
LDA $10
ADC $14 ; low 16 bits of the coordinate + velocity
STA $10
SEP #$20
LDA.b #$00
BIT $15 ; check the sign of the velocity (bit 7)
BPL .plus
DEC A ; for a negative velocity the high byte is $FF
.plus
ADC $12 ; add the carry and the sign-extended high byte
STA $12
The LDA, BIT and DEC instructions do not change the carry flag, so the carry from the first ADC instruction is passed straight to the last ADC instruction.
Acceleration and gravity
Acceleration and gravity are expressed by adding a small value to the velocity every frame as well.
; add gravity to the Y velocity ($18/$19) and cap it at the maximum fall speed
REP #$20
LDA $18
CLC
ADC.w #$0040 ; accelerate by 0.25 pixels/frame each frame
BMI .store ; leave it as is while rising (negative velocity)
CMP.w #$0400 ; maximum fall speed: 4 pixels/frame
BCC .store
LDA.w #$0400
.store
STA $18
Displaying on screen
Only the integer part is written to the sprite’s OAM.
SEP #$20
LDA $11
SEC
SBC $40 ; subtract the camera X coordinate to get the on-screen coordinate
STA $0200 ; X coordinate in the OAM copy
See also
Multi-precision addition, subtraction and comparison
Handling signed values
Displaying sprites