Copy link to clipboard
Copied
I have a question that was somewhat answered but I now have some problems with, as far as implementing the solution is concerned. I posted in August and I have revisited the file only now to see if I can create the changes necessary to center my mc's dynamically as they are drawn on the stage at runtime. They need to center to themselves rather than having their registration points in the top left corner, per display object.
Here is the thread:
http://forums.adobe.com/message/5760947#5760947
Thanks in advance for any responses.
-markerline
I attempted to reply yesterday but the forums became under maintenance (as we all re-logged in after).
What I tried to post before the system went down was to give a single example as you had mentioned. To remove the complexity of the rest of the app so this can be understood alone and then implemented into your larger system.
Centering via container in code is very simple as long as you can grab a hold of the shape in code as well.
Here's a complete AS3 example of centering a single object insid
...Copy link to clipboard
Copied
I attempted to reply yesterday but the forums became under maintenance (as we all re-logged in after).
What I tried to post before the system went down was to give a single example as you had mentioned. To remove the complexity of the rest of the app so this can be understood alone and then implemented into your larger system.
Centering via container in code is very simple as long as you can grab a hold of the shape in code as well.
Here's a complete AS3 example of centering a single object inside a container. I just want you to paste this into a new AS3 doc so you can tell me you understand how it works. After that, the more complex multi-object container in a container approach comes in:
e.g. 2 squares rotating:
import flash.display.Shape;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Sprite;
// start rotation loop using a Timer to turn all objects
var moveTimer:Timer = new Timer(10,0);
// function to rotate objects
moveTimer.addEventListener(TimerEvent.TIMER, handleTimer);
// draw a rect shape
var redrect:Shape = new Shape();
redrect.graphics.lineStyle(3,0x0,1,true);
redrect.graphics.beginFill(0xFF0000);
redrect.graphics.drawRect(0,0,100,100);
redrect.graphics.endFill();
addChild(redrect);
// position at x:100 / y:100 on stage
redrect.x = 150;
redrect.y = 200;
// now draw a blue square but with a container while centering the shape
// container
var blueContainer:Sprite = new Sprite();
addChild(blueContainer);
// draw a rect shape
var bluerect:Shape = new Shape();
bluerect.graphics.lineStyle(3,0x0,1,true);
bluerect.graphics.beginFill(0x0000FF);
bluerect.graphics.drawRect(0,0,100,100);
bluerect.graphics.endFill();
blueContainer.addChild(bluerect);
// position in center of container (subtract half width/height)
//-------------centering code----------------
bluerect.x -= bluerect.width / 2;
bluerect.y -= bluerect.height / 2;
//-------------------------------------------
// position container
blueContainer.x = 400;
blueContainer.y = 200;
// start timer which invokes function below
moveTimer.start();
// rotate the red rect (upper left reg) and blue (objects centered);
function handleTimer(e:TimerEvent):void
{
// just rotate both to see the registration
redrect.rotation += 2;
blueContainer.rotation += 2;
}
Now do understand I know I can draw my bluerect with negative coordinates to achieve the same thing inside the shape (e.g. -50,-50,100,100) but the point here is containing potentially a complex object into a single object so the entire outer contents can be measured and rotated from a single center point. That comes after this simple code is understood.
Copy link to clipboard
Copied
i was unaware of the maintenance issue and since i didnt see a response i thought you had unsubscribed from the thread, unable thus to see my latest post.
in any case i must be having difficulty with the container and child. the code i have in several different versions doesnt work. i guess i am missing either the fundamental actionscript concepts or the math or both.
Copy link to clipboard
Copied
Check the edit above, implement that and let me know if you understand why one object rotates on the typical upper left registration and why the container (repositioned) object rotates on the center.
Copy link to clipboard
Copied
Hi Sinious,
I actually do understand that code and I tried to implement something as such.
bluerect.x -= bluerect.width / 2;
bluerect.y -= bluerect.height / 2;
I even tried it the other way around yesterday since I was using an EnterFrame event:
bluerect.x =- bluerect.width / 2;
bluerect.y =- bluerect.height / 2;
With EnterFrame it would keep subtracting infinitely and disappear off the stage in your method with "-=" . At least that's what I observed yesterday.
Copy link to clipboard
Copied
Do you need to center it each frame? Is the object irregular in size? If so then on each frame just perform the full operation rather than the convenience version:
bluerect.x = -1 * (bluerect.width / 2);
bluerect.y = -1 * (bluerect.height / 2);
Copy link to clipboard
Copied
When you say "convenience version" do you mean that this will not work?
mc.x= -mc.width/2;
mc.y= -mc.height/2;
I think the problem is moreso rooted in the fact that I am defining my irregular objects (Bitmap Paths that are drawn with the lineto method) at runtime in a "drawmc" function but I am accessing the registration effect in a separate EnterFrame event.
I am doing something like this:
function onEnterEvent(e:Event):void{
for each (var mymc:Shape in PathsArray){
mymc.x=-mymc.width/2;
mymc.y=-mymc.height/2;
}
}
Since that method didn't work I also tried to use the matrix class to offset with a more complex piece of code that I found in a book about AIR development.
Copy link to clipboard
Copied
I'm familiar with the matrix method and don't really prefer it but the complexity and hierarchy of the objects you're trying to center is what really needs to be known. By adding containers, code that interacts with your display objects will need to know how to access them. If you add containers, that code may break.
By convenience I mean the subtract-from-self convenience function -=. That will take whatever the current value on the left side is and subtract from it (e.g. 10 -= 10; (first 0, then -10, then -20, then -30, ... etc -900000000)). So when you run it over and over you can see why they run off stage into high negative values.
My version just multiplys -1 to the value returned to negate it. Your version does the same thing as long as the assignment operator is spaced from the assignment operator and prefixes your value. You can see it negate the value properly:
trace(mymc.width); // normal positive width (e.g. 100)
trace(-mymc.width); // negated width (e.g. -100)
So yes it's also fine to say:
// adding extra spaces for clarity
mymc.x = -mymc.width / 2;
mymc.y = -mymc.height / 2;
Same thing.
Lastly you do need to make sure your objects exist before you perform this. I believe you were getting at this when you mentioned the values are calculated on the ENTER_FRAME event. If they don't exist yet you should wait until they do before performing it.
Copy link to clipboard
Copied
Ah, I see. That may very well be the issue: The fact that they haven't populated the stage at the time the EnterFrame event is trying to access the code.
Exactly how does Event.COMPLETE work? I'm not that familiar with using that type of Event. Can you show me an example or point me to the AS3.0 Reference manual?
Copy link to clipboard
Copied
Complete will fire off once a load operation is complete. An ENTER_FRAME happens after that. It's typically a good idea to wait until after the very first ENTER_FRAME event to assure all assets in frame 1 are loaded. Just the typical:
addEventListener(Event.ENTER_FRAME, onEF);
function onEF(e:Event):void
{
// SWF loaded, first frame has instandiated display list, now do/change what you want
// first things first, remove the ENTER_FRAME listener
removeEventListener(Event.ENTER_FRAME, onEF);
// everything else you need to do ...
}
Copy link to clipboard
Copied
Well, I guess I don't need to use Event.COMPLETE, then?
The problem is, removing the EnterFrame Event Listener causes the interaction to stop. What I'm doing is scaling the object according to sounds in the SoundChannel by using the leftPeak and rightPeak properties (actually just using leftPeak solves the interaction). I don't think I'm putting the removeEventListener in the right place since I get no motion when I hit the "play" button in my demo.
Copy link to clipboard
Copied
Remember you can set multiple listeners that report to different handler functions for the same event. e.g.
// wait for initial objects to be valid
addEventListener(Event.ENTER_FRAME, handleFirstEnterFrameF);
function handleFirstEnterFrameF(e:Event):void
{
// now in app, no longer listen
removeEventListener(Event.ENTER_FRAME, handleFirstEnterFrameF);
// now add a new ENTER_FRAME listener
addEventListener(Event.ENTER_FRAME, handleDoingOtherStuffF);
// do one-time init stuff
}
function handleDoingOtherStuffF(e:Event):void
{
// do stuff here, will continue to run once per frame
}
You shouldn't have issues with multiple listeners at the same time but what I've done above is daisy chained them. You may not want the "do stuff" function firing off before you finish initializing anything so I added the listener inside the first function.
Also remember that ENTER_FRAME is pretty expensive. It's forced to complete before the frame can finish. If you do too much work in it you will drag down your frame rate. Consider a Timer for the mechanism you use to update the graphics based on the sound transform. An example of the timer is already in a reply above.
Copy link to clipboard
Copied
Thanks for pointing out that the difference between your code and mine was in the Timer event. That solved one bug I was having in the new implementation of code I wrote.
It's funny because without knowing that you had replied, I came to the same conclusion that you had used a Timer Event in the example above and that maybe I should try that out just to see if it will optimize things for me. AND IT DID!!!! Eureka!
In any case, I'm still working on my code but to simplify things I created an explicit container on the stage with its registration point at the center to use in my application, instead of using one at run-time through coded-creation. So far I have everything scaling from the center of the stage.
In the best circumstance I would like to scale things from their specific object-centers on an individual basis, rather than as a grouped set of objects scaling from a single point to the sound of the soundChannel.
I will post again with my progress if I make some more.
Thus far, I thank you immensely for your patience and willingness to help sinious.
Regards,
-markerline
Copy link to clipboard
Copied
Getting them all individually to scale to their own centers will just be doing the same thing you're doing overall but replicating it on all the sub clips. In other words, the same thing you're doing, just on different clips.
If you're all set for now please mark any helpful/correct so we can filter unanswered questions. You're welcome and good luck!
Copy link to clipboard
Copied
done. thanks again. ![]()
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more