0

我想找到一种方法,只允许某些对象进入在类名中有某个单词的数组中。或者至少找到做这样的事情的最佳方式。这是细节。我有一个存储所有放入购物车的对象的数组。

function addProductToArray (e:MouseEvent):void{ currMC = (e.target as MovieClip); myCart.itemsInCart.push(currMC); trace(myCart.itemsInCart);}

例如,如果我删除了一个 [object BreadGrain] 和一个 [object PastaGrain]。

trace(myCart.itemsInCart);// would trace [object BreadGrain],[object PastaGrain].

很简单,没有问题。但是,如果我只想允许 2 个类名中带有“Grain”的对象进入数组,该怎么办?我想这样做,以便用户只能将每种食物中的 2 种放入“购物车”。食物的类型是谷物、水果、蔬菜、肉类等,我已经将食物的类型附加到类名的末尾,希望这样我可以用它来检测它是什么类型的食物并阻止它被添加超出限制并显示错误。即“您已经有 2 个谷物产品”。

我希望这是有道理的。无论如何,我发现这在一定程度上效果很好:

if (currMC is BreadGrain) {
                myCart.itemsInCart.push(currMC);
            } else {
                // error message code here 
            }

但是我有几个产品,我不想为它们都写一个 if/else 或 switch 语句。我希望通过类似于以下内容动态地执行此操作:

//this is an example of the logic
if (currMC classNameContainsTheWord "Grain"  AND myCart.itemsInCart DoesNotContainMoreThan 2 Grain Objects) {

myCart.itemsInCart.push(currMC); } else { // 这里是错误信息代码 }

我难住了。即使只是一句“伙计,你做错了”也会有所帮助。谢谢。

4

3 回答 3

2

您可以使用getQualifiedClassName函数获取任何对象的类名。然后,您可以尝试使用 RegExp 将字符串与某个模式匹配,或者您也可以只检查类名是否包含一些子字符串。

也就是说,我认为更好的方法是使用通用基类或接口。

//  assuming your objects extend MovieClip
public class Grain extends MovieClip{

    public function Grain() {
        super();
    }

    public function someCommonMethodToAllGrains():void {

    }
}

或者

//  It's customary to prefix interfaces name with an "I" in AS; 
//  I'm not doing it here so the code works for both a base class and an interface

public interface Grain {

    function someCommonMethodToAllGrains():void;
}

然后,如果您使用基类:

public class BreadGrain extends Grain {

    public function BreadGrain() {
        super();
    }

    override public function someCommonMethodToAllGrains():void {
        //  if this makes sense for your object...
        super.someCommonMethodToAllGrains();    
    }    

}

public class PastaGrain extends Grain {

    public function PastaGrain() {
        super();
    }

    override public function someCommonMethodToAllGrains():void {
        //  if this makes sense for your object...
        super.someCommonMethodToAllGrains();
    }    
}

或者,通过界面

public class BreadGrain extends MovieClip implements Grain {

    public function BreadGrain() {
        super();
    }

    public function someCommonMethodToAllGrains():void {

    }    

}

public class PastaGrain extends MovieClip implements Grain {

    public function PastaGrain() {
        super();
    }

    public function someCommonMethodToAllGrains():void {

    }    
}

如果这些对象是MovieClips,那么使用基类可能就不那么乏味了,因为否则您必须将对象转换回MovieClip(或DisplayObject)任何时候您想将它们添加到显示列表(或删除它们)。顺便说一句,这是因为 Adob​​e 的某个人忘记了包含一个IDisplayObject接口,并且让显示列表 API 接受实现了这个接口的对象,而不是一个你无论如何都不能直接派生的半途而废的抽象类(又名DisplayObject);这将使将显示对象视为接口变得更容易,但我离题了)。

无论如何,无论是使用接口还是通用基类,您都可以使用is运算符进行验证,但您只需要检查一种类型:Grain。

if(theObject is Graing && theArray.lenght <= 2) {
    theArray.push(theObject);
}

您也可以更进一步,使用向量而不是数组。Vector 的工作方式与 Array 几乎相同,但它是严格类型的,所以你可以这样做:

var items:Vector.<Grain> = new Vector.<Grain>();
items.push(grainObject);

如果您尝试添加不扩展/实现 Grain 的对象,您将收到编译时错误。

向量可用于 Flash Player 10,但您需要 Flash CS4(如果您使用的是 Flash IDE;否则,我认为您至少需要 3.2 SDK 才能编译)。

于 2010-10-01T02:27:33.077 回答
0

Uni 让我做了一段时间的其他事情,但最后我可以重新开始我的游戏项目。

我已经让它工作了。我使用了 Juan Pablo Califano 的方法。我最初确实使用了 Henry Cooke's,因为我想摆脱为每种食物制作一个 .AS 文件(即 apple.as、谷物.as、bread.as、oranges.as)。使用亨利库克的方法,我创建了一个

`var foodTypeLimit:Object = new Object(); foodTypeLimit["grain"]=2; foodTypeLimit["水果"]=2;

和 var foodTypeCount:Object = new Object(); 等等等等`

对于每种食物类型。然后使用了:

var type:String = getFoodTypeForObject( currMc ); if( foodTypeCount[ type ] < foodTypeLimit[ type ] ){ items.push( currMc ); foodTypeCount[ type ]++; } else { // throw error }

正如建议的那样。该函数返回了字符串,中提琴它工作正常。但是,因为我的 foodTypeCount 变量(例如foodTypeCount["grain"]=0;)在函数内部,所以每次调用这些函数时都将这些变量设置为 0,因此每次调用的增量都不会超过。所以我想,好吧,我将把这些 foodTypeCount 变量与var foodTypeCount:Object = new Object();的实例化一起放在函数之外。但是不,我不断收到:

Error #1120: Access of undefined property foodTypeObject.

尽管它就在该死的宣言之下。我知道我太菜鸟了,无法理解为什么会这样。无论如何,出于这个原因(缺少增量,这对这个函数来说是必不可少的)我硬着头皮使用了 Juan Pablo Califano 的方式。

首先我写出这样的类:

public class Bread extends MovieClip implements Grain {

public function Bread() {
    super();
}

public function someCommonMethodToAllGrains():void {

}

}

然后添加接口

`public interface Grain {

    function someCommonMethodToAllGrains():void;
}
`  

现在我的函数看起来像这样:

if(currMC is Grain){
    if(grainCount<2){
        addProductToBasket();
        grainCount++;
    } else {
        notAllowed("Grain");
    }
 }

function addProductToBasket(){
    removeChild(currMC);
    basketArray.push(currMC);
    //remove listeners set mc to null etc
 }

function notAllowed(foodType:String){
    error.text="Sorry but you already have 2"+foodType+"products";
 }

我试图将所有这些都放入一个开关中。例如:

switch(currMC){
   case is Grain:
   //do this
   break;
  }

上面的实现没有奏效。也许 switch 语句可能不应该以这种方式使用。身份证。:S

无论如何,感谢你们提供了非常棒的答案,这是我最喜欢的网站,可以找到关于宇宙和一切的答案。

于 2010-10-25T13:05:18.553 回答
0

嗯。我认为您将需要一些更复杂的东西才能使其正常工作。您实际上是在问一个由两部分组成的问题:如何跟踪内容以及如何识别内容。我将从简单的部分开始,保持跟踪。

免责声明:我的 AS3 相当生锈,但至少理论上应该是合理的,即使实现可能有点偏离。

首先,您需要定义每种食物的限制,因此:

var dctLimits = new Object(); // not really a Dictionary, but we'll use it like one
dctLimits[ "grain" ] = 3;
dctLimits[ "meat" ] = 5;
...

然后,您要保留要添加到购物车的对象的数量

var dctCount = new Object();
dctCount[ "grain" ] = 0;
dctCount[ "meat" ] = 0;
...

然后,当您添加新对象时,首先根据相关计数检查其类型。如果计数器小于限制,让它进入并增加计数器:

var type:String = getFoodTypeForObject( currMc );
if( dctCount[ type ] < dctLimit[ type ] ){
    items.push( currMc );
    dctCount[ type ]++;
} else {
    // throw error
}

您会注意到我创建了一个虚构的函数 getFoodTypeForObject()。这是更棘手的一点:识别。

您可以像这样实现您的示例逻辑:

function getFoodTypeForObject( currMc ){
    if( getQualifiedClassName( currMc ).indexOf( "Grain" ) > -1 ){
    return( "grain" );
    } else if( getQualifiedClassName( currMc ).indexOf( "Meat" ) > -1 ){
    return( "meat" );
    }
    ...
}

正如 Juan Pablo Califano 所建议的那样,使用andclassNameContainsTheWord的组合可以实现where ,但更好的是使用公共基类。不过,我会建议一种稍微不同的风格:getQualifiedClassNameindexOf

public class CartItem extends MovieClip{

    public var isGrain:Boolean;
    public var isMeat:Boolean;

    public function CartItem() {
        super();
    }
}

将其用作购物车项目 MC 的基类,然后在舞台上的 MC 实例上设置这些布尔属性。然后,您可以检测到这样的类型:

function getFoodTypeForObject( object ){
    if( object.isGrain ){
        return( "grain" );
    } else if( object.isMeat ){
        return( "meat" );
    }
    ...
}

比所有类名业务更干净,并且具有额外的好处,您可以设置独立于其类名的某些属性。

它并不完美;例如,如果您需要很多属性,则需要更高级的东西,但这应该足以让您继续前进。

于 2010-10-01T02:55:28.513 回答