砂で遊ぶ
マウスで自由に壁をつくります.
Shift + drag で消しゴムになります.
右クリックの 初期化 で初めの状態にもどります.
下に落ちたら上からまたふってきます.
砂の挙動は砂のような液体のような何か.
元ネタは名前を忘れてしまいましたが昔遊んだアプリからです.
/*
マウスで自由に壁をつくります.
Shift + drag で消しゴムになります.
右クリックの 初期化 で初めの状態にもどります.
下に落ちたら上からまたふってきます.
砂の挙動は砂のような液体のような何か.
元ネタは名前を忘れてしまいましたが昔遊んだアプリからです.
*/
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
[SWF(width=465, height=465, backgroundColor=0x000000, frameRate=60)]
public class SimSand extends Sprite
{
private var numSand:int;
private var sand:Array;
private var lineBmp:BitmapData;
private var sandBmp:BitmapData;
private var screenBmp:BitmapData;
private var lineSprite:Sprite;
private var printSprite:Sprite;
private var screenSprite:Sprite;
private var canvasWidth:int;
private var canvasHeight:int;
private var context:ContextMenu;
private var menuInit:ContextMenuItem;
public function SimSand()
{
canvasWidth = stage.stageWidth / 3;
canvasHeight = stage.stageHeight / 3;
context = new ContextMenu();
menuInit = new ContextMenuItem( "初期化", false );
contextMenu = context;
context.customItems.push( menuInit );
numSand = 1500;
init( null );
menuInit.addEventListener( ContextMenuEvent.MENU_ITEM_SELECT, init );
stage.addEventListener( Event.ENTER_FRAME, loop );
stage.addEventListener( MouseEvent.MOUSE_DOWN, startDrawCanvas );
}
private function init( e:ContextMenuEvent ):void
{
//set on and off EventListeners
stage.removeEventListener( MouseEvent.MOUSE_UP, stopDrawCanvas );
stage.removeEventListener( MouseEvent.MOUSE_MOVE, drawCanvas );
if( stage.hasEventListener( MouseEvent.MOUSE_DOWN ) == false )
{
stage.addEventListener( MouseEvent.MOUSE_DOWN, startDrawCanvas );
}
// create sand
sand = new Array();
for( var i:int = 0; i < numSand; i++ )
{
var ramX:int = Math.random() * canvasWidth / 4 + canvasWidth / 4 * 1.5;
var ramY:int = Math.random() * canvasHeight / 2 - canvasHeight / 2;
sand.push( new Sand( ramX, ramY, 0xFFFFFF00 ) );
}
lineSprite = new Sprite();
printSprite = new Sprite();
screenSprite = new Sprite();
//make standard stage
lineSprite.graphics.lineStyle( 3 , 0x0000FF , 1.0 );
lineSprite.graphics.moveTo( 0, 20 );
lineSprite.graphics.lineTo( canvasWidth / 2 - 2, 50);
lineSprite.graphics.moveTo( canvasWidth, 20 );
lineSprite.graphics.lineTo( canvasWidth / 2 + 2, 50 );
lineSprite.graphics.moveTo( canvasWidth / 5 * 2, 100 );
lineSprite.graphics.lineTo( canvasWidth / 5 * 3, 100 );
//sandglass extra stage
/*
lineSprite.graphics.lineStyle( 3 , 0x0000FF , 1.0 );
for( i = -1; i <= 1; i+=2 )
{
lineSprite.graphics.moveTo( -10 * 3 + canvasWidth / 2, i * 0.5 * 100 + 80 );
for( var j:int = -10; j <= 10; j+=1 )
{
lineSprite.graphics.lineTo( j * 3 + canvasWidth / 2, i * 0.5 * j * j + 80 );
}
if( i > 0 ) lineSprite.graphics.lineTo( -10 * 3 + canvasWidth / 2, i * 0.5 * 100 + 80 );
}
lineSprite.graphics.lineStyle( 2 , 0x000000 , 1.0 );
lineSprite.graphics.moveTo( canvasWidth / 2, 79 );
lineSprite.graphics.lineTo( canvasWidth / 2, 81 );
*/
lineBmp = new BitmapData( canvasWidth, canvasHeight, true, 0x0 );
screenBmp = new BitmapData( canvasWidth, canvasHeight, true, 0x0 );
sandBmp = new BitmapData( canvasWidth, canvasHeight, true, 0x0 );
printSprite.addChild( new Bitmap(lineBmp) );
screenSprite.addChild( printSprite );
screenSprite.addChild( lineSprite );
screenSprite.addChild( new Bitmap( sandBmp ) );
screenSprite.scaleX = stage.stageWidth / canvasWidth;
screenSprite.scaleY = stage.stageHeight / canvasHeight;
addChild(screenSprite);
}
private function loop( e:Event ):void
{
screenSprite.graphics.clear();
screenSprite.graphics.beginFill(0x0);
screenSprite.graphics.drawRect(0, 0, canvasWidth, canvasHeight);
screenSprite.graphics.endFill();
screenBmp.draw( screenSprite );
sandBmp.lock();
sandBmp.fillRect( new Rectangle(0,0,canvasWidth, canvasHeight), 0x00000000);
for( var i:int = 0; i < numSand; i++ )
{
//falling noise
var noise:int = 0;
var neighbor:uint = 0;
for( var j:int = -1; j <= 1; j++ )
{
neighbor += screenBmp.getPixel( sand[i].x + j, sand[i].y + 1 );
}
if( neighbor == 0x0 )
{
noise = 0;
}
else
{
noise = int( Math.random() * 3 - 1.5 );
if( sand[i].x + noise < 0 || sand[i].x + noise>= canvasWidth )
{
noise = 0;
}
}
//on falling down
if( screenBmp.getPixel( sand[i].x + noise, sand[i].y + 1 ) == 0x000000 )
{
sand[i].x += noise;
sand[i].y += 1;
}
//staying on wall
else
{
var deltaX:int = int( Math.random() * 3 - 1.5 );
var deltaY:int = 0;//int( Math.random() * 2 );
if( sand[i].x + deltaX > 0 && sand[i].x + deltaX < canvasWidth )
{
if( screenBmp.getPixel( sand[i].x + deltaX, sand[i].y + deltaY ) == 0x000000 )
{
sand[i].x += deltaX;
sand[i].y += deltaY;
}
}
}
if( sand[i].y > canvasHeight ) sand[i].y = 0;
sandBmp.setPixel32( sand[i].x, sand[i].y, sand[i].color );
}
sandBmp.unlock();
}
private function startDrawCanvas( e:MouseEvent ):void
{
if( e.shiftKey == false )
{
lineSprite.graphics.lineStyle( 3 , 0x0000FF ); // make-wall mode
}
else
{
lineSprite.graphics.lineStyle( 5, 0x000000 ); // eraser mode
}
lineSprite.graphics.moveTo( stage.mouseX / screenSprite.scaleX, stage.mouseY / screenSprite.scaleY );
stage.removeEventListener( MouseEvent.MOUSE_DOWN, startDrawCanvas );
stage.addEventListener( MouseEvent.MOUSE_MOVE, drawCanvas );
stage.addEventListener( MouseEvent.MOUSE_UP, stopDrawCanvas );
}
private function stopDrawCanvas( e:MouseEvent ):void
{
lineBmp.draw( lineSprite );
lineSprite.graphics.clear();
printSprite.graphics.clear();
stage.removeEventListener( MouseEvent.MOUSE_MOVE, drawCanvas );
stage.removeEventListener( MouseEvent.MOUSE_UP, stopDrawCanvas );
stage.addEventListener( MouseEvent.MOUSE_DOWN, startDrawCanvas );
}
private function drawCanvas( e:MouseEvent ):void
{
lineSprite.graphics.lineTo( stage.mouseX / screenSprite.scaleX, stage.mouseY / screenSprite.scaleY)
}
}
}
import flash.geom.Point;
class Sand
{
public var x:int;
public var y:int;
public var color:uint;
public function Sand( px:int, py:int, pcolor:uint )
{
x = px;
y = py;
color = pcolor;
}
}