Hi guys, I’ve been trying to recreate the yugop example(www.yugop.com) where the balls seem to bounce off each other, but the difference is, they can also rest on top of each other. I’ve included my example and the class for help.
Thanks.
click to add more balls.
SWF: http://www.fuzzfolio.com/workarea/myBallYugop.html
main.fla
var ballcount:Number=1;
var ballSet:Array = new Array();
for (i = 0; i < ballcount; i++){
ballSet* = new myBallDynamics(i,_root);
ballSet*.bounceAround();
}
mybox.onPress=function(){
mybox.onRollOut();
ballSet[ballcount] = new myBallDynamics(ballcount,_root);
ballSet[ballcount].startBallScale();
mybox.onMouseMove=function(){
ballSet[ballcount].followCursor();
}
mybox.onRollOut=function(){
mybox.onMouseMove=null;
ballSet[ballcount].stopBallScale();
ballSet[ballcount].bounceAround();
ballcount=ballcount+1;
};
};
mybox.onRelease=function(){
mybox.onMouseMove=null;
mybox.onRollOut=null;
ballSet[ballcount].stopBallScale();
ballSet[ballcount].bounceAround();
ballcount=ballcount+1;
};
stop();
my class
class myBallDynamics{
public var bid:Number;
private var ballX:Number;
private var ballY:Number;
private var velX:Number;
private var velY:Number;
private var gravity:Number = 0;
private var boundaries:Object;
private var parentHolder:MovieClip;
private var holder:MovieClip;
private var radius:Number;
private var mass:Number;
function myBallDynamics(numOfBalls:Number, parentMC:MovieClip){
bid = numOfBalls;
parentHolder = parentMC;
holder = parentHolder.attachMovie("ball", "ball"+numOfBalls, numOfBalls,{_x:150, _y:150});
init(10);
}
function init(pgravity:Number){
gravity = pgravity;
radius = holder._width / 2;
mass = radius;
velX = Math.random()*20-10;
velY = -Math.random()*20;
ballX = holder._x;
ballY = holder._y;
checkForWalls();
}
function getMass(){
return mass;
}
function getX(){
return holder._x;
}
function getY(){
return holder._y;
}
function getVX(){
return velX;
}
function getVY(){
return velY;
}
function getBX(){
return ballX;
}
function getBY(){
return ballY;
}
function setVX(newVX:Number){
velX = newVX;
}
function setVY(newVY:Number){
velY = newVY;
}
function setBX(newBX:Number){
ballX = newBX;
}
function setBY(newBY:Number){
ballY = newBY;
}
function getWidth(){
return holder._width;
}
function getHeight(){
return holder._height;
}
function setWidth(newWidth:Number){
holder._width = newWidth;
}
function setHeight(newHeight:Number){
holder._heifht = newHeight;
}
function setX(newX:Number){
holder._x = newX;
}
function setY(newY:Number){
holder._y = newY;
}
function getRadius(){
return radius;
}
function followCursor(){
holder._x = _root._xmouse;
holder._y = _root._ymouse;
}
function startBallScale(){
followCursor();
var dir:Number=5;
holder.onEnterFrame=function(Void):Void{
if (this._width >= 100){
dir=-5;
}
if(this._height <= 25){
dir=5;
}
this._width += dir;
this._height += dir;
}
}
function stopBallScale(){
radius = holder._width / 2;
holder.onEnterFrame=null;
}
function updateMovement(){
// render our new position
holder._x = ballX;
holder._y = ballY;
updateAfterEvent();
}
function bounceAround(){
holder['obj']=this;
holder.onEnterFrame=function(Void):Void {
this.obj.ballX = this._x;
this.obj.ballY = this._y;
this.obj.velY += this.obj.gravity;
//this.obj.ballX += this.obj.velX;
this.obj.ballY += this.obj.velY;
this.obj.checkForWalls();
this.obj.checkForBalls();
this.obj.updateMovement();
}
}
function checkForWalls():Void {
// top
if (ballY - radius < 0) {
ballY = radius;
velY *= -1;
}
// bottom
else if (ballY + radius > Stage.height) {
ballY = Stage.height - radius;
velY *= -1;
}
// left
if (ballX - radius < 0) {
ballX = radius;
if(velX > 0 ) {
velX = velX - 1;
} else {
velX = velX + 1;
}
velX *= -1;
}
// right
else if (ballX + radius > Stage.width) {
ballX = Stage.width - radius;
if(velX > 0 ) {
velX = velX - 1;
} else {
velX = velX + 1;
}
velX *= -1;
}
}
function checkForBalls():Void {
// Have a look at the other balls on the stage and see if
// we're hitting them. If so, react accordingly.
// shortcut to the array that knows about all of the Balls on
// the stage
var allBalls:Array = parentHolder.ballSet;
// for each of the balls on the stage
for (var i = 0; i < allBalls.length; i++) {
// if our bid is less than theirs
// (this makes sure that each ball only looks for a collision
// with each other ball once per frame)
// If you ever delete balls - make sure you reset all the bids
if (allBalls*.bid > bid) {
// figure out how far away we are from them
// distance on the x axis
var xdiff:Number = allBalls*.getBX() - ballX;
// distance on the y axis
var ydiff:Number = allBalls*.getBY() - ballY;
// use pythagoras' magic
var dist:Number = Math.sqrt(xdiff * xdiff + ydiff * ydiff);
// hit test is easy with circles
// if dist <= sum of radii, we're hitting
if (dist <= (radius + allBalls*.getRadius())) {
// we're hitting, call the reaction function
ballBallReaction(this, allBalls*, dist, xdiff, ydiff);
}
}
}
}
function ballBallReaction(b1:myBallDynamics, b2:myBallDynamics, dist:Number, xdiff:Number, ydiff:Number):Void {
// params
// b1 - first ball in collision
// b2 - second ball in collision
// dist - distance between the middle of the two balls
// xdiff - diff between balls on the x axis
// ydiff - diff between balls on the y axis
// This function is where the billiard goodness takes place.
// It's physics madness... I'll explain the bits I think I understand
// find the angle between the balls
var angle = Math.atan2(ydiff, xdiff);
var cosa = Math.cos(angle);
var sina = Math.sin(angle);
// find the current linear momentum on each axis for each ball
// I think this rotates the coordinate system so that we can
// determine a 2 dimensional collision
var vx1p = cosa * b1.getVX() + sina * b1.getVY();
var vy1p = cosa * b1.getVY() - sina * b1.getVX();
var vx2p = cosa * b2.getVX() + sina * b2.getVY();
var vy2p = cosa * b2.getVY() - sina * b2.getVX();
// P = momentum?
// V = velocity?
var P = vx1p * b1.getMass() + vx2p * b2.getMass();
var V = vx1p - vx2p;
vx1p = (P - b2.getMass() * V)/(b1.getMass() + b2.getMass());
vx2p = V + vx1p;
// tell each ball how fast they're going on each axis
b1.setVX(cosa * vx1p - sina * vy1p);
b1.setVY(cosa * vy1p + sina * vx1p);
b2.setVX(cosa * vx2p - sina * vy2p);
b2.setVY(cosa * vy2p + sina * vx2p);
// Work out the where the balls are colliding along the
// "Line of Action" so that we can project them far enough
// away from each other to no longer intersect
var diff = ((b1.getRadius() + b2.getRadius()) - dist) / 2;
var cosd = cosa * diff;
var sind = sina * diff;
// update their temporary positions
b1.setBX(b1.getBX()- cosd);
b1.setBY(b1.getBY()- sind);
b2.setBX(b2.getBX()+ cosd);
b2.setBY(b2.getBY()+ sind);
}
}