Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: Java: Palloja Väriliu'un päällä

Sami [20.07.2004 17:29:10]

#

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;
	}
}

tsuriga [21.07.2004 22:18:51]

#

Siinä on taas käytetty automaattista pakettien tuontia :). Hienon näköinen. Sainpa jopa muutamia ideoita omiin projekteihin, kiitos.

_Pete_ [26.07.2004 15:40:23]

#

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.

Sami [28.07.2004 11:35:46]

#

Automaattien pakettien tuonti, eli Control + Shift + O (Organize Imports) :D

_Pete_ [30.07.2004 18:00:29]

#

lainaus:

Automaattien pakettien tuonti, eli Control + Shift + O (Organize Imports) :D

Niin ja missä se toimii? Ei ainakaan mun emacs:ssa :)

Sami [31.07.2004 19:04:21]

#

Eclipse (http://www.eclipse.org)

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta