/* Copyright (c) 2011 EL-EMENT saharan * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * software and associated documentation * files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, * modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package { import flash.ui.*; import flash.text.*; import flash.geom.*; import flash.events.*; import flash.display.*; [SWF(frameRate = "60", width = "320", height = "320")] public class Sand extends Sprite { private const WIDTH:int = 320; private const HEIGHT:int = 320; private const BACK:uint = 0xff000000; private const WALL:uint = 0xff505050; private const SAND:uint = 0xffff0000; private var draw:uint; private var pmouseX:int; private var pmouseY:int; private var world:BitmapData; private var bitmap:Bitmap; private var count:int; private var press:Boolean; private var sandBitmap:BitmapData; private var randX:uint; private var randY:uint; private var randZ:uint; private var t:uint; private var pixels:Vector.; public function Sand() { if (stage) initialize(); else addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize():void { removeEventListener(Event.ADDED_TO_STAGE, initialize); randX = 123456789; randY = 987654321; randZ = 193865735; // Xorshiftのシード var sand:ContextMenuItem = new ContextMenuItem("Sand"); sand.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function():void { draw = SAND; }); var wall:ContextMenuItem = new ContextMenuItem("Wall"); wall.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function():void { draw = WALL; }); var erase:ContextMenuItem = new ContextMenuItem("Erase"); erase.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, function():void { draw = BACK; }); sandBitmap = new BitmapData(2, 2); sandBitmap.setPixel(0, 0, 0x00ffff); sandBitmap.setPixel(1, 0, 0xffffff); sandBitmap.setPixel(0, 1, 0x0055ff); sandBitmap.setPixel(1, 1, 0x00ff55); // 線の塗りBitmap contextMenu = new ContextMenu(); contextMenu.hideBuiltInItems(); contextMenu.customItems = [sand, wall, erase]; draw = SAND; count = 0; world = new BitmapData(WIDTH, HEIGHT, false, BACK); world.draw(stage); bitmap = new Bitmap(world); addChild(bitmap); stage.addEventListener(MouseEvent.MOUSE_DOWN, function():void { press = true; }); stage.addEventListener(MouseEvent.MOUSE_UP, function():void { press = false; }); addEventListener(Event.ENTER_FRAME, frame); } private function frame(e:Event):void { stage.quality = StageQuality.LOW; var s:Sprite = new Sprite(); if(press) { if (draw == SAND) { s.graphics.beginBitmapFill(sandBitmap); s.graphics.drawEllipse(mouseX - 3, mouseY - 3, 6, 6); s.graphics.endFill(); s.graphics.lineStyle(6); s.graphics.lineBitmapStyle(sandBitmap); s.graphics.moveTo(pmouseX, pmouseY); s.graphics.lineTo(mouseX, mouseY); world.draw(s); } else { s.graphics.beginFill(draw); s.graphics.drawEllipse(mouseX - 3, mouseY - 3, 6, 6); s.graphics.endFill(); s.graphics.lineStyle(6, draw); s.graphics.moveTo(pmouseX, pmouseY); s.graphics.lineTo(mouseX, mouseY); world.draw(s); } } pmouseX = mouseX; pmouseY = mouseY; var i:int; var j:int; var pixel:uint; var index:uint; pixels = world.getVector(world.rect); if(count & 1) // 左右の動きを対象化 for(j = HEIGHT - 1; j >= 0; j--) { for (i = 0; i < WIDTH; i++) { pixel = pixels[index = j * WIDTH + i]; if(pixel != BACK && pixel != WALL) { t = randX ^ (randX << 11); randX = randY; randY = randZ; if(((randZ = (randZ ^ (randZ >> 19)) ^ (t ^ (t >> 8))) & 63) != 0) if (getPix(i, j + 1) == BACK) { setPix(i, j + 1, pixel); pixels[index] = BACK; } else if (getPix(i + 1, j + 1) == BACK) { setPix(i + 1, j + 1, pixel); pixels[index] = BACK; } else if (getPix(i - 1, j + 1) == BACK) { setPix(i - 1, j + 1, pixel); pixels[index] = BACK; } else if (getPix(i + 1, j) == BACK) { setPix(i + 1, j, pixel); pixels[index] = BACK; } else if (getPix(i - 1, j) == BACK) { setPix(i - 1, j, pixel); pixels[index] = BACK; } } } } else for(j = HEIGHT - 1; j >= 0; j--) { for(i = WIDTH - 1; i >= 0; i--) { pixel = pixels[index = j * WIDTH + i]; if(pixel != BACK && pixel != WALL) { t = randX ^ (randX << 11); randX = randY; randY = randZ; if(((randZ = (randZ ^ (randZ >> 19)) ^ (t ^ (t >> 8))) & 63) != 0) if (getPix(i, j + 1) == BACK) { setPix(i, j + 1, pixel); pixels[index] = BACK; } else if (getPix(i - 1, j + 1) == BACK) { setPix(i - 1, j + 1, pixel); pixels[index] = BACK; } else if (getPix(i + 1, j + 1) == BACK) { setPix(i + 1, j + 1, pixel); pixels[index] = BACK; } else if (getPix(i - 1, j) == BACK) { setPix(i - 1, j, pixel); pixels[index] = BACK; } else if (getPix(i + 1, j) == BACK) { setPix(i + 1, j, pixel); pixels[index] = BACK; } } } } world.setVector(world.rect, pixels); count ^= 1; } private function getPix(x:uint, y:uint):uint { // 範囲外アクセスをブロック if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT) return pixels[y * WIDTH + x]; return 0xff000000; } private function setPix(x:uint, y:uint, color:uint):void { if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT) pixels[y * WIDTH + x] = color; } } }