зеркало из https://github.com/mozilla/pluotsorbet.git
Merge pull request #53 from marco-c/add_manyballs_demo
Add manyballs demo from the J2ME reference implementation
This commit is contained in:
Коммит
c4f11a838c
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
*
|
||||
*
|
||||
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 only, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 2 for more details (a copy is
|
||||
* included at /legal/license.txt).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this work; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
|
||||
* Clara, CA 95054 or visit www.sun.com if you need additional
|
||||
* information or have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.midp.demos.manyballs;
|
||||
|
||||
import javax.microedition.midlet.*;
|
||||
import javax.microedition.lcdui.*;
|
||||
|
||||
public class ManyBalls extends MIDlet implements CommandListener {
|
||||
|
||||
Display display;
|
||||
ManyCanvas canvas; // The main screen
|
||||
private Command exitCommand = new Command("Exit", Command.EXIT, 99);
|
||||
private Command toggleCommand = new Command("Stop/Go", Command.SCREEN, 1);
|
||||
private Command helpCommand = new Command("Help", Command.HELP, 2);
|
||||
private Form helpScreen;
|
||||
private String helpText = "^ = faster\n v = slower\n < = fewer\n> = more";
|
||||
|
||||
|
||||
// the GUI buttons
|
||||
// Button exitButton, clearButton, moreButton, lessButton;
|
||||
|
||||
/*
|
||||
* Create the canvas
|
||||
*/
|
||||
public ManyBalls() {
|
||||
display = Display.getDisplay(this);
|
||||
|
||||
canvas = new ManyCanvas(display, 40);
|
||||
canvas.addCommand(exitCommand);
|
||||
canvas.addCommand(toggleCommand);
|
||||
canvas.addCommand(helpCommand);
|
||||
canvas.setCommandListener(this);
|
||||
}
|
||||
|
||||
public void startApp() throws MIDletStateChangeException {
|
||||
canvas.start();
|
||||
}
|
||||
|
||||
public void pauseApp() {
|
||||
canvas.pause();
|
||||
}
|
||||
|
||||
public void destroyApp(boolean unconditional)
|
||||
throws MIDletStateChangeException {
|
||||
canvas.destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
* Respond to a command issued on the Canvas.
|
||||
*/
|
||||
public void commandAction(Command c, Displayable s) {
|
||||
if (c == toggleCommand) {
|
||||
if (canvas.isPaused())
|
||||
canvas.start();
|
||||
else
|
||||
canvas.pause();
|
||||
} else if (c == helpCommand) {
|
||||
canvas.pause();
|
||||
showHelp();
|
||||
} else if (c == exitCommand) {
|
||||
try {
|
||||
destroyApp(false);
|
||||
notifyDestroyed();
|
||||
} catch (MIDletStateChangeException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Put up the help screen. Create it if necessary.
|
||||
* Add only the Resume command.
|
||||
*/
|
||||
void showHelp() {
|
||||
if (helpScreen == null) {
|
||||
helpScreen = new Form("Many Balls Help");
|
||||
helpScreen.append("^ = faster\n");
|
||||
helpScreen.append("v = slower\n");
|
||||
helpScreen.append("< = fewer\n");
|
||||
helpScreen.append("> = more\n");
|
||||
}
|
||||
helpScreen.addCommand(toggleCommand);
|
||||
helpScreen.setCommandListener(this);
|
||||
display.setCurrent(helpScreen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
*
|
||||
*
|
||||
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 only, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 2 for more details (a copy is
|
||||
* included at /legal/license.txt).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this work; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
|
||||
* Clara, CA 95054 or visit www.sun.com if you need additional
|
||||
* information or have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.midp.demos.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();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
*
|
||||
*
|
||||
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 only, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 2 for more details (a copy is
|
||||
* included at /legal/license.txt).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this work; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
|
||||
* Clara, CA 95054 or visit www.sun.com if you need additional
|
||||
* information or have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.midp.demos.manyballs;
|
||||
|
||||
import javax.microedition.lcdui.*;
|
||||
|
||||
/**
|
||||
* A SmallBall is a lightweight animated ball that runs in it's own thread.
|
||||
* It moves within a rectangular region, bouncing off the walls.
|
||||
*/
|
||||
class SmallBall implements Runnable {
|
||||
|
||||
// random number generator
|
||||
static java.util.Random random = new java.util.Random();
|
||||
|
||||
// controls the speed of all balls; delay in centiseconds
|
||||
static int delay = 20;
|
||||
static void slower() {
|
||||
delay += 10;
|
||||
if (delay > 100) delay = 100;
|
||||
}
|
||||
|
||||
static void faster() {
|
||||
delay -= 10;
|
||||
if (delay < 0) delay = 0;
|
||||
}
|
||||
|
||||
// the matrix to transform the direction based on the
|
||||
// current direction and which wall was hit
|
||||
static int[][] matrix = {
|
||||
{ 1, -1, -1, 1, 1, 1 },
|
||||
{ -1, -1, 1, 1, -1, 1 },
|
||||
null,
|
||||
{ 1, 1, -1, -1, 1, -1 },
|
||||
{ -1, 1, 1, -1, -1, -1 }
|
||||
};
|
||||
|
||||
// the region in which the ball moves
|
||||
int top, left, width, height;
|
||||
|
||||
// the position and radius of the ball
|
||||
int posX, posY;
|
||||
int radius = 5, ballSize = radius*2;
|
||||
|
||||
// the direction of the ball is controlled by these two variables
|
||||
int deltaX;
|
||||
int deltaY;
|
||||
|
||||
// a handle onto the singleton Graphics object
|
||||
Graphics g;
|
||||
Canvas canvas;
|
||||
|
||||
// public variables to control the behaviour of the thread
|
||||
public boolean stop;
|
||||
|
||||
/**
|
||||
* Constructor defines the region in which the ball moves as well
|
||||
* as its starting position.
|
||||
*/
|
||||
SmallBall(Canvas c, int left, int top, int width, int height) {
|
||||
super();
|
||||
canvas = c;
|
||||
|
||||
this.left = left + 1;
|
||||
this.top = top + 1;
|
||||
this.width = width - (2 * radius + 2);
|
||||
this.height = height - (2 * radius + 2);
|
||||
|
||||
// use positive random #s
|
||||
this.posX = (random.nextInt()>>>1) % (this.width-20) + 10;
|
||||
this.posY = (random.nextInt()>>>1) % (this.height-20) + 10;
|
||||
|
||||
deltaX = random.nextInt() & 1;
|
||||
deltaY = random.nextInt() & 1;
|
||||
|
||||
if (deltaX == 0) deltaX = -1;
|
||||
if (deltaY == 0) deltaY = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the ball running.
|
||||
*/
|
||||
public void run() {
|
||||
// System.out.println("starting... " + this);
|
||||
int right = left + width;
|
||||
int bottom = top + height;
|
||||
|
||||
stop = false;
|
||||
while (!stop) {
|
||||
|
||||
ballSize = radius * 2;
|
||||
|
||||
// calculate a direction of the ball
|
||||
// as an integer in the range
|
||||
// -2 .. 2 (excluding 0)
|
||||
int direction = deltaX + deltaY;
|
||||
if (direction == 0) direction = deltaX + 2*deltaY;
|
||||
|
||||
// is the current position colliding with any wall
|
||||
int collision = 0;
|
||||
if (posX <= left || posX >= right) collision++;
|
||||
if (posY <= top || posY >= bottom) collision += 2;
|
||||
|
||||
// change the direction appropriately
|
||||
// if there was a collision
|
||||
if (collision != 0) {
|
||||
collision = (collision - 1) * 2;
|
||||
|
||||
deltaX = matrix[direction+2][collision];
|
||||
deltaY = matrix[direction+2][collision+1];
|
||||
}
|
||||
|
||||
// calculate the new position and queue a repaint
|
||||
posX = posX + deltaX;
|
||||
posY = posY + deltaY;
|
||||
canvas.repaint(posX - 1, posY - 1,
|
||||
ballSize + 2, ballSize + 2);
|
||||
|
||||
// use the delay to control the speed of the ball
|
||||
try {
|
||||
Thread.sleep(delay);
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paint the ball.
|
||||
*/
|
||||
void paint(Graphics g) {
|
||||
g.setColor(0);
|
||||
g.fillArc(posX, posY, ballSize, ballSize, 0, 360);
|
||||
}
|
||||
|
||||
boolean inside(int x1, int y1, int x2, int y2) {
|
||||
return (posX <= x2)
|
||||
&& (posY <= y2)
|
||||
&& ((posX + ballSize) >= x1)
|
||||
&& ((posY + ballSize) >= y1);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return super.toString() + " x = " + posX + ", y = " + posY;
|
||||
}
|
||||
|
||||
}
|
Загрузка…
Ссылка в новой задаче