## Moving Sprite loop with slow motion when changing direction.

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

sdm
Posts: 306
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

### Moving Sprite loop with slow motion when changing direction.

The object moves in a loop from point A to point B and returns. I would like to slow down the movement of the object so that it smoothly slows down the movement at each approach to these points. I tried to do two times slow motion, which will start 8pixels before those points. Ideally, if the slowdown in the direction change was more fluid (like normal speed->slow 2x->slow 4x->reverse movement->slow4x->slow2x->normal speed.
Attachments
demo.nes
monsterslo.zip
code

na_th_an
Posts: 557
Joined: Mon May 27, 2013 9:40 am

### Re: Moving Sprite loop with slow motion when changing direct

I'd use fixed point math with velocity and acceleration (linear movement equations). I'd calculate the distance to the limit where I have to begin applying deceleration. Then, if suitable, I'd make a LUT with the results.

rainwarrior
Posts: 7891
Joined: Sun Jan 22, 2012 12:03 pm
Contact:

### Re: Moving Sprite loop with slow motion when changing direct

As an alternative to using 16-bit velocity, you could take a random number (0-255) each frame, and compare it against some sort speed throttle value to decide whether or not to move this frame, i.e. "if rand() >= 128" will move at 50% speed, "if rand() >= 64" at 75% speed, etc.

na_th_an
Posts: 557
Joined: Mon May 27, 2013 9:40 am

### Re: Moving Sprite loop with slow motion when changing direct

You don't need 16 bits if the distance for the slowdown is always the same (if I've understood correctly). You can use fp during the calculations, then output a lut with integer pixel increments per frame.

sdm
Posts: 306
Joined: Tue Apr 11, 2006 4:08 am
Location: Poland

### Re: Moving Sprite loop with slow motion when changing direct

I managed to do it the way I wanted it, ie releasing 8pix before points A and B. But the code does not look too good, especially as far as optimizations are concerned, I will be grateful for the improvement of the code.

Code: Select all

``````ENM_loop:

LDA ENM_Slow			;EOR changes the value of one bit per frame
EOR #%00000001
STA ENM_Slow

lda ENM_S
and #%00000100
bne ENM_loop_Left		;Czy bit kierunku jest ustawiony? Skocz, jeśli tak.

lda ENM_MovePos
cmp ENM_INC
beq ENM_loop_chngDir		;When the max INC is reached, change the direction

LDA ENM_X
CMP ENM_SlowDEC
BCC ENM_Loop_INCslo

LDA ENM_MovePos
CMP ENM_SlowINC
BCC ENM_Loop_INCnoSlo		;When it will be 8pix before MAX INC. Do not make a branch

ENM_Loop_INCslo:

LDA ENM_Slow			;Now it is 8pix or less since max INC - now slow down the movement
CMP #1
BNE ENM_Loop_SkipINCFrame

ENM_Loop_INCnoSlo:

INC ENM_MovePos

ENM_Loop_SkipINCFrame:

RTS

ENM_loop_Left:

lda ENM_MovePos
cmp ENM_DEC
beq ENM_loop_chngDir		;When the max DEC is reached, change the direction

LDA ENM_X
CMP ENM_SlowINC
BCS ENM_Loop_DECslo

LDA ENM_MovePos
CMP ENM_SlowDEC
BCS ENM_Loop_DECnoSlo		;When it will be 8pix before MAX DEC. Do not make a branch

ENM_Loop_DECslo:

LDA ENM_Slow			;Now it is 8pix or less since max DEC - now slow down the movement
CMP #1
BNE ENM_Loop_SkipDECFrame

ENM_Loop_DECnoSlo:

DEC ENM_MovePos

ENM_Loop_SkipDECFrame:

RTS

ENM_loop_chngDir:			;CHANGE DIRECTION

JSR SND1
lda ENM_S
EOR #%01000100
sta ENM_S

ENM_loop_end:

RTS
``````
I mainly mean that the ENM_INC and ENM_DEC variables can be changed to any value, and the slowdown itself will be executed (without further changes in the ENM_Loop)

EDIT:
I made a slow down consisting of two parts (1x-> 2x-> 4x reverse direction 4x, 2x, 1x)

The code does not look beautiful, but it works. Unfortunately it is quite curly and has a large size ...

Code: Select all

``````ENM_Slowmo:

LDA ENM_Slow
EOR #%00000001
STA ENM_Slow

LDA ENM_Slow
CMP #1
BNE ENM_Slowmo_Skip

LDA ENM_Slow2
EOR #%00000001
STA ENM_Slow2

ENM_Slowmo_Skip:

RTS

;------------------------------------

ENM_loop:

JSR ENM_Slowmo

lda ENM_S
and #%00000100
bne ENM_loop_Left      ;Czy bit kierunku jest ustawiony? Skocz, jeśli tak.

lda ENM_MovePos
cmp ENM_INC
beq ENM_loop_chngDir      ;When the max INC is reached, change the direction

LDA ENM_X
CMP ENM_SlowDEC
BCC ENM_Loop_INCslo

LDA ENM_MovePos
CMP ENM_SlowINC
BCC ENM_Loop_INCnoSlo      ;When it will be 8pix before MAX INC. Do not make a branch

ENM_Loop_INCslo:

LDA ENM_Slow         ;Now it is 8pix or less since max INC - now slow down the movement
CMP #1
BNE ENM_Loop_SkipINCFrame

ENM_Loop_INCnoSlo:

LDA ENM_MovePos
CMP ENM_Slow2DEC
BCC ENM_Loop_INCSlo2

LDA ENM_MovePos
CMP ENM_Slow2INC
BCC ENM_Loop_INCnoSlo2

ENM_Loop_INCSlo2:

LDA ENM_Slow2
CMP #1
BNE ENM_Loop_SkipINCFrame

ENM_Loop_INCnoSlo2:

INC ENM_MovePos

ENM_Loop_SkipINCFrame:

RTS

ENM_loop_Left:

lda ENM_MovePos
cmp ENM_DEC
beq ENM_loop_chngDir      ;When the max DEC is reached, change the direction

LDA ENM_X
CMP ENM_SlowINC
BCS ENM_Loop_DECslo

LDA ENM_MovePos
CMP ENM_SlowDEC
BCS ENM_Loop_DECnoSlo      ;When it will be 8pix before MAX DEC. Do not make a branch

ENM_Loop_DECslo:

LDA ENM_Slow         ;Now it is 8pix or less since max DEC - now slow down the movement
CMP #1
BNE ENM_Loop_SkipDECFrame

ENM_Loop_DECnoSlo:

LDA ENM_MovePos
CMP ENM_Slow2INC
BCS ENM_Loop_DECSlo2

LDA ENM_MovePos
CMP ENM_Slow2DEC
BCS ENM_Loop_DECnoSlo2

ENM_Loop_DECSlo2:

LDA ENM_Slow2
CMP #1
BNE ENM_Loop_SkipDECFrame

ENM_Loop_DECnoSlo2:

DEC ENM_MovePos

ENM_Loop_SkipDECFrame:

RTS

ENM_loop_chngDir:         ;CHANGE DIRECTION

JSR SND1
lda ENM_S
EOR #%01000100
sta ENM_S

ENM_loop_end:

RTS
``````
Attachments
demo4.nes
monsterslo4.zip
demo2.nes

Oziphantom
Posts: 980
Joined: Tue Feb 07, 2017 2:03 am

### Re: Moving Sprite loop with slow motion when changing direct

While not really the right thing to do.. you can do something like this

Code: Select all

`````` bit Direction
bmi Backwards
;Forward
lda ENM_MovePosHi
sec
sbc ENM_EndPos
lsr a
lsr a
cmp #3
bcc safeF
lda #2
safeF
tax
lda ENM_MovePosLo
clc
sta ENM_MovePosLo
lda ENM_MovePosHi
cmp ENM_EndPos
bcc safeF2
lda #80
sta Direction
lda #0
sta ENM_MovePosLo
lda ENM_EndPos
safeF2
sta ENM_MovePosHi
rts

Backwards
lda ENM_StartPos
sec
sbc ENM_MovePosHi
lsr a
lsr a
cmp #3
bcc safeB
lda #2
safeB
tax
lda ENM_MovePosLo
sec
sbc SpeedTableFLo ,x
sta ENM_MovePosLo
lda ENM_MovePosHi
sbc SpeedTableFHi,x
cmp ENM_StartPos
bcc safeB2
lda #0
sta Direction
sta ENM_MovePosLo
lda ENM_StartPos
safeB2
sta ENM_MovePosHi
rts

SpeedTableFLo .db \$40,\$80,\$00
SpeedTableFHi .db \$00,\$00,\$10``````
Note this is off the top of my head and might have bugs

The idea is you do
EndPos - Pos
Which gives you the number of pixels until the end. Now you want to have 0-3 1 speed, 4-7 another 8+ another, so what I do is a shift right 2 times so
1000 -> 0010 8 = 2
0111 -> 0001 7 = 1
0100 -> 0001 4 = 1
0011 -> 0000 3 = 0
0001 -> 0000 1 = 0
so if the number after shift it higher than 2 I set the index to 2.
Then I use 16 bits maths to add the pixels. This is basically 8.8 fixedpoint, you set sprites based upon the Hi value.
\$100 = 1
\$080 = 0.5
\$040 = 0.25

as in
040 +
040
----
080

080 +
040
----
0C0

0C0 +
040
----
100

so basically you use it to get the 1x,0.5,0.25 speeds but you might want to scale them up so the enemy moves at 2px a frame for example, then 1, then .5 or whatever.

It then checks to see if it has gone over or hit the target, then it snaps to the target and flips the direction. Note I use \$80, \$00 so I can use BIT instruction to do the test, as BIT will pull bit 7 into the N flag, an LDA will also do the same

Backwards is the same thing, just now you do Pos-Start and then subtract the speeds to go the other way.

OmegaMax
Posts: 83
Joined: Wed Sep 21, 2016 8:55 am

### Re: Moving Sprite loop with slow motion when changing direct

How about using tables for you enemy object movement logic,I'm using the stack but you can use temp variables to save the values(NmeXVelocity,NmeYVelocity,NmeMovementPatternTimer) also the tables are integer values(you can add fixed point values like Oziphantom showed you) if you can't understand or have trouble implementing my example private message me and we can modify code that suits your game needs.Best of luck which ever way you decide."Off topic" sdm you have unconventional ways of solving problems and you manage to solve them each time,it's neat to see.

Code: Select all

``````;-------------------------------------------------------
Do_BuildNmeLogicPointer:
ldy #NmeObjLogicOffset
lda (_NMEArray),Y
sta _NmeLogicPointer+0
iny
lda (_NMEArray),Y
sta _NmeLogicPointer+1
rts
;-------------------------------------------------------
Do_NMEMovementTimers:
sec
sbc #1
sta (_NMEArray),y
rts
;-------------------------------------------------------
Do_BuildNMEMovementPattern:
ldy #NmeMovementPatternTimerOffset
lda (_NMEArray),Y
bne Do_NMEMovementTimers
jsr Do_BuildNmeLogicPointer
ldy #MovementPatternTableOffset
lda (_NMEArray),Y
tay
lda (_NmeLogicPointer),Y
iny
pha                                                        ;Push NmeXVelocity to stack
lda (_NmeLogicPointer),Y
pha                                                        ;Push NmeYVelocity to stack
iny
lda (_NmeLogicPointer),Y
bpl +
and #%01111111
ldy #\$FF
+:
iny
pha                                                         ;Push NmeMovementPatternTimer to stack
tya
ldy #NMEMovementPatternTableOffset
sta (_NMEArray),Y
pla                                                          ;Pull NmeMovementPatternTimer from stack
ldy #NmeMovementPatternTimerOffset
sta (_NMEArray),Y                                            ;Save NmeMovementPatternTimer in EnemyArray
pla                                                          ;Pull NmeYVelocity from stack
ldy #NmeYVelocityOffset
sta (_NMEArray),Y                                            ;Save NmeYVelocity in EnemyArray
pla                                                          ;Pull NmeXVelocity from stack
ldy #NmeXVelocityOffset
sta (_NMEArray),Y                                            ;Save NmeXVelocity in EnemyArray
rts

;==================================================
;Data Format
;Byte 0 = NmeXVelocity
;Byte 1 = NmeYVelocity
;Byte 2 = NmeMovementPatternTimer
;==================================================
Enemy1PatternLogicTable:
.db \$FE,\$02,\$05
.db \$FE,\$02,\$05
.db \$FE,\$FE,\$05
.db \$FE,\$FE,\$85
;-------------------------------------------------------
NME2PatternLogicTable:
.db \$FE,\$00,\$0A
.db \$FE,\$03,\$0A
.db \$FE,\$05,\$0A
.db \$FE,\$09,\$0A
.db \$FE,\$05,\$0A
.db \$FE,\$03,\$0A
.db \$FE,\$00,\$0A
.db \$FE,\$FD,\$0A
.db \$FE,\$FB,\$0A
.db \$FE,\$F7,\$0A
.db \$FE,\$FB,\$0A
.db \$FE,\$FD,\$8A ``````