Collisions between circles, velocity, mass questions -- Answered my own question

David Janik-Jones forums at artspin.com
Mon Nov 15 21:32:04 EST 2004


I've actually given up on Revolution for this task as I was able to 
recreate the whole thing I'd done, add in a 3D component, and get all 
of the velocity/mass/collision stuff done in less than two hours using 
Blender. While it's not yet perfect, and will most likely take another 
several hours to complete, it's a darn good start all things 
considered.

Odd interface, but alot of power under the hood.

Thanks,

David JJ

in my humble opinion | forums at artspin.com

On Nov 15, 2004, at 12:00 PM, use-revolution-request at lists.runrev.com 
wrote:
> ------------------------------
>
> Message: 7
>
> I'm looking to finish a small game my son suggested but I'm stumped on
> code that will produce the effects I need. The two player game
> basically involves trying to knock the opponents "marble" out of the
> (square) playing area. This means I need to script each marble (WASD or
> arrow keys) to have a radius, mass and velocity. The collisions between
> marbles must be like billiard balls on a nearly frictionless surface.
> Mass means that the marbles can transfer energy and increase/decrease
> speed not only with a direction key held down, but also through the
> collisions.
>
> Has anyone written any scripts like this?
>
> I can code this in Basic as follows, but need to know the best way to
> do it in Revolution Dreamcard.
>
> Here's how it might look in Basic (but with only one ball the player
> can control) ...
>
> int numOfBalls=2  // Change to add marbles.  Just be sure to specify
> the starting position, mass, and radius for each marble.
> int elasticity=0.5  // Elasticity is a value from 0 to 1: 0 will result
> in perfectly INELASTIC collisions (masses stick together), and a value
> of 1 will result in perfectly ELASTIC collisions
>
> float X[numOfBalls],Y[numOfBalls]
> float Vx[numOfBalls],Vy[numOfBalls]
> float M[numOfBalls]
> float radius[numOfBalls]
>
> // INITIAL VALUES SECTION -- Make sure to add more for each ball you 
> add
>
> radius[0]=28    // Marble size
> M[0]=25		// Marble mass
> X[0]=100		// X coordinate
> Y[0]=370		// Y coordinate
>
> radius[1]=28
> M[1]=25
> X[1]=660
> Y[1]=370
>
> // GAME LOOP SECTION
>
> int control
> repeat
> 	int key=raw key scancode(keyboard raw key)
> 	
> 	// Controls
> 	if up then Vy[control]=Vy[control]-0.5 'all values started at 0.5
> 	if down then Vy[control]=Vy[control]+0.5
> 	if left then Vx[control]=Vx[control]-0.5
> 	if right then Vx[control]=Vx[control]+0.5
> 	
> 	if pressed(6) // z key slows down the velocities each frame
> 		int stopCount
> 		for stopCount=0 to numOfBalls-1
> 			Vx[stopCount]=Vx[stopCount]/1.1
> 			Vy[stopCount]=Vy[stopCount]/1.1
> 		next stopCount
> 	end if
> 	
> 	int a,b
> 	for a=0 to numOfBalls-1
> 		for b=0 to numOfBalls-1
> 			if b>a  // only check combinations that haven't been checked yet;
> for example, there's no need to check (0,1) and then (1,0).
> 				float xDiff=X[b]-X[a]
> 				float yDiff=-(Y[b]-Y[a])
> 				float distance=sqrt(xDiff^2+yDiff^2)
> 				
> 				if distance<radius[a]+radius[b]  'if marbles a and b are touching
>
> 					// find angle between marbles
> 					if xdiff>=0 then float diffdir= invtan(ydiff/xdiff)
> 					if xdiff<0 then float diffdir= invtan(ydiff/xdiff)+180
> 					
> 					float dVx=Vx[a]-Vx[b]
> 					float dVy=-(Vy[a]-Vy[b])
> 		
> 					float totVel=sqrt(dVx^2+dVy^2)
> 					
> 				if totVel>0
> 					if dVx>=0 then float veldir =invtan(dVy/dVx)
> 					if dVx<0 then float veldir = invtan(dVy/dVx)+180
> 					
> 					// the impulse is the amount of transferred momentum.  The impulse
> can only be transferred along the point of contact.
> 					float
> impulse=(1+elasticity)*(M[a]*M[b])/(M[a]+M[b])*totVel*cos(veldir-
> diffdir)
> 					
> 					float VxfA=-impulse*cos(diffdir)/M[a]+Vx[a]
> 					float VyfA=impulse*sin(diffdir)/M[a]+Vy[a]
> 					float VxfB=impulse*cos(diffdir)/M[b]+Vx[b]
> 					float VyfB=-impulse*sin(diffdir)/M[b]+Vy[b]
>
> 					Vx[a]=VxfA
> 					Vy[a]=VyfA
> 					Vx[b]=VxfB
> 					Vy[b]=VyfB
> 				end if
> 				
> 					float dX=(radius[a]+radius[b]-distance)/2*cos(diffdir)
> 					float 
> dY=-((radius[a]+radius[b]-distance)/2*sin(diffdir))										
> 					X[a]=X[a]-dX
> 					Y[a]=Y[a]-dY
> 					X[b]=X[b]+dX
> 					Y[b]=Y[b]+dY
> 				end if
> 			end if
> 		next b
> 	next a
> 	
> 	float totalEnergy=0,totalMomentumX=0,totalMomentumY=0
> 	for a=0 to numOfBalls-1
> 		totalEnergy=totalEnergy+M[a]*(Vx[a]^2+Vy[a]^2)/2  //calculate the
> kinetic energy per ball, (1/2)*mass*velocity
> 		totalMomentumX=totalMomentumX+M[a]*Vx[a]   //momentum is 
> mass*velocity
> 		totalMomentumY=totalMomentumY+M[a]*Vy[a]   //x momentum and y
> momentum can be calculated separately
> 		
> 		X[a]=X[a]+Vx[a]
> 		Y[a]=Y[a]+Vy[a]
> 		if X[a]>740  //768 field width - ball width
> 			X[a]=740
> 			Vx[a]=-abs(Vx[a])
> 		else if X[a]<28
> 			X[a]=28
> 			Vx[a]=abs(Vx[a])
> 		end if
> 		
> 		if Y[a]>740   //768 field width - ball width
> 			Y[a]=740
> 			Vy[a]=-abs(Vy[a])
> 		else if Y[a]<28
> 			Y[a]=28
> 			Vy[a]=abs(Vy[a])
> 		end if
> 		
> 		if a=control
> 			set pen color blue   //player controlled ball blue
> 		else
> 			set pen color yellow   //other balls yellow
> 		end if
> 		fill oval X[a]-radius[a],Y[a]-radius[a] to
> X[a]+radius[a],Y[a]+radius[a]
> 	next a
> 	
> 	draw frame
> 	
> 	// Clear the screen for the next frame
> 	int erase
> 	for erase=0 to numOfBalls-1
> 		set pen color white
> 		fill oval X[erase]-radius[erase],Y[erase]-radius[erase] to
> X[erase]+radius[erase],Y[erase]+radius[erase]
> 	next erase
> until pressed(12)
>
> All help appreciated,
>
> David JJ



More information about the use-livecode mailing list