Issues with BitmapData of a MovieClip with rotationY applied to it - actionscript-3

So I have a simple file right now that eventually will take a movieclip and save it as an image. I am currently rotating the clip's y by 45 to give it kind of a 3D look and adding it back to the stage. I've tried googling and a couple different things, but I can't quite get it to work. The first thing I tried was getting the BitmapData of the movieclip I rotated. That flattened the clip:
test_mc.response_mc.rotationY = 45;
var mc:MovieClip = test_mc.response_mc;
var bmp:BitmapData = new BitmapData(mc.width, mc.height);
bmp.draw(mc);
var output:Bitmap = new Bitmap(bmp);
output.x = 270;
output.y = 191;
addChild(output);
The next thing I tried was getting the parent clip's BD. That gave it an angle... just the wrong one:
(same code as above with this line change)
var mc:MovieClip = test_mc;
Any thoughts here would be nice. I tried doing stuff with matrices, but had no luck. I also have images... just can't post them yet :(
Something else I've tried with no luck:
var target:DisplayObject = test_mc as DisplayObject;
var targetTransform:Matrix = target.transform.concatenatedMatrix;
var targetGlobalBounds:Rectangle = target.getBounds(target.stage);
var targetGlobalPos:Point = target.localToGlobal(new Point());
var targetOriginOffset:Point = new Point(targetGlobalPos.x - targetGlobalBounds.left, targetGlobalPos.y - targetGlobalBounds.top);
targetTransform.tx = targetOriginOffset.x;
targetTransform.ty = targetOriginOffset.y;
var cloneData:BitmapData = new BitmapData(targetGlobalBounds.width, targetGlobalBounds.height, true, 0x00000000);
cloneData.draw(target, targetTransform);
var output:Bitmap = new Bitmap(cloneData);
**Another update**
So hopefully this will help a little. I was able to recreate what I was doing using Matrix3D.
test_mc.response_mc.rotationY = 45;
var matrix:Matrix3D = new Matrix3D();
matrix.prependRotation(45, Vector3D.Y_AXIS);
test2_mc.response_mc.transform.matrix3D = matrix;
test2_mc.response_mc.transform.matrix3D.appendTranslation(0, 0, 0);
And I've come closer to getting the bitmap to look correct (thank to a Mike Chambers blog).
var mcOffset:Matrix3D = test2_mc.response_mc.transform.matrix3D;
var rawMatrixData:Vector.<Number> = mcOffset.rawData;
var globalBounds:Rectangle = test2_mc.response_mc.getBounds(test2_mc);
var matrix:Matrix = new Matrix();
matrix.a = rawMatrixData[0];
matrix.c = rawMatrixData[1];
matrix.tx = test2_mc.response_mc.x - globalBounds.x;
matrix.b = rawMatrixData[4];
matrix.d = rawMatrixData[5];
matrix.ty = test2_mc.response_mc.y - globalBounds.y;
var bmp:BitmapData = new BitmapData(150, test2_mc.height);
test2_mc.response_mc.transform.matrix3D = null;
bmp.draw(test2_mc.response_mc, matrix);
test2_mc.response_mc.transform.matrix3D = mcOffset;
var output:Bitmap = new Bitmap(bmp);

Well I took it a step further back and went to the stage. For whatever reason trying to draw the parent (test_mc) of the rotated movie clip (response_mc) WON'T work, however drawing the stage and setting the bounds to the area of the parent DOES work. Here's my code (which is sadly very simple):
var bmp:BitmapData = new BitmapData(test_mc.width, test_mc.height);
bmp.draw(stage.getChildAt(0), new Matrix(1, 0, 0, 1, -test_mc.x, -test_mc.y));
var output:Bitmap = new Bitmap(bmp);

Related

Randomising array coordinates with no duplicates AS3

very new to this kind of thing so please bear with me.
So basically I have 4 buttons that I have put to the stage using the Actions panel. They all have set coordinates so every time I run my game, they are in the same place.
Now here's my issue, I want these buttons to randomise their positions using those coordinates, but I often get duplicates, meaning one button is on top of another.
Here is my code so far
var coordArray : Array = [
new Point(44,420),
new Point(270,420),
new Point(44,550),
new Point(270,550),
];
var pointRange:Number = 4;
var randomPoint:int = Math.random()*pointRange;
answerButtons.x = coordArray[randomPoint].x;
answerButtons.y = coordArray[randomPoint].y;
var pointRange_2:Number = 4;
var randomPoint_2:int = Math.random()*pointRange_2;
answerButtons_2.x = coordArray[randomPoint_2].x;
answerButtons_2.y = coordArray[randomPoint_2].y;
var pointRange_3:Number = 4;
var randomPoint_3:int = Math.random()*pointRange_3;
answerButtons_3.x = coordArray[randomPoint_3].x;
answerButtons_3.y = coordArray[randomPoint_3].y;
var pointRange_4:Number = 4;
var randomPoint_4:int = Math.random()*pointRange_4;
answerButtons_4.x = coordArray[randomPoint_4].x;
answerButtons_4.y = coordArray[randomPoint_4].y;
I have googled this profusely and I keep getting answers to do with the splice and shift methods. Is this the type of thing I need? I'm assuming I need a function that removes a point from the array after it is used.
Cheers.
Just remove the coordinate from the list when you pick it randomly using splice:
var coordinates:Vector.<Point> = new <Point>[
new Point(44, 420),
new Point(270, 420),
new Point(44, 550),
new Point(270, 550)
];
function positionAtRandomCoordinate(object:DisplayObject):void {
var index:int = Math.random() * coordinates.length;
var coordinate:Point = coordinates.splice(index, 1)[0];
object.x = coordinate.x;
object.y = coordinate.y;
}
positionAtRandomCoordinate(answerButtons);
positionAtRandomCoordinate(answerButtons_2);
positionAtRandomCoordinate(answerButtons_3);
positionAtRandomCoordinate(answerButtons_4);

AS3: localToGlobal with perspectiveProjection

It seems that if a display object has a perspective projection applied to it, calling localToGlobal gives you the wrong coordinates. In the following code, I draw a rectangle, rotate it slightly about its X axis, then draw an oval inside it using coordinates derived from localToGlobal. It works fine, until I try to apply a perspective projection, then the coordinates are all wrong. Anyone know how to get around this problem?
var w:uint = 300, h:uint = 150;
var s:Sprite = new Sprite();
s.graphics.beginFill(0x000000);
s.graphics.drawRect(-w/2,0,w,h);
s.graphics.endFill();
s.x = 275; s.y = 200; s.z = 600;
s.rotationX = -45;
addChild(s);
var point00:Point = new Point(0,0);
var point0h:Point = new Point(0,h);
var midL:Point = new Point(-w/2,h/2);
var midR:Point = new Point(w/2,h/2);
/*var VP:PerspectiveProjection = new PerspectiveProjection();
VP.fieldOfView = 55;
var p:Point = new Point(275,100);
VP.projectionCenter = p;
s.transform.perspectiveProjection = VP;*/
var o:Shape = new Shape();
o.graphics.beginFill(0x00ff00);
o.graphics.drawEllipse(
s.localToGlobal(midL).x,
s.localToGlobal(point00).y,
s.localToGlobal(midR).x - s.localToGlobal(midL).x,
s.localToGlobal(point0h).y - s.localToGlobal(point00).y
);
addChild(o);
It seems that setting perspectiveProjection does not force the player to redraw the object, and localToGlobal depends on redraw for correct results. You can wait 1 tick like you found (setTimeout for 0ms or enterFrame for 1 frame will do it) or you can force the player to redraw using BitmapData/draw():
// ...
s.transform.perspectiveProjection = VP;
new BitmapData(1, 1).draw(s); // forces player to redraw the sprite
var o:Shape = new Shape();
o.graphics.beginFill(0x00ff00);
o.graphics.drawEllipse(
s.localToGlobal(midL).x,
s.localToGlobal(point00).y,
s.localToGlobal(midR).x - s.localToGlobal(midL).x,
s.localToGlobal(point0h).y - s.localToGlobal(point00).y
);
addChild(o);
I found a workaround that isn't terrible. All you have to do is put a slight delay before the localToGlobal calls and then they will return the right coordinates. That also fixes local3DToGlobal.

Away3d transparent bitmap Sprite3d

I'm adding some circles to away3d as sprite3ds, but for some reason they all have white backgrounds that I can't seem to remove. Anyone know what I'm missing:
var hotspot:Hotspot = e.target as Hotspot;
var spBoard:Sprite = new Sprite();
spBoard.x = circleX;
spBoard.y = circleY;
var shCircle:Shape = new Shape();
shCircle.graphics.lineStyle(2,0x000000);
shCircle.graphics.drawCircle(0,0,circleR);
shCircle.x = 0;
shCircle.y = 0;
var shFill:Shape = new Shape();
shFill.graphics.lineStyle(1,0x000000);
shFill.graphics.moveTo(0,0);
shFill.graphics.lineTo(circleR,0);
shFill.x = 0;
shFill.y = 0;
var shAngle:Shape = new Shape();
var shArrow:Shape = new Shape();
shArrow.graphics.lineStyle();
shArrow.graphics.beginFill(0x000000);
shArrow.graphics.moveTo(angleR,1);
shArrow.graphics.lineTo(angleR-5,8);
shArrow.graphics.lineTo(angleR+5,8);
shArrow.graphics.lineTo(angleR,1);
shArrow.graphics.endFill();
spBoard.addChild(shFill);
spBoard.addChild(shAngle);
spBoard.addChild(shArrow);
spBoard.addChild(shCircle);
var hotspotTimer:MovieClip = new MovieClip();
hotspotTimer.addChild(spBoard);
var bounds:Rectangle = hotspotTimer.getBounds(hotspotTimer);
var bitmapData : BitmapData = new BitmapData(512, 512);
bitmapData.draw(hotspotTimer);
var bitmapPointsTexture:BitmapTexture = new BitmapTexture(bitmapData);
var _pointsMaterial:TextureMaterial = new TextureMaterial(bitmapPointsTexture);
var inworldHotspotTimer:Sprite3D = new Sprite3D(_pointsMaterial,bitmapData.width,bitmapData.height);
inworldHotspotTimer.x = hotspot.x;
inworldHotspotTimer.y = hotspot.y;
inworldHotspotTimer.z = hotspot.z;
scene.addChild(inworldHotspotTimer);
}
I've seen in blog posts such as this
http://www.allforthecode.co.uk/aftc/forum/user/modules/forum/article.php?index=6&subindex=4&aid=315
On how they do it, but they're using an older version with the BitmapMaterial removed.
Change the line that declares the bitmapdata to this:
var bitmapData : BitmapData = new BitmapData(512, 512, true, 0x00808080);
If you don't fill the bitmap with a color that has alpha of 0, you'll get the borders in the texture.

Using text as a mask to add a gradient to the text in AS3

I want to apply a gradient to my text in Flash Develop and read that using a mask is the easiest way. Problem is that I can not get it to work. I tried to create a mask with just the textField and by adding it to a sprite, neither work.
Another strange thing is that the textmask will function as a mask for start title if I reverse them like:
starttitle.mask =textmask
When I try the code below nothing displays.
var format2:TextFormat = new TextFormat();
format2.size = 40;
format2.font = "Times New Roman";
format2.bold = true
starttitle = new TextField;
starttitle.defaultTextFormat = format2;
starttitle.text = "Memory Circles";
starttitle.textColor = 0xFF0000
starttitle.autoSize = "center";
starttitle.background = false;
starttitle.backgroundColor = 0xFF4242;
starttitle.x = (300 - starttitle.width * .5);
starttitle.y = (150 - starttitle.height * .5);
starttitle.mouseEnabled = false;
addChild(starttitle)
var textmask:Shape = new Shape
var fillType:String = GradientType.LINEAR;
var colors:Array = [0xFF0000, 0];
var alphas:Array = [1, 1];
var ratios:Array = [0, 255];
var gradientBoxMatrix:Matrix = new Matrix();
gradientBoxMatrix.createGradientBox(50,100,45,0,0);
var spreadMethod:String = SpreadMethod.REPEAT;
textmask.graphics.beginGradientFill(fillType, colors, alphas, ratios,
gradientBoxMatrix, spreadMethod);
textmask.graphics.drawRect(200,100,300,100)
addChild(textmask)
textmask.mask =starttitle
I read something about the font needing to be embedded but I'm using Times New Roman and thought this would be embedded. Also other fonts don't work.
Try to use bitmap caching on starttitle and textmask:
starttitle.cacheAsBitmap=true;
textmask.cacheAsBitmap=true;

AS3 get Bitmap from Movieclip with Mask

This works:
var a:BitmapData = new BitmapData(640,480);
var b:Bitmap = new Bitmap(a);
a.draw(movieClip);
This doesn't work:
movieClip.mask = movieClipMask;
var a:BitmapData = new BitmapData(640,480);
var b:Bitmap = new Bitmap(a);
a.draw(movieClip);
How can I draw just the visible part of a MovieClip (that uses a mask) into my Bitmap?
Create a new Sprite and add both the MovieClip and its mask to it. Then draw the parent Sprite.
var container:Sprite = new Sprite();
container.addChild (movieClip);
container.addChild (movieClipMask);
movieClip.mask = movieClipMask;
var a:BitmapData = new BitmapData(640,480);
var b:Bitmap = new Bitmap(a);
a.draw(container);