import java.awt.image.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.awt.Image;
import java.awt.Font;
import java.util.Vector; // http://java.sun.com/products/jdk/1.1/docs/api/java.util.Vector.html
//---- MAIN CLASS ------------------------------------------------------------//
public class Site3D extends tinyptc
{
//---- DATA
//- Buffers
int width, height, size;
int[] back;
int[] buf;
int[] pot;
//- Mouse
int mouse_x = 0, mouse_y = 0;
boolean mouse_click = false;
//- Particle system
int num_particles = 1300;
double[] particle_x, particle_y, particle_vx, particle_vy;
boolean[] particle_active;
double particle_force_x, particle_force_y, particle_friction;
//---- CODE
//---- fillRect
public void fillRect(int[] buf, int x1, int y1, int x2, int y2, int col)
{
int i, j;
for(j=y1; j<y2; j++) for(i=x1; i<x2; i++) buf[i+width*j] = col;
}
//---- getPot
public int getPot(double x, double y)
{
int xx = (int)x, yy = (int)y;
if(xx < 0 || xx >= width || yy < 0 || yy >= height) return 0;
return pot[xx+width*yy];
}
//---- drawParticle
public void drawParticle(int[] buf, double px, double py)
{
int i, j;
double d;
int x = (int)px - 6;
int y = (int)py - 6;
for(j=y; j<=y+12; j++)
{
for(i=x; i<=x+12; i++)
{
if(i >= 0 && i < width && j >= 0 && j < height)
{
d = (i-px)*(i-px) + (j-py)*(j-py);
d /= 25;
d = 1-d;
if(d < 0) d = 0;
if(d > 1) d = 1;
// buf[i+width*j] = (int)(buf[i+width*j] * (1-d) + 255 * d);
buf[i+width*j] += (int)(d*512);
}
}
}
}
//---- calcForce
public void calcForce(int[] buf, double px, double py)
{
int i, j;
double d;
particle_force_x = 0;
particle_force_y = 0;
particle_friction = 0.99;
double f;
int x = (int)px - 11;
int y = (int)py - 11;
for(j=y; j<=y+22; j++)
{
for(i=x; i<=x+22; i++)
{
if(i >= 0 && i < width && j >= 0 && j < height)
{
d = (i-px)*(i-px) + (j-py)*(j-py);
d /= 100;
d = 1-d;
if(d < 0) d = 0;
if(d > 1) d = 1;
//- Get value mixed with force
f = buf[i+width*j] - 5100;
if(f < 0) f =- f;
if(f < 0) f = 0;
if(f > 8000) f = 8000;
f *= d;
particle_friction -= 0.00000001 * f * d;
particle_force_x -= 0.000016 * f * d * (i-px);
particle_force_y -= 0.000016 * f * d * (j-py);
}
}
}
// particle_friction *= 0.0000005;
// particle_friction = 1-particle_friction;
if(particle_friction < 0.9) particle_friction = 0.9;
}
//---- main
public void main(int width, int height)
{
int i, j;
int x, y;
int frame = 0;
//- Set up variables
this.width = width;
this.height = height;
size = width * height;
back = new int[size];
buf = new int[size];
pot = new int[size];
//- Set up particle system
particle_x = new double[num_particles];
particle_y = new double[num_particles];
particle_vx = new double[num_particles];
particle_vy = new double[num_particles];
particle_active = new boolean[num_particles];
for(i=0; i<num_particles; i++) particle_active[i] = false;
//- Create background
for(i=size-1; i>=0; i--) back[i] = 0;
fillRect(back, 20, 100, 100, 130, 0x7FFFFFFF);
fillRect(back, 50, 190, 190, 220, 0x7FFFFFFF);
//- Animation loop
while (true)
{
//- Add a new particle if necessary
if(mouse_click)
{
for(j=0; j<3; j++)
{
for(i=0; i<num_particles && particle_active[i]; i++);
if(i < num_particles)
{
particle_active[i] = true;
particle_x[i] = mouse_x - 2 + 4*(((j*6172+frame*frame*11714)%12379)/12379.0);
particle_y[i] = mouse_y - 2 + 4*(((j*9899+frame*frame*8394)%17121)/17121.0);
particle_vx[i] = 0;
particle_vy[i] = 0;
}
}
}
//- Move particles
for(i=0; i<num_particles; i++) if(particle_active[i])
{
//- Gravity
particle_vy[i] += 0.5;
//- Update velocity
/*
if(getPot(particle_x[i] + particle_vx[i], particle_y[i] + particle_vy[i]) > 1024)
{
particle_vy[i] = 0;
}
*/
calcForce(pot, particle_x[i], particle_y[i]);
//- Limit acceleration
/*
if(particle_force_x < -3) particle_force_x = -3;
if(particle_force_x > 3) particle_force_x = 3;
if(particle_force_y < -3) particle_force_y = -3;
if(particle_force_y > 3) particle_force_y = 3;
*/
particle_vx[i] += particle_force_x;
particle_vy[i] += particle_force_y;
//- Apply friction
particle_vx[i] *= particle_friction;
particle_vy[i] *= particle_friction;
/*
if(particle_vx[i] < -5) particle_vx[i] = -5;
if(particle_vx[i] > 5) particle_vx[i] = 5;
if(particle_vy[i] < -5) particle_vy[i] = -5;
if(particle_vy[i] > 5) particle_vy[i] = 5;
*/
//- Move particle
particle_x[i] += 0.02 * (particle_vx[i] - 0.005 + 0.01*(((frame*frame*3171)%5237)/5237.0));
particle_y[i] += 0.02 * (particle_vy[i] - 0.005 + 0.01*(((frame*frame*4187)%5771)/5771.0));
//- Remove particle if necessary
if(particle_y[i] >= 256) particle_active[i] = false;
}
//- Clear buffers
for(i=size-1; i>=0; i--) buf[i] = back[i];
for(i=size-1; i>=0; i--) pot[i] = back[i];
//- Render particles
for(i=0; i<num_particles; i++) if(particle_active[i])
{
drawParticle(pot, particle_x[i], particle_y[i]);
}
//- Render water
for(i=0; i<size; i++)
{
if(pot[i] > 800) buf[i] |= 0x00FF00;
}
//- Display frame
update(buf);
frame++;
}
}
//---- mouseMove
public boolean mouseMove(Event e, int x, int y)
{
mouse_x = x;
mouse_y = y;
return true;
}
//---- mouseDrag
public boolean mouseDrag(Event e, int x, int y)
{
mouse_x = x;
mouse_y = y;
return true;
}
//---- mouseDown
public boolean mouseDown(Event e, int x, int y)
{
mouse_click = true;
return true;
}
//---- mouseUp
public boolean mouseUp(Event e, int x, int y)
{
mouse_click = false;
return true;
}
}
//---- end of code -----------------------------------------------------------//