UltraVires
UltraVires

Reputation: 25

Accessing the public properties of currentTarget

I am new to Actionscript 3 programming. I am having trouble using e.currentTarget as a reference to an object I click on. This is a abbreviated code for the object:

public class Character extends Sprite
{
    private var _bodyPartLocations:Array = new Array();

    private var _head:Head
    private var _body:Body
    public var characterImage:Sprite = new Sprite

    private var _thumbnailBackground:CharacterThumbnailBackground
    private var _headScaled:Head
    public var thumbnail:Sprite = new Sprite

    public function Character() 
    {
        _bodyPartLocations = 
        [
            [50, 0], //Head
            [53, 80], //Body
        ];

        _head = new Head();
        _body = new Body();

        Util.addSprite(_head, characterImage, _bodyPartLocations[0][0], _bodyPartLocations[0][1]);
        Util.addSprite(_body, characterImage, _bodyPartLocations[1][0], _bodyPartLocations[1][1]);

        _thumbnailBackground = new CharacterThumbnailBackground();
        _headScaled = new Head;
        _headScaled.scaleX = 0.8;
        _headScaled.scaleY = 0.8;

        Util.addSprite(_thumbnailBackground, thumbnail, 0, 0);
        Util.addSprite(_headScaled, thumbnail, 0, 0);
    }
}

Essentially, I am trying to create two sprites (characterImage and thumbnail) that will be a part of the overall Character sprite. The Util class simply contains this shortcut for addChild and position for me:

static public function addSprite(addedSprite:Sprite, toSprite:Sprite, xPos:int = 0, yPos:int = 0):void 
    {
        toSprite.addChild(addedSprite);
        addedSprite.x = xPos;
        addedSprite.y = yPos;
    }

The problem I am having arises in my character creator menu screen. Currently, it simply is comprised of a space where character thumbnails are displayed (and stored in an array), a space to display the character image when a character's thumbnail is clicked on, and finally a "create character" button. When the button is clicked, a character is created, its thumbnail is given an event listener, and the thumbnail is added to show up on the menu (the position boolean check is simply my way of tying the character positions array with the characters array, I have omitted the other position checks):

private function createCharacterHandler(e:MouseEvent):void 
    {
        if (_characters.length < 6) 
        {
            var char:Character = new Character();
            char.thumbnail.addEventListener(MouseEvent.CLICK, characterClickHandler);

            if (_positionZero == false) 
            {
                Util.addSprite(char.thumbnail, this, _characterThumbnailPositions[0][0], _characterThumbnailPositions[0][1]);
                _positionZero = true;
            }
            _characters.push(char);
    }

And this brings me to the problem. If I click on the character thumbnail, this event handler executes:

private function characterClickHandler(e:MouseEvent):void 
    {
        var selectedChar:Character = e.currentTarget as Character;
        Util.addSprite(selectedChar.characterImage, this, _characterImagePosition[0][0], _characterImagePosition[0][1]);
    }

As you can see, I have attempted to use e.currentTarget to try and display the characterImage associated with the thumbnail of the character I clicked on. The code runs when I test it, however when I click on the thumbnail of a character I have generated, the Flash player stalls and I get this error:

[Fault] exception, information=TypeError: Error #1009: Cannot access a property or method of a null object reference.

Searching the Internet, I have seen others use e.currentTarget as a reference to objects that are clicked on (but I do not want to create an instance name for each character that I generate as I plan on having characters being generated and deleted regularly, so naming each one becomes too difficult). Where am I going wrong?

EDIT WITH UPDATE:

So, changing characterClickHandler to:

private function characterClickHandler(e:MouseEvent):void 
    {
        var selectedChar:Character = DisplayObject(e.currentTarget).parent as Character;
        Util.addSprite(selectedChar.characterImage, this, _characterImagePosition[0][0], _characterImagePosition[0][1]);
    }

Still produces the same fault error. I even tried this formulation to no effect:

private function characterClickHandler(e:MouseEvent):void 
    {
        var selectedThumbnail:DisplayObject = e.currentTarget as DisplayObject;
        var selectedChar:Character = selectedThumbnail.parent as Character;
        Util.addSprite(selectedChar.characterImage, this, _characterImagePosition[0][0], _characterImagePosition[0][1]);
    }

And in order to see if my Util.addSprite was working properly, I changed the createCharacterHandler to include the character image in addition to the thumbnail:

private function createCharacterHandler(e:MouseEvent):void 
    {
        if (_characters.length < 6) 
        {
            var char:Character = new Character();
            char.thumbnail.addEventListener(MouseEvent.CLICK, characterClickHandler);

            if (_positionZero == false) 
            {
                Util.addSprite(char.thumbnail, this, _characterThumbnailPositions[0][0], _characterThumbnailPositions[0][1]);
                _positionZero = true;
            }
            Util.addSprite(char.characterImage, this, _characterImagePosition[0][0], _characterImagePosition[0][1]);
            _characters.push(char);
    }

This code gives me the end result that I want to occur after the user has clicked on the thumbnail, as the character image now automatically appears on the menu as well. However, I want to incorporate the "user clicking on the thumbnail" part.

Upvotes: 1

Views: 52

Answers (1)

BadFeelingAboutThis
BadFeelingAboutThis

Reputation: 14406

Your issue is that your event listener is not attached to the Character instance, but the thumbnail (child) of the Character:

var char:Character = new Character();
char.thumbnail.addEventListener(MouseEvent.CLICK, characterClickHandler);

So e.currentTarget is referring to that thumbnail, and doing e.currentTarget as Character; will result in null returned since the thumbnail won't cast to Character.

Looking at your code, it looks as though the thumbnail is actually the grandchild of the character, so you'd have to do this:

var selectedChar:Character = DisplayObject(DisplayObject(e.currentTarget).parent).parent as Character;

Since chaining parents like that is ugly and prone to breaking if you change hierarchy later, perhaps a better approach would be to abstract out your events. So in your Character class, do this: (where ... is your existing code)

...
public var thumbnail:Sprite;
public static const THUMBNAIL_CLICKED:String = "ThumbnailClicked";

public function Character() 
{
    ... 
    thumbnail = new Sprite();
    thumbnail.addEventListener(MouseEvent.CLICK, thumbnailClickHandler,false,0,true);

...

private function thumbnailClickHandler(e:Event):void {
    this.dispatchEvent(new Event(THUMBNAIL_CLICKED));
}

Then, in your other class you would do this:

private function createCharacterHandler(e:MouseEvent):void 
{
    if (_characters.length < 6) 
    {
        var char:Character = new Character();
        char.addEventListener(Character.THUMBNAIL_CLICKED, characterClickHandler);

...

private function characterClickHandler(e:Event):void 
{
    var selectedChar:Character = e.currentTarget as Character;
    Util.addSprite(selectedChar.characterImage, this, _characterImagePosition[0][0], _characterImagePosition[0][1]);
}

Upvotes: 1

Related Questions