多个画布层上的碰撞检测

ats*_*uab 6 javascript 2d canvas 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);
}
Run Code Online (Sandbox Code Playgroud)

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

提前致谢.在这里找到plunk链接

Bli*_*n67 1

创建对象接口。

在您的示例中,该对象barplayer都是全局的,因此从另一个对象访问一个对象是没有问题的。即在里面player你可以调用bar();它将初始化该栏。

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

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

当玩家移动时,我们想知道道路是否畅通。如果不是就不要动,如果是就动。因此,我们需要一个函数,根据给定位置的内容返回trueor 。false

界面

这里我只添加伪代码,具体细节大家可以自行练习。

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

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

    return {   // return a interface object
       init : init,  // with the function init
    };
})();
Run Code Online (Sandbox Code Playgroud)

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

bar.init(); // rather than bar() as you had it.
Run Code Online (Sandbox Code Playgroud)

扩展接口

要扩展接口以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;
    }
Run Code Online (Sandbox Code Playgroud)

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

    return {   // return an object
       init : init,  // with the function init
       test : isPositionBlocked, // with the new test function.
    };
})();
Run Code Online (Sandbox Code Playgroud)

现在您可以从对象内部访问测试函数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;
  }
Run Code Online (Sandbox Code Playgroud)

这就是在使用立即调用的对象时访问对象之间的详细信息的方式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;
})();
Run Code Online (Sandbox Code Playgroud)

我使用缩写 API(应用程序协议接口),因为首选名称interface是 Javascript 中的保留字,但任何名称都可以。该API对象可以包含您希望外部对象访问的任何内容(在其他语言中,这些称为属性),并且您不希望外部访问的public对象内部的所有内容,但在 javascript 中通常不使用这些术语。barprivate

'this' 绑定到接口

当您向对象添加函数时

API.test = function(x,y){...
Run Code Online (Sandbox Code Playgroud)

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

EG内部测试

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

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

 return {
    init : init,
    test : testFunction,
 }
Run Code Online (Sandbox Code Playgroud)

您仍然可以通过以下方式访问返回对象的属性this

var test = (function(){
     function init(){};
     function testFunction(){
        if(this.init){  
           return true;
        }
     }
     return {
        init : init,
        test : testFunction,
     }
})();

console.log(test.test()); // output >> true;
Run Code Online (Sandbox Code Playgroud)

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