Как я могу проверить наличие hitTest между объектом и классом или классом и другим классом в actionscript3?

Это все в actionscript 3.0 и кодируется во flash cs5.5. Я делаю игру «тяни-толкай», в которой игрок толкает блок. Уровни в конечном итоге будут очень большими и будут иметь множество экземпляров каждого класса, поэтому нецелесообразно называть каждый символ именем экземпляра на сцене. У меня есть этот файл engine.as, который я написал, но я не могу понять, почему он не работает. Вот весь класс, но я пытаюсь использовать функцию hitTestClass; упаковка {

import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.events.Event;

public class Engine extends MovieClip
{
    private static var _instance:MovieClip;

    public function Engine()
    {
        stop();
        _instance = this;
    }

    public static function add(object:Object):void
    {
        if (object!=DisplayObject) return;
        _instance.addChild(object as DisplayObject);
    }

    public static function remove(object:Object):void
    {
        if (object is Array) {
            removeList(object as Array);
            return;
        }
        if (!(object is DisplayObject) || object.parent!=_instance) return;
        _instance.removeChild(object as DisplayObject);
    }

    public static function removeList(objects:Array):void
    {
        while (objects.length>0) remove(objects.pop());
        //trace(objects.length);

    }

    public static function getByName(name:String):Object {
        if (_instance) {
            for (var i:int = 0; i < _instance.numChildren; i++) 
            {
                if (_instance.getChildAt(i).name==name) {
                    return _instance.getChildAt(i);
                }
            }
        }
        return null;
    }

    public static function getAllByName(name:String):Array {
        var list:Array = new Array();
        if (_instance) {
            for (var i:int = 0; i < _instance.numChildren; i++) 
            {
                if (_instance.getChildAt(i).name==name) {
                    list.push(_instance.getChildAt(i));
                }
            }
        }
        return list;
    }

    public static function getByClass(className:Class):Object {
        if (_instance) {
            for (var i:int = 0; i < _instance.numChildren; i++) 
            {
                if (_instance.getChildAt(i) is className) {
                    return _instance.getChildAt(i);
                }
            }
        }
        return null;
    }

    public static function getAllByClass(className:Class):Array {
        var list:Array = new Array();
        if (_instance) {
            for (var i:int = 0; i < _instance.numChildren; i++) 
            {
                if (_instance.getChildAt(i) is className) {
                    list.push(_instance.getChildAt(i));
                }
            }
        }
        return list;
    }

    public static function hitTestName(object:DisplayObject, name:String):Object
    {
        var list:Array = getAllByName(name);
        return hitTestList(object, list);
    }

    public static function hitTestClass(object:DisplayObject, className:Class):Object
    {
        var list:Array = getAllByClass(className);
        return hitTestList(object, list);
    }

    public static function hitTestList(object:DisplayObject, list:Array):Object
    {
        var hits:Array = new Array();
        for (var i:int=0; i<list.length; i++) {
            if (object != list[i] && object.hitTestObject(list[i])) {
                hits.push(list[i]);
            }
        }
        return hits;
    }       

}

}

На протяжении всей игры я использую функции обновления, которые находятся внутри класса каждого «блока», и именно здесь они проверяют наличие тестов попадания. Вот пример из класса wallBlock, который гарантирует, что персонаж не сможет пройти через wallBlock. функция способнаяToCheckSides () {

        if ((this).x-_root.mcChar.x<63.5 && (this).x-_root.mcChar.x>-63.5)
        {
            //trace("booty");
            //ableToCheckXSides=false;
            if((this).y-_root.mcChar.y >=-63 && (this).y-_root.mcChar.y<0 && ableToCheckXSides==false)
                   {
                    //ableToCheckXSides=false;   
                    //_root.mcChar.x=_root.mcChar.x;

                    if(hitTestObject(_root.mcChar)==true)
                        {
                            _root.mcChar.y=(this).y+63.5;

                        }



                     //if char is moving down and hits the top side of tile

                   }
                 else if((this).y-_root.mcChar.y<=63 && (this).y-_root.mcChar.y>0 && ableToCheckXSides==false)
                   {
                    //ableToCheckXSides=false;
                    //_root.mcChar.x=_root.mcChar.x;
                    if(hitTestObject(_root.mcChar)==true)
                        {
                            _root.mcChar.y=(this).y-63.5;

                        }



                     //if char is moving up and hits the bottom side of tile

                   }

        }


        if ((this).y-_root.mcChar.y<63.5 && (this).y-_root.mcChar.y>-63.5)
        {
            //trace("YYYYYY");

            ableToCheckXSides=true;
            if((this).x-_root.mcChar.x >=-63 && (this).x-_root.mcChar.x<0)
                   {
                    //trace("inside function");
                    //ableToCheckYSides=false;
                    if(hitTestObject(_root.mcChar)==true)
                        {
                            _root.mcChar.x=(this).x+63.5;
                        }


                     //if char is moving left and hits the right side of tile

                   }
                   else if((this).x-_root.mcChar.x<=63 && (this).x-_root.mcChar.x>0)
                   {
                    //ableToCheckYSides=false;
                    if(hitTestObject(_root.mcChar)==true)
                        {
                            _root.mcChar.x=(this).x-63.5;

                        }


                     //if char is moving right and hits the left side of tile   
                   }
        }
        else 
        {
            ableToCheckXSides=false;
        }

Вот где проблема вступает в игру, в той же функции «обновления», которая возникает в каждом кадре, я пытался использовать свою функцию hitTestClass, чтобы увидеть, попадает ли crateBlock в wallBLock, но она никогда не вернет true. (Если я изменю if( hits.length>0) на if(hits), он всегда возвращает true.)

var hits = Engine.hitTestClass(this, crateBlock);
        if (hits.length>0) 
        {
            Engine.remove(hits);
            trace("hitting crate");
        }

person mplouque    schedule 19.12.2013    source источник
comment
Ну, во-первых, для создания больших уровней вам в конечном итоге понадобится какой-то скрипт (XML?), а использование hitTestObject() будет непрактичным и смехотворно медленным с большим набором объектов. О том, почему if (hits) возвращает true. hits — это массив, в худшем случае — массив нулевой длины, но hits не равно null, поэтому if (hits) равно if (hits!=null) и действительно верно. Кроме того, исправьте функцию add(), у вас есть сравнение класса и объекта вместо сравнения is.   -  person Vesper    schedule 19.12.2013
comment
Скорее всего, это потому, что ваш _instance равен нулю. Для отладки используйте функцию trace(list.length) в функции hitTestClass() - по-видимому, она тоже пуста.   -  person Vesper    schedule 19.12.2013


Ответы (1)


Вы не должны использовать HitTestObject, вам следует использовать CollisionTestKit, библиотеку, доступную здесь, в коде Google:

https://code.google.com/p/collisiondetectionkit/

HitTestObject не слишком хорошо работает сам по себе. Эта библиотека позволяет делать гораздо более сложные вещи.

person Code Whisperer    schedule 19.12.2013
comment
Пока человек не понимает основ работы кода, консультировать библиотеки практически бессмысленно. Пусть сначала изобретут колеса, а потом укажут место для хранения колес, тогда они смогут эффективно использовать колеса. - person Vesper; 20.12.2013
comment
Я просто пытаюсь помочь. HitTestObject действительно не работает. ОП будет тратить свое время, пытаясь его использовать. Это зависит от него, если он хочет попробовать в любом случае. - person Code Whisperer; 20.12.2013