AS3: разрешить только определенное количество объектов определенного типа в массив - PullRequest
0 голосов
/ 01 октября 2010

Я хочу найти способ разрешить только определенным объектам в массиве, которые имеют определенное слово в названии своего класса. Или, по крайней мере, найти оптимальный способ сделать что-то подобное. Вот подробности. У меня есть массив, в котором хранятся все предметы, брошенные в корзину.

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

Если, например, я уронил [объект BreadGrain] и [объект PastaGrain].

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

Легко, проблем нет. Но что мне делать, если я хочу разрешить в массив только 2 объекта с «Зерном» в их Classname? Я хочу сделать это так, чтобы пользователь мог бросить только 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); } еще { // код сообщения об ошибке здесь }

Я в тупике. Даже просто "Чувак, ты все делаешь неправильно" поможет. Спасибо.

Ответы [ 3 ]

2 голосов
/ 01 октября 2010

Вы можете получить имя класса любого объекта с помощью функции 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) в любое время, когда вы хотите добавить их вотобразить список (или удалить их).Кстати, это потому, что кто-то в Adobe забыл включить интерфейс IDisplayObject и заставить API отображения списка принимать объекты, которые реализовали этот интерфейс, вместо недоделанного абстрактного класса, который вы все равно не можете получить напрямую (aka DisplayObject);это облегчило бы обработку экранных объектов как интерфейсов, но я отступаю).

В любом случае, с помощью интерфейса или общего базового класса вы можете выполнить проверку с помощью оператора is, но вам просто нужно проверить один тип: Grain.

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

Вы также можете пойти дальше и использовать Vector вместо массива.Вектор работает почти так же, как массив, но он строго типизирован, так что вы можете сделать:

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

Вы получите ошибку времени компиляции, если попытаетесь добавить объект, который не расширяет / не реализуетGrain.

Векторы доступны для Flash Player 10, но вам потребуется Flash CS4 (если вы используете Flash IDE; в противном случае, я думаю, вам понадобится как минимум 3.2 SDK для компиляции).

0 голосов
/ 25 октября 2010

Uni заставил меня некоторое время заниматься другими вещами, но, наконец, я могу вернуться к своему игровому проекту.

У меня это работает. Я использовал метод Хуана Пабло Калифано. Сначала я использовал Генри Кука, потому что хотел создать файл .AS для каждой еды (т.е. apple.as, cereal.as, bread.as, oranges.as). С помощью метода Генри Кука я создал

`var foodTypeLimit: Object = new Object (); foodTypeLimit [ "зерно"] = 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.

Даже при том, что это было прямо по декларации. Я понимаю, что я слишком нуб, чтобы понять, почему это так. Во всяком случае, по этой причине (отсутствие приращения, которое было необходимо для этой функции), я укусил пулю и использовал путь Хуана Пабло Калифано.

Сначала я записал классы так:

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

В любом случае, спасибо за действительно замечательные ответы, ребята, это мой любимый сайт, где можно найти ответы на вопросы о жизни во вселенной и во всем.

0 голосов
/ 01 октября 2010

Hm.Я думаю, что вам нужно что-то более сложное, чтобы заставить эту работу работать правильно.Вы на самом деле задаете вопрос, состоящий из двух частей: как отслеживать вещи и как их идентифицировать.Я начну с простого, отслеживая.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Мой 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" );
    }
    ...
}

Где classNameContainsTheWord достигается комбинацией getQualifiedClassName и indexOf,но лучше было бы использовать общий базовый класс, как предложил Хуан Пабло Калифано.Хотя я бы предложил немного другой стиль:

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" );
    }
    ...
}

Чище, чем все эти бизнесы с именами классов, и имеет дополнительное преимущество, заключающееся в том, что вы можете устанавливать свойства чего-либо независимо от имени его класса.

Это не идеально;например, вам нужно что-то более продвинутое, если вам нужно много свойств, но этого должно быть достаточно для продолжения работы.

...