A reasonably accurate (I think) representation of Newton's Cradle. It's timer based with real life values of gravity, time and length - so you could actually adjust the length of the strings in the code, and the period of oscillation should be the same as that of a real pendulum. Not sure if this is likely to be useful in a game, other than to look pretty - but it should be useful in my classroom for teaching simple harmonic motion and conservation of energy. Plus, it could be a nice screensaver.
One problem though is the collision routine which means the balls sometimes fuse together partially - if anyone can improve on it then I'd be very grateful (prefably in the code rather than using a physics wrapper)
`Project: Newton's Cradle - Physics modelling by Ric
`Created: 03/08/2004 11:39:53
`variables
s#=20 `ball size
g#=9.8 `acceleration due to gravity
l#=1.2 ` real length of string in metres
sl#=l#*100 `screen length is scaled up
angmax#=45 `maximum angle (equivilent to amplitude)
ang#=angmax# `new angle
numberlifted = 1 `this is the number of balls that are lifted at the start
e#=-90 `initial phase angle set to -90 degrees
degrad#=57.296 `conversion factor for degrees into radians
balldir$="right" `initial ball direction
p=1 `initial settings for p to q loop later on - selects which balls are moving when
camang#=-90 ` initial camera view
`user input
hide mouse
sync on
ink rgb(80,80,255),0
set text font ""
set text size 14
print
print
print "Newton's Cradle - Physics modelling exercise by Ric."
tryagain:
print "How many balls do you want to lift? (1-4)"
sync
input numberlifted
if numberlifted>4 or numberlifted<1 then goto tryagain
q=numberlifted
print "Use the left and right arrow keys to lift the balls, then press space to drop"
print "Press any key to continue......."
sync
wait key
`initial display settings
autocam off
position camera 0,0,-130,-200
point camera 0,20,-150,0
hide light 0
color backdrop rgb(0,0,0)
`make balls
b=1
c=1
for a=1 to 5
make object sphere a,s#,20,20 `these become the secondary limbs
make mesh from object a,a
delete object a
`make strings
make object cylinder b,1 `theses are primary limbs
scale object b,100,100*sl#,100 `scale cylinder to screen length
add limb b,1,a
scale limb b,1,100,100/sl#,100 `unscale the limb back to normal due to the automatic scaling when attached to the scaled body
offset limb b,1,0,-(((s#/2)+(sl#/2))/sl#),0 `offset limb by an amount which is DIVIDED by the scaling factor because offset is multiplied by the object scaling
make mesh from object b,b
delete object b
`make pivots
make object sphere c,2 `these are the bodies
add limb c,1,b
offset limb c,1,0,-sl#/2,0
position object c,((2*a)-1)*s#/2,0,0 `position body and limbs side by side
color object c, rgb(120,180,255) `some cosmetics
set object specular c,rgb(50,50,100)
set object specular power c,0.9
set object emissive c,rgb(50,50,100)
ghost object on c
set object ambient c,0
b=b+1
c=c+1
next a `repeat for 5 lots of pendulums
`light
make light 1
position light 1,-50,-150,-100
set light range 1,100000
color light 1,rgb(255,180,180)
`make reflective plane
make object plain 100,300,300
xrotate object 100,-90
position object 100,50,-181,0
set object specular power 100,0.8
set object specular 100,rgb(200,10,10)
set object diffuse 100,rgb(200,100,100)
ghost object on 100
`make 2nd camera for reflection
make camera 1
color backdrop 1,rgb(0,0,0)
position camera 1,50,-180,0 `position under the pendulums
point camera 1,50,0,0 `point up at them
set camera fov 1,125
`make secondary plane
make object plain 101,300,300
color object 100,rgb(0,0,150)
xrotate object 101,-90
position object 101,50,-183,0
ghost object on 101
set object diffuse 100,rgb(100,0,160)
set object specular power 101,0.6
set object specular 101,rgb(80,0,0)
gosub adjustandlift
`initialise timer
starttime#=timer()
`main loop
do
`set timer
t#=(timer()-starttime#)/1000 `real time in seconds
remstart
equation for the ball's angle is:
new angle = maxangle*sin(sqrt(g/l)*t+phase angle)
!BUT!! this equation only works if angles are in radians,
so all angles need to be divided by 57.296 and all trig functions need to be
multiplied by 57.296
remend
exclusionflag=0
exclusionflag2=0
reset_loop:
for a = p to q
`the actual physics of motion - yes, just two lines!!
ang#=-(angmax#/degrad#)*sin(((t#*((g#/l#)^(0.5)))+(e#/degrad#))*degrad#)*degrad#
zrotate object a,-ang#
`collision routine
if ang#<1 and balldir$="right" and exclusionflag=0
p=6-numberlifted
q=5
exclusionflag=1
goto reset_loop
endif
if ang#<-angmax#/2
balldir$="left"
endif
if ang#>-1 and balldir$="left" and exclusionflag2=0
p=1
q=numberlifted
exclusionflag2=1
goto reset_loop
endif
if ang#>angmax#/2
balldir$="right"
endif
next a
`grab reflection for plane
set camera to image 1,1,256,256
texture object 100,1
`move camera in circle
x#=200*cos(camang#)
z#=200*sin(camang#)
position camera 0,x#+20,-130,z#
point camera 0,20,-150,0
camang#=camang#+0.1
sync
loop
adjustandlift:
wait 500
do
set current camera 0
if leftkey()=1 then angmax#=angmax#+1
if rightkey()=1 then angmax#=angmax#-1
for a=1 to numberlifted
zrotate object a,-angmax#
next a
set camera to image 1,1,256,256 `make reflection
texture object 100,1
if spacekey()=1 then return
sync
loop
(tested in dBPro only)