/** * Bezier * Copyright (C) 2003 Michael Birken * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * http://www.meatfighter.com */ package bezier; import gamingtools.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class Bezier extends FrameBuilder { public static final int WIDTH = 640; public static final int HEIGHT = 480; public static final int FPS = 100; public static final int BALLS = 20; public static final int BALL_DIAMETER = 64; public static final int BALL_SPACING = 10; public static final int TIME_SEGMENTS = 200; public static final double DT = 1.0 / TIME_SEGMENTS; public static final double VELOCITY = 1000.0; public static final int ELEMENTS = BALL_SPACING * BALLS; public static final int SQUARE_SIDE = 40; private int[] xQueue; private int[] yQueue; private int[] ballIndex; private int tSegment; private int queueIndex; private Color[] colors; private double x0, dxdt0, x1, dxdt1, ax, bx, cx, dx; private double y0, dydt0, y1, dydt1, ay, by, cy, dy; private double t; private Image background; private Audio aquatic; public Bezier() { createBackground(); createColors(); createRandomDestination(); createRandomDestination(); createQueues(); GraphicsSource.enterDisplayMode(WIDTH, HEIGHT); Frame frame = GraphicsSource.getFrame(); frame.setTitle("Bezier"); frame.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { GraphicsSource.stopAnimation(); GraphicsSource.exitDisplayMode(); aquatic.stop(); aquatic.dispose(); System.exit(0); } } }); GraphicsSource.setRenderListener(this); GraphicsSource.startAnimation(FPS); } private void createQueues() { xQueue = new int[ELEMENTS]; yQueue = new int[ELEMENTS]; ballIndex = new int[BALLS]; for(int i = 0, j = 0; i < BALLS; i++, j += BALL_SPACING) ballIndex[i] = j; for(int i = 0; i < ELEMENTS; i++) { xQueue[i] = (int)x0; yQueue[i] = (int)y0; } } private void createRandomDestination() { final double angle = Math.random() * 2.0 * Math.PI; x0 = x1; dxdt0 = dxdt1; x1 = Math.random() * (WIDTH - BALL_DIAMETER); dxdt1 = VELOCITY * Math.cos(angle); ax = 2.0 * (x0 - x1) + dxdt0 + dxdt1; bx = 3.0 * (x1 - x0) - 2.0 * dxdt0 - dxdt1; cx = dxdt0; dx = x0; y0 = y1; dydt0 = dydt1; y1 = Math.random() * (HEIGHT - BALL_DIAMETER); dydt1 = VELOCITY * Math.sin(angle); ay = 2.0 * (y0 - y1) + dydt0 + dydt1; by = 3.0 * (y1 - y0) - 2.0 * dydt0 - dydt1; cy = dydt0; dy = y0; } private void createColors() { colors = new Color[BALLS]; final double RED_PHASE = 0.0; final double GREEN_PHASE = Math.PI * 2.0 / 3.0; final double BLUE_PHASE = Math.PI * 4.0 / 3.0; final double ANGLE_INCREMENT = Math.PI * 2.0 / BALLS; double angle = 0.0; for(int i = 0; i < BALLS; i++, angle += ANGLE_INCREMENT) { colors[BALLS - i - 1] = new Color( (int)(255.0 * (Math.cos(angle - RED_PHASE) * 0.5 + 0.5)), (int)(255.0 * (Math.cos(angle - GREEN_PHASE) * 0.5 + 0.5)), (int)(255.0 * (Math.cos(angle - BLUE_PHASE) * 0.5 + 0.5))); } } private void createBackground() { GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment .getLocalGraphicsEnvironment().getDefaultScreenDevice() .getDefaultConfiguration(); Image bground = graphicsConfiguration.createCompatibleImage( WIDTH, HEIGHT, Transparency.BITMASK); background = graphicsConfiguration.createCompatibleImage( WIDTH, HEIGHT, Transparency.BITMASK); float[] elements = { (float)(1.0/16.0), (float)(2.0/16.0), (float)(1.0/16.0), (float)(2.0/16.0), (float)(4.0/16.0), (float)(2.0/16.0), (float)(1.0/16.0), (float)(2.0/16.0), (float)(1.0/16.0) }; Kernel kernel = new Kernel(3, 3, elements); ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); Graphics g = null; try { g = bground.getGraphics(); Color c = Color.BLACK; for(int y = 0; y < HEIGHT; y += SQUARE_SIDE) { for(int x = 0; x < WIDTH; x += SQUARE_SIDE) { g.setColor(c); c = (c == Color.BLACK) ? Color.WHITE : Color.BLACK; g.fillRect(x, y, SQUARE_SIDE, SQUARE_SIDE); } c = (c == Color.BLACK) ? Color.WHITE : Color.BLACK; } cop.filter((BufferedImage)bground, (BufferedImage)background); g.drawImage(background, 0, 0, null); cop.filter((BufferedImage)bground, (BufferedImage)background); g.drawImage(background, 0, 0, null); cop.filter((BufferedImage)bground, (BufferedImage)background); } finally { if (g != null) g.dispose(); } } public void init() { // Aquatic Ambiance from Nintendo's Donkey Kong Country (SNES) aquatic = AudioSource.getAudio("aquatic.mid"); aquatic.loop(); } public void updateState() { xQueue[queueIndex] = (int)(t * (t * (t * ax + bx) + cx) + dx); yQueue[queueIndex] = (int)(t * (t * (t * ay + by) + cy) + dy); if (++queueIndex >= ELEMENTS) queueIndex = 0; for(int i = 0; i < BALLS; i++) if (++ballIndex[i] >= ELEMENTS) ballIndex[i] = 0; t += DT; if (++tSegment >= TIME_SEGMENTS) { t = 0.0; tSegment = 0; createRandomDestination(); } } public void renderBackground(Graphics g) { g.drawImage(background, 0, 0, null); } public void renderBackground( Graphics g, int x, int y, int width, int height) { renderBackground(g); } public void renderForeground(Graphics g) { int xMax = 0, yMax = 0, xMin = WIDTH - 1, yMin = HEIGHT - 1; for(int i = 0; i < BALLS; i++) { g.setColor(colors[i]); int index = ballIndex[i]; int x = xQueue[index]; int y = yQueue[index]; xMax = Math.max(xMax, x); yMax = Math.max(yMax, y); xMin = Math.min(xMin, x); yMin = Math.min(yMin, y); g.fillOval(x, y, BALL_DIAMETER, BALL_DIAMETER); } markDirtyRegion( xMin - 1, yMin - 1, xMax - xMin + BALL_DIAMETER + 2, yMax - yMin + BALL_DIAMETER + 2); } public boolean isBackgroundSame() { return true; } public static void main(String[] args) { Bezier bezier1 = new Bezier(); } }