我有一个简单的2d瓷砖地图游戏,但我试图让碰撞检测工作。当玩家碰到地板或天花板时看起来很好但是当玩家碰到墙壁时,它们会非常快地缩小,我不知道为什么。这是代码的jsfiddle - https://jsfiddle.net/o6dn1z6u/3/
我已经做到这一点,以便游戏检查玩家所在的每个牌(最多4个)。如果jsfiddle太乱了,这是代码
声明平铺贴图。 0是透明的,其他一切都是墙/地板等:
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;
}
}
有很多代码,这就是为什么我包含jsfiddle,但任何帮助表示赞赏:)
答案 0 :(得分:0)
我使用了JSFiddle并发现了一些有趣的东西。它不仅使玩家失望,也使他们失望。这取决于玩家是靠近顶部还是底部。然后,我通过更改代码的一个字符来解决向下传送的问题。
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不是我的技能,因此您可能必须找到一种方法来获取水平,然后再进行垂直检查。尝试将两者切换!
如果将它们切换,结果将很奇怪。我不会详细介绍。 我只是没有很多结果。