我用Javascript和Canvas做一个小游戏。我有一个碰撞检测,但是效果不是很好。我不能穿过墙壁。到目前为止还算不错,但是它只能在左侧和顶部工作而不会重叠。
我的地图是基于0和1的数组。1是可步行的,0必须阻塞
我的播放器是32x32,我的图块也是。
PosX是May Player的x坐标 PosY是May Player的y坐标
这是我的检测代码:
var tileWidth = 32; // Fliesen breite festgelegt
var tileHeight = 32; // Fliesen höhe festgelegt
var solidTiles = [0]; // var solidTiles beinhaltet die 0 aus dem array, sagt das die nicht durchdringbar sein sollen (Hol mir quasi die 0 ausem array raus
function isSolidTile(x, y) { // Funktion zu festlegung das 0 Fließen nicht durchgehbar sind, x Pixel und y Pixel der fliese
var tileX = Math.floor(x / tileWidth); // Fließe in X --> x koordinate / durch die halbe breite, damit wir den mittelpunkt der fliese als festen punkt feststellen
var tileY = Math.floor(y / tileHeight); // Fließe in Y --> y koordinate / durch die halbe breite, damit wir den mittelpunkt der fliese als festen punkt feststellen
var tile = mapKollision[ tileY ][tileX] ; // WICHTIG!: Bei Listen ist auch die Zeile und Spalte einzuhalten. Bei der Abfrage einer Kollision zu erst Y dann X
if ( tile == 0 ) { //
return true; //
} else {return false} //
}
var altPosX = PosX; // neue variable für die alte helden position
var altPosY = PosY;
if ( isSolidTile( PosX, PosY) ){ // if wenn isSolidTile getroffen wird
PosX = altPosX; // soll er DIESE PosX in die alte Pos X umwandeln
PosY = altPosY; // soll er DIESE PosY in die alte Pos Y umwandeln
}
我知道我必须说类似的话
if( PosX + 32 ) PosX = altPosX -32;
但是当我使用它时,我的播放器从“阻隔砖块”的右侧反弹回来,而当我向左走时,我的播放器穿过了其播放器剩下的所有阻隔砖块。
但是我想要的是,当我的玩家用他的32x32的右侧触摸阻塞的Tile的左侧时,他必须停下来。
我不知道为什么它不起作用。
如果您需要更多代码,请告诉我。
谢谢:)
答案 0 :(得分:0)
根据我的观察,我认为您的碰撞检测仅基于玩家精灵的单个点-最有可能是它的中心点。 为了进行更精确的碰撞检测,我们需要考虑该对象周围的拐角点及其方向 搬到。另外,我们需要检查是否会与之前之类的固体物体碰撞,我们实际上将其移动到该位置。 这样,我们可以将其并排放置在该对象上。
考虑以下示例:
我们的播放器精灵是红色方块,并且正在以每帧4像素的速度移动。可以看到精灵和蓝色的墙壁相隔仅2个像素!如果我们向右移动4个像素,则右下角会碰到墙。
要解决该问题,我们需要检查小精灵的右上角和右下角,以防可能发生碰撞。
如果我们再次检测到碰撞-在实际在屏幕上移动某些东西之前-我们将红色英雄放到块旁边。
这里有一个复杂的例子。通过单击鼠标使其聚焦,然后使用光标键移动。
var whichKey = 0;
var tileWidth = 32;
var tileHeight = 32;
var player = {
tileX: 2,
tileY: 2,
xPos: 0,
yPos: 0,
speed: 3,
width: 24,
height: 24,
topLeft: 0,
topRight: 0,
bottomLeft: 0,
bottomRight: 0
};
player.xPos = player.tileX * tileWidth + tileWidth / 2 - player.width / 2;
player.yPos = player.tileY * tileHeight + tileHeight / 2 - player.height / 2;
var map = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
var canvas = document.createElement("canvas");
canvas.width = 400;
canvas.height = 300;
var context = canvas.getContext("2d");
document.body.appendChild(canvas);
function updateMap() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "black";
for (var a = 0; a < map.length; a++) {
for (var b = 0; b < map[0].length; b++) {
if (map[a][b] == 1) {
context.fillRect(b * tileWidth, a * tileHeight, tileWidth, tileHeight);
}
}
}
context.fillStyle = "red";
context.fillRect(player.xPos, player.yPos, player.width, player.height);
player.tileX = Math.floor(player.xPos / tileWidth);
player.tileY = Math.floor(player.yPos / tileHeight);
}
function getCorners(futureX, futureY) {
var bottom = Math.floor((futureY + player.height - 1) / tileHeight);
var top = Math.floor((futureY) / tileHeight);
var left = Math.floor((futureX) / tileWidth);
var right = Math.floor((futureX + player.width - 1) / tileWidth);
player.topLeft = map[top][left];
player.topRight = map[top][right];
player.bottomLeft = map[bottom][left];
player.bottomRight = map[bottom][right];
}
function move(directionX, directionY) {
getCorners(player.xPos + player.speed * directionX, player.yPos);
if (directionX == -1) {
if (player.topLeft == 0 && player.bottomLeft == 0) {
player.xPos += player.speed * directionX;
} else {
player.xPos = player.tileX * tileWidth;
}
}
if (directionX == 1) {
if (player.topRight == 0 && player.bottomRight == 0) {
player.xPos += player.speed * directionX;
} else {
player.xPos = (player.tileX + 1) * tileWidth - player.width;
}
}
getCorners(player.xPos, player.yPos + player.speed * directionY);
if (directionY == -1) {
if (player.topLeft == 0 && player.topRight == 0) {
player.yPos += player.speed * directionY;
} else {
player.yPos = player.tileY * tileHeight;
}
}
if (directionY == 1) {
if (player.bottomLeft == 0 && player.bottomRight == 0) {
player.yPos += player.speed * directionY;
} else {
player.yPos = (player.tileY + 1) * tileHeight - player.height;
}
}
}
window.addEventListener('keydown', function(e) {
whichKey = e.keyCode;
});
window.addEventListener('keyup', function(e) {
whichKey = 0;
});
function loop() {
if (whichKey == 37) {
move(-1, 0);
}
if (whichKey == 39) {
move(1, 0);
}
if (whichKey == 38) {
move(0, -1);
}
if (whichKey == 40) {
move(0, 1);
}
updateMap();
}
var interval = setInterval(loop, 20);