Last active
March 25, 2017 12:26
-
-
Save tai2/69981555a68152ab1ad58c75246d9bd5 to your computer and use it in GitHub Desktop.
c.f. http://en.wikipedia.org/wiki/Smoking_clover This code is ported from http://sourceforge.net/projects/smokingclover/
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 { | |
import flash.display.Sprite; | |
import flash.display.Bitmap; | |
import flash.display.BitmapData; | |
import flash.events.Event; | |
public class SmokingClover extends Sprite { | |
private const N_COLORS:int = 256; | |
private const RADIUS:int = 5432; | |
private const MINVEL:Number = .003; | |
private const MAXVEL:Number = .15; | |
private var canvas:BitmapData; | |
private var canvasBitmap:Bitmap; | |
private var colors:Array; | |
private var counts:Array; | |
private var cstates:Array; | |
public function SmokingClover() | |
{ | |
var i:int; | |
Wonderfl.capture_delay(20); | |
canvas = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000); | |
canvasBitmap = new Bitmap(canvas); | |
addChild(canvasBitmap); | |
addEventListener(Event.ENTER_FRAME, enterFrame); | |
colors = new Array(N_COLORS); | |
for (i = 0; i < colors.length; i++) { | |
colors[i] = {r:0.0, g:0.0, b:0.0}; | |
var c:Object = colors[i]; | |
} | |
counts = new Array(stage.stageWidth * stage.stageHeight); | |
for (i = 0; i < counts.length; i++) { | |
counts[i] = 0; | |
} | |
cstates = new Array(3); | |
for (i = 0; i < cstates.length; i++) { | |
cstates[i] = {cur:0, vel:rnd(MINVEL, MAXVEL)}; | |
} | |
redraw_lines(); | |
redraw_dup(); | |
} | |
private function enterFrame(event:Event) : void | |
{ | |
next_color(1); | |
canvas.lock(); | |
var x:int; | |
var y:int; | |
for (y = 0; y < stage.stageHeight; y++) { | |
for (x = 0; x < stage.stageWidth; x++) { | |
var c:Object = colors[get_count(x, y) % 256]; | |
var r:int = 255 * c.r; | |
var g:int = 255 * c.g; | |
var b:int = 255 * c.b; | |
canvas.setPixel(x, y, (r<<16) | (g<<8) | (b<<0)); | |
} | |
} | |
canvas.unlock(); | |
} | |
private function rotate_colors(steps:int) : void | |
{ | |
if (steps >= N_COLORS) { | |
return; | |
} | |
var tail:Array = colors.splice(steps, colors.length - steps); | |
colors = tail.concat(colors); | |
} | |
private function next_color(steps:int) : void | |
{ | |
for (var step:int = 0; step < steps; step++) { | |
for (var i:int; i < cstates.length; i++) { | |
cstates[i].cur += cstates[i].vel; | |
if (cstates[i].cur > 1) { | |
cstates[i].cur = 1; | |
cstates[i].vel = rnd(-MAXVEL, -MINVEL); | |
} | |
if (cstates[i].cur < 0) { | |
cstates[i].cur = 0; | |
cstates[i].vel = rnd(MINVEL, MAXVEL); | |
} | |
} | |
rotate_colors(1); | |
colors[N_COLORS - 1].r = cstates[0].cur; | |
colors[N_COLORS - 1].g = cstates[1].cur; | |
colors[N_COLORS - 1].b = cstates[2].cur; | |
} | |
} | |
private function redraw_lines() : void | |
{ | |
var maxX:int = stage.stageWidth - 1; | |
var maxY:int = stage.stageHeight - 1; | |
var midX:int = maxX / 2; | |
var midY:int = maxY / 2; | |
var line_x:int = RADIUS; | |
var line_y:int = 0; | |
var line_f:int = 0; | |
for (;;) { | |
if (line_f > line_x) { | |
line_x--; | |
line_f = line_f - line_x - (line_x - 1); | |
} | |
clipLine( | |
midX, midY, | |
line_x + midX, line_y + midY, | |
0, 0, | |
maxX, maxY); | |
line_f = line_f + line_y + line_y + 1; | |
line_y++; | |
if (line_y >= line_x) { | |
break; | |
} | |
} | |
} | |
private function redraw_dup() : void | |
{ | |
var maxX:int = stage.stageWidth - 1; | |
var maxY:int = stage.stageHeight - 1; | |
var midX:int = maxX / 2; | |
var midY:int = maxY / 2; | |
var dup_x:int = midX; | |
for (;;) { | |
var nsteps:int = 4; | |
for (var step:int = 0; step < nsteps; step++) { | |
/* set vals on diagonal to 2*v-1 */ | |
if (dup_x - midX + midY <= maxY) { | |
put_count(dup_x, dup_x - midX + midY, | |
Math.max(0, 2 * get_count(dup_x, dup_x - midX + midY) - 1)); | |
} | |
/* now do a column from horizontal, down to diag */ | |
var yy:int = Math.min(maxY, dup_x - midX + midY); | |
for (var y:int = midY; y <= yy; y++) { | |
var val:int = get_count(dup_x, y); | |
var x1:int = dup_x; | |
var y1:int = y; | |
for (var i:int = 0; i < 4; i++) { | |
if ((y1 < maxY) && (y1 > 0)) { | |
put_count(midX + midX - x1, y1, val); | |
put_count(x1, y1, val); | |
} | |
var o:int = x1; | |
x1 = midX + midY - y1; | |
y1 = midY + o - midX; | |
} | |
} | |
dup_x++; | |
if (dup_x >= maxX) { | |
break; | |
} | |
} | |
if (dup_x >= maxX) { | |
break; | |
} | |
} | |
} | |
private function clipLine(x0:int, y0:int, xn:int, yn:int, xe:int, ye:int, xf:int, yf:int) : void | |
{ | |
var dx:int = Math.abs(xn - x0); | |
var dy:int = Math.abs(yn - y0); | |
if (xn > x0) { /* moving right */ | |
if (yn >= y0) { /* moving up */ | |
if (dx > dy) /* below diagonal */ | |
line(0, x0, y0, dx, dy, xe, ye, xf, yf); | |
else | |
line(1, y0, x0, dy, dx, ye, xe, yf, xf); | |
} else { | |
if (dx > dy) | |
line(7, x0, -y0, dx, dy, xe, -yf, xf, -ye); | |
else | |
line(6, -y0, x0, dy, dx, -yf, xe, -ye, xf); | |
} | |
} else { | |
if (yn >= y0) { | |
if (dx > dy) | |
line(3, -x0, y0, dx, dy, -xf, ye, -xe, yf); | |
else | |
line(2, y0, -x0, dy, dx, ye, -xf, yf, -xe); | |
} else { | |
if (dx > dy) | |
line(4, -x0, -y0, dx, dy, -xf, -yf, -xe, -ye); | |
else | |
line(5, -y0, -x0, dy, dx, -yf, -xf, -ye, -xe); | |
} | |
} | |
} | |
private function line(fun:int, x0:int, y0:int, dx:int, dy:int, xe:int, ye:int, xf:int, yf:int) : void | |
{ | |
var x:int = Math.max(x0, xe, | |
(dy == 0) ? xe : x0 + ceil(dx * (((ye - y0)<<1) - 1), (dy << 1))); | |
var num:int = dx + 2 * dy * (x - x0); | |
var lx:int = Math.min(xf, | |
(dy == 0) ? xf : x0 + ceil(dx * (((yf - y0)<<1) - 1), (dy << 1))); | |
var xx:int = Math.min(lx, x0 + (dx>>1)); | |
var y:int = y0 + floor(num, (dx<<1)); | |
var f:int = (floor(num, (dx<<1)) - dx) >> 1; | |
for (var x00:int = x; x00 < xx; x00++, f += dy) { | |
if (f + f > dx) { | |
f -= dx; | |
y++; | |
} | |
switch(fun) { | |
case 0: plot( x00, y); break; | |
case 1: plot( y, x00); break; | |
case 2: plot( -y, x00); break; | |
case 3: plot(-x00, y); break; | |
case 4: plot(-x00, -y); break; | |
case 5: plot( -y, -x00); break; | |
case 6: plot( y, -x00); break; | |
case 7: plot( x00, -y); break; | |
} | |
} | |
for (var x11:int = x00; x11 < lx; x11++, f += dy) { | |
if (f + f > dx) { | |
f -= dx; | |
y++; | |
} | |
switch(fun) { | |
case 0: plot( x11, y); break; | |
case 1: plot( y, x11); break; | |
case 2: plot( -y, x11); break; | |
case 3: plot(-x11, y); break; | |
case 4: plot(-x11, -y); break; | |
case 5: plot( -y, -x11); break; | |
case 6: plot( y, -x11); break; | |
case 7: plot( x11, -y); break; | |
} | |
} | |
} | |
private function get_count(x:int, y:int) : int | |
{ | |
return counts[stage.stageWidth * y + x]; | |
} | |
private function put_count(x:int, y:int, val:int) : void | |
{ | |
counts[stage.stageWidth * y + x] = val; | |
} | |
private function plot(x:int, y:int) : void | |
{ | |
counts[stage.stageWidth * y + x]++; | |
} | |
private function ceil(a:int, b:int) : int | |
{ | |
return (a + b - 1) / b; | |
} | |
private function floor(a:int, b:int) : int | |
{ | |
return ceil(a - b, b); | |
} | |
private function rnd(lo:Number, hi:Number) : Number | |
{ | |
return Math.random() * (hi - lo) + lo; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment