多个画布层上的碰撞检测

时间:2016-09-01 05:33:28

标签: javascript canvas 2d collision-detection

我正在努力弄清楚如何检测在不同画布层上绘制的资产上的碰撞。我制作了两个数组来保存我想要的东西"碰撞"使用名为collidable_objects_layer1和collidable_objects_layer2。这些数组基本上绘制了背面的表格和墙壁,角色不应该通过它。

bar.js基本上占据了整个酒吧"场景"你在下面的链接中看到。和main.js是让我的玩家移动的循环。我认为我的架构搞砸了,因为我没有看到将这两者结合在一起的简单方法所以对此有任何建议(这里是必要的模块还是只是伤害了我?)。它现在的方式我不知道如何添加更多"场景"不同的碰撞测试。

我假设碰撞测试发生在主循环中

function main() {
    var now = Date.now();
    var dt = (now - last_time) / 1000.0;

    clearCanvas();
    drawCharacter();
    frame++;
    last_time = now;
    requestAnimFrame(main);
}

所以真的有几个问题,算法(psuedocode)会让我的播放器在bar.js中检测到这些可碰撞的对象。第二,我的架构适合处理多个场景,例如,一旦玩家离开" bar"到"外面" (outside.js)我如何处理这种过渡,这样我的玩家就可以检测到物体而不管它的场景"。我以为我最终得到了一个Scene类或其他东西,我不确定。

提前谢谢。找到plunk链接here

1 个答案:

答案 0 :(得分:1)

创建对象接口。

对象barplayer在您的示例中都是全局的,因此从另一个访问一个是没有问题的。即在player内,你可以调用bar();来启动吧。

您要做的是为场景对象bar提供更广泛的界面。该接口以受控方式(通过函数)提供对对象的访问。

首先让我们看看需要什么。

当玩家移动时,我们想知道方式是否清楚。如果没有,那么不要移动,如果是,那么移动。因此,我们需要一个函数,根据该位置的内容返回给定位置的truefalse

界面

我只会在这里添加伪代码,你可以详细说明。

bar对象中,而不是返回函数init,返回一个对象,该对象将成为对象的公共接口bar

var bar = (function(){
    //... all the code and function

    return {   // return a interface object
       init : init,  // with the function init
    };
})();

现在,对象bar具有属性作为方法。初始化bar

bar.init(); // rather than bar() as you had it.

扩展界面

要通过碰撞测试将界面扩展到bar,您可以在bar内添加一个函数来测试给定位置

var bar = (function(){
    //... all the code and function
    function isPositionBlocked(x,y){ // returns true if location x y 
                                     // if blocked
         //... code to find what is at x,y
         if(blocked){
             return true;
         }
         return false;
    }

然后将该函数添加到返回的接口对象。

    return {   // return an object
       init : init,  // with the function init
       test : isPositionBlocked, // with the new test function.
    };
})();

现在您可以从player对象中访问测试函数(假设player可以访问对象bar

player内部

  // movex movey are the directions to move
  // posx, posy are the current direction
  if(! bar.test(posx + mousex, posy + movey)){ // if not blocked
      posx += movex;
      posy += movey;
  }

这是在使用立即调用的对象var obj = (function(){...code; return {}})();

时访问对象之间的详细信息的方法

替代实施

您还可以在bar中创建界面对象,以便从bar内访问界面。

var bar = (function(){
    //... all the code and functions
    var API = {};
    API.init = function(){ //... init code
    API.test = function(x,y){ //... blah blah

    function someInternalFunction(){
        var result = API.test(x,y);  // access the interface from 
                                           // within the bar object
    }
    return API;
})();

我使用首字母缩略词API(应用程序协议接口),因为首选名称interface是Javascript中的保留字,但任何名称都可以。 API对象可以包含您希望外部对象可以访问的任何内容(在其他语言中称为public属性)以及对象bar中您不希望在外部提供的所有内容访问权限为private,但在javascript中通常不会使用这些字词。

<强>&#39;这&#39;绑定到界面

向对象添加函数时

API.test = function(x,y){...

它会自动绑定到该对象,因此您可以通过this令牌访问该对象。

EG内部测试

API.init = function(){//...
API.test = function(x,y){//...
    this.init(); // if you wanted to init
    // this refers to the object API

因此,如果您使用直接返回对象

 return {
    init : init,
    test : testFunction,
 }

您仍然可以通过this

访问返回对象的属性
var test = (function(){
     function init(){};
     function testFunction(){
        if(this.init){  
           return true;
        }
     }
     return {
        init : init,
        test : testFunction,
     }
})();

console.log(test.test()); // output >> true;

但是从对象内部调用函数testfunction会产生不可预测的结果,因为它没有绑定到接口对象,所以要小心。我通常创建API对象,并仅将公共函数定义为该对象的一部分,以防止错误地调用它们。