Related
I'm working on a drawing app and the line quality seems to be very low and jagged compared to other drawing apps.
Or it might be that other apps are doing something different than I'm doing.
What I have done so far is use the graphics property to draw the lines. I also collect the mouse positions on the mouse move events for assigning to a path later on. Summarized it:
MouseDownHandler:
mouseDownPoint.x = event.stageX;
mouseDownPoint.y = event.stageY;
drawCommands.push(GraphicsPathCommand.MOVE_TO);
simplePath = "M " + mouseDownPoint.x + " " + mouseDownPoint.y;
MouseMoveHandler:
line.graphics.lineStyle(lineWeight, lineColor, lineAlpha, pixelHinting);
line.graphics.moveTo(previousPoint.x, previousPoint.y);
scaledPoint = new Point(localPoint.x/scaleX, localPoint.y/scaleY);
line.graphics.lineTo(scaledPoint.x, scaledPoint.y);
previousPoint.x = scaledPoint.x;
previousPoint.y = scaledPoint.y;
simplePath += " L " + scaledPoint.x + " " + scaledPoint.y;
MouseUpHandler:
myPath.data = simplePath;
As I draw I update the line (which is a UIComponent but could just as well be a Shape or Sprite - anything with a graphics property). At the same time I keep track of the mouse locations in the simplePath string.
When the mouse is up I clear the line graphics and show a path graphic element. The Path isn't important to this but I noticed it looks slightly cleaner than the line that had been drawn. That might be because it has pixel hinting (it's not much cleaner). Sometimes there are artifacts. And I'm including it in case I need to use a path for some reason.
Here is the screen shot:
The pixel hinted version looks crisper but it still is far below the quality of the line drawing in other apps and in some cases it makes it look more jagged. Is there something I'm missing?
Note: I included graphics2d and canvas2d because I believe this may not be related to the specific language or platform but might be related to drawing graphics in general.
The green line is produced by Graphics.cubicCurveTo(...) method. Initially you have a list of user-provided points A1,A2,A3...An. In order to use cubic curves you also need to figure 2 control points CFk (forward) and CBk (backward), for each Ak respectively, so you draw that big curve starting from A1 and every curve piece from Ak-1 to Ak will take arguments .cubicCurveTo(CFk-1, CBk, Ak);
For each Ak (except for A1 and An) you can calculate CFk and CBk as following:
(vector)AForward = (vector)(Ak+1 - Ak-1)
(vector)AForward.length = (vector)(Ak+1 - Ak).length / 3
CFk = Ak + (point)AForward
(vector)ABackward = (vector)(Ak-1 - Ak+1)
(vector)ABackward.length = (vector)(Ak-1 - Ak).length / 3
CBk = Ak + (point)ABackward
Then, there are A1 and An that are left out, but I am sure you can figure them on your own.
For vector math you can use ru.delimiter.math.Vector2D class (works with both Cartesian and Polar coordinates) from my small collection of useful things: https://bitbucket.org/thydmitry/ru.delimiter/src/9083fb46ce1c/classes/ru/delimiter/math/
P.S. Maybe you don't need to go that extreme and will be fine with the red line, that is a simple .curveTo(Ak, (Ak + Ak+1)/2);
UPD: a simple algorithm to inscribe a curve into zigzag provided by an array of points.
function middle(A:Point, B:Point):Point
{
return new Point((A.x + B.x) / 2, (A.y + B.y) / 2);
}
function drawTo(target:Point):void
{
graphics.lineTo(target.x, target.y);
}
function bendTo(control:Point, target:Point):void
{
graphics.curveTo(control.x, control.y, target.x, target.y);
}
// This should contain at least 2 points before you start drawing.
var PP:Vector.<Point>;
// Go to the start position.
graphics.lineStyle(0, 0xFF0000);
graphics.moveTo(PP[0].x, PP[0].y);
// Draw a straight line to the center of the first zigzag segment.
drawTo(middle(PP[0], PP[1]));
// For each 3 consequent points A,B and C, connect
// the middle of AB and the middle of BC with a curve.
for (var i:int = 2; i < PP.length; i++)
{
bendTo(PP[i - 1], middle(PP[i - 1], PP[i]));
}
// Connect the center of the last zigzag segment with the end point.
drawTo(PP[PP.length - 1]);
There are multiple reasons:
Stage quality. In Flash Player you can set the stage quality to LOW, MEDIUM, HIGH, BEST, 8x8, 8x8Linear, 16x16 and 16x16Linear. This affects if there is antialiasing applied on lines / paths and how many times it's applied. Increasing the quality helps but in 8x8 and higher quality there are bugs in the Flash Player (font size reduced by 25% on non-embedded fonts, graphics artifacts, gradient fills color count reduced).
Pixel snapping. If you have a 1px line that ends up positioned on a half pixel it is anti aliased over two lines. Normally antialiasing increases quality but in the case of an offset single pixel line it reduces quality. Setting pixel snapping helps.
Using curveTo and cubicCurveTo instead of line points as #Organis suggested. Not sure how to do this yet.
Will try to post images of the difference in each case when I get a chance.
So the issue that I'm having is that in developing an HTML5 canvas app I need to use a lot of transformations (i.e. translate, rotate, scale) and therefore a lot of calls being made to context.save() and context.restore(). The performance drops very quickly even with drawing very little (because the save() and restore() are being called as many times as possible in the loop). Is there an alternative to using these methods but still be able to use the transformations? Thank you!
Animation and Game performance tips.
Avoid save restore
Use setTransform as that will negate the need for save and restore.
There are many reasons that save an restore will slow things down and these are dependent on the current GPU && 2D context state. If you have the current fill and/or stroke styles set to a large pattern, or you have a complex font / gradient, or you are using filters (if available) then the save and restore process can take longer than rendering the image.
When writing for animations and games performance is everything, for me it is about sprite counts. The more sprites I can draw per frame (60th second) the more FX I can add, the more detailed the environment, and the better the game.
I leave the state open ended, that is I do not keep a detailed track of the current 2D context state. This way I never have to use save and restore.
ctx.setTransform rather than ctx.transform
Because the transforms functions transform, rotate, scale, translate multiply the current transform, they are seldom used, as i do not know what the transform state is.
To deal with the unknown I use setTransform that completely replaces the current transformation matrix. This also allows me to set the scale and translation in one call without needing to know what the current state is.
ctx.setTransform(scaleX,0,0,scaleY,posX,posY); // scale and translate in one call
I could also add the rotation but the javascript code to find the x,y axis vectors (the first 4 numbers in setTransform) is slower than rotate.
Sprites and rendering them
Below is an expanded sprite function. It draws a sprite from a sprite sheet, the sprite has x & y scale, position, and center, and as I always use alpha so set alpha as well
// image is the image. Must have an array of sprites
// image.sprites = [{x:0,y:0,w:10,h:10},{x:20,y:0,w:30,h:40},....]
// where the position and size of each sprite is kept
// spriteInd is the index of the sprite
// x,y position on sprite center
// cx,cy location of sprite center (I also have that in the sprite list for some situations)
// sx,sy x and y scales
// r rotation in radians
// a alpha value
function drawSprite(image, spriteInd, x, y, cx, cy, sx, sy, r, a){
var spr = image.sprites[spriteInd];
var w = spr.w;
var h = spr.h;
ctx.setTransform(sx,0,0,sy,x,y); // set scale and position
ctx.rotate(r);
ctx.globalAlpha = a;
ctx.drawImage(image,spr.x,spr.y,w,h,-cx,-cy,w,h); // render the subimage
}
On just an average machine you can render 1000 +sprites at full frame rate with that function. On Firefox (at time of writing) I am getting 2000+ for that function (sprites are randomly selected sprites from a 1024 by 2048 sprite sheet) max sprite size 256 * 256
But I have well over 15 such functions, each with the minimum functionality to do what I want. If it is never rotated, or scaled (ie for UI) then
function drawSprite(image, spriteInd, x, y, a){
var spr = image.sprites[spriteInd];
var w = spr.w;
var h = spr.h;
ctx.setTransform(1,0,0,1,x,y); // set scale and position
ctx.globalAlpha = a;
ctx.drawImage(image,spr.x,spr.y,w,h,0,0,w,h); // render the subimage
}
Or the simplest play sprite, particle, bullets, etc
function drawSprite(image, spriteInd, x, y,s,r,a){
var spr = image.sprites[spriteInd];
var w = spr.w;
var h = spr.h;
ctx.setTransform(s,0,0,s,x,y); // set scale and position
ctx.rotate(r);
ctx.globalAlpha = a;
ctx.drawImage(image,spr.x,spr.y,w,h,-w/2,-h/2,w,h); // render the subimage
}
if it is a background image
function drawSprite(image){
var s = Math.max(image.width / canvasWidth, image.height / canvasHeight); // canvasWidth and height are globals
ctx.setTransform(s,0,0,s,0,0); // set scale and position
ctx.globalAlpha = 1;
ctx.drawImage(image,0,0); // render the subimage
}
It is common that the playfield can be zoomed, panned, and rotated. For this I maintain a closure transform state (all globals above are closed over variables and part of the render object)
// all coords are relative to the global transfrom
function drawGlobalSprite(image, spriteInd, x, y, cx, cy, sx, sy, r, a){
var spr = image.sprites[spriteInd];
var w = spr.w;
var h = spr.h;
// m1 to m6 are the global transform
ctx.setTransform(m1,m2,m3,m4,m5,m6); // set playfield
ctx.transform(sx,0,0,sy,x,y); // set scale and position
ctx.rotate(r);
ctx.globalAlpha = a * globalAlpha; (a real global alpha)
ctx.drawImage(image,spr.x,spr.y,w,h,-cx,-cy,w,h); // render the subimage
}
All the above are about as fast as you can get for practical game sprite rendering.
General tips
Never use any of the vector type rendering methods (unless you have the spare frame time) like, fill, stroke, filltext, arc, rect, moveTo, lineTo as they are an instant slowdown. If you need to render text create a offscreen canvas, render once to that, and display as a sprite or image.
Image sizes and GPU RAM
When creating content, always use the power rule for image sizes. GPU handle images in sizes that are powers of 2. (2,4,8,16,32,64,128....) so the width and height have to be a power of two. ie 1024 by 512, or 2048 by 128 are good sizes.
When you do not use these sizes the 2D context does not care, what it does is expand the image to fit the closest power. So if I have an image that is 300 by 300 to fit that on the GPU the image has to be expanded to the closest power, which is 512 by 512. So the actual memory footprint is over 2.5 times greater than the pixels you are able to display. When the GPU runs out of local memory it will start switching memory from mainboard RAM, when this happens your frame rate drops to unusable.
Ensuring that you size images so that you do not waste RAM will mean you can pack a lot more into you game before you hit the RAM wall (which for smaller devices is not much at all).
GC is a major frame theef
One last optimisation is to make sure that the GC (garbage collector) has little to nothing to do. With in the main loop, avoid using new (reuse and object rather than dereference it and create another), avoid pushing and popping from arrays (keep their lengths from falling) keep a separate count of active items. Create a custom iterator and push functions that are item context aware (know if an array item is active or not). When you push you don't push a new item unless there are no inactive items, when an item becomes inactive, leave it in the array and use it later if one is needed.
There is a simple strategy that I call a fast stack that is beyond the scope of this answer but can handle 1000s of transient (short lived) gameobjects with ZERO GC load. Some of the better game engines use a similar approch (pool arrays that provide a pool of inactive items).
GC should be less than 5% of your game activity, if not you need to find where you are needlessly creating and dereferencing.
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
This is a very general question that's not related to a specific language. I'm having this array of int's:
int[100][100] map;
This contains just tile numbers, and is rendered as 256x256 tiles. So it's basically just a tile map or whatever it should be called. Thing is I want to be able to write anything to the map, anywhere, and it should stay there. For example be able to paint on stuff on the ground such as grass, flowers, stones and other stuff making the terrain more varied without having to render each of these sprites a huge number of times every time it renders. But making each tile contain it's own texture to write to would be terribly memory consuming at that would be 256x256x100x100 = 655360000 pixels to store. Would'nt that be like gigabytes of data or something!?
Does anyone know of a good general sulotion to make what I'm trying to do without killing too much memory?
If someone wonders I'm using C++ with HGE (Haaf's Game Engine).
EDIT: I've choosen to limit the amount of stuff on screen so that it can render. But look here so maybe you'll understand what I try to achieve:
Link to image because I'm not allowed to use image tags :(
If it's just tile based then you only store one instance of each unique tile and each unique "overlay" (flower, rock, etc.). You reference it by id or memory location as you have been doing.
You'd simply store a location (tile number and location on tile) and a reference to an overlay to "paint" it without consuming a lot of memory.
Also, I'm sure you know this but you only render what's on screen. So memory usage is pretty much constant once everything is loaded up.
I'm not exactly sure what you are trying to do, but you should probably have the tiles in separate layers. So say that for each "tile" you have a list of textures ordered bottom-up that you blend together, that way you only store the tile indexes.
Instead of storing just the tile number, store the overlay number and offset position also.
struct map_zone {
int tile; // tile number
int overlay; // overlay number (flower, rock, etc). In most cases will be zero
int overlay_offset_x; // draw overlay at X pixels across from left
int overlay_offset_y; // draw overlay at Y pixels down from top
}
map_zone[100][100] map;
And for rendering:
int x, y;
for(y = 0; y < 100; ++y) {
for(x = 0; x < 100; ++x) {
render_tile(map[y][x].tile)
render_overlay(map[y][x].overlay, map[y][x].overlay_offset_x, map[y][x].overlay_offset_y);
}
}
It's arguably faster to store the overlays and offsets in separate arrays from the tiles, but having each area on the map self-contained like this is easier to understand.
you have to use alpha maps..
you are going to paint a texture 256x256 which maps your whole terrain. for each channel r,g,b,a you will tile your terrain with your another texture..
r = sand.jpg
g = grass.jpg
b = water.jpg
a = soil.jpg
in shader, you will check the color of alpha map and paint with these textures..
i am doing such a thing now and i did like that
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;