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