We’ll use this method to generate a random spelunking workout.
After that, we’ll generate a few more images. This time we won’t use loops to march through every pixel. Instead we’ll loop through points on a line or timesteps in an animation! Let’s solve these problems:
draw a line between two points
bounce a ball
rotate and scale a square
See you next class!
Sincerely,
P.S. It’s Haiku Friday!
They’re little windows Shining past light, like Grandma’s I wish pixels smelled
P.P.S. Here’s the code we wrote together…
RandomSpelunking.java
packagelecture1104;
importjava.util.Random;
publicclassRandomSpelunking {
publicstaticvoid main(String[] args) {
Random generator = newRandom();
int nLevels = getNumberOfLevels();
for (int i = 0; i < nLevels; ++i) {
System.out.println(times('-', generator.nextInt(7) + 4));
}
}
publicstaticint getNumberOfLevels() {
System.out.println("Hey, we're callin' this method!");
returnnewRandom().nextInt(20);
}
publicstaticString times(char c, int n) {
String s = "";
for (int i = 0; i < n; ++i) {
s += c;
}
return s;
}
}
GifSequenceWriter.java
packagelecture1104;
// GifSequenceWriter.java// // Created by Elliot Kroo on 2009-04-25.//// This work is licensed under the Creative Commons Attribution 3.0 Unported// License. To view a copy of this license, visit// http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative// Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.importjavax.imageio.*;
importjavax.imageio.metadata.*;
importjavax.imageio.stream.*;
importjava.awt.image.*;
importjava.io.*;
importjava.util.Iterator;
publicclassGifSequenceWriter {
protectedImageWriter gifWriter;
protectedImageWriteParam imageWriteParam;
protectedIIOMetadata imageMetaData;
protectedImageOutputStream outputStream;
/**
* Creates a new GifSequenceWriter
*
* @param outputStream
* the ImageOutputStream to be written to
* @param imageType
* one of the imageTypes specified in BufferedImage
* @param timeBetweenFramesMS
* the time between frames in miliseconds
* @param loopContinuously
* wether the gif should loop repeatedly
* @throws IIOException
* if no gif ImageWriters are found
*
* @author Elliot Kroo (elliot[at]kroo[dot]net)
*/public GifSequenceWriter(File outFile,
int timeBetweenFramesMS,
boolean loopContinuously) {
try {
// my method to create a writer
gifWriter = getWriter();
imageWriteParam = gifWriter.getDefaultWriteParam();
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);
String metaFormatName = imageMetaData.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);
IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
graphicsControlExtensionNode.setAttribute("delayTime", Integer.toString(timeBetweenFramesMS / 10));
graphicsControlExtensionNode.setAttribute("transparentColorIndex", "0");
IIOMetadataNode commentsNode = getNode(root, "CommentExtensions");
commentsNode.setAttribute("CommentExtension", "Created by MAH");
IIOMetadataNode appEntensionsNode = getNode(root, "ApplicationExtensions");
IIOMetadataNode child = newIIOMetadataNode("ApplicationExtension");
child.setAttribute("applicationID", "NETSCAPE");
child.setAttribute("authenticationCode", "2.0");
int loop = loopContinuously ? 0 : 1;
child.setUserObject(newbyte[] { 0x1, (byte) (loop & 0xFF), (byte) ((loop >> 8) & 0xFF)
});
appEntensionsNode.appendChild(child);
imageMetaData.setFromTree(metaFormatName, root);
outputStream = newFileImageOutputStream(outFile);
gifWriter.setOutput(outputStream);
gifWriter.prepareWriteSequence(null);
} catch (IOException e) {
thrownewRuntimeException(e);
}
}
publicvoid appendFrame(BufferedImage img) {
try {
gifWriter.writeToSequence(newIIOImage(img, null, imageMetaData), imageWriteParam);
} catch (IOException e) {
thrownewRuntimeException(e);
}
}
/**
* Close this GifSequenceWriter object. This does not close the underlying
* stream, just finishes off the GIF.
*/publicvoid close() {
try {
gifWriter.endWriteSequence();
outputStream.close();
} catch (IOException e) {
thrownewRuntimeException(e);
}
}
/**
* Returns the first available GIF ImageWriter using
* ImageIO.getImageWritersBySuffix("gif").
*
* @return a GIF ImageWriter object
* @throws IIOException
* if no GIF image writers are returned
*/privatestaticImageWriter getWriter() throwsIIOException {
try {
Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
if (!iter.hasNext()) {
thrownewIIOException("No GIF Image Writers Exist");
} else {
return iter.next();
}
} catch (IOException e) {
thrownewRuntimeException(e);
}
}
/**
* Returns an existing child node, or creates and returns a new child node (if
* the requested node does not exist).
*
* @param rootNode
* the <tt>IIOMetadataNode</tt> to search for the child node.
* @param nodeName
* the name of the child node.
*
* @return the child node, if found or a new node created with the given name.
*/privatestaticIIOMetadataNode getNode(IIOMetadataNode rootNode,
String nodeName) {
int nNodes = rootNode.getLength();
for (int i = 0; i < nNodes; i++) {
if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0) {
return ((IIOMetadataNode) rootNode.item(i));
}
}
IIOMetadataNode node = newIIOMetadataNode(nodeName);
rootNode.appendChild(node);
return node;
}
}
Animation.java
packagelecture1104;
importjava.awt.Color;
importjava.awt.Graphics;
importjava.awt.image.BufferedImage;
importjava.io.File;
publicclassAnimation {
publicstaticvoid main(String[] args) {
File outputFile = newFile("/Users/johnch/Desktop/ball.gif");
GifSequenceWriter gif = new GifSequenceWriter(outputFile, 100, false);
BufferedImage image = newBufferedImage(512, 512, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
double x = 0;
double y = 0;
double delta = 0.1;
double velocityY = 31;
double velocityX = 12;
double acceleration = 2 * 9.81;
for (double t = 0.0; t < 30; t += delta) {
g.setColor(Color.BLUE);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.setColor(Color.YELLOW);
g.fillOval((int) x, (int) y, 100, 100);
if (y > 410) {
velocityY *= -0.9;
}
x += velocityX * delta;
y += velocityY * delta;
velocityY += acceleration;
gif.appendFrame(image);
}
gif.close();
}
}