/***********************************************************************
* MicrochipsPlayer.java - Source Code (requires java 1.1) *
* Version release date : June 24, 2003 *
* Copyright (C) 2001-2003 Neural Semantics sprl, Belgium *
* Author : Michel Petre mpetre@neuralsemantics.com *
* *
* http://www.neuralsemantics.com/ *
* *
* This code is released under the GNU GPL license, version 2 or *
* later, for educational and non-commercial purposes only. *
* If any part of the code is to be included in a commercial *
* software, please contact us first for a clearance at *
* info@neuralsemantics.com *
* *
* This notice must remain intact in all copies of this code. *
* This code is distributed WITHOUT ANY WARRANTY OF ANY KIND. *
* The GNU GPL license can be found at : *
* http://www.gnu.org/copyleft/gpl.html *
* *
***********************************************************************/
/* History & changes **************************************************
* *
******** July 20, 2001 ************************************************
* - First release *
******** June 24, 2003 ************************************************
* - Enhanced motion speed control *
* - Added motionJump control *
* - Added layer control *
* - Added welcome text *
***********************************************************************/
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
class MicrochipsPlayer extends Canvas
implements MouseListener,
MouseMotionListener,
Runnable {
public final static int LOCATE = 0;
public final static int MOVE = 1;
private int motionMode = MOVE;
public final static int MOTION_SLOW = 0;
public final static int MOTION_MEDIUM = 1;
public final static int MOTION_FAST = 2;
private int motionSpeed = MOTION_MEDIUM;
private long timer;
private long fastTimer = 30;
private long slowTimer = 350;
private long moveTimer = 3;
private int border = 1;
private int motionJump = 1;
private int cw, ch, ow, oh, sx, sy;
private int lastX, lastY, mouseX, mouseY;
private int clipX, clipY, clipW = 40, clipH = 40;
private boolean isMoving, isReleased, isCleared, isSingleLayer;
private Color bgColor = new Color(0x00, 0x00, 0x00);
private Color borderColor = new Color(0x40, 0x40, 0x40);
private Image memImg, offImg, backImg;
private Graphics graph, offGraph;
private MemoryImageSource source;
private int[] pix;
private int currentDelta, currentMask;
private int pixDelta;
private int pixMask = 0x00FFFFFF;
private String sStart;
private boolean isText;
private Color textColor = new Color(0x00, 0xC0, 0xFF);
private Font startFont = new Font("Dialog", Font.PLAIN, 12);
private Thread runner;
//**********************************************************************
// Constructors
//**********************************************************************
MicrochipsPlayer() {
addMouseListener(this);
addMouseMotionListener(this);
}
//**********************************************************************
// Methods
//**********************************************************************
private int getCode(int x, int y) {
int code = -1;
if (x < lastX) {
if (y < lastY)
code = 6;
else if (y == lastY)
code = 5;
else if (y > lastY)
code = 4;
}
else if (x == lastX) {
if (y < lastY)
code = 7;
else if (y == lastY)
code = 0;
else if (y > lastY)
code = 3;
}
else if (x > lastX) {
if (y < lastY)
code = 8;
else if (y == lastY)
code = 1;
else if (y > lastY)
code = 2;
}
return code;
}
//------------------------------------------------------------------------
private int changeX(int code) {
switch(code) {
case 8 :
case 1 :
case 2 :
return lastX + motionJump;
case 4 :
case 5 :
case 6 :
return lastX - motionJump;
}
return lastX;
}
//------------------------------------------------------------------------
private int changeY(int code) {
switch(code) {
case 2 :
case 3 :
case 4 :
return lastY + motionJump;
case 6 :
case 7 :
case 8 :
return lastY - motionJump;
}
return lastY;
}
//------------------------------------------------------------------------
private void moveMotion() {
int code = this.getCode(mouseX, mouseY);
if (code > 0) {
isMoving = true;
int xNo = changeX(code);
int yNo = changeY(code);
if ((xNo >= 0 - clipW) && (xNo < cw + clipW) &&
(yNo >= 0 - clipH) && (yNo < ch + clipH)) {
lastX = xNo;
lastY = yNo;
clipX = lastX - (int)(clipW / 2);
clipY = lastY - (int)(clipH / 2);
makeImage();
}
}
else {
isMoving = false;
if (isReleased)
timer = slowTimer;
}
}
//------------------------------------------------------------------------
private void locateMotion() {
lastX = mouseX;
lastY = mouseY;
clipX = lastX - (int)(clipW / 2);
clipY = lastY - (int)(clipH / 2);
makeImage();
isMoving = false;
if (isReleased)
timer = slowTimer;
}
//------------------------------------------------------------------------
private int[] getPixels(Image im) {
int[] px = new int[cw * ch];
PixelGrabber pg = new PixelGrabber(im, 0, 0, cw, ch, px, 0, cw);
try {
pg.grabPixels();
return px;
}
catch (InterruptedException e) { }
return null;
}
//------------------------------------------------------------------------
private synchronized void handleMouseOn(int x, int y, int mod) {
mouseX = x;
mouseY = y;
if (isReleased) {
if (mod != InputEvent.BUTTON2_MASK) {
lastX = mouseX - 1;
lastY = mouseY - 1;
}
isReleased = false;
isCleared = false;
isText = false;
}
timer = fastTimer;
isMoving = true;
}
//**********************************************************************
// Thread
//**********************************************************************
public void start() {
if (runner == null) {
runner = new Thread(this);
runner.start();
}
isReleased = true;
isCleared = true;
timer = slowTimer;
}
//------------------------------------------------------------------------
public void run() {
int pass = 0;
while (true) {
repaint();
while (isMoving) {
if (isReleased) {
isMoving = false;
timer = slowTimer;
}
else {
if (motionMode == MOVE)
this.moveMotion();
else if (motionMode == LOCATE)
this.locateMotion();
if (motionSpeed == MOTION_SLOW) {
try { Thread.sleep(moveTimer); }
catch (InterruptedException e) { }
}
else if (motionSpeed == MOTION_MEDIUM) {
pass += 1;
if (pass == 3) {
try { Thread.sleep(moveTimer); }
catch (InterruptedException e) { }
pass = 0;
}
}
}
}
if (isReleased)
timer = slowTimer;
try { Thread.sleep(timer); }
catch (InterruptedException e) { }
}
}
//------------------------------------------------------------------------
public void stop() {
this.cleanup();
}
//------------------------------------------------------------------------
public void destroy() {
this.cleanup();
}
//------------------------------------------------------------------------
private synchronized void cleanup() {
if (runner != null) {
try {
runner.stop();
runner.join();
runner = null;
}
catch(Exception e) { }
}
}
//**********************************************************************
// MouseListener Interface
//**********************************************************************
public void mouseClicked(MouseEvent e) {
this.handleMouseOn(e.getX(), e.getY(), e.getModifiers());
}
//------------------------------------------------------------------------
public void mouseEntered(MouseEvent e) {
}
//------------------------------------------------------------------------
public void mouseExited(MouseEvent e) {
}
//------------------------------------------------------------------------
public void mousePressed(MouseEvent e) {
}
//------------------------------------------------------------------------
public void mouseReleased(MouseEvent e) {
isReleased = true;
}
//**********************************************************************
// MouseMotionListener Interface
//**********************************************************************
public void mouseDragged(MouseEvent e) {
this.handleMouseOn(e.getX(), e.getY(), e.getModifiers());
}
//-------------------------------------------
public void mouseMoved(MouseEvent e) {
}
//**********************************************************************
// Painter
//**********************************************************************
private boolean checkImage() {
Dimension d = getSize();
int w = d.width;
int h = d.height;
if ((w == 0) || (h == 0))
return false;
w -= 2 * border;
h -= 2 * border;
if ((memImg == null) || (w != cw) || (h != ch)) {
cw = w;
ch = h;
Image img = createImage(cw, ch);
Graphics g = img.getGraphics();
if (backImg == null) {
g.setColor(bgColor);
g.fillRect(0, 0, cw, ch);
}
else {
g.setColor(Color.black);
g.fillRect(0, 0, cw, ch);
g.drawImage(backImg, 0, 0, cw, ch, bgColor, null);
}
pix = this.getPixels(img);
if (pix != null) {
source = new MemoryImageSource(cw, ch, pix, 0, cw);
source.setAnimated(true);
memImg = createImage(source);
}
else
memImg = null;
}
return true;
}
//------------------------------------------------------------------------
private void makeImage() {
this.checkImage();
int linePos, pos;
int minY = Math.max(0, clipY);
int maxY = Math.min(ch, clipY + clipH);
int minX = Math.max(0, clipX);
int maxX = Math.min(cw, clipX + clipW);
for (int i=minY; i<maxY; i++) {
linePos = i * cw;
for (int j=minX; j<maxX; j++) {
pos = linePos + j;
pix[pos] = ((pix[pos] + pixDelta) & pixMask) + 0xFF000000;
}
}
source.newPixels(clipX, clipY, clipW, clipH);
}
//------------------------------------------------------------------------
public void update(Graphics g) {
this.checkImage();
if ((offImg == null) || (cw != ow) || (ch != oh)) {
ow = cw;
oh = ch;
offImg = createImage(ow, oh);
offGraph = offImg.getGraphics();
FontMetrics fm = Toolkit.getDefaultToolkit().getFontMetrics(startFont);
sx = (int)((cw - fm.stringWidth(sStart)) / 2);
sy = (int)((ch - fm.getMaxDescent()) / 2) - 10;
}
if (isSingleLayer) {
offGraph.setColor(bgColor);
offGraph.fillRect(0, 0, cw - 1, ch - 1);
}
if (memImg != null) {
offGraph.drawImage(memImg, 1, 1, this);
}
if (isText) {
offGraph.setFont(startFont);
offGraph.setColor(textColor);
offGraph.drawString(sStart, sx, sy);
}
g.setColor(borderColor);
g.drawRect(0, 0, cw + 2*border - 1, ch + 2*border - 1);
g.drawImage(offImg, border, border, this);
}
//------------------------------------------------------------------------
public void paint(Graphics g) {
this.checkImage();
if (memImg != null)
g.drawImage(memImg, 1, 1, this);
g.setColor(borderColor);
g.drawRect(0, 0, cw + 2*border - 1, ch + 2*border - 1);
}
//**********************************************************************
// Public Interface
//**********************************************************************
public void setBgColor(Color c) {
bgColor = c;
}
//------------------------------------------------------------------------
public void clear() {
memImg = null;
timer = slowTimer;
isMoving = false;
repaint();
isCleared = true;
}
//------------------------------------------------------------------------
public void setDelta(int d) {
currentDelta = d;
if ((currentMask == 0) && (currentDelta == 0))
d += 1;
int r = d + ((currentMask & 4) >> 2);
int g = d + ((currentMask & 2) >> 1);
int b = d + (currentMask & 1);
pixDelta = (r<<16) | (g<<8) | b;
}
//------------------------------------------------------------------------
public void setMask(int i) {
currentMask = i;
setDelta(currentDelta);
}
//------------------------------------------------------------------------
public void setChipSize(int w, int h) {
clipW = w;
clipH = h;
}
//------------------------------------------------------------------------
public void setSingleLayer(boolean b) {
isSingleLayer = b;
}
//------------------------------------------------------------------------
public void setMotionMode(int i) {
if ((i >= 0) && (i <= 1))
motionMode = i;
}
//------------------------------------------------------------------------
public void setMotionSpeed(int i) {
if ((i >= 0) && (i <= 2))
motionSpeed = i;
}
//------------------------------------------------------------------------
public void setMotionJump(int i) {
if (i > 0)
motionJump = i;
}
//------------------------------------------------------------------------
public void setText(String s) {
if (s == null)
isText = false;
else
isText = true;
sStart = s;
}
//**********************************************************************
// Properties
//**********************************************************************
public Dimension getPreferredSize() { return getSize(); }
//------------------------------------------------------------------------
public Dimension getImageSize() { return new Dimension(cw, ch); }
//------------------------------------------------------------------------
public Image getImage() { return offImg; }
//------------------------------------------------------------------------
public boolean isCleared() { return isCleared; }
//------------------------------------------------------------------------
public int[] getRGBPixels() { return pix; }
}
|