NintendoAge http://nintendoage.com/forum/ -Sqooner Chain Physics http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=75586 2012-06-05T00:04:03 -05.00 Aaendi 6 Here is some 65816 ASM code for the SNES.  I still need to make a LUT for sinarctan and cosarctan.


lda !radius1
clc
adc !radius2
sta !total_radius

lda #$0000
sta !xsign
sta !ysign

lda !x2
sec
sbc !x1
clc
adc !xinertia
bpl x_is_positive
eor #$ffff
inc
inc !xsign
x_is_positive:
sta !x2

lda !y2
sec
sbc !y1
clc
adc !yinertia
clc
adc !gravity
bpl y_is_positive
eor #$ffff
inc
inc !ysign
y_is_positive:
sta !y
cmp !x
bmi x_is_larger_than_y

x_is_smaller_than_y:
lda !x
sta $4204   ;;division register
sep #$20
lda !y+1
sta $4206   ;;division register
nop    ;;wait for division
nop
nop
nop
nop
nop
nop
nop
ldx $4214   ;;quotient register
lda sinarctan,x
sta $4202   ;;multiplication register
lda !total_radius
sta $4203   ;;multiplication register
nop
nop
nop
nop
ldy $4216   ;;product
sty !x
lda cosarctan,x
sta $4202   ;;multiplication register
lda !total_radius
sta $4203   ;;multiplication register
nop
nop
nop
nop
ldy $4216   ;;product
sty !y
bra finish_calculating_chain_physics

x_is_larger_than_y:
lda !y
sta $4204   ;;division register
sep #$20
lda !x+1
sta $4206   ;;division register
nop    ;;wait for division
nop
nop
nop
nop
nop
nop
nop
ldx $4214   ;;quotient register
lda sinarctan,x
sta $4202   ;;multiplication register
lda !total_radius
sta $4203   ;;multiplication register
nop
nop
nop
nop
ldy $4216   ;;product
sty !y
lda cosarctan,x
sta $4202   ;;multiplication register
lda !total_radius
sta $4203   ;;multiplication register
nop
nop
nop
nop
ldy $4216   ;;product
sty !x

finish_calculating_chain_physics:
rep #$30
lda !xsign
beq add_x
lda !x1
sec
sbc !x
bra dont_add_x
add_x:
lda !x1
clc
adc !x
dont_add_x:
tax
sec
sbc !x2
sta !xinertia
stx !x2

lda !xsign
beq add_y
lda !y1
sec
sbc !y
bra dont_add_y
add_y:
lda !y1
clc
adc !y
dont_add_y:
tax
sec
sbc !y2
sta !yinertia
stx !y2 ]]>
Chain Physics http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=75586 2012-06-03T08:10:42 -05.00 Aaendi 6
mult = 1
if x2 - x1 > 0 then mult = -1
slope = abs(y/x)
x = cos(arctan(slope)) * (rad1 + rad2)) * mult
if y2 - y1 > 0 then mult = -1
y = sin(arctan(slope)) * (rad1 + rad2)) * mult

Too many if then statements/branches will result is slower code. Also, quit using => as an equals, that means insert into an array in several other languages.

Also, no need to use a copy of x and y. You're not changing the values of x1,x2,y1,y2 so..
xinertia = (x2-x1) - x
yinertia = (y2-y1) - y

Creating more variables = more used RAM.

And yes, there's an even more simple formula you can do for this that will speed it up. ]]>
Chain Physics http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=75586 2012-06-02T21:28:43 -05.00 Aaendi 6

5) Find the absolute slope of the line connecting the two sprites:

| y / x | => slope


6) Calculate the angle of the slope:

arctan( slope ) => angle


7) Calculate the new values of x and y:

if x is positive:  cos( angle ) * (radius1 + radius2) => x
if x is negative:  -cos( angle ) * (radius1 + radius2) => x

if y is positive:  sin( angle ) * (radius1 + radius2) => y
if y is negative:  -sin( angle ) * (radius1 + radius2) => y


8) Calculate new inertia value by subtracting the new coordinates by the old coordinates:

x - xcopy => xinertia
y - ycopy => yinertia


9) Calculate final screen coordinates of sprite 2:

x + x1 => x2
y + y1 => y2

]]>
Chain Physics http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=75586 2012-06-02T17:58:05 -05.00 Aaendi 6

Interesting though! I'll mess with it in javascript later. ]]>
Chain Physics http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=75586 2012-06-02T17:56:44 -05.00 Aaendi 6 Chain Physics http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=75586 2012-06-02T17:35:45 -05.00 Aaendi 6 This tutorial explains how to calculate chain physics, which is emulating the movement of one sprite chained up to another moving sprite.  I don't currently have an ASM code avaliable for this, but I'll be working on it.


1) Calculate the location of sprite 2, relative to sprite 1:

 x2 - x1 => x
 y2 - y1 => y


2) Make a copy of x and y (you'll understand why later):

 x => xcopy
 y => ycopy


3) Add inertia, to x and y:

 x + xinertia => x
 y + yinertia => y


4) Apply gravitational force

 y + gravity => y


5) Calculate the distance between sprite 1 and sprite 2:

 sqrt(x^2 + y^2) => d


6) Calculate the scale factor:

 (radius1 + radius2) / d => s


7) Multiply the coordinates by the scale factor, so sprite 2 is at a distance of (radius1 + radius2) from sprite 1, but at the same angle from sprite 2 as it otherwise would've been.

 x * s => x
 y * s => y


8) Calculate new inertia value by subtracting the new coordinates by the old coordinates:

 x - xcopy => xinertia
 y - ycopy => yinertia


9) Calculate final screen coordinates of sprite 2:

 x + x1 => x2
 y + y1 => y2

]]>