Javascript 2D平铺地图碰撞检测-播放器自动下移
我有一个简单的2d瓷砖地图游戏,但我正在尝试让碰撞检测工作。当玩家撞到地板或天花板时,看起来很好,但当玩家撞到墙壁时,他们会迅速缩小,我不知道为什么。下面是一段代码- 我这样做是为了让游戏检查玩家所在的每个磁贴(最多4个)。如果JSFIDLE太乱,下面是代码 声明平铺贴图。0是透明的,其他一切都将是墙/地板等:Javascript 2D平铺地图碰撞检测-播放器自动下移,javascript,html,collision-detection,Javascript,Html,Collision Detection,我有一个简单的2d瓷砖地图游戏,但我正在尝试让碰撞检测工作。当玩家撞到地板或天花板时,看起来很好,但当玩家撞到墙壁时,他们会迅速缩小,我不知道为什么。下面是一段代码- 我这样做是为了让游戏检查玩家所在的每个磁贴(最多4个)。如果JSFIDLE太乱,下面是代码 声明平铺贴图。0是透明的,其他一切都将是墙/地板等: var levelOne = { background: 'lightblue', collisions: [ [1,1,1,1,1,1,1,1,
var levelOne = {
background: 'lightblue',
collisions: [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,1],
[1,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0,2,2,2,2,2,2,2,1],
[1,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
],
player: {spawnX: 1, spawnY: 18}
}
标准游戏变量:
var canvas = document.getElementById('game-canvas');
var context = canvas.getContext('2d');
var tile = 40;
var FPS = 30;
var currentLevel = levelOne;
var playerLeft = false;
var playerRight = false;
var playerUp = false;
var playerDown = false;
var speed = 6;
var xSpeed = 0;
var ySpeed = 0;
var playerX = currentLevel.player.spawnX * tile;
var playerY = currentLevel.player.spawnY * tile;
function draw()
{
updateMap(currentLevel);
updatePlayer(currentLevel.player);
}
setInterval(draw, 1000/ FPS);
更新地图只是将瓷砖绘制到画布上,所以我将跳过这一步。当更新玩家时,它会得到玩家想要做的移动,如果新的移动会与墙发生碰撞,它会将他们定位在墙的旁边,因此如果他们的玩家在X:2,他们向下移动5格,它会将他们定位在X:0,而不是将他们留在X:2
function updatePlayer (player)
{
var newX = playerX;
var newY = playerY;
if (playerLeft)
{
newX -= speed;
}
if (playerRight)
{
newX += speed;
}
if (playerUp)
{
newY -= speed;
}
if (playerDown)
{
newY += speed;
}
if (!verticleCollision(newX, newY))
{
playerY = newY;
}
else
{
newY = playerY;
}
if (!horizontalCollision(newX, newY))
{
playerX = newX;
}
context.fillStyle = 'blue';
context.fillRect(playerX, playerY, tile, tile);
}
下面是碰撞函数。我想把水平方向和垂直方向都设为2,这样你就可以有效地在地板或墙上滑动。在小提琴上,我在播放器所在的4个盒子上涂上了颜色,因此我可以想象碰撞
function verticleCollision(x, y)
{
var topLeftX = Math.floor(x/tile);
var topLeftY = Math.floor(y/tile);
var bottomLeftX = Math.floor(x/tile)
var bottomLeftY = Math.ceil(y/tile);
var topRightX = Math.ceil(x/tile);
var topRightY = Math.floor(y/tile);
var bottomRightX = Math.ceil(x/tile);
var bottomRightY = Math.ceil(y/tile);
if ((currentLevel.collisions[topLeftY][topLeftX] != 0) || (currentLevel.collisions[topRightY][topRightX] != 0))
{
playerY = topLeftY * tile + tile;
return true;
}
else if ((currentLevel.collisions[bottomLeftY][bottomLeftX] != 0) || (currentLevel.collisions[bottomRightY][bottomRightX] != 0))
{
playerY = bottomLeftY * tile - tile;
return true;
}
else
{
return false;
}
}
function horizontalCollision(x, y)
{
var topLeftX = Math.floor(x/tile);
var topLeftY = Math.floor(y/tile);
var bottomLeftX = Math.floor(x/tile)
var bottomLeftY = Math.ceil(y/tile);
var topRightX = Math.ceil(x/tile);
var topRightY = Math.floor(y/tile);
var bottomRightX = Math.ceil(x/tile);
var bottomRightY = Math.ceil(y/tile);
if ((currentLevel.collisions[topLeftY][topLeftX] != 0) || (currentLevel.collisions[bottomLeftY][bottomLeftX] != 0))
{
playerX = topLeftX * tile + tile;
return true;
}
else if ((currentLevel.collisions[bottomRightY][bottomRightX] != 0) || (currentLevel.collisions[bottomLeftY][bottomLeftX] != 0))
{
playerX = bottomRightX * tile - tile;
return true;
}
else
{
return false;
}
}
有相当多的代码,这就是为什么我包括了JSFIDLE,但是非常感谢您的帮助:)我使用了JSFIDLE,并找到了一些有趣的东西。它不仅让玩家下场,也让他们上台。这取决于玩家是更接近顶部还是底部。然后,我通过改变一个字符的代码来修正下传态
function verticleCollision(x, y)
{
var topLeftX = Math.floor(x/tile);
var topLeftY = Math.floor(y/tile);
var bottomLeftX = Math.floor(x/tile)
var bottomLeftY = Math.ceil(y/tile);
var topRightX = Math.ceil(x/tile);
var topRightY = Math.floor(y/tile);
var bottomRightX = Math.ceil(x/tile);
var bottomRightY = Math.ceil(y/tile);
context.fillStyle = 'brown';
context.fillRect(topLeftX * tile, topLeftY * tile, tile, tile);
context.fillStyle = 'red';
context.fillRect(topRightX * tile, topRightY * tile, tile, tile);
context.fillStyle = 'green';
context.fillRect(bottomLeftX * tile, bottomLeftY * tile, tile, tile);
context.fillStyle = 'gold';
context.fillRect(bottomRightX * tile, bottomRightY * tile, tile, tile);
if ((currentLevel.collisions[topLeftY][topLeftX] != 0) || (currentLevel.collisions[topRightY][topRightX] != 0))
{
//I changed this from plus to minus
playerY = topLeftY * tile - tile;
return true;
}
else if ((currentLevel.collisions[bottomLeftY][bottomLeftX] != 0) || (currentLevel.collisions[bottomRightY][bottomRightX] != 0))
{
playerY = bottomLeftY * tile - tile;
return true;
}
else
{
return false;
}
}
我将第一个playerY编辑更改为“-”,而不是“+”。这可以防止玩家向下传送,但我不知道你是否也希望玩家向上传送。所以我决定试着修复另一个
嗯,原来垂直碰撞破裂了,所以擦伤它。将其切换回“+”。这次让我们试着保持水平碰撞
大约5分钟后,我发现玩家可能会在被向后碰撞之前撞到黑色瓷砖上,导致垂直碰撞首先发生。因为JS不是我的技能,就像我说的,你可能必须找到一种方法在垂直之前先检查水平面。试着把这两个调换一下
编辑:
如果你换个角度看,结果会很奇怪。我不想谈细节。
我只是还没有太多的结果。我使用了JSFIDLE并找到了一些有趣的东西。它不仅让玩家下场,也让他们上台。这取决于玩家是更接近顶部还是底部。然后,我通过改变一个字符的代码来修正下传态
function verticleCollision(x, y)
{
var topLeftX = Math.floor(x/tile);
var topLeftY = Math.floor(y/tile);
var bottomLeftX = Math.floor(x/tile)
var bottomLeftY = Math.ceil(y/tile);
var topRightX = Math.ceil(x/tile);
var topRightY = Math.floor(y/tile);
var bottomRightX = Math.ceil(x/tile);
var bottomRightY = Math.ceil(y/tile);
context.fillStyle = 'brown';
context.fillRect(topLeftX * tile, topLeftY * tile, tile, tile);
context.fillStyle = 'red';
context.fillRect(topRightX * tile, topRightY * tile, tile, tile);
context.fillStyle = 'green';
context.fillRect(bottomLeftX * tile, bottomLeftY * tile, tile, tile);
context.fillStyle = 'gold';
context.fillRect(bottomRightX * tile, bottomRightY * tile, tile, tile);
if ((currentLevel.collisions[topLeftY][topLeftX] != 0) || (currentLevel.collisions[topRightY][topRightX] != 0))
{
//I changed this from plus to minus
playerY = topLeftY * tile - tile;
return true;
}
else if ((currentLevel.collisions[bottomLeftY][bottomLeftX] != 0) || (currentLevel.collisions[bottomRightY][bottomRightX] != 0))
{
playerY = bottomLeftY * tile - tile;
return true;
}
else
{
return false;
}
}
我将第一个playerY编辑更改为“-”,而不是“+”。这可以防止玩家向下传送,但我不知道你是否也希望玩家向上传送。所以我决定试着修复另一个
嗯,原来垂直碰撞破裂了,所以擦伤它。将其切换回“+”。这次让我们试着保持水平碰撞
大约5分钟后,我发现玩家可能会在被向后碰撞之前撞到黑色瓷砖上,导致垂直碰撞首先发生。因为JS不是我的技能,就像我说的,你可能必须找到一种方法在垂直之前先检查水平面。试着把这两个调换一下
编辑:
如果你换个角度看,结果会很奇怪。我不想谈细节。
我只是还没有很多结果