If I have two instances called block1 and block2. And they move off the stage. It scrolls down the y position and it respawns back on top. But I don't want the x/y position colliding with the other blocks? I want it to respawn back to position, but I want it randomized but at the same time I don't want it touching each other?
Heres my code:
if (block1.y > stage.stageHeight)
{
block1.y = -550;
block1.x = (Math.floor(Math.random() * (maxNum - minNum + 5)) + minNum);
}
I'm pretty sure I'm calculating the respawn coordinates the wrong way, but I'm not sure how to put it in a random x and y position without colliding with other blocks.
A very simple method can be just to spawn your box, do a collision check, then if collision, remove and respawn and recheck until you find an empty spot where it fits
This is obviously quite inefficient, but is pretty simple to implement quickly if you have some sort of collision detection already working. Keep in mind if there is no spot that it can fit in, then it'll loop forever so you may want to set a max try count or something of that sort.
How fast/well it'll actually work will depend on if the spawn area is pretty sparse or pretty dense, which will increase/decrease the percentage that it'll find a good empty spot the first few times.
There is some room for improvement, going down this path though, such as if your collision detection system gives a minimum translation vector, you could just move the new shape over and use that position to spawn.
Other simple methods could involve keeping track of known occupied positions and adjusting your random range to avoid those values.
I have a car object, and I want it to gradually rotate to the direction where the user clicked.
Every frame I did math to calculate the new direction it needs, and it's stored at car.direction. The actual direction is of course in car.rotation.
Now I want to update the rotation every frame until it's equal to the direction. However I tried everything and can't figure out how to do that.
By the way, I'm using FireFly, that is a gameengine built on top of Starling Framework, But I don't think it's relevant.
I would go with Marty's suggestion, use the smallestAngle function to determine which direction you should be rotating. Basically you can move some percentage of the smallestAngle during every frame update until the percentage of that smallestAngle is below some threshold (and have it "snap" the rest of the way).
Something like
//each time this is called it will get 1/4 closer, but never get to 0, hence the need for a threshold avoid paradoxes
//http://en.wikipedia.org/wiki/Zeno's_paradoxes#Dichotomy_paradox
var angleToMove:Number = smallestAngle()/4; //the divide by 4 here means get 1/4 of the angle gap closer each time this function is called, I assume this is on a timer or frame handler, making the 4 greater will make it follow more slowly, making it lower will make it follow more quickly, never reduce to or below 0 unless you want wonkiness
if(angleToMove<someRadianThreshold)
angleToMove = smallestAngle();
//use angleToMove to adjust the current heading/rotation
I need to do an endless horizontal scroll of elements within a parent MovieClip.
No matter what ever method I try, an element of 'drift' occurs and eventually the elements start to overlap.
I've tried using relative recursive tweening for each element according
but this method seems prone to quite a bit of error after repeated starts and stops.
//CODE START
function doScroll():void {
TweenLite.to(this, .25, {x:"20", ease:Linear.easeNone,onUpdate:checkPos,onComplete:doScroll});
}
//CODE END
I've reverted to doing absolute tweens to a predefined position using a contant speed. This seems to be more accurate but still some 'drift' occurs.
//CODE START
//_dest is predefined
var speed:Number = 500;
var dist:Number = this.x - _dest;
var distAbs:Number = dist < 0 ? -dist : dist;
//kludge to get constant velocity by recalculating time every frame
_time = distAbs / speed;
TweenLite.to(this, _time, {x:_dest, ease:Linear.easeNone,onComplete:reset});
//CODE END
Thought this should be very simple.
Can anyone point me to any possible tutorials or make any suggestions?
Any help appreciated.
Solution/Discussion at http://forums.greensock.com/viewtopic.php?f=1&t=6800
(warning: this is gonna require a rather lengthy explanation...)
It's a logic problem in your code. In your onUpdate, you were running conditional logic such that if the x position is beyond 980, it kills the tween and moves x back to -980 and starts things over. You're doing that for each individual item, each of which begins at a different position. That initial position affects when it crosses that threshold, thus when they reposition, the offsets are different.
For example, let's say item1 starts at an x position of 0 and item2 starts at 490 and both start moving at 400 pixels per second and your frame rate is 60, thus they'll move 6.66666 pixels per frame. Item1 will take 147 frames to hit 980. However, item2 will take 74 frames (actually 73.5, but there's no such thing as a half-frame) to cross the 980 threshold, but when it does so it will be at an x position of 983.333333. At that point it jumps back to -980 due to your conditional logic, but notice that it traveled an EXTRA 3.333333 pixels. You intended Item1 and item2 to travel at the exact same velocities and they do during the tween, but your onUpdate logic is misaligning them on the reposition such that in the end, some are traveling more than others which affects their overall velocity.
Another issue has to do with the fact that Flash rounds x/y coordinates of DisplayObjects to the nearest 0.05. So when you do your manual reposition (wrap), small rounding errors creep in. For example, let's say TweenLite sets the exact x value to 980.799. Flash will actually round that to 980.75. Then when you reposition it like this.x -= 980 and then tween it, the value would have just lost almost 0.05 pixels on that round. Do that many times and it can add up to a half-pixel or whole pixel (or more). All your items are crossing the threshold at slightly different spots, thus the rounding errors aren't the same, thus you start seeing slight variances in the spacing. Again, this is NOT an issue with the tweening engine. You'll see that the engine itself sets the values correctly, but Flash rounds them internally when applied to DisplayObjects.
A solution was posted at http://forums.greensock.com/viewtopic.php?f=1&t=6800 that includes an FLA and support files.
As others have suggested, I'd recommend having a single chunk of code that manages ALL the items that you're aligning/scrolling. It would lay things out from a single reference point so that everything lines up perfectly every time. You could tween a getter/setter that applies the logic. I use that technique all the time and it works great. You can see a smaller-scale example in the code I attached in the above URL (the scrollX getter/setter in ItemBase.as)
If you will be tweening all background elements at the same rate indefinitely on a single dimension - why not use a Timer and bypass tweening libraries entirely?
i'm trying to implement kinetic scrolling of a list object, but i'm having a problem determining the amount of friction (duration) to apply based on the velocity.
my applyFriction() method evenly reduces the velocity of the scrolling object based on a duration property. however, using the same duration (IE: 1 second) for every motion doesn't appear natural.
for motions with a small amount of velocity (IE: 5 - 10 pixels) a 1 second duration appears fine, but applying friction over a 1 second duration for motions with lots of velocity (IE: 100+ pixels) the scrolling object will appear to slow and stop much faster.
essentially, i'm trying to determine the appropriate duration for each motion so that both small and large amounts of velocity will share a matching friction, so the moving object will appear to always have a constant "weight".
is there a general algorithm for determining the duration of kinetic movement based on different velocities?
note: i'm programming in ActionScript 3.0 and employing the Tween class to reduce the velocity of a moving object over a duration.
A better model for friction is that the frictional force is proportional to velocity. You'll need a constant to determine the relationship between force and acceleration (mass, more or less). Writing the relationships as a difference equation,
F[n] = -gamma * v[n-1]
a[n] = F[n]/m
v[n] = v[n-1] + dt * a[n]
= v[n-1] + dt * F[n] / m
= v[n-1] - dt * gamma * v[n-1] / m
= v[n-1] * (1 - dt*gamma/m)
So, if you want your deceleration to look smooth and natural, instead of linearly decreasing your velocity you want to pick some constant slightly less than 1 and repeatedly multiply the velocity by this constant. Of course, this only asymptotically approaches zero, so you probably want to have a threshold below which you just set velocity to zero.
So, for example:
v_epsilon = <some minimum velocity>;
k_frict = 0.9; // play around with this a bit
while (v > v_epsilon) {
v = v * k_frict;
usleep(1000);
}
v = 0;
I think you'll find this looks much more natural.
If you want to approximate this with a linear speed reduction, then you'll want to make the amount of time you spend slowing down proportional to the natural log of the initial velocity. This won't look quite right, but it'll look somewhat better than what you've got now.
(Why natural log? Because frictional force proportional to velocity sets up a first-order differential equation, which gives an exp(-t/tau) kind of response, where tau is a characteristic of the system. The time to decay from an arbitrary velocity to a given limit is proportional to ln(v_init) in a system like this.)
i had looked into this problem before: why does Android momentum scrolling not feel as nice as the iPhone?
Fortunately, a guy already got out a video camera, recorded an iPhone scrolling, and figured out what it does: archive
flick list with its momentum scrolling and deceleration
When I started to work [on this], I did not pay attention carefully to the way the scrolling works on iPhone. I was just assuming that the deceleration is based on Newton’s law of motion, i.e. a moving body receiving a friction which is forced to stop after a while. After a while, I realized that this is actually not how iPhone (and later iOS devices such as iPad) does it. Using a camera and capturing few dozens scrolling movement of various iOS applications, it came to me that all the scrolling will stop after the same amount of time, regardless the size of the list or the speed of the flick. How fast you flick (which determines the initial velocity of the scrolling) only determines where the list would stop and not when.
This lead him to the greatly simplified math:
amplitude = initialVelocity * scaleFactor;
step = 0;
ticker = setInterval(function() {
var delta = amplitude / timeConstant;
position += delta;
amplitude -= delta;
step += 1;
if (step > 6 * timeConstant) {
clearInterval(ticker);
}
}, updateInterval);
In fact, this is how the deceleration is implemented in Apple’s own PastryKit library (and now part of iAd). It reduces the scrolling speed by a factor of 0.95 for each animation tick (16.7 msec, targeting 60 fps). This corresponds to a time constant of 325 msec. If you are a math geek, then obviously you realize that the exponential nature of the scroll velocity will yield the exponential decay in the position. With a little bit of scriblling, eventually you find out that
325 = -16.7ms / ln(0.95)
Giving the motion:
Your question was about the duration to use. i like how the iPhone feels (as opposed to Android). i think you should use 1,950 ms:
- (1000 ms / 60) / ln(0.95) * 6 = 1950 ms
I've written a fairly simple java application that allows you to drag your mouse and based on the length of the mouse drag you did, it will shoot a ball in that direction, bouncing off walls as it goes.
Here is a quick screenshot:
alt text http://img222.imageshack.us/img222/3179/ballbouncemf9.png
Each one of the circles on the screen is a Ball object. The balls movement is broken down into an x and y vector;
public class Ball {
public int xPos;
public int yPos;
public int xVector;
public int yVector;
public Ball(int xPos, int yPos, int xVector, int yVector) {
this.xPos = xPos;
this.yPos = yPos;
this.xVector = xVector;
this.yVector = yVector;
}
public void step()
{
posX += xVector;
posY += yVector;
checkCollisions();
}
public void checkCollisions()
{
// Check if we have collided with a wall
// If we have, take the negative of the appropriate vector
// Depending on which wall you hit
}
public void draw()
{
// draw our circle at it's position
}
}
This works great. All the balls bounce around and around from wall to wall.
However, I have decided that I want to be able to include the effects of gravity. I know that objects accelerate toward the earth at 9.8m/s but I don't directly know how this should translate into code. I realize that the yVector will be affected but my experimentation with this didn't have the desired effect I wanted.
Ideally, I would like to be able to add some gravity effect to this program and also allow the balls to bounce a few times before settling to the "ground."
How can I create this bouncing-elastic, gravity effect? How must I manipulate the speed vectors of the ball on each step? What must be done when it hits the "ground" so that I can allow it to bounce up again, but somewhat shorter then the previous time?
Any help is appreciated in pointing me in the right direction.
Thanks you for the comments everyone! It already is working great!
In my step() I am adding a gravity constant to my yVector like people suggested and this is my checkCollision():
public void checkCollision()
{
if (posX - radius < 0) // Left Wall?
{
posX = radius; // Place ball against edge
xVector = -(xVector * friction);
}
else if (posX + radius > rightBound) // Right Wall?
{
posX = rightBound - radius; // Place ball against edge
xVector = -(xVector * friction);
}
// Same for posY and yVector here.
}
However, the balls will continue to slide around/roll on the floor. I assume this is because I am simply taking a percentage (90%) of their vectors each bounce and it is never truly zero. Should I add in a check that if the xVector becomes a certain absolute value I should just change it to zero?
What you have to do is constantly subtract a small constant (something that represents your 9.8 m/s) from your yVector. When the ball is going down (yVector is already negative), this would make it go faster. When it's going up (yVector is positive) it would slow it down.
This would not account for friction, so the things should bounce pretty much for ever.
edit1:
To account for friction, whenever it reverses (and you reverse the sign), lower the absolute number a little. Like if it hits at yVector=-500, when you reverse the sign, make it +480 instead of +500. You should probably do the same thing to xVector to stop it from bouncing side-to-side.
edit2:
Also, if you want it to react to "air friction", reduce both vectors by a very small amount every adjustment.
edit3:
About the thing rolling around on the bottom forever--Depending on how high your numbers are, it could be one of two things. Either your numbers are large and it just seems to take forever to finish, or you are rounding and your Vectors are always 5 or something. (90% of 5 is 4.5, so it may round up to 5).
I'd print out a debug statement and see what the Vector numbers are like. If they go to somewhere around 5 and just stay there, then you can use a function that truncates your fraction to 4 instead of rounding back to 5. If it keeps on going down and eventually stops, then you might have to raise your friction coefficient.
If you can't find an easy "rounding" function, you could use (0.9 * Vector) - 1, subtracting 1 from your existing equation should do the same thing.
When the balls are all rolling around on the ground, yes, check to see if the velocity is below a certain minimum value and, if so, set it to zero. If you look at the physics behind this type of idealized motion and compare with what happens in the real world, you'll see that a single equation cannot be used to account for the fact that a real ball stops moving.
BTW, what you're doing is called the Euler method for numerical integration. It goes like this:
Start with the kinematic equations of motion:
x(t) = x0 + vx*t + 0.5*axt^2
y(t) = y0 + vyt + 0.5*ayt^2
vx(t) = vx0 + axt
vy(t) = vy0 + ay*t
Where x and y are position, vx and vy are velocity, ax and ay are acceleration, and t is time. x0, y0, vx0, and vy0 are the initial values.
This describes the motion of an object in the absence of any outside force.
Now apply gravity: ay = -9.8 m/s^2
To this point, there's no need to do anything tricky. We can solve for the position of each ball using this equation for any time.
Now add air friction: Since it's a spherical ball, we can assume it has a coefficient of friction c. There are typically two choices for how to model the air friction. It can be proportional to the velocity or to the square of velocity. Let's use the square:
ax = -cvx^2
ay = -cvy^2 - 9.8
Because the acceleration is now dependent on the velocity, which is not constant, we must integrate. This is bad, because there's no way to solve this by hand. We'll have to integrate numerically.
We take discrete time steps, dt. For Euler's method, we simply replace all occurances of t in the above equations with dt, and use the value from the previous timestep in place of the initial values, x0, y0, etc. So now our equations look like this (in pseudocode):
// Save previous values
xold = x;
yold = y;
vxold = vx;
vyold = vy;
// Update acceleration
ax = -cvxold^2;
ay = -cvyold^2 - 9.8;
// Update velocity
vx = vxold + axdt;
vy = vyold + aydt;
// Update position
x = xold + vxold*dt + 0.5*axdt^2;
y = yold + vyolddt + 0.5*ay*dt^2;
This is an approximation, so it won't be exactly correct, but it'll look OK. The problem is that for bigger timesteps, the error increases, so if we want to accurately model how a real ball would move, we'd have to use very tiny values for dt, which would cause problems with accuracy on a computer. To solve that, there are more complicated techniques. But if you just want to see behavior that looks like gravity and friction at the same time, then Euler's method is ok.
Every time slice you have to apply the effects of gravity by accelerating the ball in teh y downwards direction. As Bill K suggested, that's as simple as making a subtraction from your "yVector". When the ball hits the bottom, yVector = -yVector, so now it's moving upwards but still accelarating downwards. If you want to make the balls eventually stop bouncing, you need to make the collisions slightly inelastic, basically by removing some speed in the y-up direction, possibly by instead of "yVector = -yVector", make it "yVector = -0.9 * yVector".
public void step()
{
posX += xVector;
posY += yVector;
yVector += g //some constant representing 9.8
checkCollisions();
}
in checkCollisions(), you should invert and multiply yVector by a number between 0 and 1 when it bounces on the ground. This should give you the desired effect
It's a ballistic movement. So you got a linear movement on x-axis and an uniform accelerated movement on y-axis.
The basic idea is that the y-axis will follow the equation:
y = y0 + v0 * t + (0.5)*a*t^2
Or, in C code, for example:
float speed = 10.0f, acceleration = -9.8f, y = [whatever position];
y += speed*t + 0.5f*acceleration*t^2;
Where here I use tiem parametrization. But you could use Torricelli:
v = sqrt(v0^2 + 2*acceleration*(y-y0));
And, on this model, you must maintain the last values of v and y.
Finally, I've done something similar using the first model with dt (time's differential) being fixed at 1/60 second (60 FPS).
Well, both models give good real-like results, but sqrt(), for example, is expensive.
You really want to simulate what gravity does - all it does is create force that acts over time to change the velocity of an object. Every time you take a step, you change the velocity of your ball a little bit in order to "pull" it towards the bottom of the widget.
In order to deal with the no-friction / bouncing ball settles issue, you need to make the "ground" collision exert a different effect than just strict reflection - it should remove some amount of energy from the ball, making it bounce back at a smaller velocity after it hits the ground than it would otherwise.
Another thing that you generally want to do in these types of bouncy visualizations is give the ground some sideways friction as well, so that when it's hitting the ground all the time, it will eventually roll to a stop.
I agree with what "Bill K" said, and would add that if you want them to "settle" you will need to reduce the x and y vectors over time (apply resistance). This will have to be a very small amount at a time, so you may have to change your vectors from int to a floating point type, or only reduce them by 1 every few seconds.
What you want to do is change the values of xVector and yVector to simulate gravity and friction. This is really pretty simple to do. (Need to change all of your variables to floats. When it comes time to draw, just round the floats.)
In your step function, after updating the ball's position, you should do something like this:
yVector *= 0.95;
xVector *= 0.95;
yVector -= 2.0;
This scales the X and Y speed down slightly, allowing your balls to eventually stop moving, and then applies a constant downward "acceleration" to the Y value, which will accumulate faster than the "slowdown" and cause the balls to fall.
This is an approximation of what you really want to do. What you really want is to keep a vector representing the acceleration of your balls. Every step you would then dot product that vector with a constant gravity vector to slightly change the ball's acceleration. But I think that my be more complex than you want to get, unless you're looking for a more realistic physics simulation.
What must be done when it hits the
"ground" so that I can allow it to
bounce up again
If you assume a perfect collision (ie all the energy is conserved) all you have to do reverse the sign of one of the velocity scalar depending on which wall was hit.
For example if the ball hits the right or left walls revese the x scalar component and leave the the y scalar component the same:
this.xVector = -this.xVector;
If the ball hits the top or bottom walls reverse the y scalar component and leave the x scalar component the same:
this.yVector = -this.yVector;
but somewhat shorter then the previous
time?
In this scenario some of the energy will be lost in the collision with the wall so just add in a loss factor to take of some of the velocity each time the wall is hit:
double loss_factor = 0.99;
this.xVector = -(loss_factor * this.xVector);
this.yVector = -(loss_factor * this.yVector;