import java.applet.*; import java.awt.*; import java.util.*; public class randfun extends Applet implements Runnable { Thread m_randfun = null; private Random r; private randcnvs cnvsRand = new randcnvs(); private Image LogoImg = null; private Graphics grand; private int iSpeed; private int iSpeedix; private boolean m_prmSmooth = false; private boolean m_prmNscape = false; private Dimension ScnDim; private Dimension RandDim; private int RandMin; private int RandType = 0; private long randseq = 0; private long s1 = 0; private long s2 = 0; private int gNiceMinPerc = 10; private int gNiceMaxPerc = 60; private Choice c_type; private Choice c_speed; private Checkbox c_smooth; private Checkbox c_nscape; private int DrawSeq = 0; private int BlockSeq = 0; private int BlockNumX,BlockNumY; private int BlockSide; private int BlockOriginX,BlockOriginY; private int BlockWalkX,BlockWalkY; private int LineWalkSeq = 0; private int LineWalkX1,LineWalkY1,LineWalkX2,LineWalkY2; private long gc_count = 0; private Rectangle rect; private boolean bRunning; private long BlockChangeTime; private long TrigChangeTime; private int rc,gc,bc; private long BlockTimeLimit = 60000; private long TrigTimeLimit = 60000; private Color CurrColor; private Runtime rt; private final int MAX_TRIG = 12; private float trigm[]; private float arg1 = 0.0F; private float arg2 = 0.0F; private int TrigType = 0; private float gTrigIncX = 0.005F; private float gTrigIncY = 0.005F; private boolean TrigChange = false; private boolean bShowLabels = false; final int dirtabx[] = { -1, 0, 1, -1, 1, -1, 0, 1 }; final int dirtaby[] = { -1, -1, -1, 0, 0, 1, 1, 1 }; final private int SpeedTab[] = { 400, 200, 150, 100, 50, 25, 10, 0 }; final private int SmoothTab[] = { 15, 10, 8, 6, 4, 3, 2, 1 }; final private int BlkChkTab[] = { 10, 50, 100, 200, 300, 500, 1000, 2000 }; final private int gcTab[] = { 10, 20, 25, 40, 60, 100, 200, 400 }; private final String PARAM_showlabels = "ShowLabels"; //-------------------------------------------------------------------------- public randfun() { } //-------------------------------------------------------------------------- public String getAppletInfo() { return "Name: randfun\r\n" + "Author: Greg Keogh \r\n" + "Created with Microsoft Visual J++ Version 1.1"; } //-------------------------------------------------------------------------- public String[][] getParameterInfo() { String[][] info = { { PARAM_showlabels, "boolean", "Show control labels" }, }; return info; } //-------------------------------------------------------------------------- public void init() { String param; param = getParameter(PARAM_showlabels); if (param != null) bShowLabels = (Integer.parseInt(param) == 0 ? false : true); bRunning = false; LogoImg = getImage(getCodeBase(),"randlogo.jpg"); cnvsRand.SetLogoImage(LogoImg); rect = new Rectangle(); RandDim = new Dimension(); rt = Runtime.getRuntime(); BlockChangeTime = 0; TrigChangeTime = 0; NextRandColor(); trigm = new float[MAX_TRIG]; for (int i=0; i= RandDim.width) LineWalkX1 -= RandDim.width; if (LineWalkY1 >= RandDim.height) LineWalkY1 -= RandDim.height; dir = (int)(randn() % 8); LineWalkX2 += dirtabx[dir]; LineWalkY2 += dirtaby[dir]; if (LineWalkX2 < 0) LineWalkX2 += RandDim.width; if (LineWalkY2 < 0) LineWalkY2 += RandDim.height; if (LineWalkX2 >= RandDim.width) LineWalkX2 -= RandDim.width; if (LineWalkY2 >= RandDim.height) LineWalkY2 -= RandDim.height; ++DrawSeq; } //-------------------------------------------------------------------------- private void DoRandShapes() { grand.setColor(CurrColor); Rectangle rect = GetNiceSubrect(); if (RandType == 0) grand.fillRect(rect.x,rect.y,rect.width,rect.height); else grand.fillOval(rect.x,rect.y,rect.width,rect.height); ++DrawSeq; } //-------------------------------------------------------------------------- private void DoRandPolygons() { int px[] = { 0,0,0,0,0,0,0,0 }; int py[] = { 0,0,0,0,0,0,0,0 }; int vertex = (int)((randn() % 6) + 3); for (int j=0; j TrigTimeLimit) { if (!TrigChange) { TrigType = 0; //(TrigType + 1) % 3; TrigChange = true; } } else TrigChange = false; switch (TrigType) { case 0 : grand.drawLine(Tx1,Ty1,Tx2,Ty2); DrawSeq++; break; case 1 : grand.drawOval(Tx1,Ty1,Math.abs(Tx1-Tx2),Math.abs(Ty1-Ty2)); DrawSeq++; break; case 2 : grand.drawRect(Tx1,Ty1,Math.abs(Tx1-Tx2),Math.abs(Ty1-Ty2)); DrawSeq++; break; } arg1 += gTrigIncX; arg2 += gTrigIncY; } //-------------------------------------------------------------------------- private void DoRandBlocks() { BlockSeqCheck(); grand.setColor(CurrColor); int x = RandIntRange(0,BlockNumX-1); int y = RandIntRange(0,BlockNumY-1); grand.fillRect(x*BlockSide+BlockOriginX,y*BlockSide+BlockOriginY,BlockSide,BlockSide); ++DrawSeq; } //-------------------------------------------------------------------------- private void DoRandBlockWalk() { BlockSeqCheck(); grand.setColor(CurrColor); grand.fillRect(BlockWalkX*BlockSide+BlockOriginX,BlockWalkY*BlockSide+BlockOriginY,BlockSide,BlockSide); int dir = (int)(randn() % 8); BlockWalkX += dirtabx[dir]; BlockWalkY += dirtaby[dir]; if (BlockWalkX < 0) BlockWalkX += BlockNumX; if (BlockWalkY < 0) BlockWalkY += BlockNumY; if (BlockWalkX >= BlockNumX) BlockWalkX -= BlockNumX; if (BlockWalkY >= BlockNumY) BlockWalkY -= BlockNumY; ++DrawSeq; } //-------------------------------------------------------------------------- // At intervals we change the size of the blocks and erase the screen. //-------------------------------------------------------------------------- private void BlockSeqCheck() { if (BlockSeq++%BlkChkTab[iSpeedix] == 0) { long currtime = System.currentTimeMillis(); if ((currtime - BlockChangeTime) > BlockTimeLimit) { BlockChangeTime = currtime; int BlockNum; if (RandType == 4) BlockNum = RandIntRange(6,40); else BlockNum = RandIntRange(30,50); // Walking blocks are smaller BlockSide = RandMin / BlockNum; BlockNumX = RandDim.width / BlockSide; BlockNumY = RandDim.height / BlockSide; BlockWalkX = BlockNumX / 2; BlockWalkY = BlockNumY / 2; BlockOriginX = (RandDim.width % BlockSide) / 2; BlockOriginY = (RandDim.height % BlockSide) / 2; NewRandomBackground(); } } } //-------------------------------------------------------------------------- // One of the controls has been acted upon. //-------------------------------------------------------------------------- public boolean action(Event e, Object o) { Object etarget = e.target; if (etarget instanceof Button) { Button ebtn = (Button)etarget; String ebtntxt = ebtn.getLabel(); //**** Start the animation **** if (ebtntxt.compareTo("Start") == 0) { StartThread(); NewRandomBackground(); ebtn.setLabel("Stop"); //ebtn.disable(); } //**** Stop the animation **** if (ebtntxt.compareTo("Stop") == 0) { StopThread(); ebtn.setLabel("Start"); } } if (etarget instanceof Choice) { Choice c = (Choice)etarget; //**** Change of type **** if (c.equals(c_type)) { RandType = c.getSelectedIndex(); if (bRunning) NewRandomBackground(); } //***** Change of speed **** if (c.equals(c_speed)) { iSpeedix = c.getSelectedIndex(); iSpeed = SpeedTab[iSpeedix]; } } if (etarget instanceof Checkbox) { Checkbox c = (Checkbox)etarget; //**** Change of Smooth Colour **** if (c.equals(c_smooth)) { m_prmSmooth = c.getState(); } //**** Change of Netscape option **** if (c.equals(c_nscape)) { m_prmNscape = c.getState(); } } return true; } //-------------------------------------------------------------------------- public Color NextColor() { if (m_prmSmooth) { int inc = SmoothTab[iSpeedix]; rc += inc * (((randn() % 2) == 0) ? 1 : -1); bc += inc * (((randn() % 2) == 0) ? 1 : -1); gc += inc * (((randn() % 2) == 0) ? 1 : -1); if (rc < 0) rc = 0; if (rc > 255) rc = 255; if (gc < 0) gc = 0; if (gc > 255) gc = 255; if (bc < 0) bc = 0; if (bc > 255) bc = 255; } else NextRandColor(); CurrColor = null; /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ THIS IS A RESOURCE LEAK PATCH. EVERY nnn DRAWS WE SHOW MEMORY STATISTICS AND OPTION- ALLY GARBAGE COLLECT. FIX FOR NETSCAPE. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ if (DrawSeq%gcTab[iSpeedix] == 0) // Why not 400? { long memtotl = rt.totalMemory(); long memfree = rt.freeMemory(); int freepct = (int)((100L*memfree)/memtotl); String st = "Total=" + memtotl/1024L + "KB Free=" + memfree/1024L + "KB (" + freepct + "%) gc=" + (m_prmNscape ? Long.toString(gc_count) : "(off)"); showStatus(st); if (m_prmNscape) { System.gc(); gc_count++; } } CurrColor = new Color(rc,gc,bc); //################## RESOURCE LEAK HERE ########### return CurrColor; } //-------------------------------------------------------------------------- public void NextRandColor() { rc = RandIntRange(0,255); gc = RandIntRange(0,255); bc = RandIntRange(0,255); } //-------------------------------------------------------------------------- public void NewRandomBackground() { grand = cnvsRand.getGraphics(); NextRandColor(); // Always a totally random colour grand.setColor(new Color(rc,gc,bc)); grand.fillRect(0,0,RandDim.width,RandDim.height); NextRandColor(); // Next colour must be unrelated } //-------------------------------------------------------------------------- // Returns a random rectangle with a "nice" size between MinPerc% and // MaxPerc% of the width of the paint area. This avoids ugly very thin // and very fat rectangles. //-------------------------------------------------------------------------- public Rectangle GetNiceSubrect() { int wideperc = (int)((randn() % (gNiceMaxPerc - gNiceMinPerc)) + gNiceMinPerc); int highperc = (int)((randn() % (gNiceMaxPerc - gNiceMinPerc)) + gNiceMinPerc); int wide = (RandMin * wideperc) / 100; int high = (RandMin * highperc) / 100; int x1 = (int)(randn() % (RandDim.width - wide)); int y1 = (int)(randn() % (RandDim.height - high)); rect.move(x1,y1); rect.resize(wide,high); return rect; } //-------------------------------------------------------------------------- private void StartThread() { if (m_randfun == null) { RandDim = cnvsRand.GetDrawSize(); RandMin = Math.min(RandDim.width,RandDim.height); m_randfun = new Thread(this); } RandType = c_type.getSelectedIndex(); m_randfun.start(); bRunning = true; } //-------------------------------------------------------------------------- private void StopThread() { if (m_randfun != null) { m_randfun.stop(); m_randfun = null; bRunning = false; } } //-------------------------------------------------------------------------- // Generate a random integer in a specified range. //-------------------------------------------------------------------------- private int RandIntRange(int lowrng, int hirng) { return (int)(Math.abs(randn() % (hirng-lowrng+1))) + lowrng; } //-------------------------------------------------------------------------- // Use the combined MCLG from Communications of the ACM Vol.31 No.6 // to generate a very long (2x10^18) pseudo-random sequence. //-------------------------------------------------------------------------- private long randn() { long z,k; if (randseq == 0) { s1 = System.currentTimeMillis() % 7837703; s2 = System.currentTimeMillis() % 97531; } k = s1 / 53668; s1 = 40014 * (s1 - k*53668) - k*12211; if (s1 < 0) s1 += 2147483563; k = s2 / 52774; s2 = 40692 * (s2 - k*52774) - k*3791; if (s2 < 0) s2 += 2147483399; z = s1 - s2; if (z < 1) z += 2147483562; randseq = randseq + 1; return(z); } }