Marble @ https://www.dropbox.com/s/fvu405zeqkb7wu0/marble.png
Aarch.. Here's the Dropbox misery again. Cannot run the app. I quit, sorry.
2D Elastic Collision Spheres
- Mr. Kibernetik
- Site Admin
- Posts: 4786
- Joined: Mon Nov 19, 2012 10:16 pm
- My devices: iPhone, iPad, MacBook
- Location: Russia
- Flag:
Re: 2D Elastic Collision Spheres
This version runs with or without sprite image.
Also fixes fps counter.
Also fixes fps counter.
Code: Select all
rem 2D elastic collision with spheres v1.2
rem 1.1 avoiding double calculations : ) to speed a bit
rem 1.2 using sprites, 53-56 fps with 20 marbles
rem 2.0 using complex numbers
rem based on:
rem http://www.vobarian.com/collisions/2dcollisions2.pdf
rem http://blogs.love2d.org/content/circle-collisions
rem
rem SB 3.4 / iPad mini 1.gen. / iOS 7.0.4 / Operator
rem mod by Mr.K.
graphics
graphics clear 0,0,1
option sprite pos central
option base 1
draw color 1,1,1
draw font name "Chalkduster"
endd = 0
sch = screen_height()
scw = screen_width()
init_speed = 5
max_balls = 20
dim balls_xy(max_balls), balls_v(max_balls), balls_m(max_balls)
dim marb$(max_balls)
ball_r = 15
ball_d = ball_r * 2
f$ = "/Sprites/marble.png"
if file_exists(f$) then
sprite "marble" load f$
else
sprite "marble" begin ball_d, ball_d
fill color 1,1,0
fill circle ball_r, ball_r size ball_r
sprite "marble" end
end if
fill color 0,0,1
'preload balls array x,y,vx,vy,mass and marbles (sprites)
for i = 1 to max_balls
balls_xy(i) = ball_r + rnd(scw - ball_d) + (ball_r + rnd(sch - ball_d)) * 1i
balls_v(i) = (-1 + 2*rndc(2))*rnd(init_speed)
balls_m(i) = 1
sprite "marble" copy "marble"&i
marb$(i) = "marble"&i
sprite marb$(i) show
next i
draw font size 50
t$ = "smart BASIC"
draw text t$ AT scw - text_width(t$),sch - text_height(t$)
draw font size 20
timer reset
total_loops = 0
do
'graphics lock
'graphics clear 0,0,0
'draw balls
for i = 1 to max_balls
'draw balls
'ab_v = abs(balls_v(i))/2
'fill color ab_v,ab_v,ab_v
'fill circle balls(i,x),balls(i,y) size ball_r
'sprite marb$(i) alpha ab_v 'un mark but cost some fps!
pos = balls_xy(i)
sprite marb$(i) at real(pos),imag(pos)
'move balls
balls_xy(i) += balls_v(i)
'wall (screen margin) collision detect & react
x = real(balls_xy(i))
y = imag(balls_xy(i))
vx = real(balls_v(i))
vy = imag(balls_v(i))
if x <= ball_r Then
balls_xy(i) = ball_r + y * 1i
balls_v(i) = vy * 1i - vx
end if
if x >= scw - ball_r Then
balls_xy(i) = scw - ball_r + y * 1i
balls_v(i) = vy * 1i - vx
end if
if y <= ball_r Then
balls_xy(i) = x + ball_r * 1i
balls_v(i) = vx - vy * 1i
end if
if y >= sch - ball_r Then
balls_xy(i) = x + (sch - ball_r) * 1i
balls_v(i) = vx - vy * 1i
end if
'ball to ball collision detect and react
for j = i + 1 to max_balls
vec_n = balls_xy(i) - balls_xy(j)
if abs(vec_n) <= ball_d Then
'col_str$ = "ball "&str$(i)&" colliding ball "&str$(j)
'draw text col_str$ at 10,10
'resolve collision of ball(i) with ball(j)
'colission vector = normal vector
'calculate normal vector of collision: _n
'normalize L=1 normal vector of collision
'distance (vec_n_L) should be 2*ball_r
vec_n_L = abs(vec_n)
'separate balls penetration along the
'"line of collision".
midpt = (balls_xy(i) + balls_xy(j)) / 2
factor = ball_r / vec_n_L
balls_xy(i) = midpt + factor * (balls_xy(i) - balls_xy(j))
balls_xy(j) = midpt + factor * (balls_xy(j) - balls_xy(i))
'.. continue normalization..
vec_nn = vec_n / vec_n_L
'calculate normalized tangent vector to
'normal vector
vec_nn_x = real(vec_nn)
vec_nn_y = imag(vec_nn)
vec_tn_x = -vec_nn_y
vec_tn_y = vec_nn_x
vec_tn = vec_tn_x + vec_tn_y * 1i
'resolve the velocity vectors, v1 and v2
'into normal and tangential components
' --> dot product
ix = real(balls_v(i))
iy = imag(balls_v(i))
jx = real(balls_v(j))
jy = imag(balls_v(j))
v1_n = vec_nn_x * jx + vec_nn_y * jy
v2_n = vec_nn_x * ix + vec_nn_y * iy
v1_t = vec_tn_x * jx + vec_tn_y * jy
v2_t = vec_tn_x * ix + vec_tn_y * iy
'find the "new" tangential velocities
'after the collision (remain the same)
v1_t_ac = v1_t
v2_t_ac = v2_t
'find the new normal velocities after
'collision _ac
im = balls_m(i)
jm = balls_m(j)
imjm = im + jm
jmim = jm - im
v1_n_ac = (v1_n * jmim + 2 * im * v2_n) / imjm
v2_n_ac = (-v2_n * jmim + 2 * jm * v1_n) / imjm
'convert the scalar normal and tangential
'velocities into vectors
vec_v1_n_ac = v1_n_ac * vec_nn
vec_v1_t_ac = v1_t_ac * vec_tn
vec_v2_n_ac = v2_n_ac * vec_nn
vec_v2_t_ac = v2_t_ac * vec_tn
'final velocity vectors by adding the
'normal and tangential components
balls_v(j) = vec_v1_n_ac + vec_v1_t_ac
balls_v(i) = vec_v2_n_ac + vec_v2_t_ac
end if
next j
next i
total_loops += 1
fill rect 0,0 to 280,40
draw text "Frames per Second "&str$(int(total_loops * 1000/timer())) AT 0,5
'graphics unlock
until 0
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: 2D Elastic Collision Spheres
LOL, 160 fps on the iPhone 5s. I've got to slow it down to check the collisions.
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: 2D Elastic Collision Spheres
Just an example of avoiding superfluous indexing:
Instead of the code
For i=1 to limit
.
. do a lot of calculations with balls(i,x) and likewise array elements
.
Next i
Use the code:
For i=1 to limit
b_i_x = balls(i,x). ( convert to single variable )
.
. do a lot of calculations with b_i_x and likewise converted single variables
.
balls(i,x)=b_i_x ( if b_i_x itself was modified too )
Next i
The gain in speed however will be small with respect to the other improvement mentioned by mr. K. ( he should know best, after all )
Instead of the code
For i=1 to limit
.
. do a lot of calculations with balls(i,x) and likewise array elements
.
Next i
Use the code:
For i=1 to limit
b_i_x = balls(i,x). ( convert to single variable )
.
. do a lot of calculations with b_i_x and likewise converted single variables
.
balls(i,x)=b_i_x ( if b_i_x itself was modified too )
Next i
The gain in speed however will be small with respect to the other improvement mentioned by mr. K. ( he should know best, after all )
Re: 2D Elastic Collision Spheres
Just uploading marble.png,
"just rename it"
will come back later on...
"just rename it"
will come back later on...
- Attachments
-
- 412619801.794688.png (2.02 KiB) Viewed 3876 times
- Dutchman
- Posts: 851
- Joined: Mon May 06, 2013 9:21 am
- My devices: iMac, iPad Air, iPhone
- Location: Netherlands
- Flag:
Re: 2D Elastic Collision Spheres
Nice program. It is like an open fire, it keeps attracting your attention. Fascinating
dS>0...Everywhere!
To all of us who presumed, there was reversibility or determinism at least in our tiny niche...
But have a look for yourselves...and tap on the screen if/ when you feel like.
joel
N.B. My sincere apologies to the authors(Operator, Mr. K., et al.) of that wonderful program, that I have kinda ... abused...but I simply couldn't resist...
interesting article btw:
https://en.m.wikipedia.org/wiki/Reversible_computing
But have a look for yourselves...and tap on the screen if/ when you feel like.
joel
N.B. My sincere apologies to the authors(Operator, Mr. K., et al.) of that wonderful program, that I have kinda ... abused...but I simply couldn't resist...
interesting article btw:
https://en.m.wikipedia.org/wiki/Reversible_computing
Code: Select all
REM 2D elastic collision with spheres v1.2
REM 1.1 avoiding double calculations : ) to speed a bit
REM 1.2 using sprites, 53-56 fps with 20 marbles
REM 2.0 using complex numbers
REM based on:
REM http://www.vobarian.com/collisions/2dcollisions2.pdf
REM http://blogs.love2d.org/content/circle-collisions
REM
REM SB 3.4 / iPad mini 1.gen. / iOS 7.0.4 / Operator
REM mod by Mr.K.
REM abused by joel
GRAPHICS
GRAPHICS CLEAR 0,0,1
OPTION SPRITE POS CENTRAL
OPTION BASE 1
DRAW COLOR 1,1,1
DRAW FONT NAME "Chalkduster"
endd = 0
sch = SCREEN_HEIGHT()
scw = SCREEN_WIDTH()
init_speed = 2
max_balls = 21 '(n^2+n)/2 V n%2=0
DIM balls_xy(max_balls), balls_v(max_balls), balls_m(max_balls)
DIM marb$(max_balls)
ball_r = 15
ball_d = ball_r * 2
f$ = "marble.png"
IF FILE_EXISTS(f$) THEN
SPRITE "marble" LOAD f$
ELSE
SPRITE "marble" BEGIN ball_d, ball_d
FILL COLOR 1,1,0
FILL CIRCLE ball_r, ball_r SIZE ball_r
SPRITE "marble" END
END IF
FILL COLOR 0,0,1
setup_length=CEIL(SQR(2*max_balls+.25)-.5)
row_counter=0 ! column_counter=setup_length
'preload balls array x,y,vx,vy,mass and marbles (sprites)
FOR i = 1 TO max_balls
row_counter+=1
balls_xy(i)= (row_counter*(4/3*ball_d))-ball_d + (setup_length*(4/3*ball_d)+ball_d/3-(column_counter)*(ball_d+10))*1i
'balls_xy(i) = ball_r + RND(scw - ball_d) + (ball_r + RND(sch - ball_d)) * 1i
balls_v(i) = (-1 + 2*RNDC(2))*RND(init_speed)
balls_m(i) = 1
SPRITE "marble" COPY "marble"&i
marb$(i) = "marble"&i
SPRITE marb$(i) SHOW
IF row_counter=column_counter THEN
row_counter=0
column_counter -=1
ENDIF
NEXT i
DRAW FONT SIZE 50
t$ = "smart BASIC"
DRAW TEXT t$ AT scw - TEXT_WIDTH(t$),sch - TEXT_HEIGHT(t$)
DRAW FONT SIZE 20
TIMER RESET
total_loops = 0
DO
IF TOUCH_X(0)>0 THEN
WHILE TOUCH_X(0) > 0 ! END WHILE
invert_speed
ENDIF
'graphics lock
'graphics clear 0,0,0
'draw balls
FOR i = 1 TO max_balls
'draw balls
'ab_v = abs(balls_v(i))/2
'fill color ab_v,ab_v,ab_v
'fill circle balls(i,x),balls(i,y) size ball_r
'sprite marb$(i) alpha ab_v 'un mark but cost some fps!
POS = balls_xy(i)
IF FILE_EXISTS(f$) THEN
SPRITE marb$(i) AT REAL(POS),IMAG(POS) SCALE ball_r/15
ELSE
SPRITE marb$(i) AT REAL(POS),IMAG(POS)
ENDIF
'move balls
balls_xy(i) += balls_v(i)
'wall (screen margin) collision detect & react
x = REAL(balls_xy(i))
y = IMAG(balls_xy(i))
vx = REAL(balls_v(i))
vy = IMAG(balls_v(i))
IF x <= ball_r THEN
balls_xy(i) = ball_r + y * 1i
balls_v(i) = vy * 1i - vx
END IF
IF x >= scw - ball_r THEN
balls_xy(i) = scw - ball_r + y * 1i
balls_v(i) = vy * 1i - vx
END IF
IF y <= ball_r THEN
balls_xy(i) = x + ball_r * 1i
balls_v(i) = vx - vy * 1i
END IF
IF y >= sch - ball_r THEN
balls_xy(i) = x + (sch - ball_r) * 1i
balls_v(i) = vx - vy * 1i
END IF
'ball to ball collision detect and react
FOR j = i + 1 TO max_balls
vec_n = balls_xy(i) - balls_xy(j)
IF ABS(vec_n) <= ball_d THEN
'col_str$ = "ball "&str$(i)&" colliding ball "&str$(j)
'draw text col_str$ at 10,10
'resolve collision of ball(i) with ball(j)
'colission vector = normal vector
'calculate normal vector of collision: _n
'normalize L=1 normal vector of collision
'distance (vec_n_L) should be 2*ball_r
vec_n_L = ABS(vec_n)
'separate balls penetration along the
'"line of collision".
midpt = (balls_xy(i) + balls_xy(j)) / 2
factor = ball_r / vec_n_L
balls_xy(i) = midpt + factor * (balls_xy(i) - balls_xy(j))
balls_xy(j) = midpt + factor * (balls_xy(j) - balls_xy(i))
'.. continue normalization..
vec_nn = vec_n / vec_n_L
'calculate normalized tangent vector to
'normal vector
vec_nn_x = REAL(vec_nn)
vec_nn_y = IMAG(vec_nn)
vec_tn_x = -vec_nn_y
vec_tn_y = vec_nn_x
vec_tn = vec_tn_x + vec_tn_y * 1i
'resolve the velocity vectors, v1 and v2
'into normal and tangential components
' --> dot product
ix = REAL(balls_v(i))
iy = IMAG(balls_v(i))
jx = REAL(balls_v(j))
jy = IMAG(balls_v(j))
v1_n = vec_nn_x * jx + vec_nn_y * jy
v2_n = vec_nn_x * ix + vec_nn_y * iy
v1_t = vec_tn_x * jx + vec_tn_y * jy
v2_t = vec_tn_x * ix + vec_tn_y * iy
'find the "new" tangential velocities
'after the collision (remain the same)
v1_t_ac = v1_t
v2_t_ac = v2_t
'find the new normal velocities after
'collision _ac
im = balls_m(i)
jm = balls_m(j)
imjm = im + jm
jmim = jm - im
v1_n_ac = (v1_n * jmim + 2 * im * v2_n) / imjm
v2_n_ac = (-v2_n * jmim + 2 * jm * v1_n) / imjm
'convert the scalar normal and tangential
'velocities into vectors
vec_v1_n_ac = v1_n_ac * vec_nn
vec_v1_t_ac = v1_t_ac * vec_tn
vec_v2_n_ac = v2_n_ac * vec_nn
vec_v2_t_ac = v2_t_ac * vec_tn
'final velocity vectors by adding the
'normal and tangential components
balls_v(j) = vec_v1_n_ac + vec_v1_t_ac
balls_v(i) = vec_v2_n_ac + vec_v2_t_ac
END IF
NEXT j
NEXT i
total_loops += 1
FILL RECT 0,0 TO 280,40
DRAW TEXT "Frames per Second "&STR$(INT(total_loops * 1000/TIMER())) AT 0,5
'graphics unlock
UNTIL 0
DEF invert_speed
FOR i=1 TO .max_balls
.balls_v(i)=-1*REAL(.balls_v(i))-(IMAG(.balls_v(i))*1i)
NEXT i
END DEF