//******************************************************************************** // MashimaroFollower.java // // "MashimaroFollower" // // (c) 2001 Maeda Mameo http://hw001.gate01.com/frog/ //******************************************************************************** public class MashimaroFollower extends java.applet.Applet implements java.awt.event.MouseListener, java.awt.event.MouseMotionListener, Runnable{ private java.awt.Image imageOff, imageBackground; private java.awt.Graphics gOff, gBackground; private boolean paintRequest, refreshRequest; private java.awt.FontMetrics theFontMetrics; private int theWidth, theHeight; private Thread theThread; static final double PI = Math.PI; static final java.awt.Color colorBackground = java.awt.Color.white; static final java.awt.Color colorCursor = java.awt.Color.orange; static final java.awt.Color colorLetter = java.awt.Color.lightGray; static final java.awt.Color colorShadow = java.awt.Color.gray; private java.awt.Image imageMashimaro[] = new java.awt.Image[ 12]; static final int MAXMASHIMARONUM = 100; private double X[] = new double[ MAXMASHIMARONUM]; private double Y[] = new double[ MAXMASHIMARONUM]; private double VX[] = new double[ MAXMASHIMARONUM]; private double VY[] = new double[ MAXMASHIMARONUM]; private double CX[] = new double[ MAXMASHIMARONUM]; private double CY[] = new double[ MAXMASHIMARONUM]; private double A[] = new double[ MAXMASHIMARONUM]; private int mashimaroNum; private int preparingImageNum; private int horizontalNum, verticalNum; private int mouseX, mouseY; private boolean fpsRequest; private String fpsString; static final long MINIMUMDELAY = 20; static final int MAXFPS = 20; //******************************************************************************** //******************************************************************************** public void init(){ java.awt.Dimension d; fpsRequest = false; fpsString = ""; paintRequest = false; setBackground( colorBackground); d = getSize(); theWidth = d.width; theHeight = d.height; imageOff = createImage( theWidth, theHeight); gOff = imageOff.getGraphics(); imageBackground = createImage( theWidth, theHeight); gBackground = imageBackground.getGraphics(); gBackground.setFont( new java.awt.Font( "TimesRoman", java.awt.Font.BOLD, 60)); theFontMetrics = gBackground.getFontMetrics(); addMouseListener( this); addMouseMotionListener( this); } public void start(){ theThread = new Thread( this); theThread.start();} public void stop(){ theThread = null;} public void update( java.awt.Graphics g){ paint( g);} public void paint( java.awt.Graphics g){ if( paintRequest){ if( fpsRequest) showStatus( fpsString); g.drawImage( imageOff, 0, 0, this); paintRequest = false; } } public void mouseClicked( java.awt.event.MouseEvent e){} public void mouseDragged( java.awt.event.MouseEvent e){} public void mouseEntered( java.awt.event.MouseEvent e){ fpsRequest = true;} public void mouseExited( java.awt.event.MouseEvent e){ fpsRequest = false; showStatus( null);} public void mouseMoved( java.awt.event.MouseEvent e){ mouseX = e.getX(); mouseY = e.getY();} public void mousePressed( java.awt.event.MouseEvent e){} public void mouseReleased( java.awt.event.MouseEvent e){} public boolean imageUpdate( java.awt.Image img, int infoFlags, int x, int y, int width, int height){ if(( infoFlags & java.awt.image.ImageObserver.ALLBITS) != 0){ preparingImageNum--; return false; } return true; } //******************************************************************************** //******************************************************************************** public void run(){ int i; String s; int fpsRefreshCount; long delay, averageTime, latestTimeMillis, t; loadMashimaroImage(); resetMashimaro(); fpsRefreshCount = 0; delay = MINIMUMDELAY; latestTimeMillis = System.currentTimeMillis(); refreshRequest = true; while( theThread != null){ if( refreshRequest){ gBackground.setColor( colorBackground); gBackground.fillRect( 0, 0, theWidth, theHeight); s = "MashiMaro"; gBackground.setColor( colorLetter); gBackground.drawString( s, ( theWidth - theFontMetrics.stringWidth( s)) / 2, ( theHeight + theFontMetrics.getAscent()) / 2); for( i = 0; i < theHeight; i += 3) gBackground.drawLine( 0, i, theWidth - 1, i); gBackground.setColor( colorBackground); for( i = 1; i < theHeight; i += 3) gBackground.drawLine( 0, i, theWidth - 1, i); refreshRequest = false; } sleeper( delay); while( paintRequest) sleeper( 1); gOff.drawImage( imageBackground, 0, 0, this); moveMashimaro(); drawConnection(); if( fpsRequest){ gOff.setColor( colorCursor); gOff.fillOval( mouseX - 40, mouseY - 40, 81, 81); } drawMashimaro(); paintRequest = true; repaint(); if( ++fpsRefreshCount == MAXFPS){ t = System.currentTimeMillis(); averageTime = ( t - latestTimeMillis) / MAXFPS; fpsString = "" + 1000 / averageTime + "." + 10000 / averageTime % 10 + " frames / second"; delay = Math.max( MINIMUMDELAY, 1000 / MAXFPS - averageTime + delay); latestTimeMillis = t; fpsRefreshCount = 0; } } } private void moveMashimaro(){ int i, mx, my; double a; mx = mouseX; my = mouseY; for( i = 0; i < mashimaroNum; i++){ if( fpsRequest && Math.pow( X[ i] - mx, 2) + Math.pow( Y[ i] - my, 2) < 2500){ a = getAngle( X[ i] - mx, Y[ i] - my); if( angleDifference( a, getAngle( X[ i] - CX[ i], Y[ i] - CY[ i])) > 0) a += PI / 30; else a -= PI / 30; X[ i] = mx + 60 * Math.cos( a); Y[ i] = my + 60 * Math.sin( a); VX[ i] = 0; VY[ i] = 0; } else{ X[ i] += VX[ i]; Y[ i] += VY[ i]; if( X[ i] < CX[ i]) VX[ i]++; else VX[ i]--; if( Y[ i] < CY[ i]) VY[ i]++; else VY[ i]--; VX[ i] *= .95; VY[ i] *= .95; } if( fpsRequest){ A[ i] = getAngle( mx - X[ i], my - Y[ i]); } else{ A[ i] = PI / 2; } } } private void drawConnection(){ int i; gOff.setColor( colorShadow); for( i = 0; i < mashimaroNum; i++){ if( i / horizontalNum < verticalNum - 1) gOff.drawLine( (int)X[ i], (int)Y[ i], (int)X[ i + horizontalNum], (int)Y[ i + horizontalNum]); if( i % horizontalNum < horizontalNum - 1) gOff.drawLine( (int)X[ i], (int)Y[ i], (int)X[ i + 1], (int)Y[ i + 1]); } } private void drawMashimaro(){ int i; for( i = 0; i < mashimaroNum; i++){ gOff.drawImage( imageMashimaro[ ((int)( A[ i] * 12 / 2 / PI) + 9) % 12], (int)X[ i] - 21, (int)Y[ i] - 79 + 10, null); } } void resetMashimaro(){ int i, j; horizontalNum = 1 + ( theWidth - 100) / 50; verticalNum = 1 + ( theHeight - 100) / 50; for( i = 0; i < verticalNum; i++){ for( j = 0; j < horizontalNum; j++){ if( mashimaroNum < MAXMASHIMARONUM){ CX[ mashimaroNum] = 50 - 12.5 + j * 50 + ( i % 2) * 25; CY[ mashimaroNum] = 75 + i * 50; X[ mashimaroNum] = CX[ mashimaroNum]; Y[ mashimaroNum] = CY[ mashimaroNum]; VX[ mashimaroNum] = Math.cos( PI + mashimaroNum); VY[ mashimaroNum] = Math.sin( PI + mashimaroNum); mashimaroNum++; } } } } private double getAngle( double vx, double vy){ double a; if( vy == 0) if( vx < 0) return PI; else return 0; a = Math.acos( vx / Math.sqrt( vx * vx + vy * vy)); if( vy > 0) return a; else return ( 2 * PI - a); } private double angleDifference( double t, double s){ double a; a = t - s; if( a > PI) return( a - 2 * PI); if( a < -PI) return( a + 2 * PI); return a; } private void sleeper( long t){ try{ theThread.sleep( t);} catch( InterruptedException e){}} private void loadMashimaroImage(){ int a, i, w, h, pix[]; boolean f; java.awt.Image imageMashimaroSource; preparingImageNum = 1; imageMashimaroSource = getImage( getDocumentBase(), "Mashimaro12.gif"); if( prepareImage( imageMashimaroSource, this)) preparingImageNum--; while( preparingImageNum > 0) sleeper( 10); w = imageMashimaroSource.getWidth( this); h = imageMashimaroSource.getHeight( this); pix = new int[ w * h]; try{ new java.awt.image.PixelGrabber( imageMashimaroSource, 0, 0, w, h, pix, 0, w).grabPixels();} catch( InterruptedException e){} a = pix[ 1]; for( i = 0; i < w * h; i++) if( pix[ i] == a) pix[ i] = 0; for( i = 0; i < 12; i++){ preparingImageNum = 1; imageMashimaro[ i] = createImage( new java.awt.image.MemoryImageSource( 42, 79, pix, 1 + ( i % 6) * 43 + i / 6 * 79 * w, w)); if( prepareImage( imageMashimaro[ i], this)) preparingImageNum--; while( preparingImageNum > 0) sleeper( 10); } } }