Javascript画布游戏 – 碰撞检测

我正在构建一个小型迷你瓦片引擎游戏.我目前正致力于实现简单的基于块的碰撞检测,但是我遇到了真正的问题.我用谷歌搜索了几个小时看不同的实现,但似乎无法理解它.我目前的努力(目前仅在玩家向右移动时检测到碰撞),大部分都有效,但允许玩家通过障碍物的底部.碰撞使用法线贴图阵列来检测碰撞,地图中任何2的值都是实体对象.

我理解我需要做的概念 – 在移动我的播放器之前,计算播放器最终会进入的单元格.检查分配给该单元格的值.如果是2,请勿让玩家移动.

我的问题是弄清楚玩家将在技术上最终进入的细胞,在点上,玩家可以同时在4个细胞中.我尝试过使用原点和4角检测来解决这个问题,但我无法让它发挥作用.

JS Fiddle HERE – https://jsfiddle.net/j1xqxze8/

我的守则;

    var Player = function() {
        this.width = 16;
        this.height = 16;
        this.position   = {};
        this.position.x = 32;
        this.position.y = 32;
        this.speed      = 8;

        this.render = function() {
            window.context.fillStyle = 'white';
            window.context.fillRect(this.position.x,this.position.y,this.width,this.height);
        };

        var _self = this;

        this.didCollide = function(dir) {
            if(dir == 'right'){
                var newBlock = window.tileMap.getCell(Math.floor((_self.position.x + _self.width) / 32),Math.floor((this.position.y + this.height / 2) / 32));

                if(newBlock == 2)
                    return true;
            }
        };

        window.addEventListener('keydown',function(e) {
            if(e.keyCode == 38 || e.keyCode == 87){
                _self.position.y -= _self.speed;
            }

            if(e.keyCode == 40 || e.keyCode == 83){
                _self.position.y += _self.speed;
            }

            if(e.keyCode == 37 || e.keyCode == 65){
                _self.position.x -= _self.speed;
            }

            if(e.keyCode == 39 || e.keyCode == 68){
                if(!_self.didCollide('right')){
                    _self.position.x += _self.speed;
                }
            }
        })
    };

var TileMap = function() {
    this.map = [
        [1,1,1],[1,2,1]
    ];

    this.tileSize = 32;
    this.colors = ['black','red','green'];

    this.getCell = function(x,y){
      return this.map[y][x];
    };

        this.render = function(){
            for(var x = 0; x < this.map.length; x++){
                for(var y = 0; y < this.map.length; y++){
                    // SWAP Y AND X IN THE FILLSTYLE DUE TO BACKWARDS/MIRRORED JS ARRAY READING
                    window.context.fillStyle = this.colors[this.map[y][x]];
                    window.context.fillRect((x * this.tileSize) - window.camera.position.x,(y * this.tileSize) - window.camera.position.y,this.tileSize,this.tileSize);

                    window.context.strokeStyle = 'yellow';
                    window.context.strokeRect((x * this.tileSize) - window.camera.position.x,this.tileSize);
                }
            }
        }
    };
最佳答案
由于您在每个keydown移动玩家8个位置,因此在keydown中您必须测试这8个临时位置中的每个位置以查看是否发生碰撞.

警告:未经测试的代码 – 需要一些调整(可能!)

window.addEventListener('keydown',function(e) {
    // save x,y before the move
    var beginningX=_self.position.x;
    var beginningY=_self.position.y;

    // test each interim positon between the beginning & 
    // current position for collisions
    // if a collision occurs,stop at the collision position
    if(e.keyCode == 38 || e.keyCode == 87){
        _self.position.y -= _self.speed;
        _self.position.y = testInterimVerticalCollisions(
            beginningY,_self.position.y,_self.position.x);
    }

    if(e.keyCode == 40 || e.keyCode == 83){
        _self.position.y += _self.speed;
        _self.position.y = testInterimVerticalCollisions(
            beginningY,_self.position.x);
    }

    if(e.keyCode == 37 || e.keyCode == 65){
        _self.position.x -= _self.speed;
        _self.position.x = testInterimHorizontalCollisions(
            beginningX,_self.position.x,_self.position.y);
    }

    if(e.keyCode == 39 || e.keyCode == 68){
        _self.position.x += _self.speed;
        _self.position.x = testInterimHorizontalCollisions(
            beginningX,_self.position.y);
        }
    }
})

// test if any interim movement caused a collision
// if yes,return the x that caused the collision
// if no,return the ending x
function testInterimHorizontalCollisions(beginningX,endingX,y){
    for(var x=beginningX;x<=endingX;x++){
        // TODO: adjust for camera position offset
        var cellX = parseInt(x/cellWidth);
        var cellY = parseInt(y/cellHeight);
        if(getCell(cellX,cellY)==2){return(x);}
    }
    return(endingX);
}

// test if any interim movement caused a collision
// if yes,return the y that caused the collision
// if no,return the ending y
function testInterimVerticalCollisions(beginningY,endingY,x){
    for(var y=beginningY;y<=endingY;y++){
        // TODO: adjust for camera position offset
        var cellX = parseInt(x/cellWidth);
        var cellY = parseInt(y/cellHeight);
        if(getCell(cellX,cellY)==2){return(y);}
    }
    return(endingY);
}

相关文章

kindeditor4.x代码高亮功能默认使用的是prettify插件,prett...
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代...
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小