lundi 20 février 2017

What is causing this card to change dimensions? [Video & Code]

I am programming a board game in Starling (Action Script 3). The Starling version that I am using has a class called Sprite3D, which allows me to conveniently and easily code the flipping of the cards used in this game. I am troubled by the fact that my card changes dimension when flipped, and I cannot find the source of the change.

All help is appreciated.

The problem can be viewed on this youtube video.

The code can be seen in full on github at this github page.

I will continue here with more detail... All the following information is covered in the video.

The Card class contains no visual information. It is a controller class. It does hold two sprites. One sprite fills the front face, and the other sprite fills the back face. The Card class also has a mask applied and dimension attributes so that the faces will be of equal size and shape.

The Card class also holds the animation code. The code to animate the card is very similar to the code used in a video found on the starling blog that shows how Stage3D can be used implemented in a 2D game of Memory very quickly and easily. The Card class animates the rotation by using a tween to change the card's rotationY property from 0 to PI and from PI to 0 on touch events. The error occurs during the flipping process, so I will include the flipping code here:

public function flip() : void {
    _state = !(this._state);
    if( this.animations ){
        var tween : starling.animation.Tween = new Tween( this, 2, starling.animation.Transitions.EASE_OUT_BOUNCE );
        var card : Card = this;
        var didFlip : Boolean = false;
        tween.animate("rotationY", this._state == Card.FACE_UP ? Math.PI : 0 );
        tween.onUpdate = updateVisibility;
        Starling.juggler.add( tween );
    }
}
private function updateVisibility():void
{
    var sHelper:Vector3D = new Vector3D();
    var card : Card = this;
    stage.getCameraPosition( card, sHelper );
    if( sHelper ){
        this._front_face.visible = sHelper.z < 0;
        this._back_face.visible = sHelper.z >= 0;
    }
}

The FrontFace and BackFace classes both derive from the class CardFace. The CardFace class takes a card as a reference and sets a mask equal to the size and shape of the card's mask. This is likely redundant, as the card's mask should mask all children DisplayObjects, but we do it anyway.

The BackFace has text, a logo, a texture and a color.

The FrontFace does nothing. It is subclassed with specific behaviors and will convert a data object into a display layout.

In this case, we are subclassing FrontFace with ProfileFrontFace. ProfileFrontFace takes the card object and a profile data object as constructor arguments. The card object is passed to CardFace via super() calls, and the profile object is saved for later use.

When the ProfileFrontFace is added to the stage, the class extracts the title, income, and expenses from the profile data object. It creates text fields for each of these items. It also calculates a cash flow and creates a text field for this value. A background is created using a PNG texture, which is a simple white square, that is stretched over the whole face of the card's dimensions. Over this white square, we apply a color texture. After it is created, the background image is not altered. The code appears as follows:

//we remove the event listener so this function code is only executed once
this.removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
var width : int = this.cardWidth; /* 400 */
var height : int = this.cardHeight; /* 300 */
var bg : Image = new Image( Game.assets.getTexture("blank") );
/* start the background in the top left */
bg.x = 0;
bg.y = 0;
/* have the background fill the card dimension space */
bg.width = width;
bg.height = height;
/* apply a color so that the background is not pure white */
bg.color = ColorScheme.OPAL;
/* add the background to the stage */
this.addChild( bg );

In the rest of the function, we create the text and display it. I am not including that code here for simplicity. In testing, I have removed that code and seen that it has no impact on the peculiar behavior that changes the dimensions of the card when flipped to the front face.

Has anyone seen a case where masks on a Sprite3D fail to perform as a mask?

Has anyone seen cases where a mask fails to perform on a regular Sprite object?

What about the Tween.animate() method might cause strange behavior when Tween is used to change the value of "rotationY" on an object?

Any and all answers will help. Thank you!

Aucun commentaire:

Enregistrer un commentaire