001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package example.audiodemo;
033:
034: import javax.microedition.lcdui.*;
035: import javax.microedition.media.control.*;
036:
037: /**
038: * A SmallBall is a lightweight animated ball that runs in its own thread.
039: * It moves within a rectangular region, bouncing off the walls.
040: */
041: class SmallBall implements Runnable {
042: // random number generator
043: static java.util.Random random = new java.util.Random();
044:
045: // Global flag to temporarily pause all balls
046: public static boolean paused = false;
047: private static final int DEFAULT_DELAY = 80;
048: private static final int MIN_DELAY = 40;
049: private static final int MAX_DELAY = 320;
050: private static final int DELAY_INCREMENT = 40;
051: private static final int POS_MULTIPLIER = 3;
052:
053: // controls the speed of all balls; delay in milliseconds
054: static int delay = DEFAULT_DELAY;
055:
056: // the matrix to transform the direction based on the
057: // current direction and which wall was hit
058: static int[][] matrix = { { 1, -1, -1, 1, 1, 1 },
059: { -1, -1, 1, 1, -1, 1 }, null, { 1, 1, -1, -1, 1, -1 },
060: { -1, 1, 1, -1, -1, -1 } };
061:
062: // the region in which the ball moves
063: int top, left, width, height;
064:
065: // the position and radius of the ball
066: int posX, posY;
067: int radius = 5;
068: int ballSize = radius * 2;
069:
070: // the direction of the ball is controlled by these two variables
071: int deltaX, deltaY;
072:
073: // a handle onto the singleton Graphics object
074: Graphics g;
075: Canvas canvas;
076: int note = ToneControl.C4;
077: int clr = 0;
078:
079: // public variables to control the behaviour of the thread
080: public boolean stop; // = false
081:
082: // if true, this thread will call repaint()
083: public boolean doRepaint; // = false;
084:
085: /**
086: * Constructor defines the region in which the ball moves as well
087: * as its starting position.
088: */
089: SmallBall(Canvas c, int left, int top, int width, int height) {
090: super ();
091: canvas = c;
092:
093: this .left = left + 1;
094: this .top = top + 1;
095: this .width = width - ((2 * radius) + 2);
096: this .height = height - ((2 * radius) + 2);
097:
098: // use positive random #s
099: this .posX = ((random.nextInt() >>> 1) % (this .width - 20)) + 10;
100: this .posY = ((random.nextInt() >>> 1) % (this .height - 20)) + 10;
101:
102: deltaX = random.nextInt() & 1;
103: deltaY = random.nextInt() & 1;
104:
105: if (deltaX == 0) {
106: deltaX = -1;
107: }
108:
109: if (deltaY == 0) {
110: deltaY = -1;
111: }
112:
113: stop = true;
114: }
115:
116: static void slower() {
117: delay += DELAY_INCREMENT;
118:
119: if (delay > MAX_DELAY) {
120: delay = MAX_DELAY;
121: }
122: }
123:
124: static void faster() {
125: delay -= DELAY_INCREMENT;
126:
127: if (delay < MIN_DELAY) {
128: delay = MIN_DELAY;
129: }
130: }
131:
132: /**
133: * Returns the speed in percent of
134: * the DEFAULT_DELAY
135: */
136: static int getSpeedPercent() {
137: int ret = 100; // start with 100%
138: int this Delay = delay;
139:
140: while (this Delay > DEFAULT_DELAY) {
141: this Delay /= 2;
142: ret -= 10;
143: }
144:
145: while (this Delay < DEFAULT_DELAY) {
146: this Delay *= 2;
147: ret += 10;
148: }
149:
150: return ret;
151: }
152:
153: public void setNote(int note) {
154: this .note = note;
155: }
156:
157: /**
158: * Starts the ball running.
159: */
160: public void run() {
161: int right = left + width;
162: int bottom = top + height;
163:
164: while (!stop) {
165: ballSize = radius * 2;
166:
167: // calculate a direction of the ball as an integer in the range
168: // -2 .. 2 (excluding 0)
169: int direction = deltaX + deltaY;
170:
171: if (direction == 0) {
172: direction = deltaX + (2 * deltaY);
173: }
174:
175: // is the current position colliding with any wall
176: int collision = 0;
177:
178: if ((posX <= left) || (posX >= right)) {
179: collision++;
180: }
181:
182: if ((posY <= top) || (posY >= bottom)) {
183: collision += 2;
184: }
185:
186: // change the direction appropriately if there was a collision
187: if (collision != 0) {
188: try {
189: javax.microedition.media.Manager.playTone(note,
190: 100 /*ms*/, 100);
191: } catch (Exception ex) {
192: System.out.println("failed to play tone");
193: }
194:
195: collision = (collision - 1) * 2;
196:
197: deltaX = matrix[direction + 2][collision];
198: deltaY = matrix[direction + 2][collision + 1];
199: }
200:
201: // calculate the new position and queue a repaint
202: posX += POS_MULTIPLIER * deltaX;
203: posY += POS_MULTIPLIER * deltaY;
204:
205: if (doRepaint) {
206: canvas.repaint();
207: }
208:
209: // use the delay to control the speed of the ball
210: // if the MIDlet is paused, keep on waiting
211: do {
212: try {
213: // if paused, always wait 100 millis,
214: // regardless of ball speed
215: Thread.sleep(paused ? 100 : delay);
216: } catch (InterruptedException e) {
217: }
218: } while (paused && !stop);
219: }
220: }
221:
222: /**
223: * Paint the ball.
224: */
225: void paint(Graphics g) {
226: g.setColor(clr);
227: g.fillArc(posX, posY, ballSize, ballSize, 0, 360);
228: }
229:
230: public void setColor(int clr) {
231: this .clr = clr;
232: }
233:
234: public String toString() {
235: return super .toString() + " x = " + posX + ", y = " + posY;
236: }
237: }
|