When I deduct/some 0.05 it some/deduct 0.05000001 (the var was declared as Number) - actionscript-3

Here is the problem:
when VX is some or deduct by 0.05 it deduct/some 0.05000001
(This take part in the Enter-frame, FPS)
**if(vx < 5 && KR){
vx += 0.05;
}else if(vx > 0 && !KR){
vx -= 0.05;
}else if(vx < 0 && !KL){
vx += 0.05;
}else if(vx < -5 && KL){
vx -= 0.05;
}
if(vy < 5 && KD){
vy += 0.05;
}else if(vy > 0 && !KD){
vy -= 0.05;
}else if(vx < -5 && KU){
vy -= 0.05;
}else if(vx < 0 && !KU){
vy += 0.05;
}

Floating point numbers are inherently imprecise - the set of rational numbers is infinite but floating point Number-s are stored on 64 bits, according to the IEEE-754 standard. Obviously, 64 bits is not an infinite number of bits so certain floating point values can be represented exactly and others cannot.
In general, you cannot rely on a floating point number to have the same exact value you're trying to assign to it.
var n:Number = 0.05;
will be translated by the compiler to a floating point representation of 0.05 and that may introduce a rounding error.
When working with floating point numbers, you usually have to use a range around the desired number, instead of checking for exact equality. So instead of doing
if ( n == 0.05 ) // this may or may not fail, based on rounding
you should do something like
if ( ( n > 0.04 ) && ( n < 0.06 ) ) // this will more likely work
The range is up to you - you must decide how much difference is acceptable when you do the check (here I used 0.01). The smaller the range, the more likely you run into rounding errors, though. The larger the range, you'll get more and more imprecise numbers that pass through the check.
Here's a pretty decent article that goes into more detail. The internet also has a lot of resources on how to properly work with floating point numbers.

Related

If condition explanation AS3

I found this code online. But I'm not completely sure what it means. It's to create a bouncing ball. Im just not sure whats saying in this if condition.
is it about the speed of the object or the where it's going to appear in the stage? Could u please add a //comment for a brief explanation. Thank you in advance!
if ( this.x >= nStageWidth - 10 )
{
this.x = nStageWidth - 10;
nSpeedX *= -1;
}
else if ( this.x <= 10 )
{
this.x = 10;
nSpeedX *= -1;
}
if ( this.y >= nStageHeight - 10 )
{
this.y = nStageHeight - 10;
nSpeedY *= -1;
}
else if ( this.y <= 10 )
{
this.y = 10;
nSpeedY *= -1;
}
This code checks the x or y property of an object to make sure it's within certain boundaries. If it's not, the object's nSpeedX or nSpeedY property is multiplied by -1.
For example, if x is less than 10 or greater than or equal to
nStageWidth-10, nSpeedX is multiplied by -1, which I assume sends
the object traveling in the opposite direction.
Without more code, I can't give you the exact implementation. However, based on how everything's named, my guess is that this code sends an object bouncing from one side of the stage to the other (with 10 pixels of padding on either side).

Multiple conditions for an if statement? (code doesn't work)

This is for a jigsaw-like puzzle game. I want it so it goes directly to the next scene after all the pieces are in place. So beside each "map piece" is the coordinate where it will be in its proper place.
BUT //surprise surprise// it doesn't work :c is it even possible to put so many conditions in the first place?
Thank you for reading c: (justABeginner)
if (map1.x== 259.45 &&
map1.y== 77.05 &&
map2.x== 368.3 &&
map2.y== 69.45 &&
map3.x== 445.30 &&
map3.y== 90.4 &&
map4.x== 288.5 &&
map4.y== 207.15 &&
map5.x== 325.75 &&
map5.y== 164.65 &&
map6.x== 436.20 &&
map6.y== 187.65)
{
gotoAndStop (1, "Scene 3");
}
The code looks fine to me. If the condition doesn't evaluate to true, then it might actually be the values which are different. How about a simple debugging step before the If statement like printf to check if the values are exactly the same.
Sometimes, the precision will play a large role in such If statements.
Happy coding :)
You'll probably find its not working because its particularly difficult to align an object with sub pixel accuracy. Because of this, you may want to consider "flooring" or "rounding" your numbers. I would suggest flooring to avoid it being rounded up to the next value.
if (Math.floor(map1.x) == 259 && Math.floor(map1.y) == 77 &&
Math.floor(map2.x) == 368 && Math.floor(map2.y) == 69 &&
Math.floor(map3.x) == 445 && Math.floor(map3.y) == 90 &&
Math.floor(map4.x) == 288 && Math.floor(map4.y) == 207 &&
Math.floor(map5.x) == 325 && Math.floor(map5.y) == 164 &&
Math.floor(map6.x) == 436 && Math.floor(map6.y) == 187)
{
gotoAndStop (1, "Scene 3");
}
Doing something like this will give you a more "fuzzy" comparison and should be easier to line up the puzzle pieces. Also, you may want to consider perhaps helping the user by adding a "snap to place" feature ...
function inrange(targetX, targetY, mapX, mapY, strength) {
targetX -= (strength / 2);
targetY -= (strength / 2);
return (mapX >= targetX && mapX <= (targetX+strength) &&
mapY >= targetY && mapY <= (targetY+strength));
}
//snap map piece into place if within 3 pixels
if (inrange(259, 77, map1.x, map1.y, 3)) {
map1.x = 259;
map1.y = 77;
}
As a general piece of advice, you should never use an equality check (==) with a floating point number. At some point you will find that you can't trust that 0.5 + 0.2 would equal 0.7. it may end up equalling 0.70000000001 or 0.6999999999999
As others have mentioned, try rounding your numbers, or better yet, try a small range, within which the piece is snapped into position, say plus or minus 10 pixels either way?

Preventing object from getting stuck on walls and rapidly bouncing between two points

I currently have objects populating the screen randomly and bouncing around the stage. The problem is, some of the objects are getting stuck and bouncing back and forth rapidly between two points. How can I prevent this?
Here's how I have the EnterFrame setup:
var ballT = e.target
ballT.x += ballT.vx;
ballT.y += ballT.vy;
if (ballT.x + ballT.width / 2 >= sWidth || ballT.x - ballT.width / 2 <= 0) {
ballT.vx = - ballT.vx;
} else if (ballT.y + ballT.height / 2 >= sHeight || ballT.y - ballT.height / 2 <= 0) {
ballT.vy = - ballT.vy;
}
Any ideas or any good reads worth checking out?
Most likely, your objects are going a bit "too much out of bounds", so that when you turn them around, they don't make it inside the bounds before you turn them around again. You may want to change the code to be a bit more clear on when to turn things around;
var ballT = e.target
ballT.x += ballT.vx;
ballT.y += ballT.vy;
// Outside to the right and heading right - turn around
if ( ballT.x + ballT.width / 2 >= sWidth && ballT.vx > 0 )
ballT.vx = -ballT.vx;
// Outside to the left and heading left - turn around
if ( ballT.x - ballT.width / 2 <= 0 && ballT.vx < 0 )
ballT.vx = -ballT.vx;
// Outside at the bottom and heading down - turn around
if ( ballT.y + ballT.height / 2 >= sHeight && ballT.vy > 0 )
ballT.vy = -ballT.vy;
// Outside at the top and heading up - turn around
if ( ballT.y - ballT.height / 2 <= 0 && ballT.vy < 0 )
ballT.vy = -ballT.vy;

Why am I flunking modulo subtraction?

Oh god this must be so simple. I have a heading in range (0, 2π) and two points from which I get the heading in between. I must compare them to see if one is within a range of the other. What I've got so far is.
//get the angle
float angle = atan(here.x - there.x, here.y - there.y);
//atan2 uses (-pi, pi) range, convert to (0, 2pi)
if(angle < 0) angle += 2*pi;
//subtract them pesky headings
float diff = angle - givenAngle;
//a difference of 350 degrees really is a difference of 10 degrees
if(diff > pi) diff = 2*pi - diff;
//a difference of -10 degrees really is a difference of 10 degrees
if(diff < 0) diff *= -1;
//check if the point is in range of givenAngle
if(diff > fov) do_magic(diff - fov);
However, I get all sorts of issues when both angles wrap around to zero and I've been wasting way too much brainpower in solving this solved problem.
Where am I doing it wrong? How can I find the difference between two headings correctly?
I suspect the order of your operations may be slightly wrong:
//a difference of 350 degrees really is a difference of 10 degrees
if(diff > pi) diff = 2*pi - diff;
//a difference of -10 degrees really is a difference of 10 degrees
if(diff < 0) diff *= -1;
This doesn't account for an diff of -350, but if you switch the statements it does:
//a difference of -10 degrees really is a difference of 10 degrees
if(diff < 0) diff *= -1;
//a difference of ±350 degrees really is a difference of 10 degrees
if(diff > pi) diff = 2*pi - diff;
One of the main problems was in this line:
float angle = atan(here.x - there.x, here.y - there.y);
It was kind of tricky to notice, but that's not the right argument order for atan - even the mathematical definition on wikipedia takes the y component (sine) before the x component (cosine).
float angle = atan(here.y - there.y, here.x - there.x);
A second problem is that, as it turns out, angle was off by 180 degrees. In other words, instead of calculating here - there, I should be calculating there - here.
float angle = atan(there.y - here.y, there.x - here.x);
Add in sverre's observation about the incorrect order of operations, and we have something that works much better:
float angle = atan(there.y - here.y, there.x - here.x);
if(angle < 0) angle += pi * 2; //use (0, 2pi) range, the same as angle
float diff = abs(angle - givenAngle);
if(diff > pi) diff = 2*pi - diff;
if(diff > fov) do_magic(diff - fov);

AS3 - Y Velocity 6.123031769111886E-17

When given 0,0 to 0,5, the y velocity becomes that number and breaks my code. I know I must have done something wrong as I just copy and pasted code (since I am horrible at maths)..
This is how I calculate the numbers:
var radian = Math.atan2(listOfNodes[j].y - listOfNodes[i].y,listOfNodes[j].x - listOfNodes[i].x);
var vy = Math.cos(radian);
var vx = Math.sin(radian);
Thanks
There i am assuming the velocity vector is FROM 0,0 TO 0,5. And 0,0 is i and 0,5 is j.
In that case the velocity vector is only along y and the y component should be 5 and x component 0. It is coming as opposite because,
cos(radian) whould be x velocity component and sin(radian) the y compunent.
And the number 6.123031769111886E-17 is actually returned in place of 0.
Look at the following figure:
Also as can be seen from the figure you do not need the trigonometric computations at all.
You can simply get the x and y components as follows:
// y2 - y1
var vy = listOfNodes[j].y - listOfNodes[i].y;
// x2 - x1
var vx = listOfNodes[j].x - listOfNodes[i].x;
This will avoid the floating point inaccuracy caused by the trig finctions due to which you are seeing 6.123031769111886E-17 instead of 0.
You only need to use atan2 if you actually need the angle θ in your code.
Update:
Well if you need only unit (normalized) vector's components you can divide the vx and vy with the length of the original vector. Like this:
// y2 - y1
var vy = listOfNodes[j].y - listOfNodes[i].y;
// x2 - x1
var vx = listOfNodes[j].x - listOfNodes[i].x;
// vector magnitude
var mag = Math.sqrt(vx * vx + vy * vy);
// get unit vector components
vy /= mag;
vx /= mag;
Using the above you will get the exactly the same results as you are getting from trig sin and cos functions.
But if you still need to use the original code and want to make 6.12...E-17 compare to 0, you can use the epsilon technique for comparing floats. So you can compare any value within epsilon's range from 0, using flllowing code:
function floatCompare(a:Number, b:Number, epsilon:Number):Boolean{
return (a >= (b - epsilon) && a <= (b + epsilon));
}
// To check for zero use this code, here i'm using 0.0001 as epsilon
if(floatCompare(vx, 0, 0.0001)){
// code here
}
So any deviation in the range of [b-epsilon, b+epsilon] would successfully compare to b. This is essential in case of floating point arithmetic.