detect mask fill as3 - actionscript-3

how to detect if my mask is filled about 90%? here is my drawing code.
var my_shape:Sprite = new Sprite();
var bitmapData:BitmapData = new BitmapData(shida.width, shida.height);
bitmapData.draw(shida);
shidaq.addEventListener(MouseEvent.MOUSE_MOVE, draw);
function draw(e:MouseEvent):void {
addChild(my_shape);
my_shape.mask = shida;
my_shape.graphics.beginFill(0xA7A9AC,1);
my_shape.graphics.drawCircle(mouseX, mouseY, 40);
my_shape.graphics.endFill();
}

Related

Dynamically creating objects in actionscript 3?

I'm fairly new to AS3, and I've been trying to make a side scrolling shooter. I made some progress but I've hit a wall on the bullets themselves. The code I've been using is:
var circle:Sprite = new Sprite();
function shoot() {
circle.graphics.beginFill(0xFF794B);
circle.graphics.drawCircle(0, 00, 7.5);
circle.graphics.endFill();
addChild(circle);
circle.x = ship_mc.x;
circle.y = ship_mc.y + 43;
}
The problem with this is it only allows for one bullet on the screen at a time. How can I change this so the bullets are created so that I can have an unlimited amount of them?
Create the object inside the method
function shoot() {
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0xFF794B);
circle.graphics.drawCircle(0, 00, 7.5);
circle.graphics.endFill();
addChild(circle);
circle.x = ship_mc.x;
circle.y = ship_mc.y + 43;
}
Otherwise, you would only have one circle variable. This time, a new circle is created each time the method is called.
However, you will probably want to store all your circles somehow so that you can remove them later.
var allCircles: Vector.<Sprite> = new Vector.<Sprite>();
function shoot() {
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0xFF794B);
circle.graphics.drawCircle(0, 00, 7.5);
circle.graphics.endFill();
addChild(circle);
circle.x = ship_mc.x;
circle.y = ship_mc.y + 43;
allCircles.push(circle);
}
Then, at a later time, you can loop through all your circles:
for each (var circle: Sprite in allCircles) {
// do something with this circle
}
And to clear all circles:
for each (var circle: Sprite in allCircles) {
removeChild(circle);
}
allCircles.clear();
You want to store an array of Sprites, not just one of them. First you declare your Array:
var circles:Array = new Array();
Then you change your shoot function to make a new one and then push it into the Array:
function shoot() {
var circle:Sprite = new Sprite();
circle.graphics.beginFill(0xFF794B);
circle.graphics.drawCircle(0, 00, 7.5);
circle.graphics.endFill();
circle.x = ship_mc.x;
circle.y = ship_mc.y + 43;
circles.push(circle);
addChild(circles[circles.length-1]);
}

How can I use a dynamically-resized hitArea for an EaselJS DisplayObject?

I'd like to use a hitArea to capture click events in my EaselJS project, but the hitArea Shape I've assigned doesn't seem to be respected.
jsFiddle Example
var stage = new createjs.Stage($("#game")[0]);
// This will be a big button
var container = new createjs.Container();
stage.addChild(container);
// This defines the hit area of the button
var hitArea = new createjs.Shape();
var hitAreaGraphics = hitArea.graphics;
// A 1x1 black square, centered about the origin
hitAreaGraphics.beginFill("#000").drawRect(-0.5, -0.5, 1, 1).endFill();
// Assign the hitArea
container.hitArea = hitArea;
// container.addChild(hitArea);
container.onTick = function() {
var canvas = container.getStage().canvas;
container.x = canvas.width / 2;
container.y = canvas.height / 2;
container.scaleX = canvas.width;
container.scaleY = canvas.height;
};
container.onPress = function() {
alert("Eureka!");
};
// Run the simulation
updater = {
tick: function() { stage.update(); }
};
createjs.Ticker.addListener(updater);
​
If I add the hitArea shape as a child of the container object, the click events work fine.

how to set a bitmap as a mask

i want to apply a picture which contains transparent areas as a mask to a display object.
the mask only show the area which the mask has color.but in fact,the display object still show the whole area.so i convert bitmap to a vector image,that's solve the problem,but the convert method is horrible.
public static function createVectorImage(bd:BitmapData,colorKey:uint = 0):Shape{
if(bd==null){
return null;
}
var sh:Shape = new Shape();
var g:Graphics = sh.graphics;
g.beginBitmapFill(bd);
var beginPixel:int = -1;
var i:int,il:int,j:int,jl:int;
var value:uint;
for(i = 0,il=bd.height;i<il;i++){
for(j = 0,jl = bd.width;j<jl;j++){
value = bd.getPixel32(j,i);
if(value!=colorKey&&beginPixel==-1){
beginPixel = j;
}else if(value==colorKey&&beginPixel!=-1){
//draw rect
g.drawRect(beginPixel,i,j-beginPixel,1);
beginPixel = -1;
}
}
if(beginPixel!=-1){
g.drawRect(beginPixel,i,j-beginPixel,1);
beginPixel = -1
}
}
g.endFill();
return sh;
}
is there any way better than this?
You can convert your display object to a bitmap then apply a mask on it.
Convert you display object to a bitmap data:
var rect:Rectangle = displayObject.getRect();
var displayBD:BitmapData = new BitmapData(rect.width, rect.height, true, 0);
displayBD.draw(displayObject);
Apply the mask:
private static const ORIG:Point = new Point(0, 0);
private static function createBitmapDataWithMask(
baseBD:BitmapData, maskBD:BitmapData):BitmapData
{
var bitmapData:BitmapData;
bitmapData = new BitmapData(baseBD.width, baseBD.height, true, 0x000000);
bitmapData.copyPixels(baseBD, baseBD.rect, ORIG, maskBD, ORIG, true);
return bitmapData;
}
Display the bitmap data:
var bitmapData:BitmapData = createBitmapDataWithMask(displayBD, maskBD);
var bitmap:Bitmap = new Bitmap(bitmapData, "auto", true);
addChild(bitmap);
If you remove the bitmap from the stage, don't forget the free the bitmap data!
removeChild(bitmap);
bitmap.bitmapData.dispose();
bitmap = null;
Another option would be to use bitmap caching. It needs to be applied to the mask as well as the maskee:
var bd:BitmapData = new BitmapData(200, 200, true, 0x00000000);
bd.fillRect(new Rectangle(0, 0, 40, 40), 0xff000000);
var mask:Bitmap = new Bitmap(bd);
mask.cacheAsBitmap = true;
var maskee:Sprite = new Sprite();
maskee.cacheAsBitmap = true;
maskee.graphics.beginFill(0xff0000, 1);
maskee.graphics.drawRect(0, 0, 200, 200);
maskee.graphics.endFill();
maskee.mask = mask;
addChild(mask);
addChild(maskee);

ColorTransform removes shadow

I've got movie clip on stage that has shadow filter.
When I apply ColorTransform to that movie clip, the shadow removes.
var ct:ColorTransform = new ColorTransform;
ct.color = 0x99CC00;
lamp.transform.colorTransform = ct;
How to save shadow?
The idea is to
save the filters (shadow) of your clip lamp,
apply the transformation,
put the clip in a master clip and
re-apply the filters to this untransformed parent.
code:
var lampFilters:Array = lamp.filters.slice(); //save filters
lamp.filters = []; //empty filters
var ct:ColorTransform = new ColorTransform();
ct.color = 0x99CC00;
lamp.transform.colorTransform = ct; //apply your transformation
var superLamp:Sprite = new Sprite();
superLamp.addChild(lamp); //nest the clip
addChild(superLamp);
superLamp.filters = lampFilters; //re-apply the filters
ColorTransform will transform the entire MovieClip, unfortunately, the filter is included. I suggest you layer lamp and apply the transform to the top most layer keeping the bottom layer (shadow) untouched.
Test example:
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x00FF00, 1);
ball.graphics.drawCircle(50, 50, 50);
ball.graphics.endFill();
ball.filters = [new DropShadowFilter()]; //default black
ball.addEventListener(MouseEvent.CLICK, changeColor);
addChild(ball);
//...
private function changeColor(evt:MouseEvent):void {
var ball:Sprite = evt.target as Sprite;
var ct:ColorTransform = new ColorTransform();
ct.color = 0x99CC00; // green-ish
ball.transform.colorTransform = ct;
ball.filters = [new DropShadowFilter(4, 45, 0xFFFFFF)]; //now white
}
Even with the shadow filter reapplied you can see it's still going to be green-ish as set by the transform.
You should use nested display objects to achieve this...
for instance you can create a movieclip within another movieclip. apply the colortransform to inner movie clip and apply the shadow to outer movie clip. works like a charm for me :)
Here is an alternate method that does not require a parent object. You basically use an AdjustColor and ColorMatrix to change the color instead of a ColorTransform.
Note:If you are using an IDE other than Flash, like Flex or FlashDevelop, you will need to include flash.swc into your library from 'Common/Configuration/ActionScript 3.0/libs/flash.swc' for the fl.motion.AdjustColor package/class. You can also Google the swc.
var mc:Sprite = new Sprite();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawCircle(100, 100, 100);
mc.graphics.endFill();
addChild(mc);
// White out the entire shape first
var whiteAC:AdjustColor = new AdjustColor();
whiteAC.brightness = 100;
whiteAC.contrast = 100;
whiteAC.saturation = -100;
whiteAC.hue = 0;
var whiteMatrix:Array = whiteAC.CalculateFinalFlatArray();
var whiteCMF:ColorMatrixFilter = new ColorMatrixFilter(whiteMatrix);
// Now use ColorMatrixFilter to change color
var colorMatrix:Array = hexToMatrix(0x0000FF);
var colorCMF:ColorMatrixFilter = new ColorMatrixFilter(colorMatrix);
// Create Drop Shadow
var myDropShadow:DropShadowFilter = new DropShadow();
mc.filters = [whiteCMF, colorCMF, myDropShadow];
function hexToMatrix ( hex:uint, alpha:Number = 1 )
{
var r:Number = ((hex & 0xFF0000) >> 16);
var g:Number = ((hex & 0x00FF00) >> 8);
var b:Number = ((hex & 0x0000FF));
var matrix:Array = [];
matrix = matrix.concat([r, 0, 0, 0, 0]); // red
matrix = matrix.concat([0, g, 0, 0, 0]); // green
matrix = matrix.concat([0, 0, b, 0, 0]); // blue
matrix = matrix.concat([0, 0, 0, alpha, 0]); // alpha
return matrix;
}

ActionScript 3.0 Getting Size/Coordinates From Loader Content

i'm attempting to position a textfield to the bottom left of an image that is added to the display list from the Loader() class. i don't know how to access the width/height information of the image.
var dragSprite:Sprite = new Sprite();
this.addChild(dragSprite);
var imageLoader:Loader = new Loader();
imageLoader.load(new URLRequest("picture.jpg"));
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, displayPic, false, 0, true);
function displayPic(evt:Event):void
{
dragSprite.addChild(evt.target.content);
evt.target.removeEventListener(Event.COMPLETE, displayPic);
}
var tf:TextField = new TextField();
tf.text = "Picture Title";
tf.width = 200;
tf.height = 14;
tf.x //same x coordinate of dragSprite
tf.y //same y coordinate of dragSprite, plus picture height, plus gap between picture and text
addChild(tf);
within the displayPic function, i could assign the evt.target.content.height and evt.target.content.width to variables that i could use to position the text field, but i assume there is a more appropriate and direct way?
There is no direct way since you have to wait the image to be loaded to access width, and height.
But you can place you text as soon as the complete is done if it`s fit your design. Store the value into some var so you can reuse it when moving the sprite.
//...
var tf:TextField = new TextField();
tf.text = "Picture Title";
tf.width = 200;
tf.height = 14;
addChild(tf);
var imageLoader:Loader = new Loader();
imageLoader.load(new URLRequest("picture.jpg"));
imageLoader.contentLoaderInfo.addEventListener(
Event.COMPLETE, displayPic, false, 0, true
);
var offsetX:Number=0;
var offsetY:Number=0;
function positionText():void {
tf.x=dragSprite.x + offsetX;
tf.y=dragSprite.y + offsetY;
}
function displayPic(evt:Event):void {
var li:LoaderInfo=evt.target as LoaderInfo;
if (li===null)
return;
li.removeEventListener(Event.COMPLETE, displayPic);
var dob:DisplayObject=li.content;
if (dob!==null) {
dragSprite.addChild(dob);
// set only once the offset depending on the loaded image
offsetX = ...//
offsetY = dob.height+gap //...
// position text using the offset setted
// so you can reuse the function when moving your sprite
positionText();
}
}