/** * Get the current image in the animation sequence. This will change over time. * * @return The current image */ public GreenfootImage getCurrentImage() { long delta = System.currentTimeMillis() - time; while (delta >= delay[currentIndex] && !pause) { delta -= delay[currentIndex]; time += delay[currentIndex]; currentIndex = (currentIndex + 1) % images.length; } return images[currentIndex]; }
/** * Construct a new GifImage instance using the specified image file. The animation will initially * be running. Use getImage() at any time to get the current image in the animation sequence. */ public GifImage(String file) { this.file = file; pause = false; if (file.toLowerCase().endsWith(".gif")) { loadImages(); } else { images = new GreenfootImage[] {new GreenfootImage(file)}; delay = new int[] {1000}; // Doesn't matter, as long as it's not zero currentIndex = 0; time = System.currentTimeMillis(); } }
/** Load the images */ private void loadImages() { GifDecoder decode = new GifDecoder(); decode.read(file); int numFrames = decode.getFrameCount(); if (numFrames > 0) { images = new GreenfootImage[numFrames]; delay = new int[numFrames]; } else { images = new GreenfootImage[1]; images[0] = new GreenfootImage(1, 1); } for (int i = 0; i < numFrames; i++) { GreenfootImage image = new GreenfootImage(decode.getFrame(i).getWidth(), decode.getFrame(i).getHeight()); BufferedImage frame = image.getAwtImage(); Graphics2D g = (Graphics2D) frame.getGraphics(); g.drawImage(decode.getFrame(i), null, 0, 0); delay[i] = decode.getDelay(i); images[i] = image; } time = System.currentTimeMillis(); }
/** Resume the animation. */ public void resume() { pause = false; time = System.currentTimeMillis(); }
/** * Creates new frame image from current data (and previous frames as specified by their * disposition codes). */ protected void setPixels() { // expose destination image's pixels as int array int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); // fill in starting image contents based on last image's dispose code if (lastDispose > 0) { if (lastDispose == 3) { // use image before last int n = frameCount - 2; if (n > 0) { lastImage = getFrame(n - 1); } else { lastImage = null; } } if (lastImage != null) { int[] prev = ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); System.arraycopy(prev, 0, dest, 0, width * height); // copy pixels if (lastDispose == 2) { // fill last image rect area with background color Graphics2D g = image.createGraphics(); Color c = null; if (transparency) { c = new Color(0, 0, 0, 0); // assume background is transparent } else { c = new Color(lastBgColor); // use given background color } g.setColor(c); g.setComposite(AlphaComposite.Src); // replace area g.fill(lastRect); g.dispose(); } } } // copy each source line to the appropriate place in the destination int pass = 1; int inc = 8; int iline = 0; for (int i = 0; i < ih; i++) { int line = i; if (interlace) { if (iline >= ih) { pass++; switch (pass) { case 2: iline = 4; break; case 3: iline = 2; inc = 4; break; case 4: iline = 1; inc = 2; } } line = iline; iline += inc; } line += iy; if (line < height) { int k = line * width; int dx = k + ix; // start of line in dest int dlim = dx + iw; // end of dest line if ((k + width) < dlim) { dlim = k + width; // past dest edge } int sx = i * iw; // start of line in source while (dx < dlim) { // map color and insert in destination int index = ((int) pixels[sx++]) & 0xff; int c = act[index]; if (c != 0) { dest[dx] = c; } dx++; } } } }
/** * Update the lastState property. Should ideally be called on each World.act(), or at least before * getState() in a frame where mouse info is wanted. */ public void act() { MouseInfo mouseinfo = Greenfoot.getMouseInfo(); /* To-be properties of MouseState */ boolean held = lastState.held; boolean down = false; boolean up = false; boolean moved; Vector position; if (mouseinfo != null) { /* Get the new mouse position */ position = new Vector(mouseinfo.getX(), mouseinfo.getY()); /* We have moved if there is a difference between this mouse position and * the previous mouse position. */ moved = lastState.position == null || position.subtract(lastState.position).length() > 0.5; } else { /* mouseinfo == null */ /* Use the previous mouse position */ position = lastState.position; /* We haven't moved the mouse pointer. */ moved = false; } if (lastState.held) { /* Figure out if the mouse has been released. This has to be done * differently on Mac OS X, as MouseInfo contains different info in case * of mouse release on that platform. */ if (System.getProperty("os.name").equals("Mac OS X")) { if (Greenfoot.mouseClicked(null) || mouseinfo != null && (mouseinfo.getActor() != concerning || mouseinfo.getButton() != 1)) { up = true; held = false; } } else { /* TODO: Check if this behaves correctly in Windows */ if (Greenfoot.mouseClicked(concerning) || mouseinfo != null && (mouseinfo.getActor() != concerning || mouseinfo.getButton() != 0)) { up = true; held = false; } } } else { /* !lastState.held */ /* Figure out if mouse has been pressed. This is thankfully * cross-platform consistent. */ if (Greenfoot.mousePressed(concerning)) { down = true; held = true; } } /* Store the state in the lastState property. */ lastState = new MouseState(held, down, up, moved, position); }