001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.demos.manyballs;
028:
029: import javax.microedition.lcdui.*;
030:
031: public class ManyCanvas extends javax.microedition.lcdui.Canvas {
032:
033: Display display;
034:
035: // a set of free roaming balls
036: SmallBall[] balls;
037: int numBalls;
038: int width, height;
039: boolean paused;
040: static int NUM_HISTORY = 8;
041: long times[] = new long[NUM_HISTORY];
042: int times_idx;
043:
044: public ManyCanvas(Display d, int maxBalls) {
045:
046: display = d; // save the display
047:
048: // initialize the array of balls
049: balls = new SmallBall[maxBalls];
050:
051: width = getWidth();
052: height = getHeight();
053:
054: // Start with one ball
055: balls[0] = new SmallBall(this , 0, 0, width, height - 12 - 20);
056: numBalls = 1;
057: paused = true;
058: }
059:
060: /**
061: * Draws the drawing frame (which also contains the ball) and the
062: * controls.
063: */
064: String msg = null;
065:
066: protected void paint(Graphics g) {
067: int x = g.getClipX();
068: int y = g.getClipY();
069: int w = g.getClipWidth();
070: int h = g.getClipHeight();
071:
072: // Draw the frame
073: g.setColor(0xffffff);
074: g.fillRect(x, y, w, h);
075:
076: // Draw each ball
077: for (int i = 0; i < numBalls; i++) {
078: if (balls[i].inside(x, y, x + w, y + h)) {
079: balls[i].paint(g);
080: }
081: }
082:
083: g.setColor(0);
084: g.drawRect(0, 0, width - 1, height - 1);
085:
086: long now = System.currentTimeMillis();
087: String str = null;
088: if (times_idx >= NUM_HISTORY) {
089: long oldTime = times[times_idx % NUM_HISTORY];
090: if (oldTime == now) {
091: // in case of divide-by-zero
092: oldTime = now - 1;
093: }
094: long fps = ((long) 1000 * (long) NUM_HISTORY)
095: / (now - oldTime);
096: if (times_idx % 20 == 0) {
097: str = numBalls + " Ball(s) " + fps + " fps";
098: }
099: } else {
100: if (times_idx % 20 == 0) {
101: str = numBalls + " Ball(s)";
102: }
103: }
104:
105: if (msg != null) {
106: g.setColor(0xffffff);
107: g.setClip(0, height - 14, width, height);
108: g.fillRect(0, height - 20, width - 2, 18);
109:
110: g.setColor(0);
111: g.drawString(msg, 5, height - 14, 0);
112: g.drawRect(0, 0, width - 1, height - 1);
113: msg = null;
114: }
115: if (str != null) {
116: /*
117: * Do a complete repaint, so that the message will
118: * be shown even in double-buffer mode.
119: */
120: repaint();
121: msg = str;
122: }
123:
124: times[times_idx % NUM_HISTORY] = now;
125: ++times_idx;
126:
127: }
128:
129: /**
130: * Handle a pen down event.
131: */
132: public void keyPressed(int keyCode) {
133:
134: int action = getGameAction(keyCode);
135:
136: switch (action) {
137: case LEFT:
138: // Reduce the number of threads
139: if (numBalls > 0) {
140:
141: // decrement the counter
142: numBalls = numBalls - 1;
143:
144: // stop the thread and remove the reference to it
145: balls[numBalls].stop = true;
146: balls[numBalls] = null;
147: }
148: break;
149:
150: case RIGHT:
151: // Increase the number of threads
152: if (numBalls < balls.length) {
153:
154: // create a new ball and start it moving
155: balls[numBalls] = new SmallBall(this , 0, 0, width,
156: height - 12 - 20);
157: new Thread(balls[numBalls]).start();
158:
159: // increment the counter
160: numBalls = numBalls + 1;
161: }
162: break;
163:
164: case UP:
165: // Make them move faster
166: SmallBall.faster();
167: break;
168:
169: case DOWN:
170: // Make them move slower
171: SmallBall.slower();
172: break;
173: }
174: repaint();
175: }
176:
177: /**
178: * Destroy
179: */
180: void destroy() {
181: // kill all the balls and terminate
182: for (int i = 0; i < balls.length && balls[i] != null; i++) {
183: balls[i].stop = true;
184:
185: // enable the balls to be garbage collected
186: balls[i] = null;
187: }
188: numBalls = 0;
189: }
190:
191: /*
192: * Return whether the canvas is paused or not.
193: */
194: boolean isPaused() {
195: return paused;
196: }
197:
198: /**
199: * Pause the balls by signaling each of them to stop.
200: * The ball object still exists and holds the current position
201: * of the ball. It may be restarted later.
202: * The thread will terminate.
203: * TBD: is a join needed?
204: */
205: void pause() {
206: if (!paused) {
207: paused = true;
208: for (int i = 0; i < balls.length && balls[i] != null; i++) {
209: balls[i].stop = true;
210: }
211: }
212: repaint();
213: }
214:
215: /*
216: * Start creates a new thread for each ball and start it.
217: */
218: void start() {
219: if (paused) {
220: paused = false;
221: display.setCurrent(this );
222: for (int i = 0; i < balls.length && balls[i] != null; i++) {
223: Thread t = new Thread(balls[i]);
224: t.start();
225: }
226: }
227: repaint();
228: }
229:
230: }
|