Skip navigation
NintendoAge
Welcome, Guest! Please Login or Join
Loading...

Chain Physics

Jun 2, 2012 at 5:35:45 PM
Aaendi (0)

(Andy Koenigs) < Eggplant Wizard >
Posts: 332 - Joined: 05/31/2012
United States
Profile

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


Jun 2, 2012 at 5:56:44 PM
NESHomebrew (21)
avatar
(Brad Bateman - Strange Brew Games) < King Solomon >
Posts: 4264 - Joined: 04/28/2008
Saskatchewan
Profile
This seems like it would be hard to make efficient. None the less, I'd love to see a demo. Sounds like this would be a collision detection nightmare.

Jun 2, 2012 at 5:58:05 PM
removed04092017 (0)
This user has been banned -- click for more information.
< Bowser >
Posts: 7316 - Joined: 12/04/2010
Other
Profile
all that multiplying and division will take forever, got something usable in a game?

Interesting though! I'll mess with it in javascript later.

Jun 2, 2012 at 9:28:43 PM
Aaendi (0)

(Andy Koenigs) < Eggplant Wizard >
Posts: 332 - Joined: 05/31/2012
United States
Profile
I have another way of doing this:


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



Edited: 06/02/2012 at 09:29 PM by Aaendi

Jun 3, 2012 at 8:10:42 AM
dra600n (300)
avatar
(Adym \m/) < Bonk >
Posts: 16975 - Joined: 09/16/2010
Connecticut
Profile
you should do something like:

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.

-------------------------
Proud owner of post #1800 in Inner Circle HQ thread

Jun 5, 2012 at 12:04:03 AM
Aaendi (0)

(Andy Koenigs) < Eggplant Wizard >
Posts: 332 - Joined: 05/31/2012
United States
Profile
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


Edited: 06/05/2012 at 12:10 AM by Aaendi