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