当在另一个类中设置其值时,如何更新类中的变量?

时间:2012-10-09 00:07:43

标签: actionscript-3 flash

我对AS3很新,所以请原谅我,如果我的问题显得很愚蠢。

让我澄清一下我特别想要的东西:玩家继续执行任务,当他在路上抓到一些物体时他会获得积分,例如物体A给出一个点,物体B给出两个点,物体C给出奖励积分等等......如果玩家在途中遇到障碍,他就无法完成任务,他必须重播游戏直到他到达目的地(等级结束)。

所以我想要的是我如何能够存储玩家在遇到障碍之前所获得的积分,并且每当玩家必须重放游戏直到他达到游戏等级结束时积累的积分将被积累玩家获得的总积分将是所有积分的总和,包括他在实际到达游戏等级结束之前所获得的积分。

我的类播放器是属于框架WCK的类Box的子类。有没有办法让我正确地实现依赖注入以将变量传递给另一个类以便将它们存储在那里?

提前感谢您的帮助!

ADDED:这是我根据Amy的例子实现的,并进行了一些调整以适应我的游戏设置。它仍然不起作用,因为变量_totalEarnedPoints的值没有通过EventDispatcher更新类PlayerClient中的变量_earnedPoints,当我试图在Class Player中检索它以累积所有点时。我不确定我做错了什么或错过了什么?任何人都可以指出并告诉我如何从类PlayerClient中检索变量_totalEarnedPoints?

CLASS玩家:

package  
{

public class Player extends Box  
{  
    private var contacts:ContactList;  
    private var myLoader:SWFLoader;  
    private var mcTemp:MovieClip;  
    private var bonusPoints:int = 0;  
    private var onePoint:int = 0;  
    private var twoPoints:int = 0;  
    private var objectACount:int = 0;  
    private var objectBCount:int = 0;  
    private var objectCCount:int = 0;  
    private var replayCount:int = 0;
    protected var _earnedPoints:int; 
    private var myPlayerClient:PlayerClient = new PlayerClient();  
}

public function Player()  
{  
    super();  
}

public override function create():void  
{  
    super.create();  
    listenWhileVisible(this, ContactEvent.BEGIN_CONTACT, handleContact);  
    contacts = new ContactList();  
    contacts.listenTo(this);  
}

public function handleContact(e:ContactEvent):void   
{  
    //Detect collison with other static objects  
    var myObjectA:objectA = e.other.m_userData as objectA;  
    var myObjectB:objectB = e.other.m_userData as objectB;  
    var myObjectC:objectC = e.other.m_userData as objectC;  
    var myObstacle:obstacle = e.other.m_userData as obstacle;       

    if(myObjectC)   
    {
        objectCCount++;  
        myObjectC.remove();  
        if (objectCCount > 0)  
        {  
           bonusPoints = bonusPoints + 5;                   
        }               
    }

    else if(myObjectA) 
    {
        objectACount++;
        myObjectA.remove();
        if (objectACount > 0)
        {
           onePoint = onePoint + 1;                         
        }
    }

    else if(myObjectB) 
    {
        objectBCount++;
        myObjectB.remove();
        if (objectBCount > 0)
        {
          twoPoints = twoPoints + 2;                            
        }
    }       
    else if(myObstacle)
        {               
        var myEarnedPoints:int = myPlayerClient.totalEarnedPoints;
        _earnedPoints = bonusPoints + onePoint + twoPoints + myEarnedPoints;
        dispatchEvent(new Event("EarnedPointChanged"));

        myLoader = new SWFLoader("myMovie.swf",{container:swfHolder,alpha:0,onComplete:completeHandler});
       //adds the loader content to the display list before raw content is loaded.
       addChild(myLoader.content);
       stop();
       myLoader.load();

       function completeHandler(e:LoaderEvent):void
       {
          replayCount++;

          if (replayCount <= 1)
          {
                TweenMax.to(e.target.content, 1, {alpha:1});
                mcTemp = myLoader.rawContent;
                mcTemp.gotoAndPlay(1);
          }
          else if (replayCount >= 1)
          {
                mcTemp = myLoader.rawContent.stop();
                myLoader.unload();
                mcTemp = null;  
          }

       }
       myObstacle.remove();

     }              

}

public function get earnedPoints():int  
{  
     return _earnedPoints;  
}  
}

CLASS PlayerClient

package  
{

public dynamic class PlayerClient extends MovieClip
{
    private var _totalEarnedPoints:int;
    protected var _player:Player;

    public function get player():Player
    {
        return _player;
    }

    public function set player(value:Player):void 
    {
        if (value != _player) 
        {
            if (_player) 
            {
                //[prevent memory leaks][2]
                _player.removeEventListener("EarnedPointChanged", updatePlayerScore);
                //don't need this if we don't have a player
                removeEventListener(Event.REMOVED_FROM_STAGE, cleanUp);
            }
            _player = value;
            if (_player) 
            {
                //listen for changes
                _player.addEventListener("EarnedPointChanged", updatePlayerScore);
                //we added a listener to the new player, need to make sure is removed
                addEventListener(Event.REMOVED_FROM_STAGE, cleanUp);
            }
        }
    }

    protected function cleanUp(e:Event):void 
    {
        _player.removeEventListener("EarnedPointChanged", updatePlayerScore);
    }


    protected function updatePlayerScore(e:Event):void 
    {
        _totalEarnedPoints = _player.earnedPoints;

    }


    public function get totalEarnedPoints():int
    {
        return _totalEarnedPoints;
    }
}
} 

2 个答案:

答案 0 :(得分:1)

首先,你正在做的事情将会给你带来一个伤害的世界,除非你的项目是一个横幅或者你知道100%你将会工作2天并且永远不会再看的东西。见http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/

你需要意识到的是,如果你创建一个新的Player实例,你的Points.pointsEarned看起来只会改变,如果你有几个玩家,每个新玩家将有更多的点数开始比之前的那个。这可能不是你想要的。你并没有真正说出你想要的是什么,所以让我抛弃你可能想要的东西并告诉你如何编码它。如果这不对,我们将从那里开始。

编辑:

好的,现在我们知道你希望能够增加获得的积分,所以这个类现在变得更加简单(检查帖子的修订历史以查看删除了哪些部分):

package{
  public class Player extends EventDispatcher {
    protected var _earnedPoints:int;
    public function Player() {
       super();//not passing a parameter, so target of events will be this
    }
    public function get earnedPoints():int {
       return _earnedPoints;
    }
    public function set earnedPoints(value:int):void {
       if (value != _earnedPoints) {
          _earnedPoints = value;
          //other Classes can listen for this to see if earnedPoints has changed:
          dispatchEvent(new Event('earnedPointsChanged');
       }
    }
  }
}

你没有问过这个部分,但我认为这是你理解的必要部分。我将解释它,以防它不明显。你的“对象”需要有自己的类:

package {
   class TargetObject extends MovieClip {
      public var points:int;
   }
}

您可以在创建每个TargetObject时设置这些值,也可以创建多个子类,其中值是硬编码的。

所以现在,只要发生碰撞,你就可以这样做:

_player.earnedPoints += target.points;

当您设置该变量时,您的PlayerClient将更新,即使它是从另一个类设置的。

总之,您需要生成一个其他实例可以监听的事件来自行更新:

package {
   public class PlayerClient extends MovieClip {
      public var playerScoreText:TextField;//assume this is on stage
      protected var _player:Player;
      //assume [dependency injection][1] 
      public function get player():Player {
         return _player;
      }
      public function set player(value:Player):void {
         if (value != _player) {
            if (_player) {
               //[prevent memory leaks][2]
               _player.removeEventListener('earnedPointsChanged', updatePlayerScore);
               //don't need this if we don't have a player
               removeEventListener(Event.REMOVED_FROM_STAGE, cleanUp);
            }
            _player = value;
            if (_player) {
               //listen for changes
               _player.addEventListener('earnedPointsChanged', updatePlayerScore);
               //we added a listener to the new player, need to make sure is removed
               addEventListener(Event.REMOVED_FROM_STAGE, cleanUp);
            }
         }
      }
      protected function cleanUp(e:Event):void {
          _player.removeEventListener('earnedPointsChanged', updatePlayerScore);
      }
      /* This will trigger no matter what changes the value of
         earnedPoints or bonusPoints.
      */
      protected function updatePlayerScore(e:Event):void {
          if (playerScoreText) /*in case it wasn't put on stage */ {
              playerScoreText.text = _player.earnedPoints
          }
      }
    }
}

答案 1 :(得分:0)

我自己解决了我的问题:我使用SharedObject方法存储点,然后将点值返回到我的类Player中进行累积。 EventDispatcher确实将点数传递给了另一个类,但是一旦玩家遇到障碍物并且游戏重放,所有点值都会回到初始状态,这使得我很难将我传递给其他类的点返回到类Player积累。在我的案例研究中,SharedObject方法帮助我解决了这个问题。