Skip to content

Instantly share code, notes, and snippets.

@tai2
Last active March 25, 2017 12:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tai2/69981555a68152ab1ad58c75246d9bd5 to your computer and use it in GitHub Desktop.
Save tai2/69981555a68152ab1ad58c75246d9bd5 to your computer and use it in GitHub Desktop.
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