Latest snippets

Adding Very Large Numbers

// tracing out large numbers will go into exponent notation
trace(1000000000000000000000000);
// outputs: 1e+24

var a:String =  "1000000000000000000000009";
var b:String = "12000000000000000000000001";

// bigAdd function adds two large numbers 
trace(bigAdd(a, b));
// outputs: 13000000000000000000000010

// unclear what regular addition is doing here:
trace(int(a) + int(b));
// outputs: -3758096384

function bigAdd(a:String, b:String):String{
       var answer:String="";
       var carry:int = 0;
	   var zeros:int = 0;
	   var i:int = 0;
	   var max:int = 0;
	    
		// obtain max variable and prepend zeros to the shortest string
	   if (a.length > b.length){
		  max = a.length;
		  zeros = max - b.length;
		   for (i= 0; i<zeros; i++) {
				b = "0" + b;
		   }
	   }else if (b.length >  a.length){
		   max = b.length;
		   zeros = max - a.length;
		   for (i= 0; i<zeros; i++) {
				a = "0" + a  ;
			}
	   }else{
		   // a and b have same number of digets
		   max = a.length;   
	   }
	   
	   // add each character starting with the last (max - 1), 
	   // carry the 1 if the sum has a length of 2
       for (i = max - 1;  i > -1; i--){ 
               var sum:String = String(int(a.charAt(i)) + int(b.charAt(i)) + carry);

               if (sum.length == 2){
                       answer = sum.charAt(1) + answer;
                       carry = 1;
               }else{
                       carry = 0;
                       answer = sum + answer;
               }
       }
	   if (carry == 1){
           answer = 1 + answer;
       }
       return answer;
}

This snippet demos a function called bigAdd(), which can be used to add very large numbers that the standard numerical datatypes (int, Number, etc) won’t really work with. It uses a string based addition algorithm.

When I decided to write this snippet I dug around for awhile trying to find a nice elegant algorithm to port, something done without prepending zeros etc…. but I couldn’t find one that suited my needs… so I just created this one from scratch. There’s room for optimization and improvement but it works well enough for just playing around.

BigDecimal & BigInteger

A few months back I needed to do some programming with very large numbers. I dug around for awhile and eventually found out that java has a built in BigInteger andBigDecimal class…. I used java to write the program I had in mind, but thought it would be fun to eventually create something similar for ActionScript….

E?

trace(Math.pow((1+1/10000000),10000000));

trace(Math.E);

/*outputs :

2.7182816939803724
2.718281828459045

*/

E

2.7182818284590452353602874713526624977572470936999595749669676277240766303535
47594571382178525166427427466391932003059921817413596629043572900334295260595630
73813232862794349076323382988075319525101901157383418793070215408914993488416750
92447614606680822648001684774118537423454424371075390777449920695517027618386062
61331384583000752044933826560297606737113200709328709127443747047230696977209310
14169283681902551510865746377211125238978442505695369677078……

Clamp Math.max(Math.min())

// this one-liner is good to know:
// Math.max(minValue, Math.min(maxValue, valueToClamp));

// wrapped in a function it looks like this:
const MIN:Number = 0;
const MAX:Number = 100;

function clamp(val:Number, min:Number = MIN, max:Number = MAX){
	return Math.max(min, Math.min(max, val))
}

for (var i:int = 0; i<1000; i++){
	var val:Number = Math.random()*1000 - 500;
    // clamp the above random value between -100 and +100
    trace(clamp(val, -100, 100));
}

Although I show a function implementation above, I use this technique inline a good deal. If there is some value that I need to clamp I’ll often just “max min it”:

var val:Number = Math.random()*1000;
// clamp it - 0-100
trace(Math.max(0, Math.min(100, val));

Constants as Function Argument Defaults

const RADIUS = 10;
const COLOR = 0xCCCCCC;

function createCircle(xp:Number, yp:Number, radius:Number = RADIUS, col:uint = COLOR):void{
	var c:Sprite = new Sprite();
	c.graphics.beginFill(col);
	c.graphics.drawCircle(xp, yp, radius);
	addChild(c);
}

// optional last 2 values are populated with const defaults
createCircle(100,100);
// optional color value is populated with default 0xCCCCCC;
createCircle(200,100, 20);
//
createCircle(300,100, 50,0x0000FF);

x2

var c:Number = 1;
addEventListener(Event.ENTER_FRAME, function(){c *= 2,  trace(c)});

and….
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
2147483648
4294967296
8589934592
17179869184
34359738368
68719476736
137438953472
274877906944
549755813888
1099511627776
2199023255552
4398046511104
8796093022208
17592186044416
35184372088832
70368744177664
140737488355328
281474976710656
562949953421312
1125899906842624
2251799813685248
4503599627370496
9007199254740992
18014398509481984
36028797018963970
72057594037927940
144115188075855870
288230376151711740
576460752303423500
1152921504606847000
2305843009213694000
4611686018427388000
9223372036854776000
18446744073709552000
36893488147419103000
73786976294838210000
147573952589676410000
295147905179352830000
590295810358705700000

etc…

Isometric to Cartesian

var centerX:Number=stage.stageWidth/2;
var centerY:Number=stage.stageHeight/2;
// 1 to 2 ratio
// try others 1 / 1.5 etc...
var theta:Number = Math.atan(1 / 2);
 
var cosX:Number=Math.cos(theta);
var sinX:Number=Math.sin(theta);
var pnt:Point = new Point();

function iso3D(x:Number, y:Number, z:Number):Point {
	pnt.x = centerX + (x-z) *  cosX;
	pnt.y = centerY -  (x+z) * sinX - y;
	return pnt;
}

var p:Point = iso3D(0,0,0);

graphics.beginFill(0x000000);
graphics.drawCircle(p.x, p.y, 2);

// x axis positive
trace("x = red");
for (var i:int = 1; i<10; i++){
	graphics.beginFill(0xFF0000);
	p = iso3D(i*10, 0, 0);
	graphics.drawCircle(p.x, p.y, 2);
}

// y axis positive
trace("y = green");
for (i= 1; i<10; i++){
	graphics.beginFill(0x00FF00);
	p = iso3D(0, i * 10, 0);
	graphics.drawCircle(p.x, p.y, 2);
}

// z axis positive
trace("z = blue");
for (i= 1; i<10; i++){
	graphics.beginFill(0x0000FF);
	p = iso3D(0, 0, i * 10);
	graphics.drawCircle(p.x, p.y, 2);
}

The above code demos a conversion from isometric coordinates to cartesian coordinates. It draws out part of the x, y and z axis using the iso3D() function.

I’ve always faked isometric conversion by just tweaking numbers. A few years ago I created some strange isometric engines (here’s another example ). The other day when I wrote the isometric voxels snippet I just created the iso3D() function with a little trial and error. As you’ll see it’s not exactly the same as the one here. This new conversion is the result of some googling. The updated conversion is pretty close to the one that I wrote for the voxel post, but has one less multiplication… and a clearer place to control the scale ratio …

Matrix.transformPoint()

var circle:Shape = Shape(addChild(new Shape()));
with(circle.graphics) beginFill(0x00000), drawCircle(0,0,10);

var point:Point = new Point();
var trans:Matrix = new Matrix();
trans.rotate(Math.PI);
trans.scale(.5, .5);
trans.tx = stage.stageWidth / 2;
trans.ty = stage.stageHeight / 2;

addEventListener(Event.ENTER_FRAME, onLoop);

function onLoop(evt:Event):void {
	point.x = mouseX - trans.tx;
	point.y = mouseY - trans.ty;
	
	point = trans.transformPoint(point);
	
	circle.x = point.x;
	circle.y = point.y;
}

If you don’t feel like rolling your own transformations Matrix.transformPoint() is a very powerful method. It simply applies the tranformations of a given matrix to a Point. The above example scales rotates and translates a point which is then used to position a circle Shape.

Matrix.transformPoint() is well suited for creating orbiting behavior:

var circle:Shape = Shape(addChild(new Shape()));
with(circle.graphics) beginFill(0x00000), drawCircle(0,0,10);

var point:Point = new Point(100,0);
var trans:Matrix = new Matrix();
 trans.rotate(.1);
 trans.scale(.99,.99);

addEventListener(Event.ENTER_FRAME, onLoop);

function onLoop(evt:Event):void {
	 
      point = trans.transformPoint(point);
	 
      circle.x = point.x + stage.stageWidth / 2;
      circle.y = point.y + stage.stageHeight / 2;
}

This code will cause the circle Shape to move in a spiral formation.

BitmapData.floodFill()

var canvas:BitmapData = new BitmapData(400,400,false, 0xCC0000);
addChild(new Bitmap(canvas));

var s:Shape = new Shape();
s.graphics.beginFill(0x00CCCC);
s.graphics.moveTo(Math.random()*400,Math.random()*400);
for(var i:int = 0; i<10; i++){
	s.graphics.lineTo(Math.random()*400,Math.random()*400);
}
canvas.draw(s);

stage.addEventListener(MouseEvent.CLICK, onDown);
function onDown(evt:MouseEvent):void {
	canvas.floodFill(mouseX, mouseY, 0x000000);
}

floodFill() is basically the paint bucket (fill) tool in any bitmap drawing program. The above example draws an arbitrary blue polygon to a red background. Click anywhere on the resulting image to see floodFill() in action.

floodFill() takes 3 arguments… x, y and color.

E4X and ActionScript Variables

var backgroundColor:uint = 0xEFEFEF;
var borderColor:uint = 0xFF0000;
var buttonOverColor:uint = 0x0000FF;
var buttonOutColor:uint = 0x00CCCC;

var uiColors:XML = <ui>
	<default color="0xCCCCCC" />
	<background color = { backgroundColor } />
	
	<!-- note hexidecimal formatting code -->
	<border color={ ("0x" + borderColor.toString(16)) } />
	
	<button overColor={ buttonOverColor} outColor={ buttonOutColor } />
</ui>

trace(uiColors.toXMLString());

/*outputs:
<ui>
  <default color="0xCCCCCC"/>
  <background color="15724527"/>
  <border color="0xff0000"/>
  <button overColor="255" outColor="52428"/>
</ui>
*/

The first time I needed to use an ActionScript variable within inline XML I was stumped. I couldn’t figure it out and I wasn’t able to easily find it on google. I eventually found it somewhere (don’t remember where… possibly hidden away in the docs).

Now a search for “insert actionscript variables into e4x” on google gives plenty of results. But I figure it’s worth a post.

I use actionscript to generate XML all the time so this comes in handy. I also store color values in automatically generated XML all the time. If I’m feeling organized I’ll use something like what you see on line 10:

<border color={ ("0x" + borderColor.toString(16)) } />

If you look at the output you’ll see this formats the uint so that it’s readable as a hex number. By default (as you can see in the output) uints will show up in decimal notation. This really doesn’t make any difference if you don’t care about XML readability … or if you just don’t care about the readability of the colors stored in your XML…..