CellSet cellset; Raindrop[] raindrops; int rdn = 0; float wind = 0; PImage kazeimg; PImage kaze2img; PImage ameimg; PImage ame2img; void setup(){ background( 0, 0, 0 ); size( 580, 380 ); cellset = new CellSet( 50, 50, 20, 9 ); raindrops = new Raindrop[rdn]; for( int i = 0; i < rdn; i++ ){ raindrops[i] = new Raindrop(); } kazeimg = loadImage( "za.png" ); kaze2img = loadImage( "a.png" ); ameimg = loadImage( "si.png" ); ame2img = loadImage( "to.png" ); } void draw(){ background( 0, 0, 100 ); for( int i = 0; i < rdn; i++ ){ raindrops[i].update(); raindrops[i].mappingTo( cellset ); } cellset.update(); } void keyPressed(){ switch( key ){ case 'w': if( rdn < 30 ){ rdn++; } raindrops = new Raindrop[rdn]; for( int i = 0; i < rdn; i++ ){ raindrops[i] = new Raindrop(); } break; case 'q': if( rdn > 0 ){ rdn--; } raindrops = new Raindrop[rdn]; for( int i = 0; i < rdn; i++ ){ raindrops[i] = new Raindrop(); } break; case 'a': if( wind > 0.1f ){ wind -= 0.1f; } if( abs(wind) <= 0.1f ){ wind = 0; } break; case 's': if( wind < 3.0f ){ wind += 0.1f; } break; } println( "雨粒の数:" + rdn + ", 風力:" + wind ); } //雨粒 class Raindrop{ float x, y; float dx, dy; Raindrop(){ init(); } private void init(){ x = random( width ); y = 0; dx = 10-random(20); dy = random(20)+20; } void mappingTo( CellSet cellset ){ int ix, iy; float lenx, leny, len; for( iy = 0; iy < cellset.h; iy++ ){ for( ix = 0; ix < cellset.w; ix++ ){ lenx = cellset.cells_a[ix+iy*cellset.w].x+cellset.x-x; leny = cellset.cells_a[ix+iy*cellset.w].y+cellset.y-y; len = sqrt( lenx*lenx+leny*leny ); if( len < Cell.CELL_W-7 ){ cellset.cells_a[ix+iy*cellset.w].dx2 += dx*0.4f; cellset.cells_a[ix+iy*cellset.w].dy2 += dy*0.4f; } if( ix < cellset.w-1 && iy < cellset.h-1 ){ lenx = cellset.cells_b[ix+iy*(cellset.w-1)].x+cellset.x-x; leny = cellset.cells_b[ix+iy*(cellset.w-1)].y+cellset.y-y; len = sqrt( lenx*lenx+leny*leny ); if( len < Cell.CELL_W-7 ){ cellset.cells_b[ix+iy*(cellset.w-1)].dx2 += dx*0.2f; cellset.cells_b[ix+iy*(cellset.w-1)].dy2 += dy*0.2f; } } } } } void update(){ //stroke( 255, 255, 255 ); //line( x, y, x+dx, y+dy ); x += dx; y += dy; if( x < 0 || x > width || y > height ){ init(); } } } //セルの管理クラス class CellSet{ int x, y; int w, h; Cell[] cells_a; Cell[] cells_b; private float windx, windy; private float windnx, windny; private float srcny, srcy; private int counter; CellSet( int x, int y, int w, int h ){ this.x = x; this.y = y; this.w = w; this.h = h; this.windx = this.windy = 0; this.windnx = this.windny = 0; this.srcny = this.srcy = 0; this.counter = 0; cells_a = new Cell[w*h]; cells_b = new Cell[(w-1)*(h-1)]; for( int iy = 0; iy < h; iy++ ){ for( int ix = 0; ix < w; ix++ ){ cells_a[ix+iy*w] = new Cell( ix*Cell.CELL_W, iy*Cell.CELL_H ); if( ix < w-1 && iy < h-1 ){ cells_b[ix+iy*(w-1)] = new Cell( ix*Cell.CELL_W+Cell.CELL_W/2-10, iy*Cell.CELL_H+Cell.CELL_H/2-2 ); } } } } void update(){ //風 if( counter++ > 20 ){ windnx = (random(width)-width/2)*wind; windny = (random(height)-height/2)*wind; srcny = random(h); counter = 0; } windx += (windnx-windx)*0.1f; windy += (windny-windy)*0.1f; srcy += (srcny-srcy)*0.1f; float da; for( int iy = 0; iy < h; iy++ ){ da = (1.0f-(float)abs(srcy-iy)/h)+0.3f; da *= da; cells_a[iy*w].move( windx*0.15f*da, windy*0.15f*da ); if( iy < h-1 ){ cells_b[iy*(w-1)].move( windx*0.08f*da, windy*0.08f*da ); } } //伝播 for( int iy = 0; iy < h; iy++ ){ for( int ix = w-1; ix >= 1; ix-- ){ cells_a[ix+iy*w].move( cells_a[(ix-1)+iy*w].dx, cells_a[(ix-1)+iy*w].dy ); if( ix < w-1 && iy < h-1 ){ cells_b[ix+iy*(w-1)].move( cells_b[(ix-1)+iy*(w-1)].dx, cells_b[(ix-1)+iy*(w-1)].dy ); } } } //描画 fill( 50, 50, 200 ); noStroke(); pushMatrix(); translate( x, y ); for( int iy = 0; iy < h; iy++ ){ for( int ix = 0; ix < w; ix++ ){ cells_a[ix+iy*w].update( 0 ); if( ix < w-1 && iy < h-1 ){ cells_b[ix+iy*(w-1)].update( 1 ); } } } popMatrix(); } } //セル(構成要素) class Cell{ float x, y; float tx, ty; float dx, dy; float dx2, dy2; static final float CELL_W = 25; static final float CELL_H = 35; Cell( float x, float y ){ this.x = this.tx = x; this.y = this.ty = y; this.dx = this.dy = 0; this.dx2 = this.dy2 = 0; } void move( float dx, float dy ){ this.dx = dx; this.dy = dy; x = tx + dx + dx2; y = ty + dy + dy2; } void update( int type ){ dx2 *= 0.5f; dy2 *= 0.5f; float len = sqrt( dx*dx+dy*dy )+3; float rlen = sqrt( dx2*dx2+dy2*dy2 ); if( rlen > 0.1f){ if( type == 0 ){ len += rlen; image( ameimg, x-len/2, y-len/2, len, len ); } else{ len += rlen*2.0f; image( ame2img, x-len/2, y-len/2, len, len ); } } else if( len < 8 ){ len *= 0.5f; ellipse( x, y, len, len ); }else{ if( type == 0 ){ image( kazeimg, x-len/2, y-len/2, len, len ); } else{ image( kaze2img, x-len/2, y-len/2, len, len ); } } } }