By Zevan | February 21, 2009
Actionscript:
-
[SWF(width = 600, height = 400)]
-
-
// draw the same grid as yesterday
-
var tileSize:int = 40;
-
var cols:int = stage.stageWidth / tileSize;
-
var rows:int = stage.stageHeight / tileSize;
-
var grid:Sprite = Sprite(addChild(new Sprite()));
-
grid.graphics.lineStyle(0,0x000000);
-
var i:int = 0;
-
for (i = 1; i<cols; i++){
-
var posX:Number = i * tileSize
-
grid.graphics.moveTo(posX, 0);
-
grid.graphics.lineTo(posX, stage.stageHeight);
-
}
-
for (i = 1; i<rows; i++){
-
var posY:Number = i * tileSize
-
grid.graphics.moveTo(0, posY);
-
grid.graphics.lineTo(stage.stageWidth, posY);
-
}
-
-
//
-
// -- add a circle that snaps to the grid when dragged
-
//
-
var circle:Sprite = Sprite(addChild(new Sprite()));
-
with (circle.graphics) beginFill(0xFF0000), drawCircle(0,0,10);
-
circle.x = circle.y = tileSize * 3;
-
circle.buttonMode = true;
-
-
circle.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
-
function onDown(evt:MouseEvent):void {
-
addEventListener(Event.ENTER_FRAME, onRunSnapping);
-
}
-
-
function onRunSnapping(evt:Event):void {
-
circle.x = Math.round(mouseX / tileSize) * tileSize;
-
circle.y = Math.round(mouseY / tileSize) * tileSize;
-
}
-
-
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
-
function onUp(evt:MouseEvent):void {
-
removeEventListener(Event.ENTER_FRAME, onRunSnapping);
-
}
This builds on yesterdays post by adding a draggable red circle that snaps to the grid. This is the real trick:
Actionscript:
-
circle.x = Math.round(mouseX / tileSize) * tileSize;
-
circle.y = Math.round(mouseY / tileSize) * tileSize;
By Zevan | February 20, 2009
Actionscript:
-
// try changing the size of the stage
-
[SWF(width = 600, height = 400)]
-
-
// try changing the tile size (make sure swf width and height are evenly divisible by this number)
-
var tileSize:int = 20;
-
-
-
var cols:int = stage.stageWidth / tileSize;
-
var rows:int = stage.stageHeight / tileSize;
-
-
var grid:Sprite = Sprite(addChild(new Sprite()));
-
grid.graphics.lineStyle(0,0x000000);
-
-
var i:int = 0;
-
-
for (i = 1; i<cols; i++){
-
var posX:Number = i * tileSize
-
grid.graphics.moveTo(posX, 0);
-
grid.graphics.lineTo(posX, stage.stageHeight);
-
}
-
for (i = 1; i<rows; i++){
-
var posY:Number = i * tileSize
-
grid.graphics.moveTo(0, posY);
-
grid.graphics.lineTo(stage.stageWidth, posY);
-
}
This is a quick way to fill the stage with a grid. I like my grids to have square tiles with sizes like 5x5, 10x10 20x20 etc.... So as long as you make sure that you're swf width and height are evenly divisible by your tileSize, this snippet will work nicely.
By Zevan | February 19, 2009
Actionscript:
-
// best thing about this are the random seeds
-
var s1:Number= 0xFFFFFF;
-
var s2:Number = 0xCCCCCC;
-
var s3:Number= 0xFF00FF;
-
-
// saw this algorithm on this somewhat annoying thread:
-
// http://www.reddit.com/r/programming/comments/7yjlc/why_you_should_never_use_rand_plus_alternative/
-
// additional googling brought me to this: http://wakaba.c3.cx/soc/kareha.pl/1100499906/
-
// and finally to this ( didn't understand most of this one) www.ams.org/mcom/1996-65-213/S0025-5718-96-00696-5/S0025-5718-96-00696-5.pdf
-
-
function rand():Number {
-
s1=((s1&4294967294)<<12)^(((s1<<13)^s1)>>19);
-
s2=((s2&4294967288)<<4)^(((s2<<2)^s2)>>25);
-
s3=((s3&4294967280)<<17)^(((s3<<3)^s3)>>11);
-
var r:Number = (s1^s2^s3) * 2.3283064365e-10;
-
r = (r<0) ? r+=1 : r;
-
return r;
-
}
-
-
// see a visual comparison between this and actionscript's Math.random()
-
-
var canvas:BitmapData = new BitmapData(400,400,false, 0xCCCCCC);
-
addChild(new Bitmap(canvas));
-
-
var posX:Number;
-
var posY:Number;
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
-
function onLoop(evt:Event):void {
-
-
for (var i:int = 0; i<100; i++){
-
posX = rand() * 180
-
posY = rand() * 180
-
canvas.setPixel( 100 + posX, 10 + posY, 0x000000);
-
}
-
-
for (i = 0; i<100; i++){
-
posX = Math.random() * 180
-
posY = Math.random() * 180
-
canvas.setPixel( 100 + posX, 210 + posY, 0x000000);
-
}
-
}
The above snippet demo's an alternative random number generator that uses the Tausworthe method.
Top square is Tausworthe and bottom is Math.random()
I don't actually know much about this, or fully understand how it works. I just saw it on a random reddit thread, googled about it for a few minutes and then ported it to actionscript.
There's lots of talk about what the BEST random number generator is.... which one is the fastest, which one is the most random. etc... I don't really know much about that, especially since I'm just playing around with code and I don't need a RNG for some scientific experiment. For me, what's nice about this approach is the three random seeds. For some reason, Math.random() doesn't have a place where you can enter a seed for random numbers. Random seeds are very useful when you want to do something random but want to be able to replicate the random results at a later time. For instance:
Actionscript:
-
var s1:Number= 0xFFFFFF;
-
var s2:Number = 0xCCCCCC;
-
var s3:Number= 0xFF00FF;
-
-
trace("first three values:");
-
trace(rand());
-
trace(rand())
-
trace(rand())
-
-
s1 = 0xFF;
-
s2 = 0xEFEFEF;
-
s3 = 19008;
-
-
trace("\nfirst three values with different seeds:");
-
trace(rand());
-
trace(rand())
-
trace(rand())
-
-
s1 = 0xFFFFFF;
-
s2 = 0xCCCCCC;
-
s3 = 0xFF00FF;
-
-
trace("\noriginal three values:");
-
trace(rand());
-
trace(rand())
-
trace(rand())
-
-
function rand():Number {
-
s1=((s1&4294967294)<<12)^(((s1<<13)^s1)>>19);
-
s2=((s2&4294967288)<<4)^(((s2<<2)^s2)>>25);
-
s3=((s3&4294967280)<<17)^(((s3<<3)^s3)>>11);
-
var r:Number = (s1^s2^s3) * 2.3283064365e-10;
-
r = (r<0) ? r+=1 : r;
-
return r;
-
}
-
-
/*
-
outputs:
-
first three values:
-
0.051455706589931385
-
0.050584114155822715
-
0.417276361484596
-
-
first three values with different seeds:
-
0.6032885762463134
-
0.9319786790304015
-
0.8631882804934321
-
-
original three values:
-
0.051455706589931385
-
0.050584114155822715
-
0.417276361484596
-
*/
I stumbled upon a bunch of other random number algorithms, maybe I'll throw them in a class in the next couple days.
By Zevan | February 18, 2009
Actionscript:
-
var angOffset:Number = 0;
-
var percent:Number = 0;
-
-
var dial:Sprite = Sprite(addChild(new Sprite()));
-
with(dial.graphics) lineStyle(1, 0x000000), beginFill(0xCCCCCC), drawCircle(0,0,100), lineTo(0,0);
-
dial.x = stage.stageWidth / 2;
-
dial.y = stage.stageHeight / 2;
-
-
dial.addEventListener(MouseEvent.MOUSE_DOWN, onDialDown);
-
stage.addEventListener(MouseEvent.MOUSE_UP, onStageUp);
-
function onDialDown(evt:MouseEvent):void {
-
calcOffset();
-
dial.addEventListener(Event.ENTER_FRAME, onRotateDial);
-
}
-
-
function calcOffset():void {
-
angOffset = Math.atan2(mouseY - dial.y, mouseX - dial.x) / Math.PI * 180 - dial.rotation;
-
}
-
-
function onRotateDial(evt:Event):void {
-
dial.rotation = Math.atan2(mouseY - dial.y, mouseX - dial.x) / Math.PI * 180 - angOffset;
-
percent = dial.rotation;
-
if (percent <0){
-
percent += 360;
-
}
-
percent /= 360;
-
// range 0 - 1
-
trace(percent);
-
}
-
-
function onStageUp(evt:Event):void {
-
dial.removeEventListener(Event.ENTER_FRAME, onRotateDial);
-
}
The above shows the meat of what you need to create some kind of dial UI... this would also work well if you need to create an interactive turntable (record scratching etc...).
Everytime I needed to create dials for UI, the client wanted left -> right mouse motion rather than a circular... like what you see in Reason. Someone recently asked me how to do a circular motion style dial and this is the technique I came up with.
Posted in UI | Tagged actionscript, flash |