Path: blob/master/src/demo/share/jfc/J2Ddemo/java2d/demos/Mix/Balls.java
41175 views
/*1*2* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7*8* - Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10*11* - Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* - Neither the name of Oracle nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS20* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,21* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR22* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR23* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,24* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,25* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR26* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF27* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING28* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/31package java2d.demos.Mix;323334import static java.awt.Color.BLUE;35import static java.awt.Color.GREEN;36import static java.awt.Color.ORANGE;37import static java.awt.Color.RED;38import static java.awt.Color.WHITE;39import static java.awt.Color.YELLOW;40import static java.lang.Math.random;41import static java.lang.Math.sqrt;42import java.awt.Color;43import java.awt.Component;44import java.awt.Dimension;45import java.awt.Graphics2D;46import java.awt.event.ActionEvent;47import java.awt.event.ActionListener;48import java.awt.image.BufferedImage;49import java.awt.image.DataBufferByte;50import java.awt.image.IndexColorModel;51import java.awt.image.Raster;52import java.awt.image.WritableRaster;53import java2d.AnimatingControlsSurface;54import java2d.CustomControls;55import javax.swing.AbstractButton;56import javax.swing.JComboBox;57import javax.swing.JToggleButton;58import javax.swing.JToolBar;596061/**62* Animated color bouncing balls with custom controls.63*/64@SuppressWarnings("serial")65public class Balls extends AnimatingControlsSurface {6667private static Color[] colors = { RED, ORANGE, YELLOW, GREEN.darker(), BLUE,68new Color(75, 00, 82), new Color(238, 130, 238) };69private long now, deltaT, lasttime;70private boolean active;71protected Ball[] balls = new Ball[colors.length];72protected boolean clearToggle;73protected JComboBox<String> combo;7475public Balls() {76setBackground(WHITE);77for (int i = 0; i < colors.length; i++) {78balls[i] = new Ball(colors[i], 30);79}80balls[0].isSelected = true;81balls[3].isSelected = true;82balls[4].isSelected = true;83balls[6].isSelected = true;84setControls(new Component[] { new DemoControls(this) });85}8687@Override88public void reset(int w, int h) {89if (w > 400 && h > 100) {90combo.setSelectedIndex(5);91}92}9394@Override95public void step(int w, int h) {96if (lasttime == 0) {97lasttime = System.currentTimeMillis();98}99now = System.currentTimeMillis();100deltaT = now - lasttime;101active = false;102for (Ball ball : balls) {103if (ball == null) {104return;105}106ball.step(deltaT, w, h);107if (ball.Vy > .02 || -ball.Vy > .02 || ball.y + ball.bsize < h) {108active = true;109}110}111if (!active) {112for (Ball ball : balls) {113ball.Vx = (float) random() / 4.0f - 0.125f;114ball.Vy = -(float) random() / 4.0f - 0.2f;115}116clearToggle = true;117}118}119120@Override121public void render(int w, int h, Graphics2D g2) {122for (Ball b : balls) {123if (b == null || b.imgs[b.index] == null || !b.isSelected) {124continue;125}126g2.drawImage(b.imgs[b.index], (int) b.x, (int) b.y, this);127}128lasttime = now;129}130131public static void main(String[] argv) {132createDemoFrame(new Balls());133}134135136protected static final class Ball {137138public static final int nImgs = 5;139public int bsize;140public float x, y;141public float Vx = 0.1f;142public float Vy = 0.05f;143public BufferedImage[] imgs;144// Pick a random starting image index, but not the last: we're going UP145// and that would throw us off the end.146public int index = (int) (random() * (nImgs - 1));147private static final float inelasticity = .96f;148private static final float Ax = 0.0f;149private static final float Ay = 0.0002f;150private static final int UP = 0;151private static final int DOWN = 1;152private int indexDirection = UP;153private float jitter;154private Color color;155private boolean isSelected;156157public Ball(Color color, int bsize) {158this.color = color;159makeImages(bsize);160}161162public void makeImages(int bsize) {163this.bsize = bsize * 2;164int R = bsize;165byte[] data = new byte[R * 2 * R * 2];166int maxr = 0;167for (int Y = 2 * R; --Y >= 0;) {168int x0 = (int) (sqrt(R * R - (Y - R) * (Y - R)) + 0.5);169int p = Y * (R * 2) + R - x0;170for (int X = -x0; X < x0; X++) {171int xx = X + 15;172int yy = Y - R + 15;173int r = (int) (Math.hypot(xx, yy) + 0.5);174if (r > maxr) {175maxr = r;176}177data[p++] = r <= 0 ? 1 : (byte) r;178}179}180181imgs = new BufferedImage[nImgs];182183int bg = 255;184byte[] red = new byte[256];185red[0] = (byte) bg;186byte[] green = new byte[256];187green[0] = (byte) bg;188byte[] blue = new byte[256];189blue[0] = (byte) bg;190191for (int r = 0; r < imgs.length; r++) {192float b = 0.5f + ((r + 1f) / imgs.length / 2f);193for (int i = maxr; i >= 1; --i) {194float d = (float) i / maxr;195red[i] = (byte) blend(blend(color.getRed(), 255, d), bg, b);196green[i] = (byte) blend(blend(color.getGreen(), 255, d), bg,197b);198blue[i] =199(byte) blend(blend(color.getBlue(), 255, d), bg, b);200}201IndexColorModel icm = new IndexColorModel(8, maxr + 1,202red, green, blue, 0);203DataBufferByte dbb = new DataBufferByte(data, data.length);204int[] bandOffsets = { 0 };205WritableRaster wr = Raster.createInterleavedRaster(dbb,206R * 2, R * 2, R * 2, 1, bandOffsets, null);207imgs[r] = new BufferedImage(icm, wr, icm.isAlphaPremultiplied(),208null);209}210}211212private int blend(int fg, int bg, float fgfactor) {213return (int) (bg + (fg - bg) * fgfactor);214}215216public void step(long deltaT, int w, int h) {217218jitter = (float) random() * .01f - .005f;219220x += Vx * deltaT + (Ax / 2.0) * deltaT * deltaT;221y += Vy * deltaT + (Ay / 2.0) * deltaT * deltaT;222if (x <= 0.0f) {223x = 0.0f;224Vx = -Vx * inelasticity + jitter;225//collision_x = true;226}227if (x + bsize >= w) {228x = w - bsize;229Vx = -Vx * inelasticity + jitter;230//collision_x = true;231}232if (y <= 0) {233y = 0;234Vy = -Vy * inelasticity + jitter;235//collision_y = true;236}237if (y + bsize >= h) {238y = h - bsize;239Vx *= inelasticity;240Vy = -Vy * inelasticity + jitter;241//collision_y = true;242}243Vy = Vy + Ay * deltaT;244Vx = Vx + Ax * deltaT;245246if (indexDirection == UP) {247index++;248}249if (indexDirection == DOWN) {250--index;251}252if (index + 1 == nImgs) {253indexDirection = DOWN;254}255if (index == 0) {256indexDirection = UP;257}258}259} // End class Ball260261262final class DemoControls extends CustomControls implements ActionListener {263264Balls demo;265JToolBar toolbar;266267@SuppressWarnings("LeakingThisInConstructor")268public DemoControls(Balls demo) {269super(demo.name);270this.demo = demo;271add(toolbar = new JToolBar());272toolbar.setFloatable(false);273addTool("Clear", true);274addTool("R", demo.balls[0].isSelected);275addTool("O", demo.balls[1].isSelected);276addTool("Y", demo.balls[2].isSelected);277addTool("G", demo.balls[3].isSelected);278addTool("B", demo.balls[4].isSelected);279addTool("I", demo.balls[5].isSelected);280addTool("V", demo.balls[6].isSelected);281add(combo = new JComboBox<>());282combo.addItem("10");283combo.addItem("20");284combo.addItem("30");285combo.addItem("40");286combo.addItem("50");287combo.addItem("60");288combo.addItem("70");289combo.addItem("80");290combo.setSelectedIndex(2);291combo.addActionListener(this);292}293294public void addTool(String str, boolean state) {295JToggleButton b =296(JToggleButton) toolbar.add(new JToggleButton(str));297b.setFocusPainted(false);298b.setSelected(state);299b.addActionListener(this);300int width = b.getPreferredSize().width;301Dimension prefSize = new Dimension(width, 21);302b.setPreferredSize(prefSize);303b.setMaximumSize(prefSize);304b.setMinimumSize(prefSize);305}306307@Override308public void actionPerformed(ActionEvent e) {309if (e.getSource() instanceof JComboBox) {310int size = Integer.parseInt((String) combo.getSelectedItem());311for (Ball ball : demo.balls) {312ball.makeImages(size);313}314return;315}316JToggleButton b = (JToggleButton) e.getSource();317if (b.getText().equals("Clear")) {318demo.clearSurface = b.isSelected();319} else {320int index = toolbar.getComponentIndex(b) - 1;321demo.balls[index].isSelected = b.isSelected();322}323}324325@Override326public Dimension getPreferredSize() {327return new Dimension(200, 40);328}329330@Override331@SuppressWarnings("SleepWhileHoldingLock")332public void run() {333try {334Thread.sleep(999);335} catch (Exception e) {336return;337}338Thread me = Thread.currentThread();339((AbstractButton) toolbar.getComponentAtIndex(2)).doClick();340while (thread == me) {341try {342Thread.sleep(222);343} catch (InterruptedException e) {344return;345}346if (demo.clearToggle) {347if (demo.clearSurface) {348combo.setSelectedIndex((int) (random() * 5));349}350((AbstractButton) toolbar.getComponentAtIndex(0)).doClick();351demo.clearToggle = false;352}353}354thread = null;355}356} // End DemoControls357} // End Balls358359360361