/*
* @(#)ManyCanvas.java 1.13 02/07/30 @(#)
*
* Copyright (c) 1999-2001 Sun Microsystems, Inc. All rights reserved.
* PROPRIETARY/CONFIDENTIAL
* Use is subject to license terms.
*/
package example.manyballs;
import javax.microedition.lcdui.*;
public class ManyCanvas extends javax.microedition.lcdui.Canvas {
Display display;
// a set of free roaming balls
SmallBall[] balls;
int numBalls;
int width, height;
boolean paused;
static int NUM_HISTORY = 8;
long times[] = new long[NUM_HISTORY];
int times_idx;
public ManyCanvas(Display d, int maxBalls) {
display = d; // save the display
// initialize the array of balls
balls = new SmallBall[maxBalls];
width = getWidth();
height = getHeight();
// Start with one ball
balls[0] = new SmallBall(this, 0, 0, width, height-12-20);
numBalls = 1;
paused = true;
}
/**
* Draws the drawing frame (which also contains the ball) and the
* controls.
*/
String msg = null;
protected void paint(Graphics g) {
int x = g.getClipX();
int y = g.getClipY();
int w = g.getClipWidth();
int h = g.getClipHeight();
// Draw the frame
g.setColor(0xffffff);
g.fillRect(x, y, w, h);
// Draw each ball
for (int i = 0; i < numBalls; i++) {
if (balls[i].inside(x, y, x + w, y + h)) {
balls[i].paint(g);
}
}
g.setColor(0);
g.drawRect(0, 0, width-1, height-1);
long now = System.currentTimeMillis();
String str = null;
if (times_idx >= NUM_HISTORY) {
long oldTime = times[times_idx % NUM_HISTORY];
if (oldTime == now) {
// in case of divide-by-zero
oldTime = now - 1;
}
long fps = ((long)1000 * (long)NUM_HISTORY) / (now - oldTime);
if (times_idx % 20 == 0) {
str = numBalls + " Ball(s) " + fps + " fps";
}
} else {
if (times_idx % 20 == 0) {
str = numBalls + " Ball(s)";
}
}
if (msg != null) {
g.setColor(0xffffff);
g.setClip(0, height-14, width, height);
g.fillRect(0, height-20, width-2, 18);
g.setColor(0);
g.drawString(msg, 5, height-14, 0);
g.drawRect(0, 0, width-1, height-1);
msg = null;
}
if (str != null) {
/*
* Do a complete repaint, so that the message will
* be shown even in double-buffer mode.
*/
repaint();
msg = str;
}
times[times_idx % NUM_HISTORY] = now;
++ times_idx;
}
/**
* Handle a pen down event.
*/
public void keyPressed(int keyCode) {
int action = getGameAction(keyCode);
switch (action) {
case LEFT:
// Reduce the number of threads
if (numBalls > 0) {
// decrement the counter
numBalls = numBalls - 1;
// stop the thread and remove the reference to it
balls[numBalls].stop = true;
balls[numBalls] = null;
}
break;
case RIGHT:
// Increase the number of threads
if (numBalls < balls.length) {
// create a new ball and start it moving
balls[numBalls] =
new SmallBall(this, 0, 0, width, height-12-20);
new Thread(balls[numBalls]).start();
// increment the counter
numBalls = numBalls + 1;
}
break;
case UP:
// Make them move faster
SmallBall.faster();
break;
case DOWN:
// Make them move slower
SmallBall.slower();
break;
}
repaint();
}
/**
* Destroy
*/
void destroy() {
// kill all the balls and terminate
for (int i = 0; i < balls.length && balls[i] != null; i++) {
balls[i].stop = true;
// enable the balls to be garbage collected
balls[i] = null;
}
numBalls = 0;
}
/*
* Return whether the canvas is paused or not.
*/
boolean isPaused() {
return paused;
}
/**
* Pause the balls by signaling each of them to stop.
* The ball object still exists and holds the current position
* of the ball. It may be restarted later.
* The thread will terminate.
* TBD: is a join needed?
*/
void pause() {
if (!paused) {
paused = true;
for (int i = 0; i < balls.length && balls[i] != null; i++) {
balls[i].stop = true;
}
}
repaint();
}
/*
* Start creates a new thread for each ball and start it.
*/
void start() {
if (paused) {
paused = false;
display.setCurrent(this);
for (int i = 0; i < balls.length && balls[i] != null; i++) {
Thread t = new Thread(balls[i]);
t.start();
}
}
repaint();
}
}
|