This is a Java class that uses some trigonometry and vector mathematics in its implementation.
An object of type MovingBall holds data about a “ball” that has a color, radius, position, speed, and direction. The ball is restricted to moving around inside a rectangle in the xy-plane. The ball can draw itself in a graphics context and will move when it is told to move.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | import java.awt.*; public class MovingBall { private double xmin, xmax; // The horizontal limits on the ball's position. // The x-coordinate of the ball statisfies // xmin <= x <= xmax. private double ymin, ymax; // The vertical limits on the ball's position. // The y-coordinate of the ball statisfies // ymin <= y <= ymax. private double x,y; // Current position of the ball. private double dx,dy; // The velocity (speed + direction) of the ball. // When the travel() method is called, the // ball moves dx pixesl horizontally and dy // pixels vertically. private Color color; // The color of the ball. private double radius; // The radius of the ball. public MovingBall(double left, double right, double top, double bottom) { // Create a ball that moves within the specified limits, // left <= x <= right and top <= y <= bottom. The ball is initially // located in the middle of this range. It has a random speed // between 4 and 12 and a random direction. Its radius is 5 // and its color is red. xmin = left; xmax = right; ymin = top; ymax = bottom; x = (xmin + xmax) / 2; y = (ymin + ymax) / 2; radius = 5; color = Color.red; double angle = 2 * Math.PI * Math.random(); // Random direction. double speed = 4 + 8*Math.random(); // Random speed. dx = Math.cos(angle) * speed; dy = Math.sin(angle) * speed; } public void draw(Graphics g) { // Draw the ball in the graphics context g. Note: The drawing color // in g is changed to the color of the ball. g.setColor(color); g.fillOval( (int)(x-radius), (int)(y-radius), (int)(2*radius), (int)(2*radius) ); } public void travel() { // Move the ball by one time unit. The ball moves in its current // direction for a number of pixels equal to its current speed. // That is, speed is given in terms of pixels per time unit. // Note: The ball won't move at all if the width or height // of the rectangle is smaller than the ball's diameter. travel(1.0); } public void travel(double time) { // Move the ball for the specified number of time units. // The ball is restricted to the specified rectangle. // Note: The ball won't move at all if the width or height // of the rectangle is smaller than the ball's diameter. /* Don't do anything if the rectangle is too small. */ if (xmax - xmin < 2*radius || ymax - ymin < 2*radius) return; /* First, if the ball has gotten outside its rectangle, move it back. (This will only happen if the rectagnle was changed by calling the setLimits() method or if the position of the ball was changed by calling the setLocation() method.) */ if (x-radius < xmin) x = xmin + radius; else if (x+radius > xmax) x = xmax - radius; if (y - radius < ymin) y = ymin + radius; else if (y + radius > ymax) y = ymax - radius; /* Compute the new position, possibly outside the rectangle. */ double newx = x + dx*time; double newy = y + dy*time; /* If the new position lies beyond one of the sides of the rectangle, "reflect" the new point through the side of the rectangle, so it lies within the rectangle. */ if (newy < ymin + radius) { newy = 2*(ymin+radius) - newy; dy = Math.abs(dy); } else if (newy > ymax - radius) { newy = 2*(ymax-radius) - newy; dy = -Math.abs(dy); } if (newx < xmin + radius) { newx = 2*(xmin+radius) - newx; dx = Math.abs(dx); } else if (newx > xmax - radius) { newx = 2*(xmax-radius) - newx; dx = -Math.abs(dx); } /* We have the new values for x and y. */ x = newx; y = newy; } // end travel() public void setColor(Color c) { // Set the color of the ball (if c is non-null). if (c != null) color = c; } public void setRadius(int r) { // Set the radius of the ball. Adjust the radius, if necessary, // so the diameter of the ball is at least one pixel. radius = r; if (radius < 0.5) radius = 0.5; } public void setLimits(double left, double right, double top, double bottom) { // Set the horizontal and vertical limits on the motion of the ball. xmin = left; xmax = right; ymin = top; ymax = bottom; } public void setLocation(double x, double y) { // Set the location of the ball. this.x = x; this.y = y; } public void setSpeed(double speed) { // Set the speed of the ball, if speed > 0. The speed is // restricted to being strictly positive. (If you want the // ball to stay still, don't call the travel() method!) if (speed > 0) { double currentSpeed = Math.sqrt(dx*dx + dy*dy); dx = dx * speed / currentSpeed; dy = dy * speed / currentSpeed; } } public void headTowards(int a, int b) { // Adjust the direction of motion of the ball so that it is // headed towards the point (a,b). If the ball happens to // lie exactly at the point (a,b) already, this operation is // undefined, so nothing is done. double vx = a - x; double vy = b - y; double dist = Math.sqrt(vx*vx + vy*vy); if (dist > 0) { double speed = Math.sqrt(dx*dx + dy*dy); dx = vx / dist * speed; dy = vy / dist * speed; } } public void setVelocity(double dx, double dy) { // Set the velocity of the ball. At least one of dx and // dy must be non-zero, so that the speed will be positive. if (dx != 0 || dy != 0) { this.dx = dx; this.dy = dy; } } } // end class MovingBall |