Created
April 30, 2011 04:44
-
-
Save yogthos/949426 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import java.awt.Graphics | |
import java.awt.Dimension | |
import javax.swing.JFrame | |
import java.awt.Color | |
import java.awt.Canvas | |
object Metaball extends Canvas { | |
val WIDTH = 600 | |
val HEIGHT = 600 | |
val MIN_THRESHOLD = 1 | |
val MAX_THRESHOLD = 50 | |
setBounds(0, 0, WIDTH, HEIGHT) | |
setBackground(Color.BLACK) | |
val frame = new JFrame("Metaballs") | |
frame.setSize(new Dimension(WIDTH, HEIGHT)) | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) | |
frame.getContentPane.add(this) | |
frame.setResizable(false) | |
frame.setVisible(true) | |
createBufferStrategy(2) | |
val buffer = getBufferStrategy | |
val graphics = buffer.getDrawGraphics | |
class Ball(var x: Double, var y: Double, var vx: Double, var vy: Double, val radius: Double, val color: Color) | |
def random(min: Double, max: Double) = min + Math.random * (max - min + 1.0) | |
def getInfluence(ball: Ball, px: Int, py: Int): Double = { | |
val dx = ball.x - px | |
val dy = ball.y - py | |
return ball.radius / Math.sqrt(dx * dx + dy * dy) | |
} | |
def move(ball: Ball) { | |
ball.vx = if (ball.x > WIDTH || ball.x < 0) -ball.vx else ball.vx | |
ball.vy = if (ball.y > HEIGHT || ball.y < 0) -ball.vy else ball.vy | |
ball.x += ball.vx | |
ball.y += ball.vy | |
} | |
def colorFalloff(color: Double, sum: Double): Int = { | |
val distance = if (sum > MAX_THRESHOLD) MAX_THRESHOLD - sum else MIN_THRESHOLD + sum | |
val newColor = (color / distance * 2).toInt | |
if (newColor < 0) return 0 | |
else if (newColor > 255) return 255 | |
return newColor | |
} | |
def drawPixel(g: Graphics, c: Color, x: Int, y: Int, size: Int) { | |
g.setColor(c) | |
g.fillRect(x, y, size, size) | |
} | |
def render(balls: IndexedSeq[Ball]) { | |
val sampleSize = 4 | |
val xrange = Range(0, WIDTH / sampleSize) map ((n) => n * sampleSize) | |
val yrange = Range(0, HEIGHT / sampleSize) map ((n) => n * sampleSize) | |
for (x <- xrange) { | |
for (y <- yrange) { | |
var red = 0.0 | |
var green = 0.0 | |
var blue = 0.0 | |
var sum = 0.0 | |
for (ball <- balls) { | |
val influence = getInfluence(ball, x, y) | |
red += ball.color.getRed * influence | |
green += ball.color.getGreen * influence | |
blue += ball.color.getBlue * influence | |
sum += influence | |
} | |
if (sum <= MAX_THRESHOLD) drawPixel(graphics, Color.white, x, y, sampleSize) | |
if (sum >= MIN_THRESHOLD) { | |
val color = new Color( | |
if (red > 255) 255 else red.toInt, | |
if (blue > 255) 255 else blue.toInt, | |
if (green > 255) 255 else green.toInt) | |
drawPixel(graphics, color, x, y, sampleSize) | |
} else { | |
val color = new Color(colorFalloff(red, sum), colorFalloff(blue, sum), colorFalloff(green, sum)) | |
drawPixel(graphics, color, x, y, sampleSize) | |
} | |
} | |
} | |
if (!buffer.contentsLost) buffer.show | |
for (ball <- balls) move(ball) | |
Thread.sleep(10) | |
render(balls) | |
} | |
def main(args: Array[String]) { | |
val balls = Range(0, 6) map | |
((_) => | |
new Ball(random(10, WIDTH - 10), | |
random(10, HEIGHT - 10), | |
random(1, 10), | |
random(1, 10), | |
random(50, 70), | |
new Color(random(1, 255).toInt, random(1, 255).toInt, random(1, 255).toInt))) | |
render(balls) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Canvas; | |
import java.awt.Color; | |
import java.awt.Dimension; | |
import java.awt.Graphics; | |
import java.awt.image.BufferStrategy; | |
import java.util.ArrayList; | |
import java.util.List; | |
import javax.swing.JFrame; | |
import javax.swing.JPanel; | |
public class Main extends Canvas { | |
private static final long serialVersionUID = 1L; | |
private static double MIN_THRESHOLD = 1; | |
private static double MAX_THRESHOLD = 1.1; | |
final static int WIDTH = 500; | |
final static int HEIGHT = 500; | |
public BufferStrategy strategy; | |
static class Metaball { | |
public double x, y; | |
public double radius; | |
public double xspeed, yspeed; | |
public Color color; | |
Metaball(double x, double y, double xspeed, double yspeed, double radius, Color color) { | |
this.x = x; | |
this.y = y; | |
this.xspeed = xspeed; | |
this.yspeed = yspeed; | |
this.radius = radius; | |
this.color = color; | |
} | |
} | |
List<Metaball> balls = new ArrayList<Metaball>(); | |
static double random(double min, double max) { | |
return min + Math.random() * (max - min + 1); | |
} | |
static double getInfluence(Metaball ball, int px, int py) { | |
double dx = (ball.x - px); | |
double dy = (ball.y - py); | |
return ball.radius / Math.sqrt(dx * dx + dy * dy); | |
} | |
static void move(Metaball ball) { | |
ball.xspeed = (ball.x > WIDTH || ball.x < 0) ? -ball.xspeed : ball.xspeed; | |
ball.yspeed = (ball.y > HEIGHT || ball.y < 0) ? -ball.yspeed : ball.yspeed; | |
ball.x += ball.xspeed; | |
ball.y += ball.yspeed; | |
} | |
static int colorInRange(double c) { | |
return c < 0 ? 0 : c > 255 ? 255 : (int) c; | |
} | |
static int colorFalloff(int color, double sum) { | |
double distance; | |
if (sum > MAX_THRESHOLD) | |
distance = MAX_THRESHOLD - sum; | |
else | |
distance = MIN_THRESHOLD + sum; | |
return colorInRange((int) (color / distance * 2)); | |
} | |
static void drawPixel(Graphics g, Color c, int x, int y, int size) { | |
g.setColor(c); | |
g.fillRect(x, y, size, size); | |
} | |
public void render(Graphics g) { | |
double sum; | |
int red, green, blue; | |
int sampleSize = 4; | |
while (true) { | |
g.setColor(Color.black); | |
g.fillRect(0, 0, getWidth(), getHeight()); | |
for (int x = 0; x < WIDTH; x += sampleSize) { | |
for (int y = 0; y < HEIGHT; y += sampleSize) { | |
red = 0; | |
green = 0; | |
blue = 0; | |
sum = 0; | |
for (Metaball ball : balls) { | |
double influence = getInfluence(ball, x, y); | |
red += ball.color.getRed() * influence; | |
green += ball.color.getGreen() * influence; | |
blue += ball.color.getBlue() * influence; | |
sum += influence; | |
} | |
if (sum <= MAX_THRESHOLD) { | |
drawPixel(g, Color.white, x, y, sampleSize); | |
} | |
if (sum >= MIN_THRESHOLD) { | |
drawPixel(g, new Color(colorInRange(red), colorInRange(green), colorInRange(blue)), x, y, sampleSize); | |
} else { | |
drawPixel(g, | |
new Color(colorInRange(colorFalloff(red, sum)), | |
colorInRange(colorFalloff(green, sum)), | |
colorInRange(colorFalloff(blue, sum))), | |
x, y, sampleSize); | |
} | |
} | |
} | |
if (!strategy.contentsLost()) | |
strategy.show(); | |
for (Metaball ball : balls) { | |
move(ball); | |
} | |
try { | |
Thread.sleep(10); | |
} catch (InterruptedException ignored) { | |
} | |
} | |
} | |
public Main() { | |
for (int i = 0; i < 10; i++) { | |
balls.add(new Metaball(random(10, WIDTH - 10), | |
random(10, HEIGHT - 10), | |
random(1, 3), | |
random(1, 3), | |
random(20, 25), | |
new Color((int) random(1, 255), (int) random(1, 255), (int) random(1, 255)))); | |
} | |
render(init()); | |
} | |
private Graphics init() { | |
setBounds(0, 0, WIDTH, HEIGHT); | |
setBackground(Color.BLACK); | |
JPanel panel = new JPanel(); | |
panel.setPreferredSize(new Dimension(WIDTH, HEIGHT)); | |
panel.setLayout(null); | |
panel.add(this); | |
JFrame frame = new JFrame("Invaders"); | |
frame.add(panel); | |
frame.setBounds(0, 0, WIDTH, HEIGHT); | |
frame.setResizable(false); | |
frame.setVisible(true); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
createBufferStrategy(2); | |
strategy = getBufferStrategy(); | |
return strategy.getDrawGraphics(); | |
} | |
public static void main(String[] args) { | |
new Main(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment