【问题标题】:Checking character hit test with all scene objects in AS3使用 AS3 中的所有场景对象检查角色命中测试
【发布时间】:2013-02-21 10:22:11
【问题描述】:

好的,这是我的问题,需要一点时间来解释。

班级正在用 AS3 开发街机游戏。该大学有一台街机,机器上的操作系统由我们的老师开发,并提供软件开发工具包。它没有什么疯狂的,所以大部分都很简单。我只是想指出这一点,主要是因为我没有使用 ENTER_FRAME 事件和循环函数,而是使用 SDK 提供的名为 update() 的覆盖函数来执行每帧的更新。

好吧,这就是我的问题。我有一个名为 GameState 的文档类,它基本上在该状态下处理游戏。在这堂课中,我设置了世界和角色。现在它只有 2 座山、2 座城堡、3 个岛屿和角色。

private function initWorld():void
    {
        trace("World has initiated");
        addChild(hazardArea)
        positionElement(hazardArea, 0, 560);

        addChild(mountainSideRight);
        positionElement(mountainSideRight, 730, 200)

        addChild(mountainSideLeft);
        positionElement(mountainSideLeft, 0, 200);

        addChild(castleOne);
        positionElement(castleOne, 5, 160);

        addChild(castleTwo);
        positionElement(castleTwo, 765, 160);

        addIslands();
    }

位置元素只是一个设置我添加到舞台的MC的x和y坐标的函数。现在我还在 AddChild 上创建了一个覆盖,这样每次我将 Child 添加到阶段时,它都会将它保存到我以后可以访问的数组中:

override public function addChild(object:*):void
    {
        super.addChild(object);
        worldObjects.push(object);
    }

好的,三个岛是通过 addIsland 添加的,如下所示:

private function addIslands():void
    {
        var island:Array = Islands.getIslandCords();
        for (var x:int = 0; x < DiceNumbers.NUM_ISLS; x++) 
        {
            addChild(island[x].mc);
            positionElement(island[x].mc, island[x].x, island[x].y);

        }
    }

Islands 只是一个类,它用一堆数学和东西为我的 3 个岛屿找到一个位置......并不重要返回的数组只是 3 个包含 moveclip 和 x 实例的对象和你的坐标。

我还有一个单独的角色类来代表我的侏儒(我游戏中的角色)。课堂上没有什么奇怪的,除了我有一个看起来像这样的重力系统:

var gravity:Number = 2;
public var moveX:Number = 300;
public var moveY:Number = 50;
public var xSpeed:Number = 0;
public var ySpeed:Number = 2;
public static const playerSpeed:Number = 3;
public var friction:Number = .75;

然后我提到的 update() 函数就像 EVENT_FRAME 循环一样工作,里面有这个:

public function update():void
{
    xSpeed *= friction;
    moveX += xSpeed;
    moveY += ySpeed
    theDwarf.y += gravity;

    this.x = moveX;
    this.y = moveY;

    updateControls();
}

theDwarf 是我的侏儒影片剪辑的实例,而 updateControls 为我的侏儒提供了移动的功能。

Ok.... 所以最后在我的 GameState 类中的 update() 函数下,我调用我的碰撞类并将包含场景中所有对象的数组传递给它。在这个类中,我检查碰撞:

public function checkCollision(listOfObjects:Vector.<MovieClip>):void
    {   

        for (var i:int = 0; i < worldObjects.length; i++) {
            if(worldObjects[i] is Player){

                var objOne:MovieClip = worldObjects[i];             
                for (var j:int = 0; j < worldObjects.length; j++){
                    if (j == i){
                        // elimates self comparisons.
                    }
                    else{
                        var objTwo:MovieClip = worldObjects[j];
                        checkIntersect(objOne, objTwo )
                    }
                }
            }
        }
    }

private function checkIntersect(player:MovieClip, objTwo:MovieClip):void
    {
        if(player.hitTestObject(objTwo)){
            player.ySpeed = -1;
        }
        else{
            player.ySpeed = 2;
        }
    }

我的问题是:这个函数会根据舞台上的每个对象检查我的播放器。因此,即使我的矮人降落在 1 个岛上,他也没有撞到其他 2 个岛屿,因此 ySpeed 一直重置为 2。如果我摆脱 else 语句,我的矮人重力永远不会回到 2,他也永远不会再跌倒。我找不到解决方案...我非常努力地想找到一种方法来解决这个问题,我很困惑...我希望我的侏儒摔倒,除非他在我的一个岛屿或一座山上。我希望我已经足够清楚地解释我的问题,这现在已经成为一个巨大的帖子......:D谢谢!

【问题讨论】:

  • 如果你击中物体,你必须打破循环,所以它不会做进一步的检查和可能的重置玩家速度。

标签: actionscript-3 collision-detection hittest


【解决方案1】:

为了更好地解释我之前的评论,您必须像这样更改最后两个函数:

public function checkCollision(listOfObjects:Vector.<MovieClip>):void
{   

   OuterLoop: for (var i:int = 0; i < worldObjects.length; i++) {
        if(worldObjects[i] is Player){

            var objOne:MovieClip = worldObjects[i];             
            for (var j:int = 0; j < worldObjects.length; j++){
                if (j == i){
                    // elimates self comparisons.
                }
                else{
                    var objTwo:MovieClip = worldObjects[j];
                    player.ySpeed = checkIntersect(objOne, objTwo )
                    if (player.ySpeed == -1)
                        break OuterLoop;
                }
            }
        }
    }
}

private function checkIntersect(player:MovieClip, objTwo:MovieClip):int
{
    if(player.hitTestObject(objTwo)){
        return -1;
    }
    else{
        return 2;
    }
}

这也可以做得更好。但这是解决您问题的最快方法。

【讨论】:

  • 谢谢!!你的例子对我不起作用,玩家是 checkIntersect 的私有属性,并且在 checkCollision 中不存在,即使它可以更改为 objOne,但即便如此,我测试了它,我的侏儒根本没有摔倒。然而!感谢您的逻辑,我只是​​以不同的方式实现了它,其中 checkIntersect 返回布尔值,如果没有命中则返回布尔值,如果命中则返回 true。然后在 checkCollision 我创建一个名为 hit 的布尔变量,然后将 checkIntersect 返回分配给它并创建一个类似的 if 条件,如果 TRUE 我只是返回该函数。到目前为止似乎工作!
  • 另外,如果您有时间,我会对如何以更好的方式完成它非常感兴趣。
猜你喜欢
  • 1970-01-01
  • 2016-08-23
  • 1970-01-01
  • 2021-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
相关资源
最近更新 更多