如何让Flash AS3中的非文档类类“识别”舞台组件?

时间:2010-12-02 21:56:35

标签: actionscript-3 flash-cs5

我正在制作一个文本冒险游戏,该游戏将始终在舞台上至少包含一些组件(用于用户输入的叙述和文本输入的文本区域)。因此,我通过Flash的WYSIWYG设计环境静态创建了这些组件。我分别给了他们实例名称“myTA”和“myTI”。我能够让我的主类(舞台的文档类)与它们交互(在运行时像打字机那样一次动态添加一个字符),但是同一个包中的其他类似乎无法识别舞台组件。以下是相关代码:

案例A,其中所有内容都发生在Main类中:

package { 
    public class Main extends MovieClip { 
      public var myTA:TextArea; 
      var displayedChar:String = new String(); 
      var textToWrite:String = new String(); 
      var i:int = 0; var intervalId:uint; 
      var done:int = 0; 

      public function Main { 
       setUpTA(); 
      } 

      public function setUpTA(){ 
       myTA.text = "" + playAtInterval("Hello Player!"); 
      }         

      public function writeCharsSlowly(){     
        textToWrite = arguments[0];     
        displayedChar=textToWrite.substring(i,i+1); 
        myTA.appendText(displayedChar);                             
        i++;     
        if (i == textToWrite.length) {         
          done = 1;         
          clearInterval(intervalId);     
        }             
      }                 

      public function playAtInterval(theText:String) {                
        i = 0;              
        intervalId = setInterval(writeCharsSlowly, 100, theText);           
      }  
    } 
}

案例B,Main调用第二类'TypeWriter'来处理打字机打印:

主:

package { 
    public class Main extends MovieClip { 
      public var myTA:TextArea; 
      public var myTI:TextInput; 
      var str:String = new String(); 

      public function Main{ 
        testTypeWriter(); 
      } 

      public function testTypeWriter(){ 
        typeW.playAtInterval("Hello Player");
        typeW.addEventListener(MouseEvent.CLICK,testTypeWriter2);
        typeW.addEventListener(KeyboardEvent.KEY_DOWN,inputEngine2) 
        addChild(typeW); 
      } 

      public function testTypeWriter2(event:MouseEvent){ 
        if (myTI.text == "a") {   
          typeW.playAtInterval("yo");  
        } else {   
          typeW.playAtInterval("Greetings, I am a test...");  
        }             
        addChild(typeW); 
      } 

      public function inputEngine2(event:KeyboardEvent){ 
        str = String.fromCharCode(event.charCode); 
        myTI.appendText(str); 
      }

打字机:

package { 
    public class TypeWriter extends MovieClip { 
      public var myTI:TextInput; 
      public var myTA:TextArea; 
      var i:int = 0; 
      var done:int = 0; 
      var intervalId:uint; 
      var displayedChar:String = new String(); 
      var textToWrite:String = new String(); 

      public function TypeWriter(){ 
        ///nothing here 
      } 

      public function writeCharsSlowly(){     
        textToWrite = arguments[0];     
        displayedChar = textToWrite.substring(i,i+1);
        myTA.appendText(displayedChar);                             
        i++;     
        if (i == textToWrite.length) {         
          done = 1;         
          clearInterval(intervalId);     
        }             
      }                 

      public function playAtInterval(theText:String) {                
        i = 0;              
        intervalId = setInterval(writeCharsSlowly, 100, theText);           
      }  
    } 
}

案例A有效,但是如果B Flash给我错误“错误#1009:无法访问空对象引用的属性或方法”并注意到TypeWriter中的第一行,我尝试在myTA上操作问题

除了文档类“了解”现有舞台组件之外,我怎样才能创建其他类?

谢谢,

CCJ

5 个答案:

答案 0 :(得分:1)

我会为此推荐Service Locator Pattern。最天真的方法是创建一个包含公共静态变量的资源类。然后在文档类中将舞台实例分配给资源类中的相应静态变量。然后您可以在任何地方访问这些舞台组件。

var someTextArea = Resource.TA; //probably should rename to something more meaningful

对于一些更巧妙的东西,你应该阅读我链接的文章。

我认为这比依赖注入要好,因为构造函数注入会导致巨大的参数列表,因为你可能会向舞台添加更多的项目,而且我不太喜欢setter注入,因为很容易忘记设置它们。

修改

为了让它更清晰,我想我会添加一些代码:)

资源类

package
{
    //TODO imports
    public class Resource
    {
        public static var TA:TextArea;
        public static var TI:TextInput;
    }
}

文档类

//....setup function
Resource.TA = myTA; //myTA is the name of the instance on stage
Resource.TI = myTI;

Foo class

Resource.TA.x = 100;
//or
_myClassMemberVariable = Resource.TA;
_myClassMemberVariable.x = 100;

答案 1 :(得分:0)

我认为一些依赖注入将解决这个问题。实例化Typewriter课程时,请将引用传递给myTAmyTI。例如:

public function Main{ 
    testTypeWriter(this.myTA, this.myTI); 
} 

然后你的Typewriter构造函数应如下所示:

public function TypeWriter(ta:TextArea, ti:TextArea){ 
    this.myTA = ta;
    this.myTI = ti;
  } 

这也有助于使您的应用程序不那么紧密耦合,例如,您可以重复使用不同文本区域和文本输入的Typewriter类。

修改

将来可能对您有所帮助的一些额外信息:您可以通过根对象访问舞台元素。但这仅适用于已添加到显示列表的对象。假设Typewriter表示显示列表中的对象,您可以像这样访问myTA

MovieClip(root).myTA

(如果这是您的文档类扩展的话,请将MovieClip更改为Sprite

但是,由于似乎Typewriter没有添加到显示列表中,我建议使用我的第一个依赖注入建议。

同时查看this page,它会讨论使用CasaLib从任何对象访问舞台。我个人还没有尝试过,所以这就是为什么它最终在这里; - )

答案 2 :(得分:0)

myTA和myTI实际上是在作者时间在舞台上还是动态添加?

在第一种情况下,只需为每个实例添加一个实例名称。然后为每个类添加一个变量

var main_mc : Main = root as Main;

You can then access the instances via main_mc.myTA and main_mc.myTI(假设这些是您选择的实例名称),所有内容都应该是类型安全的。

在动态情况下,只需确保在添加主要类时将其保存到每个类中。

另一种选择是让myTA和myTI的类在其构造函数中发送一个事件来宣告它们的存在。然后,主类可以监听这些并注册引用。

老实说,你将显示器与逻辑混合在一起。特别是阅读MVC和PureMVC。通过良好的设计,可以通过消息处理所有内容,并且实例不需要直接引用彼此。 IIRC,Moock的AS3书中有一章关于MVC(但它可能是他的AS2书)。

答案 3 :(得分:0)

他们将一直在舞台上的事实不应该阻止你为他们创建特定的课程。

根据您的游戏结构,您可以使用TextField创建MovieClip并将它们链接到Typewriter类,或者只是为TextField创建一个类并使用Events来修改文本内容。

您正在使用外部类,因此没有理由在Flash CS中保留任何类型的逻辑。

答案 4 :(得分:0)

要清楚。在编写舞台时,您实际上是指flash文档的文档类。 Stage是一个类,每个已添加到displaylist的实例都可以访问。

我会将文本字段传递给需要更新它们的类。

var tw : Typewriter = new Typewriter();
    tw.inputField = myTI;
    tw.textArea = myTA;

或者

var tw : Typewriter = new Typewriter(myTI, myTA);