As3:不穿过物体?这背后的逻辑是怎样的?

时间:2014-03-04 22:38:08

标签: actionscript-3 logic collision-detection hittest

我有一个可以控制角色的功能。

我在舞台上还有一个名为assassin_table的电影剪辑。

我想这样做,以便角色不能在桌子上移动,a.k.a使桌子像墙一样工作。

我有这段代码:

if(!this.hitTestObject(_root.assassin_table))
{
    if(upKeyDown)
    {
        gotoAndStop(4);
        y-=Math.cos(rotation/-180*Math.PI)*(mainSpeed +7);
        x-=Math.sin(rotation/-180*Math.PI)*(mainSpeed +7);

    }
    if(!upKeyDown)
    {
        gotoAndStop(3);
    }
 }

然而,如果我触摸桌子,那么我根本无法移动。

我知道这是因为if(!this.hitTestObject(_root.assassin_table)),但我不理解不穿过物体的逻辑。我宁愿拥有一个接近像素的完美碰撞检测系统,但由于很难在网上找到任何不易混淆的信息,我现在坚持使用hitTestObject:)

编辑:尝试了一些事情,并没有那么好用。

    if(!_root.assassinDead && !teleporting && this.currentFrame != 5)
        {
            if(this.hitbox.hitTestObject(_root.assassin_table))
            {
                _root.assassin_table.gotoAndStop(2);

                if(this.x > _root.assassin_table.x)
                {
                    trace("Can't move right");
                    canMoveRight = false;
                }

                if(this.x <_root.assassin_table.x)
                {
                    trace("Can't move left");
                    canMoveLeft = false;
                }

                if(this.y > _root.assassin_table.y)
                {
                    trace("Can't move up");
                    canMoveUp = false;
                }

                if(this.y < _root.assassin_table.y)
                {
                    trace("Can't move down");
                    canMoveDown = false;
                }
            }
            else
            {
                canMoveRight = true;
                canMoveLeft = true;
                canMoveUp = true;
                canMoveDown = true;
            }
        }

这使我有时能够走遍桌子。我认为这是因为我的角色基本上可以在每个可能的角度移动(因为他总是面向鼠标并且没有瓷砖/网格)。

我如何才能使它适用于我的高级机芯?

向上移动运行:

y-=Math.cos(rotation/-180*Math.PI)*(mainSpeed +7);
x-=Math.sin(rotation/-180*Math.PI)*(mainSpeed +7);

旋转由此决定:

this.rotation = Math.atan2((stage.mouseY - this.y), (stage.mouseX - this.x)) * 180/ Math.PI + 90;

2 个答案:

答案 0 :(得分:0)

你应该为四个不同的移动方向分离你的最热门功能。 我的意思是,你不应该使用这个“hitTestObject”的东西,只返回一个布尔值“true”或“false”,这对你不起作用。

你需要一个像“testPoint(player.x,player.y);”这样的功能。并返回给定位置的对象,这样就可以像你那样为你的游戏实现它

   if (upKeyDown && testPoint(player.x, player.y - mainSpeed +7) == null) y-=Math.cos(rotation/-180*Math.PI)*(mainSpeed +7);

player.y - mainSpeed +7 //检查加上mainSpeed + 7,因为在对象内部堆叠之前试图阻止你的玩家

答案 1 :(得分:0)

基本上你的逻辑流程应该是这样的:

  • 样本输入(按键)
  • 移动角色
  • 检查碰撞
  • 如果碰撞然后将角色移动到它正在触摸的对象“外面”

在你的特殊情况下,如果你的角色位于桌子的左边,并且你正在向右移动,那么首先要先移动你的角色。在您的新位置,检查是否有任何碰撞。如果你有一个集合,那么因为你是从左边移动,我们想要在我们碰撞的对象的左边,在这种情况下是表格,所以我们将我们的角色放在桌子的左边。

第一部分(检查角色是否已经击中表格)称为碰撞检测。移动角色以使其超出表格范围称为碰撞响应。碰撞检测是一个非常大的领域,实际上取决于你正在制作的游戏类型;你可以做基于网格的,基于命中测试(如果你没有大量的物体),基于物理的,基于数学的等等。碰撞响应可以是任何东西,取决于你想对一个反应如何碰撞 - 你可以摧毁物体(穗上的气球),改变它的速度(穿过泥浆的角色),从它上面反弹(球离墙),或者阻止任何进一步的移动(角色靠墙)。

让事情变得更容易:

  • 分离您的系统 - 例如,您的输入不应取决于您的碰撞。如果向上键是关闭的,只需注册这个事实 - 你以后用它做什么(让你的角色移动)取决于你
  • 将内存中的对象位置与屏幕上的位置分开 - 这将让您移动它,对碰撞做出反应等等,只有当一切都很好时,才更新图形(停止图形进入墙壁之类的东西只会跳出来下一帧)
  • 一次解决一个轴 - 例如首先在x轴上碰撞,然后在y
  • 上碰撞
  • 很少需要像素完美碰撞:)非旋转的盒子和圆圈比你想象的要多得多
  • 有点相关 - 你的物体的形状不一定是你碰撞的形状 - 例如你的桌子碰撞形状可能只是一个盒子;你的角色碰撞形状可能只是一个圆圈

<强>更新

  

这使我有时能够走遍桌子

假设我们要将我们的角色和桌子碰撞为盒子,你需要考虑它们的大小 - 即我们不只是比较x值,而是我们角色框的右侧在桌子盒子的左侧等。像:

// assumes objects have their anchor point in the top left - if its
// not the case, adjust as you see fit
if( char.x + char.width > table.x ) // right side of the char is overlapping the left side of the table
    canMoveRight = false;
else if( char.x < table.x + table.width ) // left side of char vs right side of table
    canMoveLeft = false;

// etc

使用碰撞时,总是很高兴看到实际的盒子,以便进行调试。像这样:

var debug:Shape = new Shape;
debug.addEventListener( Event.ENTER_FRAME, function():void
{
    debug.graphics.clear();
    debug.graphics.lineStyle( 2.0, 0xff0000 );

    // char (again assuming anchor point is top left)
    debug.graphics.drawRect( char.x, char.y, char.width, char.height );

    // table
    debug.graphics.drawRect( table.x, table.y, table.width, table.height );
});

// add our debug. NOTE: make sure it's above everything
stage.addChild( debug );