我在命中检测方面遇到问题

I am having trouble with hit detection

我无法让我的命中检测在 as3 中工作。我正在制作一个像游戏一样飞扬的小鸟,当玩家死亡并返回到第 2 帧时,我们收到错误 #1009。我对此很陌生,所以如果你能尽可能简单地做到这一点,那将是 appreciated.Thank 你!这是我的代码。

import flash.events.Event;

stage.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);

function fl_MouseClickHandler(event:MouseEvent):void
{
    player.y += -100;
}

var randomX:Number = Math.random() * 550;
player.x = 50;
player.y = 50;

var speed:Number = 5;

player.addEventListener(Event.ENTER_FRAME, moveDown);

function moveDown(e:Event):void {
    e.target.y += speed; 

    if(e.target.y >= 400) {

        {
            gotoAndStop(2);
            player.removeEventListener(Event.ENTER_FRAME, moveDown);

        }
    }
}
var gravity = 8;

    stage.addEventListener(Event.ENTER_FRAME, movewt);
function movewt(e:Event):void 
{
    wt.x = wt.x - 5;
}

stage.addEventListener( Event.ENTER_FRAME, handleCollision)

function handleCollision( e:Event ):void
{
    if(player.hitTestObject(wt))
       {
         gotoAndStop(2);
         stage.removeEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
         player.removeEventListener(Event.ENTER_FRAME, moveDown);
         stage.removeEventListener(Event.ENTER_FRAME, movewt);
         stage.removeEventListener( Event.ENTER_FRAME, handleCollision);


       }
}

问题

当此代码转到第 2 帧时

if(e.target.y >= 400) 
{
    {
        gotoAndStop(2);
        player.removeEventListener(Event.ENTER_FRAME, moveDown);

    }
}

它只会从 player 中删除 ENTER_FRAME 事件侦听器,所有其他处理程序仍然存在,即:

  1. fl_MouseClickHandler
  2. movewt
  3. handleCollision

后两个是自己执行的,这使它们成为有问题的,因为它们访问的对象不一定出现在第 2 帧上。

movewt 访问 wthandleCollision 访问 playerwt。如果第 2 帧上不存在 playerwt,则它们是 null.

解决方案

不要使用框架! 虽然基于框架构建导航看起来很容易,但您很快就会 运行 遇到类似手头问题的问题。框架是为动画制作的,他们很擅长做这件事,所以就用它们吧。如何不使用框架超出了这个答案的范围,网络上有很多关于如何做到这一点的资源。大多数游戏框架甚至没有框架,而是为此目的使用状态机。强烈建议查看游戏框架如何处理此问题。

另一个问题是您在帧之间切换的方式不一致。有时您会删除一个事件侦听器,有时您会删除其他一些事件侦听器......您是否只是忘记删除所有这些事件侦听器? 为什么你首先有这种重复的逻辑?如果你有不同的游戏状态(例如,游戏本身,它当前在第 1 帧(或您发布的代码所在的任何帧)和一些 游戏结束 屏幕在第 2 帧),那么您应该有一个明确定义的方式在两种状态之间转换.

如果您想进入 游戏结束 状态,请使用一个函数执行此操作并在该函数中执行所有清理工作:

function gameOver():void
{
    gotoAndStop(2);
    stage.removeEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
    player.removeEventListener(Event.ENTER_FRAME, moveDown);
    stage.removeEventListener(Event.ENTER_FRAME, movewt);
    stage.removeEventListener( Event.ENTER_FRAME, handleCollision);
}

现在,无论是因为关卡结束还是因为碰撞,只要您想更改为该状态,都可以调用该函数:

import flash.events.Event;

var speed:Number = 5;
var gravity = 8;
var randomX:Number = Math.random() * 550;

player.x = 50;
player.y = 50;

stage.addEventListener(Event.ENTER_FRAME, movewt);
stage.addEventListener( Event.ENTER_FRAME, handleCollision);
player.addEventListener(Event.ENTER_FRAME, moveDown);
stage.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);

function fl_MouseClickHandler(event:MouseEvent):void
{
    player.y += -100;
}

function moveDown(e:Event):void 
{
    e.target.y += speed; 

    if(e.target.y >= 400) 
    {
        gameOver();
    }
}

function movewt(e:Event):void 
{
    wt.x = wt.x - 5;
}

function handleCollision(e:Event):void
{
    if(player.hitTestObject(wt))
    {
        gameOver();
    }
}

function gameOver():void
{
    gotoAndStop(2);
    stage.removeEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
    player.removeEventListener(Event.ENTER_FRAME, moveDown);
    stage.removeEventListener(Event.ENTER_FRAME, movewt);
    stage.removeEventListener( Event.ENTER_FRAME, handleCollision);
}

同样,理想情况下,您会使用提供 类 表示游戏状态的框架。这允许明确定义状态之间的转换: 按照现在的代码,您必须记住应该调用 gameOver() 以便正确过渡到 game over 状态,您仍然可以用另一种方式进行.对于图书馆,没有 "other way",只有一个。但就目前而言,gameOver() 应该可以解决您的问题。