Arpoo paikan, värin ja koon 50 pallolle ja piirtää ne. Päällekäin menevät pallot sulautuvat kiinni toisiinsa ja taustalle piirretään satunnaisen värinen väriliuku (jokaiselle kulmalle arvotaan omat väriarvonsa).
Kuvan piirtäminen 733 MHz prosessorilla ja 1024 * 768 resoluutiolla kesti keskimäärin 15 sekuntia (4 testin keskiarvo, pienin 13 s, suurin 16.5 s).
Pallojen määrää, kokoa, väriä ja paikkaa voi muuttaa aivan vapaasti ja saada tulokseksi aina vain uusia kuvia, mutta pallojen määrän tai koon kasvaessa laskenta-aikakin kasvaa (500 pallolla laskenta aika oli n. 1 min 15 s, 50 pallolla säteen ollessa nelinkertainen laskenta aika oli n. 30 s)
Tähän mennessä yksi tyylikkäimmistä javalla tehdyistä efekteistäni. Valmiiksi käännetyt luokat voi noutaa osoitteesta http://www.paivola.fi/~sami/java/Balls.zip mutta niissä ei pääse leikkimään ohjelman koodilla...
Balls.java
import java.awt.Color; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import javax.swing.JFrame; public class Balls extends JFrame implements WindowListener, KeyListener { //Pallojen määrä static int BALLS = 50; //Pallo-oliotaulukko (sis. tiedon pallon koordinaateista, väristä ja koosta) Ball[] balls = new Ball[BALLS]; //Koneen resoluution selvittämistä varten Toolkit toolkit; public Balls() { //Laitetaan ikkuna koko ruudun kokoiseksi ja poistetaan 'turha' otsikkorivi toolkit = Toolkit.getDefaultToolkit(); this.setSize(toolkit.getScreenSize().width, toolkit.getScreenSize().height); this.setUndecorated(true); this.setVisible(true); addWindowListener(this); addKeyListener(this); } public void paint(Graphics g) { //Taustan väriliu'un väriarvot. Saa muuttaa... int R_LEFT_TOP = (int)(Math.random() * 2) * 255; int G_LEFT_TOP = (int)(Math.random() * 2) * 255; int B_LEFT_TOP = (int)(Math.random() * 2) * 255; int R_RIGHT_TOP = (int)(Math.random() * 2) * 255; int G_RIGHT_TOP = (int)(Math.random() * 2) * 255; int B_RIGHT_TOP = (int)(Math.random() * 2) * 255; int R_LEFT_BOT = (int)(Math.random() * 2) * 255; int G_LEFT_BOT = (int)(Math.random() * 2) * 255; int B_LEFT_BOT = (int)(Math.random() * 2) * 255; int R_RIGHT_BOT = (int)(Math.random() * 2) * 255; int G_RIGHT_BOT = (int)(Math.random() * 2) * 255; int B_RIGHT_BOT = (int)(Math.random() * 2) * 255; //Taulukot taustan ylimmän ja alimman rivin väriarvoille int[] redTop = new int[this.getWidth()]; int[] redBot = new int[this.getWidth()]; int[] greenTop = new int[this.getWidth()]; int[] greenBot = new int[this.getWidth()]; int[] blueTop = new int[this.getWidth()]; int[] blueBot = new int[this.getWidth()]; //Vähennetään huomattavasti tarvittavien laskutoimitusten määrää laskemalla taustan //ylimmän ja alimman rivin väriarvot valmiiksi (niitä käytetään koko taustan laskemisessa... for (int x = 0; x < this.getWidth(); x++) { redTop[x] = ((this.getWidth() - x) * R_LEFT_TOP + x * R_RIGHT_TOP) / this.getWidth(); redBot[x] = ((this.getWidth() - x) * R_LEFT_BOT + x * R_RIGHT_BOT) / this.getWidth(); greenTop[x] = ((this.getWidth() - x) * G_LEFT_TOP + x * G_RIGHT_TOP) / this.getWidth(); greenBot[x] = ((this.getWidth() - x) * G_LEFT_BOT + x * G_RIGHT_BOT) / this.getWidth(); blueTop[x] = ((this.getWidth() - x) * B_LEFT_TOP + x * B_RIGHT_TOP) / this.getWidth(); blueBot[x] = ((this.getWidth() - x) * B_LEFT_BOT + x * B_RIGHT_BOT) / this.getWidth(); } //Arvotaan päälle tuleville palloille koordinaatit, väri ja koko for (int i = 0; i < BALLS; i++) { balls[i] = new Ball(); balls[i].setX((int)(Math.random() * this.getWidth())); balls[i].setY((int)(Math.random() * this.getHeight())); balls[i].setRadius((int)(Math.random() * 50) + 20); balls[i].setRed((int)(Math.random() * 255)); balls[i].setGreen((int)(Math.random() * 255)); balls[i].setBlue((int)(Math.random() * 255)); } //Käydään jokainen kuvan piste läpi ja lasketaan sille väriarvo for (int x1 = 0; x1 < this.getWidth() / 200; x1++) { for (int x = x1; x < this.getWidth(); x += this.getWidth() / 200) { for (int y = 0; y < this.getHeight(); y++) { //Oletuksena pisteen väri on musta int red = 0, green = 0, blue = 0; //Lasketaan mitkä kaikki pallot ovat riittävän lähellä pistettä for (int i = 0; i < BALLS; i++) { //Hyödynnetään Pythagoraan lausetta etäisyyden laskemisessa double distance = Math.sqrt((x - balls[i].getX()) * (x - balls[i].getX()) + (y - balls[i].getY()) * (y - balls[i].getY())); //Jos pallo on riittävän lähellä, kasvatetaan pisteen väriarvoa if (distance < balls[i].getRadius()) { red = red * red + (int)(Math.pow(((balls[i].getRadius() - distance) / balls[i].getRadius()) * balls[i].getRed(), 2)); green = green * green + (int)(Math.pow(((balls[i].getRadius() - distance) / balls[i].getRadius()) * balls[i].getGreen(), 2)); blue = blue * blue + (int)(Math.pow(((balls[i].getRadius() - distance) / balls[i].getRadius()) * balls[i].getBlue(), 2)); red = (int)(Math.sqrt(red)); green = (int)(Math.sqrt(green)); blue = (int)(Math.sqrt(blue)); } } //Kaikkein kirkkaimmissa pisteissä saattaa joutua pudottamaan väriarvoja hieman... if (red > 255) red = 255; if (green > 255) green = 255; if (blue > 255) blue = 255; //Jos yksikään pallo ei ollut riittävän lähellä pistettä, niin piirretään taustaa if (red == 0 && green == 0 && blue == 0) { red = ((this.getHeight() - y) * redTop[x] + y * redBot[x]) / this.getHeight(); green = ((this.getHeight() - y) * greenTop[x] + y * greenBot[x]) / this.getHeight(); blue = ((this.getHeight() - y) * blueTop[x] + y * blueBot[x]) / this.getHeight(); } g.setColor(new Color(red, green, blue)); g.fillRect(x, y, 1, 1); } } } } public static void main(String[] args) { Balls liuku = new Balls(); } public void windowActivated(WindowEvent arg0) { } public void windowClosed(WindowEvent arg0) { } public void windowClosing(WindowEvent arg0) { System.exit(0); } public void windowDeactivated(WindowEvent arg0) { } public void windowDeiconified(WindowEvent arg0) { } public void windowIconified(WindowEvent arg0) { } public void windowOpened(WindowEvent arg0) { } //Näppäinkomennot: Väli tai esc lopettaa, Enter piirtää uuden kuvan public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_SPACE || e.getKeyCode() == KeyEvent.VK_ESCAPE) { System.exit(0); } if (e.getKeyCode() == KeyEvent.VK_ENTER) { repaint(); } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } }
Ball.java
public class Ball { private int x; private int y; private int red; private int green; private int blue; private int radius; public Ball() { } public Ball(int x,int y,int red,int green,int blue,int radius) { this.x = x; this.y = y; this.red = red; this.green = green; this.blue = blue; this.radius = radius; } public int getBlue() { return blue; } public int getGreen() { return green; } public int getRadius() { return radius; } public int getRed() { return red; } public int getX() { return x; } public int getY() { return y; } public void setBlue(int blue) { this.blue = blue; } public void setGreen(int green) { this.green = green; } public void setRadius(int radius) { this.radius = radius; } public void setRed(int red) { this.red = red; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } }
Siinä on taas käytetty automaattista pakettien tuontia :). Hienon näköinen. Sainpa jopa muutamia ideoita omiin projekteihin, kiitos.
lainaus:
Siinä on taas käytetty automaattista pakettien tuontia :). Hienon näköinen. Sainpa jopa muutamia ideoita omiin projekteihin, kiitos.
Mikä ja missä on "automaattinen pakettien tuonti" ? IMHO, importit on tässä esitely aivan oikein.
Automaattien pakettien tuonti, eli Control + Shift + O (Organize Imports) :D
lainaus:
Automaattien pakettien tuonti, eli Control + Shift + O (Organize Imports) :D
Niin ja missä se toimii? Ei ainakaan mun emacs:ssa :)
Eclipse (http://www.eclipse.org)
Aihe on jo aika vanha, joten et voi enää vastata siihen.