Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
541 views
in Technique[技术] by (71.8m points)

flash - AS3 - hitTestObject Collision Not Registering Correctly

I had a problem with my hitTestObject collision detection a couple of days ago which has since been fixed (How can I solve my hitTestObject Collision Null Object Ref Error) with the help of you folks (thanks).

My problem now is as such:

When my "enemy.hit" comes into contact with "player.hit" it registers as a hit - this is good.

When my "building.collide" comes into contact with "player.hit" it registers as a hit - this is good.

However, when my "building.collide" comes into contact with my "enemy.hit" it does not register, but sometimes it does register even though the only enemy on-screen is many pixels away from it - as if either the building or enemy "hitBox" is somewhere other than directly on the graphic(MovieClip in this case).

I don't understand how this could be. My enemy class has a hit.hitTestObject(player.hit) which works fine. My building class has a collide.hitTestObject(player.hit) that also works fine. So, it should reason that my building class collide.hitTestObject(enemy.hit) should also work fine - but it does not. Any ideas?

My code consists of 10 or so .as files & I'm not entirely sure which of these is causing the problem. I don't want to be rude and post a 1000 lines of my amateur code for you to dig through -though, I will if need be.

Green parts are the hitBoxes (which is a layer within that particular MovieClip)

gunslingersnapshot

I hope this convoluted description is easy enough to follow. Thank you for looking.

I think I know what is going on but, I have no idea how to correct it. I use an ObjectPlacer class to place buildings, flora, fauna, etc and I believe that when I call - var targetCowboy:Cowboy = new Cowboy(stageRef); var enemyJoe:EnemyJoe = new EnemyJoe(stageRef, targetCowboy); var Buildings03Left:BuildingsLeft03 = new BuildingsLeft03(stage, 0, -720, targetCowboy, enemyJoe);
stageRef.addChildAt((Buildings03Left), 2); build01Place = false;

That this is actually creating multiple instances of both Cowboy and EnemyJoe and this is what is confusing flash. How can I reference Cowboy and EnemyJoe without using "new"?(e.g. var targetCowboy:Cowboy = new Cowboy(stageRef);)

ObjectPlacer code:

    package com.gamecherry.gunslinger
    {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;

public class  ObjectPlacer extends MovieClip
{

    private var Build01Timer:Timer;
    private var Build02Timer:Timer;
    private var CactiSet01Timer:Timer;

    private var build01Place:Boolean = false;// if true - addChild starts at first frame
    private var build02Place:Boolean = false;
    private var cactiSet01Place:Boolean = false;
    private var stageRef:Stage;


    public function ObjectPlacer(stageRef:Stage)
    {
        this.stageRef = stageRef;


    var Build01Timer = new Timer(1000, 1);
    var Build02Timer = new Timer(25000, 1);
    var CactiSet01Timer = new Timer(0, 1);


    Build01Timer.addEventListener(TimerEvent.TIMER, build01TimerHandler, false, 0, true);
    Build02Timer.addEventListener(TimerEvent.TIMER, build02TimerHandler, false, 0, true);
    CactiSet01Timer.addEventListener(TimerEvent.TIMER, cactiSet01TimerHandler, false, 0, true);

        addEventListener(Event.ENTER_FRAME, loop, false, 0, true);

        Build01Timer.start();
        Build02Timer.start();
        CactiSet01Timer.start();
    }


    public function loop(e:Event): void
    {
        BuildSet01();
        BuildSet02();
        CactiSet01();

    }   

    private function BuildSet01(): void
    {

        if (build01Place)
        {
        var Buildings01Right:BuildingsLeft = new BuildingsLeft(stage, 720, -624);   
        Buildings01Right.scaleX = -1;
        stageRef.addChildAt((Buildings01Right), 2);

        var targetCowboy:Cowboy = new Cowboy(stageRef);
        var enemyJoe:EnemyJoe = new EnemyJoe(stageRef, targetCowboy);
        var Buildings03Left:BuildingsLeft03 = new BuildingsLeft03(stage, 0, -720, targetCowboy, enemyJoe);              
        stageRef.addChildAt((Buildings03Left), 2);
        build01Place = false;


        }

    }

    private function BuildSet02(): void
    {

        if (build02Place)
        {

        var Buildings04Left:BuildingsLeft04 = new BuildingsLeft04(stage, 0, -800);
        stageRef.addChildAt((Buildings04Left), 2);
        build02Place = false;
        }
    }

    private function CactiSet01(): void
    {
        if (cactiSet01Place)
        {
            var cactus01:GScactus01 = new GScactus01(stage, 0, 300);
            stageRef.addChildAt((cactus01), 2);
            var cactus01b:GScactus01 = new GScactus01(stage, 190, 50);
            stageRef.addChildAt((cactus01b), 2);
            var cactus01c:GScactus01 = new GScactus01(stage, 660, -40);
            stageRef.addChildAt((cactus01c), 2);
            cactus01c.scaleX = -1;
            var cactus01d:GScactus01 = new GScactus01(stage, 710, 340);
            stageRef.addChildAt((cactus01d), 2);
            cactus01d.scaleX = -1;
            var cactus02:GScactus02 = new GScactus02(stage, 420, -50);
            stageRef.addChildAt((cactus02), 2);
            var cactus02b:GScactus02 = new GScactus02(stage, 600, 180);
            stageRef.addChildAt((cactus02b), 2);
            var cactus02c:GScactus02 = new GScactus02(stage, 300, 240);
            stageRef.addChildAt((cactus02c), 2);
            var cactus03:GScactus03 = new GScactus03(stage, 540, 100);
            stageRef.addChildAt((cactus03), 2);
            var cactus03b:GScactus03 = new GScactus03(stage, 30, 5);
            stageRef.addChildAt((cactus03b), 2);
            cactus03b.scaleX = -1;
            var cactus03c:GScactus03 = new GScactus03(stage, 520, 420);
            stageRef.addChildAt((cactus03c), 2);

            cactiSet01Place = false;
        }
    }



    private function build01TimerHandler(e: TimerEvent) : void
    {
        build01Place = true;
    }
    private function build02TimerHandler(e: TimerEvent) : void
    {
        build02Place = true;
    }


    private function cactiSet01TimerHandler(e: TimerEvent) : void
    {
        cactiSet01Place = true;
    }











    private function removeSelf() : void
    {
        removeEventListener(Event.ENTER_FRAME, loop);

        if (stageRef.contains(this))
        stageRef.removeChild(this); 
    }   

}

}

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

One thing to be wary of is that hitTestObject does AABB (axis-aligned bounding box) collision, meaning that it fits a rectangle around your object, and uses that to test for collisions. Your buildings appear to have complex, concave shapes -- hitTestObject won't take these into consideration, it simply plops a giant rectangle over the building and uses that to test. Also note that if collide is a single MovieClip with all of the building areas inside of it, then the rectangle gets wrapped over that entire area as opposed to having separate areas for the individual buildings. You'd have to split your collision areas up into separate rectangles and test against them individually. This is likely why you are seeing some false positives and bad behavior.

hitTestPoint will take into account the object's shape and do pixel-perfect collision when the shapeFlag parameter set to true, but this will only test a single point. To test a larger shape, you can try to do multiple hitTestPoint calls iteratively. If that's not sufficient, look into more sophisticated collision methods. Check out this set of tutorials from the creators of N.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...