My startDrag rectangle isn't where I set it to be - actionscript-3

I've made a rectangle, a rectangular sprite and a circular sprite. The rectangular sprite has the exact same properties of my rectangle, and I set my circle to be positioned in the center of the stage, which is the middle of both of these rectangles.
After tracing the values of the rectangle, I can safely say that the rectangle is the same as the rect sprite. So then of course, if I wanted to drag the circle around the rectangle, it should stay within the bounds of it, right?
stop();
var isDragging:Boolean;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.display.Sprite;
import flash.geom.Point;
var px:Number = boundingBox.x;
var py:Number = boundingBox.y;
var h:Number = boundingBox.height;
var w:Number = boundingBox.width;
var box:Rectangle = new Rectangle(px,py,w,h);
trace(box);
var blob:Sprite = new Sprite();
blob.graphics.beginFill(0x000000);
blob.graphics.lineStyle(1.2, 0xFFFFFF);
blob.graphics.drawCircle(stage.stageWidth/2, stage.stageHeight/2, 18);
blob.graphics.endFill();
addChild(blob);
var box2:Sprite = new Sprite();
box2.graphics.lineStyle(1, 0xFFCC00);
box2.graphics.drawRect(px,py,w,h);
addChild(box2);
blob.addEventListener(MouseEvent.MOUSE_DOWN, drag);
function drag(event:MouseEvent):void {
event.target.startDrag(false, box);
isDragging = true
}
Well that doesn't seem be the case. Maybe I'm just a noob but I have no idea what's going on.
When I run the scene, everything looks normal.
The orange/dotted line is two rectangles I made, one is a movie clip that I used to set the properties of the rectangle I made in AS3 (dotted) and the orange is the AS3 sprite.
The circle is in the middle of the stage and it all looks as exactly how I wanted to be programmed.
But as soon as I click on it, it teleports over here.
And when I try to drag it, it seems as if the box's top left corner has been translated to that point all the way down there, and it only drags around in the bottom-right quadrant of the stage, and even drags further off screen.
I'm not sure if the rectangle that I put into the startDrag function is somehow distorted from the actual rectangle.
I have no idea why this happens, because when I tried to do this using a movie clip that I added to the stage, everything worked fine. But as soon as I try to do it programmatically, everything goes tits up.
I'd appreciate some help on why this isn't working. Thanks for reading.

There's your problem:
blob.graphics.drawCircle(stage.stageWidth/2, stage.stageHeight/2, 18);
You draw this circle and only seem to care about the circle:
if I wanted to drag the circle around the rectangle, it should stay within the bounds of it, right?
No. Just because you added something to the .graphics doesn't mean As3 automagically knows that this is what should stay within the bounding Rectangle that's being passed to startDrag().
The thing that stays within the bounding Rectangle is the registration point of the Sprite. That registration point is not where you drew the circle. It is in fact still at its default position of 0/0 in your first image. I added a green star at the registration point of blob. I also added a red rectangle that connects the registration point and your point. Think of this as some jelly that both your circle and the registration point are stuck in. This should help illustrate that just because you drew a circle somewhere doesn't mean that you are only dealing with that circle:
But as soon as I click on it, it teleports over here.
As soon as you click, the movement limitation of startDrag() is applied. The registration point has to be in the Rectangle that you specified and that's exactly what happens. The whole red jelly blob is moved over so that the green star is in the Rectangle:
To solve this, first create your blob in a reasonable fashion, which means drawing the circle around the registration point at 0/0 and then moving the Sprite object around if you want to have the circle at another position. This way, there's no red jelly and the green star is right at the center of the circle. The visual helpers that I added become superfluous, because your perception of the situation now matches with how it actually is.
const RADIUS:Number = 18;
var blob:Sprite = new Sprite();
blob.graphics.beginFill(0x000000);
blob.graphics.lineStyle(1.2, 0xFFFFFF);
blob.graphics.drawCircle(0, 0, RADIUS);
blob.x = stage.stageWidth/2;
blob.y = stage.stageHeight/2;
blob.graphics.endFill();
addChild(blob);
This will keep the blob within the bounds for the most part or more precisely: its center point. If you want to keep the entire circle within the bounds, you'd have to subtract the circle from the bounding Rectangle Minkowski-style. Mink-what? yeah...err, that's a fancy way of saying: make the bounding Rectangle smaller by the radius, so that this smaller boundary can be applied to the center of the radius to ensure that the whole circle stays within the bigger original boundary.
In your case Rectangle's inflate() should do:
var px:Number = boundingBox.x;
var py:Number = boundingBox.y;
var h:Number = boundingBox.height;
var w:Number = boundingBox.width;
var box:Rectangle = new Rectangle(px,py,w,h);
box.inflate(-RADIUS, -RADIUS);
trace(box);

Related

Add blur to everything in an area AS3

I'd like to know how can I add blur in a certain area for example behind a movieclip, maybe a mask that will blur everything in the area of that moviclip.
I don't want to blur everything, just what's behind a movieclip :)
Sort of like Apple is doing with their menus
The only way to do this in AS3 is draw whatever is behind the MovieClip to a Bitmap, then blur the bitmap.
For example, say your MovieClip is a modal dialog of some sort with a semi-transparent background, you could use the following script (inside the MovieClip) to blur whatever is on the stage behind it onto a bitmap surface:
// create a bitmap surface to use as a blurred background
var blurData:BitmapData = new BitmapData(width, height, false);
var blur:Bitmap = new Bitmap(blurData);
addChildAt(blur, 0); // put the blur surface behind everything in the movieclip
// this function draws the portion of the stage that's behind the movieclip
// onto the bitmap surface, then blurs it
function drawBlurBehind():void {
// fill the bitmap with the stage color first
blurData.fillRect(blurData.rect, stage.color);
// account for the coordinate offset of the stage and movieclip
var offset:Point = globalToLocal(new Point());
var matrix:Matrix = new Matrix();
matrix.tx = offset.x;
matrix.ty = offset.y;
// hide the movieclip so it doesn't show up in the blurred background
visible = false;
// draw the stage behind the movieclip onto the bitmap
blurData.draw(stage, matrix);
// blur the background bitmap
blurData.applyFilter(blurData, blurData.rect, new Point(), new BlurFilter(25, 25));
// show the movieclip after the background has been blurred
visible = true;
}
Note that this drawing is not "live" and any time anything changes (you move the movieclip or what's behind it changes) you have to redraw. You could use an ENTER_FRAME event handler to continually redraw every frame, which would basically make it live, but that will be relatively expensive so avoid it if you can.
Also note that this script draws and blurs the whole stage (excluding the movieclip), not what is strictly "behind" the movieclip. So if you want things to appear above the movieclip and not appear blurred behind the movieclip, you'll have to set those to visible=false while you draw the blurred background.

[AS3]Rotate a Sprite around it's center

I need some help with a really specific problem.
I've looked and found some answers, but nothiung as specific as what I need.
I'm using flashdevelop, and for now, I've a rectangle (it's a Sprite) following my mouse cursor (centered).
I'd like to apply a rotation on it when I scroll my mouse wheel, but I need the rotation to apply on it's center, and I need the object to stay centered on my mouse cursor at the same time.
And I also need to apply the rotation in radians, not in degree.
For now I got this :
var mod:Number;
if (e.delta <= 0) {
mod = -0.1;
}else {
mod = 0.1;
}
Could someone help me with it please ? After what I've seen it seems that I've to use matrix, and complex maths, but I've no idea how to do what I want to do with this.
You just need to keep the registration point of the sprite in center of the rectangle to rotate it about it's center. When you draw a sprite from (0,0) the registration point is top-left and not center. Here's how you make it center:
var rectangleSprite:Sprite = new Sprite();
rectangleSprite.graphics.lineStyle(3,0x00ff00);
rectangleSprite.graphics.beginFill(0x0000FF);
//please note that i am not drawing the sprite from (0,0),
//instead i start from (-width/2,-height/2)
rectangleSprite.graphics.drawRect(-150,-75,300,150);
rectangleSprite.graphics.endFill();
And for degree to radian conversion you just need multiply your value in radians by (180/Math.PI) before applying your rotation.
var rotationInDegrees = rotationInRadians*(180/Math.PI);

I am trying to make 2 circles around a point and fill between these points and listen for a click between the circles

i'm trying to make something for a game i'm making. When someone clicks on the movieclip i want it to draw an inner circle and an outer circle. I'd like to fill between the circles with a opaque colour (purple in the image) so people can see basically a large thick circle around the movieclip but not touching the movieclip. I then need to check if the mouseclick happens between the two circles only.
The image below shows what i mean. The thing is the thickness of the purple bit has to be adjustable (not in game as such), if you click on 1 movieclip the thickness of the purple bit may be 10pixels, a different clip may be 50. Obviously checking for a click greater than inner circle x and less than outer circle only works on a straight line across from the clip, once you move up or down this doesn't work so well. Any help is much appreciated as i can't seem to work this out. I've tried drawing 2 circles and also tried using 2 movieclip circles but can't get it to work.
Seems i cant upload pictures on here. Easiest way is to think of a no entry sign without the / line going through the middle. The centre is the movieclip, the inside part of the red circle the inner circle and the outer is the outer circle but at no point does the red touch the movieclip
I would measure the distance from the center of the circles to the mouse click point. Then you just need to check is that distance greater than the inner circle radius and less than the outer circle radius.
Something along these lines:
var clickPoint:Point = new Point(mouseX, mouseY);
var centerPoint:Point = new Point(circleMC.x circleMC.y);
var dist:Number = Point.distance(clickPoint, centerPoint);
if(dist > innerRadius && dist < outerRadius){
trace("the click happened between circles
}

AS3 erase bitmap that has filters

So I use bitmap.bitmapData.draw(erase,null,null,"erase"); to erase part of a bitmap that has the sprite called erase over it. The problem is that I need the bitmap to be blurred, and after I apply a blur filter the bitmapData.draw function doesn't work anymore. Meaning absolutely nothing happens. I tried using bitmapdata.applyFilter, which almost works except when I erase near a blurred edge it "unblurs" itself.
var erase:Sprite=new Sprite();
erase.cacheAsBitmap = true;
var blur:BlurFilter = new BlurFilter(10,10,10);
var blurs:Array=new Array();
blurs.push(blur);
bitmap=new Bitmap(bitmapdata);
bitmap.blendMode = "layer";
bitmap.y=-10;
bitmap.x=-10;
Refs._stage.addChildAt(bitmap,0);
also:
erase.graphics.beginFill(0xFF0000);
erase.graphics.drawCircle(stage.mouseX+10,stage.mouseY+10,35);
erase.filters = blurs;
erase.graphics.endFill();
bitmap.bitmapData.draw(erase,null,null,"erase");
It's just how the erase draw works. It erases pixels based on the alpha value of the object being drawn in erase mode. Where the alpha is above 0.5, that pixel get its alpha dropped to zero. Other pixels are not touched. This is what you experience when you draw with erase, then blur, then draw with erase again. No, Flash is not intelligent enough to do erase-blur, you might have to do it yourself. You might try drawing a transparent BitmapData with BlendMode.ERASE to do a blur-erase, but I don't expect it to return a blurred bitmap with blurred erased regions.

Objects added to stage with coordinates 0,0 appear near the middle...why?

I'm using Flash Builder to build an flash-web application, and whenever I try to add objects to the stage, they appear near the center even if their coordinates are set at 0,0. I've tried track the mouse movement to see what the coordinates of the upper left corner are, and they are always a negative number.
Strangely, the stage coordinates and position of the children change based on how large the flash object is. For example, if the flash object is 500 pixels wide, the top left corner of the stage is at about -130 and if the flash object is 800 pixels wide, its at about -200. Why is the coordinate system wrong? Do I have to alter an anchor point or something like that?
Here is a sample of an object I'm trying to position at 0,0:
var square:Sprite = new Sprite();
addChild(square);
square.graphics.lineStyle(3,0x00ff00);
square.graphics.beginFill(0x0000FF);
square.graphics.drawRect(0,0,100,100);
square.graphics.endFill();
square.x = 0;
square.y = 0;
This shows up near the center and I can't figure out why.
Is the object you are using a MovieClip or Sprite? If so then your registration point could be in an incorrect position.
Usually registration points are placed right in the middle of the object instead of lets say the top left as you would want it. So the co-ordinates would be different to the stage.
I fixed this by adding
stage.align = StageAlign.TOP_LEFT;
to the main function.