stage.swapChildren(MClip1, Mclip2); not working - actionscript-3

i have made a drag and match game where i have a rectangle circle movieclip ..when rectangle/or circle hit a specific box rectangle will always be behind circle and circle will always be over retangle,if i drag rectangle first then circle its ok..but if i drag circle first then rectangle ..circle always takes its position behind ractengle i used stage.swapChildren(ccircle, crect) but its not working ...here is my code
crect.addEventListener(MouseEvent.MOUSE_DOWN, item_onMouseDown1);
function item_onMouseDown1(event:MouseEvent):void
{
crect = MovieClip(event.target);
startX1 = crect.x;
startY1 = crect.y;
crect.startDrag();
setChildIndex(crect, this.numChildren-1);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_onMouseUp1);
}
function stage_onMouseUp1(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_UP, stage_onMouseUp1);
crect.stopDrag();
if(crect.hitTestObject(box3))
{
TweenMax.to(crect, 0.5, {x:hit2X, y:hit2Y,height:height2Y, width:weight2X, ease:Cubic.easeOut});
//crect.mouseEnabled=false;
}
else
{
TweenMax.to(crect, 0.5, {x:startX1, y:startY1, ease:Bounce.easeOut});
}
}
ccircle.buttonMode=true;
ccircle.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown1);
function onMouseDown1(event:MouseEvent):void
{
ccircle = MovieClip(event.target);
startX1 = ccircle.x;
startY1 = ccircle.y;
ccircle.startDrag();
setChildIndex(ccircle, this.numChildren-1);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp1);
}
function onMouseUp1(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp1);
ccircle.stopDrag();
if(ccircle.hitTestObject(box3))
{
TweenMax.to(ccircle, 0.5, {x:hit1X, y:hit1Y,height:height1Y, width:weight1X, ease:Cubic.easeOut});
//stage.swapChildren(ccircle, crect);
//setChildIndex(ccircle, this.numChildren-1);
//ccircle.mouseEnabled=false;
}
else
{
TweenMax.to(ccircle, 0.5, {x:startX1, y:startY1, ease:Bounce.easeOut});
}
}

You can't change ccircle index to -1. Only 0, 1, 2, ...
stage.setChildIndex(ccircle, -1);
You should write:
if (getChildIndex(ccircle) < getChildIndex(crect))
swapChildren(ccircle, crect);
It means: If ccircle is under crect then put ccircle on top.

You can just use
removeChild(crect);
addChild(crect);
That will always put crect on top. Of course if you need ccircle on top, do the same to it.

i simply set setChildIndex(crect, this.numChildren-2);
and setChildIndex(crect, this.numChildren-2); and its working perfect,because its not for setting circle on top only.while dragging i have to put dragged object on top of other objects..

I also found some info you can read on
Gary Rosenzweig website that I been studying myself on the display list in flash.
The site is http://flashgameu.com/ and scroll down an look for "understanding the display list."
It explains swapping children by name and also by location in the display list.
Watching his pod cast will help you understand the options using the display list with swapping children, addChild,removeChild and childIndex.
Its also free and a good site with some information on how to do things with flash and as3 programming.

Related

AS3 - How to use pixel/point detection with mouse event instead of object detection

This seems like it should be so easy that I'm embarrassed to ask, but I just can't get it.
I have a large round MovieClip (being used as a button). This MovieClip contains a PNG with a transparent background inserted into the MovieClip.
Due to its size there are large empty registration areas on the 4 corners (the bounding box).
How can I have the mouse register as being over only the circle pixels and not the blank space (of Alpha channel pixels) in the square boundary box?
Simple sample code:
public function simpleSample () : void
{
mc1.buttonMode = true;
mc1.addEventListener(MouseEvent.CLICK, doStuff);
}
public function doStuff (event:MouseEvent) : void
{
mc2.gotoAndStop(2);
}
Here are 3 different ways to accomplish this.
EDIT Since you've later explained that your button is an image, this first option won't work for you
If the shape flag on hitTestPoint works with your button (eg it's a shape), you can use hitTestPoint inside your mouse click handler to figure out if the click is actually over the object:
public function doStuff(event:MouseEvent){
//only continue if hit test point is true,
//the x and y values are global (not relative to the mc your testing as one might suppose)
//the third parameter should be true, so it takes into account the shape of object and not just it's bounds
if(mc1.hitTestPoint(stage.mouseX, stage.mouseY, true)){
mc2.gotoAndStop(2);
}
}
If the above doesn't work because you have bimtap data in your button, then an easy way to accomplish this is to just add a shape mask to the button.
So, either inside your button using FlasPro, mask everything with a circle shape, or, do it via code by doing the following when you first show the button:
var s:Shape = new Shape();
s.graphics.beginFill(0);
s.graphics.drawCircle(mc1.x + (mc1.width * .5), mc1.y + (mc1.height * .5), mc1.width / 2);
addChild(s);
mc1.mask = s;
If using an image as the button, or you want to set a threshold of how transparent to consider a click, then you can check the transparency of the pixel under the mouse:
function doStuff(event:MouseEvent){
//only continue if pixel under the mosue is NOT transparent
//first, you need a bitmap to work with
//if you know for sure the position of your bitmap, you can do something like this:
var bm:Bitmap = mc1.getChildAt(0) as Bitmap;
//annoyingly though, FlashPro makes timeline bitmaps shapes,
//so the above won't work UNLESS you take your bitmap in the FlashPro Library
//and export it for actionscript, giving it a class name, then it will be an actual bitmap on the timeline.
//As an alternative, you could (very CPU expensively) draw the whole button as a bitmap
var bmd:BitmapData = new BitmapData(mc1.width,mc1.height,true,0x00000000);
bmd.draw(mc1);
var bm:Bitmap = new Bitmap(bmd);
//we get the 32bit pixel under the mouse point
var pixel:uint = bm.bitmapData.getPixel32(bm.x + event.localX,bm.y + event.localY);
//then we grab just the Alpha part of that pixel ( >> 24 & 0xFF ).
//if the value is 0, it's totally transparent, if it's 255, it's totally opaque.
//for this example, let's say anything greater than 0 is considered good to be a click
if((pixel >> 24 & 0xFF) > 0){
mc2.gotoAndStop(2);
}
}

swipe gesture is not smooth for frame jumping

I have made an as3 android app where I have used swipe gesture for going next frame and previous frame. but I want when I jump to next or previous frame it swipes smoothly.I have tried to use tween max but it is not working.I have found that tween plugins always work for movie clips.So how can I make the swipe smooth.Can I make it smooth without tween plugins?here is my code....
Multitouch.inputMode = MultitouchInputMode.GESTURE;
stage.addEventListener (TransformGestureEvent.GESTURE_SWIPE, SwipeHandler);
function SwipeHandler(event:TransformGestureEvent):void
{
switch(event.offsetX)
{
// swiped right
case 1:
{
prevFrame();
break;
}
// swiped left
case -1:
{
if(currentFrame == 10)
{
stop();
}
else
{
nextFrame();
break;
}
}
}
}
In order for you to be able to smooth swap you need to have both frames on your screen, which is not the case with genuine Flash frames. Smooth transitions are animated via ENTER_FRAME handlers, with a potential hide of actual frame change process. So, in order to do a smooth transition, you need to move a picture of one frame to the left, and for the other frame to move in from the right instead of plain nextFrame(). Let's say you have a 60fpa stage, and try to smooth transition left. You will need two screen-sized objects, one depicting current frame and one the frame to be displayed, ready to be displayed as a single transition. An example:
var transition:Sprite;
var bitmaps:Array;
var leftSide:Bitmap
var rightSide:Bitmap;
// initialization code, best placed in constructor
leftSide=new Bitmap();
rightSide=new Bitmap();
bitmaps=[];
transition=new Sprite();
transition.addChild(leftSide);
transition.addChild(rightSide);
rightSide.x=stage.stageWidth; //left side and right side should be aside each other
This is the declaration of the needed structures. The plan is to show the transition, giving it two Bitmaps that will be linked to two different BitmapData objects that'll hold pictures of new frame and old frame. We will draw our current frame on current frame's bitmapdata, then take a stored next frame bitmap data and the do transition.
function swipeHandler((event:TransformGestureEvent):void {
var doSwitch:Boolean=false;
var targetFrame:int=currentFrame;
switch(event.offsetX) {
// swiped right
case 1: {
if (currentFrame>2) {
// let's say we're not allowed to swipe right from frame 2
targetframe=currentFrame-1;
doSwitch=true;
}
break;
}
// swiped left
case -1: {
if(currentFrame < 10) {
targetFrame=currentFrame+1;
doSwitch=true;
}
break;
}
}
if (!doSwitch) return;
// prepare transition
if (!bitmaps[targetFrame]) bitmaps[targetFrame]=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
// ^ make a new bitmap if there's none for target frame
if (!bitmaps[currentFrame]) bitmaps[currentFrame]=new BitmapData(stage.stageWidth,stage.stageHeight,false,0xffffff);
// the same for source frame
bitmaps[currentFrame].fillRect(bitmaps[currentFrame].rect,0xffffff);
bitmaps[currentFrame].draw(stage); // draw current frame on the bitmap
// with this and stored bitmaps, old frame would remain drawn on the cached bitmap
// and able to be used as a transition image
if (targetFrame>currentFrame) {
leftSide.bitmapData=bitmaps[currentFrame];
rightSide.bitmapData=bitmaps[targetFrame];
transition.x=0;
// here is the place to initialize TweenMax tween to move "transition"
// and don't forget to removeChild(transition) at the end of the tween
} else {
rightSide.bitmapData=bitmaps[currentFrame];
leftSide.bitmapData=bitmaps[targetFrame];
transition.x=-1*stage.stageWidth;
// same here for tweening
}
stage.addChild(transition);
gotoAndStop(targetFrame);
}
This places a prepared transition object on screen above all the underlying items, effectively masking the exact frame switch, done by gotoAndStop() call. This object's x coordinate can be tweened afterwards, and the object should be removed from stage once the tween is ofer.
Hope this helps.

In AS3, how can I check to see if mouse is inside a rectangle?

In AS3, how can I check to see if mouse is inside a rectangle after the stage has been clicked in that area?
for example:
var rec:Rectangle = new Rectangle(50, 200, 50, 200);
And the onclick function would do:
if (mouseX <=rec.left && etc...
I've tried many methods, but have still come up empty. Any ideas?
(What I really wanted to do was make an event listener for the rectangle, but it kept throwing errors so I'm trying to figure out a way to do it with an if statement instead.)
This isn't pertinent that I know this, because I can just do this with flat numbers. I'm trying to learn more about rectangles and points. I figured this would work with a rectangle too, but nope.
You can use Rectangles function contains which accepts 2 arguments x and y.
Like this:
var r:Rectangle = new Rectangle(50,200,50,200);
stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
if(r.contains(e.stageX,e.stageY))
{
trace("inside");
}
}

how to check, whether user is dragging the object rightside or leftside in actionscript 3

I am creating a flash based application, where user can change a rectangle shapes, width and height using mouse drag. here is a quick prototype image.
let me explain briefly: In the image you can see, i am having a tiny red rectangle, which one now sitting is starting position and user can drag that only 100px to right side. The idea is when, user is dragging that to right, i want to rectangle also expand right side with that, like a flexible box. if he is dragging back then it will return with that.
so, the doubt is: how will check, whether user is dragging right side or left side. so based on that we can update the rectangle width.
Here is the code :
import flash.geom.Rectangle;
import flash.events.MouseEvent;
var horizRect:Rectangle = new Rectangle(scrollPathHoriz.x, scrollPathHoriz.y, 100, 0);
var horizCount:Number;
//event listener for the anchor point.
scrollHoriz.addEventListener(MouseEvent.MOUSE_DOWN, dragScroller);
stage.addEventListener(MouseEvent.MOUSE_UP, dropScroller);
//mouse down and mouse up event handler.
function dragScroller(evt:MouseEvent):void {
horizCount= scrollHoriz.x;
scrollHoriz.startDrag(false, horizRect);
scrollHoriz.addEventListener(MouseEvent.MOUSE_MOVE, calculateHorizPixel);
}
function dropScroller(evt:MouseEvent):void {
scrollHoriz.stopDrag();
scrollHoriz.removeEventListener(MouseEvent.MOUSE_MOVE, calculateHorizPixel);
}
function calculateHorizPixel(evt:MouseEvent):void {
horizCount ++;
trace(horizCount);
}
Since you are already saving the starting x position,
You simply need the difference between starting position & current position :
function calculateHorizPixel(evt:MouseEvent):void {
var dx = scrollHoriz.x - horizCount;
trace(dx);
}
A negative value of dx indicates that scrollHoriz moved left, else right.
Or try this:
import flash.events.MouseEvent;
stage.addEventListener(MouseEvent.MOUSE_MOVE, moveMouse);
function moveMouse(event:MouseEvent):void
{
var dx:Number = mouseX - stage.stageWidth/2;
trace(dx);
}

As3 mouseover background not working as expected

I'm not having any success, getting a background to show at 0.5 alpha on a mouseover, with a Sprite as the parent of a TextArea. The best I can get is the text appearing at 0.5 transparency on MouseOver, which is completely not what I'm looking for. I want the text at maximum alpha regardless of Mouse State and only the background(Sprite) to appear at half transparency on MouseOver. I'd rather avoid tweens if possible. Here's my code:
var textSprite:Sprite = new Sprite();
public function Main()
{
textSprite.graphics.beginFill(0x000000, 0);
textSprite.graphics.drawRect(94.95, 80.95, 390, 130);
textSprite.graphics.endFill();
textSprite.addChild(picArea1);//textarea added on stage, same dimensions, transparent background
textSprite.buttonMode = true;
textSprite.useHandCursor = true;
stage.addChild(textSprite);
textSprite.addEventListener(MouseEvent.MOUSE_OVER, applyAlpha);
textSprite.addEventListener(MouseEvent.MOUSE_OUT, noApplyAlpha);
}
function applyAlpha(event:MouseEvent):void {
textSprite.alpha = 0.5;
}
function noApplyAlpha(event:MouseEvent):void {
textSprite.alpha = 0;
}
Setting the sprite's alpha also affects all of it's children (by design) which is your current issue.
The way you're currently doing it (drawing the background with the graphics object), you'd have to redraw the graphics of the sprite on mouse over/out.
Here is method you could use:
public function Main()
{
drawTextBG(); //a new function I made to avoid duplicating code
textSprite.addChild(picArea1);//textarea added on stage, same dimensions, transparent background
textSprite.buttonMode = true;
textSprite.useHandCursor = true;
stage.addChild(textSprite);
textSprite.addEventListener(MouseEvent.MOUSE_OVER, applyAlpha);
textSprite.addEventListener(MouseEvent.MOUSE_OUT, noApplyAlpha);
}
//new function I made, this draws the background and makes the transparency the value passed in. I set the default to 1 (totally visible)
function drawTextBG(bgAlpha:Number = 1):void {
textSprite.graphics.clear();
textSprite.graphics.beginFill(0x000000, bgAlpha);
textSprite.graphics.drawRect(94.95, 80.95, 390, 130);
textSprite.graphics.endFill();
}
function applyAlpha(event:MouseEvent):void {
drawTextBG(.5); //redraw the background with half (.5) alpha
}
function noApplyAlpha(event:MouseEvent):void {
drawTextBG(); //redraw the background with the default value (1 - totaly visible)
}
Now, if your using a TLF (text-layout-framework) text field you can just use the backgroundColor and backgroundAlpha properties of the text field and forgo drawing a background manually.