Same mouseover/-out effect for many buttons - actionscript-3

Last time I touched flash was 10 years ago, or so... In other words, I'm quite rusty. I am going to make a interactive map of Europe. I want the strongly green circles to have a mouseover/-out effect (First I was thinking some size-change, but I think maybe I'll go for opacityfading). I have a couple problems. The code under is working, but Is there a good way to either force the fadingout(...) to finish, before fadingin(...) is called? If not, is there a smart way to get the current opacityvalue when fadingin(...) and make that the start value. If the user moves the mouse outside quickly, the effect is not looking very nice. Also, what is the best way to get these functions to work with every circle in the map? If the user drags the mouse around, I want this to create a tracing effect.
import fl.transitions.Tween;
import fl.transitions.easing.*;
var outTween:Tween;
myButton.addEventListener(MouseEvent.MOUSE_OVER, fadingout);
myButton.addEventListener(MouseEvent.MOUSE_OUT, fadingin);
function fadingout(event:MouseEvent): void {
outTween = new Tween(myButton, "alpha", None.easeNone, 1, 0, 1, true);
}
function fadingin(event:MouseEvent): void {
outTween = new Tween(myButton, "alpha", None.easeNone, 0, 1, 1, true);
}

What I would probably do is create a class for the circle. In there I would create the eventlisteners for mouseover and mouseout to change the opacity and/or size.
On a second note, I recommend that you use TweenLite or TweenMax from greensock http://www.greensock.com/tweenlite/
TweenLite should probably suffice for you. Look into it's properties especially the "overwrite"-property which controls the tween overriding you mentioned
overwrite : int Controls how (and if)
other tweens of the same target are
overwritten by this tween. There are
several modes to choose from, but only
the first two are available in
TweenLite unless
OverwriteManager.init() has been
called

You could very well create a class for the green circles, and contain all listeners and tweened reaction features within it. A very solid method.
You may also leverage event propagation on a movie clip / sprite containing all mouseable elements to achieve the same thing with a single listener set:
var myContainer:Sprite = new Sprite();
//add all elements
myContainer.addEventListener(MouseEvent.MOUSE_OVER, over, true, 0, false);
myContainer.addEventListener(MouseEvent.MOUSE_OUT, out, true, 0, false);
private function over(e:MouseEvent):void
{
TweenLite.to(e.target, .5, { alpha:1.0 });
}
private function out(e:MouseEvent):void
{
TweenLite.to(e.target, .5, { alpha:0.5});
}
Basically, you add the listener to the containing object, and events are passed down to the children, who then receive the event instructions. The ".target" of the propagating object, received in the MouseEvent argument is the key here.
I'm using the fantastic TweenLite framework here, as mentioned by others, and you should too.
cheers and good luck!

Related

How to make a MovieClip change to get lighter or darker?

Is there a way to have a movie clip in your flash game and when something happens (such as a mouse hovering over it) for it to become lighter or darker?
MovieClip.addEventListener(MouseEvent.MOUSE_OVER, onContact);
public function onContact(event:MouseEvent):void
{
//Not Sure What To Put Here
}
Is there a way to do this?
Thanks in advance,
Jason
Every object that has a colorTransform has the ability to manipulate it's colour.
For example try this:
public function onContact(contact:MouseEvent):void
{
var displayObject:DisplayObject = contact.currentTarget as DisplayObject;
displayObject.transform.colorTransform = new ColorTransform( .3, .3, .3); // makes object darker
}
Also, it's common to use tweening engines like TweenLite/TweenMax (http://www.greensock.com/tweenmax/) to tween the colorTransform. If you'll navigate to the provided link there is a plug-in explorer that allows you to test and experiment with different tweening plug-ins including Color Transform.

How to set mouse click to do not hit transparent pixels

Imagine a painting program. I have two imagens overlaping each other. I must be able to click on the image behind if I click on a transparent part of the above one.
I add an event listener on each image. So I must prevent the first one to dispatch click event in order to the behind one dispatch it.
(I mean, I already check for transparent pixels, but i can't cancel that event to the other imagem dispatch it.)
There is some dirty solution. Say your "images" are encapsulated in Sprites, otherwise you can't attach a listener to a Bitmap object or a Shape object. MovieClips - well, should still work, although checking alpha is a lot harder. You have your listeners attached to those sprites. First, that sprite in itself can check transparency, and if not transparent, proceed the event. To get what's behind, you can call stage.getObjectsUnderPoint(), this will return an Array of DisplayObjects, with foreground being on top. So you might have one single listener that would call this to enumerate what's under the point, then do as Roman Trofimov advises to determine that object's transparency. Once you'll find a non-transparent object, you do:
// "b" is a non-transparent DisplayObject found beforehand
while (b && (!(b is InteractiveObject))) b = b.parent;
if (b) {
var p:Point = new Point(e.stageX, e.stageY);
p = b.globalToLocal(p);
b.dispatchEvent(new MouseEvent('click', true, true, p.x, p.y));
}
This will dispatch a click event to the object that's able to receive events, and is opaque enough to obscure the background.
The MovieClip property 'mouseEnabled' can prevent click events from triggering on objects in front of other objects, for example, take two movie clips of the same size and same position:
mc1.addEventListener(MouseEvent.CLICK, click1);
function click1(e:MouseEvent) : void
{
trace("1");
}
mc2.addEventListener(MouseEvent.CLICK, click2);
function click2(e:MouseEvent) : void
{
trace("2");
}
mc1.mouseEnabled = false;
Output would be "2" as the click would essentially go 'through' mc1.
In flex you can add mouseEnabledWhereTransparent="false" to components. Not fully sure if that variable is available to you though
Generally, you will always get first event from first sprite (if it was not capture phase ot priority change). But as I understand, you need to check was it transparent and if not - stop bubbling this event.
To stop event - use event.stopImmediatePropagation() in event handler.
To determine transparency:
1) If it is just only the one bitmap, you can check its .bitmapData with method .getPixel32, it returns you alpha value.
2) If it is combined sprite (vector and bitmap), you need to manually render it to Bitmap using BitmapData.draw and then use solution from second case
3) To understand if it was absolutelly miss click, you can try this method: Check transparency

How to make animation from many images(Actionscript)

How much images I need to make a good animated person or someone like stickman?
I have created a class Person for example and added an event listener onEnterFrame there, so every stickman have its own animation
private function onEnterFrame(e:Event):void{
addChild(image[i])
i++;
//thus every times increasing the i++, and add a new image
}
for example if I have a speed of 24 fps, the images are changing to fast and the animation isn't good enough, can you give me an advice on how to do that right?
ps: how to add and remove the child to delete the unnecesary previous image? in the onEnterFrame event?
Use graphics of the container Sprite/MovieClip. Ref: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Graphics.html
Assuming image[i] is Bitmap
graphics.clear();
var bitmapData:BitmapData = image[i].bitmapData;
graphics.beginBitmapFill(bitmapData, new Matrix());
graphics.endFill();

Prevent height change of a DisplayObject

Is there a way to prevent the automatic change of the height property of a DisplayObject? It automatically resizes to match content, though my swf file is 32 pixels height. The code below can show prove of this, first frame enemy.height is 32 but later is 27.5, and this messes up my script.
getRect() and getBounds() return exactly the same. Also, I want to know why in the first frame it shows the correct height and in the second it changes, it should show 27.5 from the beginning.
package {
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite {
private var enemy:Sprite;
[Embed(source = '../lib/enemy.swf')] private var swf:Class;
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function update(e:Event):void {
trace(enemy.height);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
enemy = new swf();
addChild(enemy);
addEventListener(Event.ENTER_FRAME, update);
}
}
}
This has to do with the fact that you're instantiating a whole SWF, and 1 frame has to pass for it to be synced to the Main swf. What I would do is export the symbol in the .fla, then use the "embed symbol" syntax in Flex:
[Embed(source='enemy.swf#Symbol1')]
private var swf:Class;
In this case, the height will be consistent even in the first ENTER_FRAME. If it's not the height you want, you can use the invisible shape to set the bounds.
A "hacky" solution might be to add a shape to the enemy that has the max size you want, then set it to be invisible. I have created hit boxes for objects that way and it worked quite well.
One way would be to add it when creating the object in the Flash IDE. Just draw it and position it as you want the shape to be, then give it an instance name, like "sizeHolder". After you create the enemy you would then call
enemy.sizeHolder.visible = false;
In the Flash IDE you could place it on another timeline, then make that timeline invisible and lock it, so it wouldn't get in your way when editing the actual object.
The other way would be to add it by code. Draw the object in another DisplayObject, set it to invisible and then addChild it to enemy.
The enemy sprite animation sequence
will vary in height.This is part of
the animation process. Hence the
actual height per frame will vary
based on bounding box of the sprite.
As you very well observed this is the
default behavior.
The ways:
The One you are presently following storing height and using for calculations.(better)
As EyeSeeEm suggested if i understood him correctly having an invisible height sprite background with proper centering of the movie clip center point and centering of the sprite in each frame to be contained in the invisible height sprite bounds.
You will often find that you will come across features in action script not working the way you want it to.Whats important is that you adapt the coding to facilitate the solution . It is not hack y or inefficient when and coding/method allows for easily making further changes/extensions.
P.S:
This would depend on situation but personally i would rather the height be dynamic according to the sprite animation instance so any hits to the enemy just nearly over its head by projectiles doesn't actually kill the enemy.
Try
import flash.display.StageAlign;
import flash.display.StageScaleMode;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;

Movieclip stacking in Actionscript

I'm building a game of which the interface is one of the first items to load on screen. Sound button, pause and all the bits -
During the game - all manor of things are dynamically added and removed to the stage. Therefore my interface goes behind my game scene.
How do I ensure the movieclip always stays on top?
Can I override the addChild of my Document Class and every time a new child is added, I restack the interface to the top?
You can use setChildIndex to rearrange objects that are already contained within a MovieClip or Sprite. For example, if you have an object called container, which contains a redBall, blueBall and many other ball objects, you can use the following to make sure redBall is behind everything else:
container.setChildIndex(redBall, 0);
Equally you can make sure that blueBall will be displayed infront of everything else using:
container.setChildIndex(blueBall, container.numChildren-1);
addChildAt will sort you out for adding children straight into their correct position, and setChildIndex will allow you to re-position objects already placed. Hope that helps.
debu
Look into addChildAt, it allows you to specify the index that the new object should be added too.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObjectContainer.html#addChildAt%28%29
A good strategy is to keep all interface elements in one parent Sprite/MovieClip, and all game assets in another. (With the interface one on top)
With your guys suggestion I made this, apparently, if you addChild an object already on the screen, it's simply reindex'd to the top. Does this look ok?
private var topLevelChildrenArray:Array = [];
public function addTopLevelChild(child:DisplayObject):DisplayObject
{
topLevelChildrenArray.push(child)
return this.addChildAt( child, this.numChildren - 1 );
}
override public function addChild(child:DisplayObject):DisplayObject
{
this.addChildAt(child, this.numChildren);
for each(var topChild:DisplayObject in topLevelChildrenArray)
{
super.addChild(topChild);
}
return child
}