Math, Ratios between +/-'s

ok… here’s where all you math genius’ get to help me out. I know that this principal is not difficult and was taught sometime during my highschool years.

I need a math formula which reduces the ratio of any x:y to the smallest quanity possible. Basicaly so that the smaller of the two numbers is 1 and the other number is whatever it would be, compared to 1… but, I need it to work for both posative and negative numbers.

(I’m the ultimate Math newb… bear with me)

so. I have x=20, y=20 is 1:1
-20, y=-10 is -2:-1
x=10, y=-5 is 2:-1
ect.

so what is the formula for that? my mind is blank today… between alergies and a cold… I can’t think of this for the life of me.

the main concept would be :

x : y = x2 : y2
x/y = x2/y2
when we cross-multiply we get
xy2 = yx2
therefore, y2 = yx2/x and x2 = xy2/y

what you can do is something like:


(x<y)? x2 = 1 : y2 = 1
if (x<0) {
        x2 = -x2
} else if (x>0) {
        y2 = -y2
}

if (x2 === 1 || x2 === -1 ) {
        y2 = y*x2/x
} else if (y2 === 1 || y2 === -1 ) {
        x2 = x*y2/y
}

trace(x+" : "+y+" = "+x2+" : "+y2)

I’m kind of sleepy, I might’ve missed out something silly :stuck_out_tongue:
I’m not sure if this is the best way to do it, hope it helps anyways :slight_smile:

[edit]

ok… i’ve just tested it, doesnt really work. I’ll fix it though :slight_smile:

Looks similar to something I’ve been fiddling with. Really I’m just trying to figure out wether I’m over thinking it, and in fact it’s some silly formula that every first year Algebra student knows. I’m glad I wasn’t that far off.

I’ll continue to write the code as I am working on it. If you see some redundencies, let me know.


oBallClass.prototype.fCalculatePath = function(){
  if(this.vXVelocity>0){
    this.vXModify=1;
  }else{
    this.vXModify= -1;
  }
  if(this.vYVelocity>0){
    this.vYModify=1;
  }else{
    this.vYModify= -1;
  }
  this.vXRatio=Math.abs(this.vXVelocity);
  this.vYRatio=Math.abs(this.vYVelocity);
  if(this.vXRatio<this.vYRatio){
    this.vYRatio=this.vYModify(this.vYRatio/this.vXRatio);
    this.vXRatio=this.vXModify(this.vXRatio/this.vXRatio);
  }else{
    this.vXRatio=this.vXModify(this.vXRatio/this.vYRatio);
    this.vYRatio=this.vYModify(this.vYRatio/this.vYRatio);
  }
  
  //this.aPathX*=this.vXRatio*i
  //this.aPathY*=this.vYRatio*i
}


function ratio(x, y) {
(Math.abs(x)<Math.abs(y))? x2 = 1 : y2 = 1
if (x<0) {
        x2 = -x2
} else if (y<0) {
        y2 = -y2
}

if (x2 === 1 || x2 === -1 ) {
        y2 = y*x2/x
} else if (y2 === 1 || y2 === -1 ) {
        x2 = x*y2/y
}

trace(x+" : "+y+" = "+x2+" : "+y2)
}

** usage ** 
ratio(10, 20)

:slight_smile:

if the object oBall has a vXVelocity and a vYVeolcity would the code look something like this?


oBallClass.prototype.fCalculatePath = function(){
          (Math.abs(this.vXVelocity)<Math.abs(this.vYVelocity))? this.vXRatio = 1 : this.vYRatio = 1
  if (this.vXVelocity<0) {
    this.vXRatio = -this.vXRatio;
  } else if (this.vYVelocity<0) {
    this.vYRatio  = -this.vYRatio;
  }
  if (this.vXRatio === 1 ||  this.vXRatio === -1 ) {
    this.vYRatio=this.vYVelocity*this.vXRatio/this.vXVelocity
  } else if (this.vYRatio === 1 || this.vYRatio === -1 ) {
    this.vXRatio=this.vXVelocity*this.vYRatio/this.vYVelocity
  }        
}

(I really don’t know much about the “?” usage in line two

yep!

the statement in the second line is… i forgot what it’s called, but it works kind of like an if-statement…

(password = "sesame") ? trace("correct password") : trace("password is incorrect")

// if the expression in brackets is true, trace 
//"correct password". If not, trace "password is incorrect"... 

:slight_smile:

how does the === work in this?

is there a way that Math.max() and Math.min() could be useful to streamline this?

ok… I looked up both of those and I think I understand what’s happening… however… don’t you need to set the absolutes first and switch the “if for reverse” check to the end like so?

oBallClass.prototype.fCalculatePath = function(){
        this.vXRatio=Math.abs(this.vXVelocity);
        this.vYRatio=Math.abs(this.vYVelocity);
        (this.vXRatio<this.vYRatio)? this.vXRatio = 1 : this.vYRatio = 1
        if (this.vXRatio === 1 ||  this.vXRatio === -1 ) {
                this.vYRatio=this.vYVelocity*this.vXRatio/this.vXVelocity
        } else if (this.vYRatio === 1 || this.vYRatio === -1 ) {
                this.vXRatio=this.vXVelocity*this.vYRatio/this.vYVelocity
        }
        if (this.vXVelocity<0) {
                this.vXRatio = -this.vXRatio;
        } else if (this.vYVelocity<0) {
                this.vYRatio  = -this.vYRatio;
        }
}

just slap me with a trout if I’m not using this code right.

*Originally posted by david *
**ok… I looked up both of those and I think I understand what’s happening… however… don’t you need to set the absolutes first and switch the “if for reverse” check to the end like so?
**
Only when doing the comparison between x and y do we need the absolute values. Later on, the numbers need to retain their value. :slight_smile:

I’m not sure about switching the ‘if for reverse’. It works fine the way it is, and might work just as well if you switched them. Try that and tell me how it goes :slight_smile:

Math.min and/or Math.max could be used, but they wouldn’t optimize the code anywho. Using Math.min would look like this:

 (Math.min(this.vXVelocity, this.vYVelocity) === this.vXVelocity)? this.vXRatio = 1 : this.vYRatio = 1

as opposed to

        (Math.abs(this.vXVelocity)<Math.abs(this.vYVelocity))? this.vXRatio = 1 : this.vYRatio = 1

so it isn’t really much of a difference i guess :slight_smile:

:trout: :stuck_out_tongue:

ok… I got the ratio working right. Thanks ahmed.

Now I’m working on a “ping” function. Ugg… this is tough stuff.

:slight_smile:

Ping function? like… DOS’s ‘PING’? or is it something different also refered to as ping? :beam:

What I’m attempting to do is send out a signal, from the ball, in the direction indicated by the ratio, to the edge of the board, and to test for each location. If there is a hit indicated with an object, then the ping returns a maximum x and y distance to travel (ensuring that a ball moving at 20 pixels per click will not move past an object that is only 10 pixels in size, without registering a hit.

It may end up being too processor intensive.

I may also, rather than using a hitTest, opt to keep track of all the locations of objects in an array, and then test against that instead. I may find this will work better… but as I haven’t even gotten the ping to register correctly, I don’t know yet.

I’ve been trying to use a while loop
Something like this


this.i=0;
vHit=false;
while(!vHit){
  this.i++
  for(obj in _root){
    if(_root[obj].hitTest(this.vXRatio*this.i,this.vYRatio*this.i)){
      this.vXPing=Math.min(this.vXPing,this.vXRatio*this.i);
      this.vYPing=Math.min(this.vYPing,this.vYRatio*this.i);
      this.vHit=true;
    }else{
      this.vXPing=this.vXRatio*this.i;
      this.vYPint=this.vYRatio*this.i;
      if(this.vXVelocity>0&&this.vXPing>_root.vRight){
        this.vHit=true;
        this.vXMaxDist=_root.vRight;
      }else if(this.vXVelocity<0&&this.vXPing<_root.vLeft){
        this.vHit=true;
        this.vXMaxDist=_root.vLeft;
      }else if(this.vYVelocity>0&&this.vYPing>_root.vBottem){
        this.vHit=true;
        this.vYMaxDist=_root.vBottem;
      }else if(this.vYVelocity<0&&this.vYPing<_root.vTop){
        this.vHit=true;
        this.vYMaxDist=_root.vTop;
      }
    }
 }

however… I run into infinite loops whenever I try to use while. I haven’t gotten this quite right yet.

oh oh I see.

For a case like this I would achieve it through a tile-based approach. Although your way seems logical enough, and more flexible/accurate in some ways :slight_smile:

[edit]

*Originally posted by david *
**to keep track of all the locations of objects in an array, and then test against that instead. I may find this will work better… **
yeah… that’s what i was talking about :stuck_out_tongue:

I think that in the end, you’ll be right. I’ll be forced to do it that way.

Question for ya… if you know the answer.

Is it any faster to loop through an array’s data than to loop through all objects in the _root through a for in loop with hitTest?

I know that technicaly the for in loop is just sorting through an array that the comp has internaly… but I’m unaware if there are any differences

as for “flexible/accurate”… yeah I know what you mean… I’m really creative when it comes to figuring out how this stuff should be done. Unfortunately I’m not nearly as good at figuring how how it must be done… if you know what I mean.

My way seems well suited for a compiled programming language like C… it’s sad that Flash can’t handle nearly as much data control.

*Originally posted by david *
**Is it any faster to loop through an array’s data than to loop through all objects in the _root through a for in loop with hitTest? **
I’ve read somewhere that flash stores all objects in the arrays _root (or _this and _parent), so when you’re looping through arrays on either cases, whether you store the data in an array or use the movie’s built-in array… "(References to) MC’s, variables, etc (all objects basically) are stored inside an associative array on the timeline they’re on. "

*Originally posted by david *
**as for “flexible/accurate”… yeah I know what you mean… I’m really creative when it comes to figuring out how this stuff should be done. Unfortunately I’m not nearly as good at figuring how how it must be done… if you know what I mean.

My way seems well suited for a compiled programming language like C… it’s sad that Flash can’t handle nearly as much data control. **

Yeah, a tile-based approach kind of limits you in a way that there are no ‘in-betweens’… you’re either on this tile or another one. On my current project, I’m moving objects 2 pixels/frame, and the tile size is 17 pixels … that’s causing a lot of headache :-\

I agree, we really need a better flash player :hair: