Take glow from a DisplayObject and put it in another - actionscript-3

I have a grid of DisplayObjects that when I put a glow on any of them, the glow overlap the other objects.
I was wondering if I could take the glow created by a DisplayObject and put it another, so I can attach it to a container that's behind all the objects? If someone can suggest a better idea, that would be much appreciated too.

Kodiak has the right idea here but it sounds like once you add the glow to the object it stays there and you don't remove it. (For example you don't do somethings like on mouse hover -> glow, on mouse out -> no glow) You want something like Once I hover over the object it glows and the glow itself is always behind the other display objects.
This seems odd to me but what you could is create a duplicate of the grid and place it underneath of the top level ones and then do somethings like...
public function test() {
// constructor code
primaryDisObj:Array() = new Array(primaryDO1, primaryDO2);// an array of the instances of the Display Objects on top
secondaryDisObj:Array() = new Array(secondDO1, secondDO2);// an array of the instances of the Display Objects underneath the originals
for(var i:uint = 0; i < primaryDisObj.length; i++){
primaryDisObj[i].name = i;
primaryDisObj[i].addEventListener(MouseEvent.MOUSE_OVER, overPrimary);
}
}
private function overPrimary(e:MouseEvent):void{
secondaryDisObj[e.target.name as uint).filters = [new GlowFilter(0xFF6699, .75, 25, 25, 2, 2, false, false)];//Or however you want you filer to look
}
Without seeing you code it's kind of hard to figure out what you're going for but this is the simplest way I can think of to do this.

Can't you just change the index of the glowing object to put it in the back?
myItem.parent.setChildIndex(myItem, 0);

Related

Flex 4 image object returning as MovieClip object

I am working on a custom context menu in Flex4. The context menu itself works fine but I am looking for a way to tell if the ContextMenuEvent mouseTarget is an image. As it stands, the mouseTarget shows that it is a "[object MovieClip]". Which is strange because I have no movie clips in my application, only image containers. Any idea what is going on?
private function openContextMenu(e:ContextMenuEvent):void {
Alert.show(e.mouseTarget.toString());// shows [object MovieClip] when it should show [Object Image]
}
Thanks
You need to set mouseChildren on the Image to false, then the MouseEvent will refer to the Image:
if (event.target is Image) {
//do stuff
}
So after a few more hours of research I came up with the below attached to the contextMenu's item select event listener. I am sure there has to be a better way to do this, but until then...
for(var i:int = 0; i < getObjectsUnderPoint(new Point(this.mouseX, this.mouseY)).length; i++)
{
if(getObjectsUnderPoint(new Point(this.mouseX, this.mouseY))[i].parent.parent is Image)
{
//do what I need to do
}
}
Thanks NHubben for your input. It got me going down the right path of looking at children.
The component name Image has no relevance concerning what makes it up. The flex inheritance is: Image -- SWFLoader -- UIComponent -- FlexSprite -- [...] (from mx.controls.Image docs).
So what you need to do is understand what you actually have when you bring it into a AS3 environment. It seems like it gets wrapped up in a MovieClip to allow it be in the Flash's display list. It also looks like you have to go through a loader, but I'm not sure of that.
Run a test or two to find out what the object is actually made up of:
// not foolproof, and will break on some stuff,
// so you will have to fix this as needed:
private function loopDisplay(obj:Sprite):void
{
trace(obj.name + ": " + obj);
if (obj.numChildren > 0)
{
for (var i:int = 0; i < this.numChildren; i++)
{
loopDisplay(obj.getChildAt(i));
}
}
}
If you put this in a mouse down handler, then you can see what is actually there.
However, the event.target or event.currentTarget should also hold the menu item object, so you can also just loop into those objects and see what is in them.

action script 3 - is it possible to trigger click event only when mouse is clicked on the image part?

I have a problem and I have potential solution. But I wanted to confirm if there is an easy and simple way to solve my problem.
App type:
Isometric Game
Problem statement:
I am loading images in my flash app and have mouse events attached to them.
The images I load are prop images like vehicles, trees, buildings etc., and all of them are transparent.
Example: Red ball asset (please ignore the yellow background which I applied to describe the problem)
If I click on the actual image area (colored in red), then every thing works perfect
I don't want to trigger mouseevent when I click on empty image part (or transparent area, which I have shown in yellow color)
There is one way I know by creating masks in flash. I don't want to do it unless that is the final option left because I load image assets instead of flash assets and I don't want to create a new mask asset for all the assets
There is another method I was going to adopt by using getPixel method of Bitmap. Which is discussed here.
But there is another problem with this method.
I might be able to ignore the click event when I click on the empty part of the asset but if there is some other asset is behind the image in the same location, then I need to process the click event for the occluded image.
Well, thinking of solution to this problem takes me to the getObjectsUnderPoint where I can scan the occluded assets
Well, what you proposed as a solution is 100% valid. Just move the logic of determining what game object is clicked outside of that object.
Listen for MOUSE_DOWN/MOUSE_UP events at container which contains your game objects.
Catch an event
Check if the game object which is the target of this event is transparent at this point using BitmapData.getPixel32
If it is use getObjectsUnderPoint to find out all other game objects at this point
Find in a loop the first object which is not transparent at this point
Now you got the actual object which is hit.
One interesting solution is to use Sprite objects with the individual non-transparent pixels burnt onto them.
Suppose this is your Loader "complete" handler:
private function loaderCompleteHandler(event:Event):void
{
// Loader is not our child, we use a Sprite instead (below).
var loader:Loader = Loader(event.target);
var sprite:Sprite = new Sprite();
addChild(sprite);
var w:Number = loader.content.width;
var h:Number = loader.content.height;
// Use transparent bitmap.
var bitmapData:BitmapData = new BitmapData(w, h, true, 0);
bitmapData.draw(loader.content);
// Now burn the image onto the Sprite object, ignoring
// the transparent pixels.
for (var xPos:int = 0; xPos < w; xPos++) {
for (var yPos:int = 0; yPos < h; yPos++) {
var pixel32:uint = bitmapData.getPixel32(xPos, yPos);
var alpha:int = pixel32 >>> 24;
if (alpha != 0) {
sprite.graphics.beginFill(pixel32 & 0xFFFFFF, alpha / 0xFF);
sprite.graphics.drawRect(xPos, yPos, 1, 1);
sprite.graphics.endFill();
}
}
}
}
Essentially you want "empty" pixels that aren't clickable, and fully transparent pixels aren't quite the same thing. With this solution you get empty pixels.
Only problem is that this might be slow. Give it a shot.

ActionScript 3: Bullet Ricocheting

I've been having a problem with my Actionscript code. I am fairly new to Flash and AS3, so I apologize if my code seems crude or rudimentary, but I'm doing this as best as I can.
Well, in this project I'm trying to get a bullet to ricochet off a wall once. If it hits a wall again after ricocheting, the bullet will disappear.
I've created a for loop which moves the bullets, in an array. At the same time, I try to keep track of each bullet's individual number of ricochets. This works fine when I shoot a first bullet - it will ricochet and then disappear after hitting another wall. However, every bullet I fire after that disappears on the first wall it hits, before it has ricocheted. I've tried to get this to work but I just can't seem to do it.
I would be grateful if somebody could show me the problem, or suggest a change to my code.
Here is a link to my code as it is now.
Thanks, to anybody who helps.
Here are some suggestions I have:
1: Create a Bullet class that tracks its own collisions against walls. I'd also move the clearBullet() method into the bullet class itself.
public class Bullet extends Sprite
{
public var collisions:int = 0;
public var xv:Number = 0;
public var yv:Number = 0;
public function clear():void
{
if(parent)
parent.removeChild(this);
}
}
2: Update your loop to deal with this new info.
for each(var i:Bullet in bulletholder)
{
// Move bullet.
// Check for collision.
// When there is a collision, do this:
i.collisions ++;
if(i.collisions >= 2)
{
var n:int = bulletholder.indexOf(i);
bulletholder.splice(n, 1);
i.clear();
}
else
{
// Deal with changing bullet position.
}
}
I see at least a couple of problems with your code:
Your ricochetcount is clearly out of sync. i.e. you need to delete an element from that array as well.
When you delete an element from the bulletholder array (via clearBullet), you're still incrementing i, which means you end up inadvertently skipping an element.
Also I'm not sure why you need clearBullet(). You already have the index i as well as a reference to the bullet object right there in the main loop.

Is there a way to keep an object always at the top of the display list?

Is there a way to make a display object always be at the top of the display list?
For example, I know you can set the childIndex, i.e:
setChildIndex(myDisplayObject, numChildren-1);
But is there a way that an object has sensed that something else has been added to the display list and restack themselves accordingly?
You can listen to the Event.ADDED event on the container. This event will bubble up, so you'll get called whenever a display object is added to the container or any of its children.
Here's an example of how you could do this. You'll see the black box always stays on top.
var container:DisplayObjectContainer = this; // this is a frame script but just change this line as necessary
container.addEventListener(Event.ADDED,handleAdded,true);
function handleAdded(e:Event):void {
// this if tries to cover some edge cases, unlikely to happen in your code, from your description
if(container == topElement.parent && container.numChildren > 0 && container.getChildIndex(topElement) != container.numChildren - 1) {
container.setChildIndex(topElement,numChildren - 1);
}
}
function getSprite(c:uint):Sprite {
var sp:Sprite = new Sprite();
sp.graphics.beginFill(c);
sp.graphics.drawRect(0,0,100,100);
sp.graphics.endFill();
return sp;
}
var topElement:Sprite = getSprite(0);
container.addChild(topElement);
var sp:Sprite = getSprite(0xff0000);
container.addChild(sp);
sp.addChild(getSprite(0xff00));
var sp2:Sprite = getSprite(0xff);
container.addChild(sp2);
However, I think it's much simpler and cleaner just to have 2 containers, say, top and bottom, kind of like layers. In top you'd add the element that always must be on top (or this could be your element as you probably don't need to have this extra container). In bottom you'd add and remove whatever you want. Then you can forget about manually restacking stuff (at least to keep the top element atop).
You can override the addChild() method in the parent object. In that method you can move your child to the top using
setChildIndex(myDisplayObject, numChildren-1);
In this way everytime an object is added to the parent, the parent moves your object to the top.

ActionScript - clicking and determining the sprite's class

i'd like to add all or most of my mouse events to stage, but in order to do that i need to be able to tell what is the type of the sprite being clicked.
i've added two sprites to the display list, one of which is from a class called Square, the other from a class called Circle.
var mySquare:Sprite = new Square();
var myCircle:Sprite = new Circle();
addChild(mySquare);
addChild(myCircle);
now when i click on these sprites, i'd like to know from which class they are from, or which type of sprite it is.
//mousePoint returns mouse coordinates of the stage
var myArray:Array = stage.getObjectsUnderPoint(mousePoint());
if (myArray[myArray.length - 1] is Sprite)
...
so far i know how to do is determine if it IS a sprite display object, but since i'll only be working with sprites i need something more specific. rather than checking "is Sprite", is there a way i can check "is Square" or "is Circle"?
if (myArray[myArray.length - 1] is Square)
You've answered your own question.
if (myArray[myArray.length - 1] is Square)
If this doesn't work, then it should, so something else is wrong.