(JS / Canvas)sidescroller的碰撞/移动

时间:2013-10-25 20:35:49

标签: javascript canvas

http://jsfiddle.net/xknbn/ http://jsfiddle.net/xknbn/embedded/result/

嘿伙计们。我遇到问题让我的碰撞系统正常运行。目前,如果我走得太快,我会嵌入对象中,我的碰撞解决方案就会失败。我很确定问题的发生是因为我的速度设置如何,但我不知道如何解决这个问题。任何帮助将不胜感激。

friction = 0.9,
gravity = 0.3;

function keycheck() {

if (keys[32]) {
    if (!player.jumping) {
        player.jumping = true;
        player.vely = -player.speed;
    }
}

if (keys[68]) {
    if (player.velx < player.speed) {
        player.velx++;
    }
}
if (keys[65]) {
    if (player.velx > -player.speed) {
        player.velx--;
    }
}
}

ctx.startx = player.x;
ctx.starty = player.y;
function playerupdate() {

player.Intersects = function(object) {                                      
    return player.x < object.x + object.width + 1  &&
    player.x + player.width + 1 > object.x &&
    player.y < object.y + object.height + 1 &&
    player.y + player.height + 1 > object.y;
}

solidcount = 0;
for (i = 0; i < tgen.length; i++) {

    for (ii = 0; ii < tgen[i].length; ii++) {

        if ( player.Intersects(tgen[i][ii]) && tgen[i][ii].solid ) {
            var pright = player.x + player.width,
                pleft = player.x,
                ptop = player.y,
                pbottom = player.y + player.height,
                oright = tgen[i][ii].x + tgen[i][ii].width,
                oleft = tgen[i][ii].x,
                otop = tgen[i][ii].y,
                obottom = tgen[i][ii].y + tgen[i][ii].height;

            //if player is to the right of his previous position, and his right side has collided with objects left
            if (player.x >= ctx.startx && pright > oleft - 1) {
                player.x--;
            }
            //if player is to the left of his previous position, and his left side has collided with objects right
            if (player.x <= ctx.startx && pleft < oright + 1) {
                player.x++;
            }
            //if player is above his previous position, and his top side has collided with objects bottom
            if (player.y <= ctx.starty && ptop < obottom + 1) {
                player.y++;
            }
            //if player is below his previous position, and his bottom side has collided with objects top
            if (player.y >= ctx.starty && pbottom > otop - 1) {
                player.y--;
                player.vely = 0;
                player.jumping = false;
            }
            solidcount++;
        }
    }

    if ( i == tgen.length - 1 && solidcount == 0 ) {
        player.jumping = true;
    }
}

ctx.diffx = player.x - ctx.startx;
ctx.diffy = player.y - ctx.starty;

if (player.x <= bgimg.width - width/2 && player.x >= width/2) {
    ctx.translate(-ctx.diffx,0);
}

if (player.y <= bgimg.height - 360 - player.height) {
    ctx.translate(0,-ctx.diffy);
}

ctx.startx = player.x;
ctx.starty = player.y;

ctx.clearRect(player.x-width/2,player.y-height/2,width,height);

ctx.fillStyle = 'red';
ctx.fillRect(player.x,player.y,player.width,player.height);

keycheck();

player.velx *= friction;
if (player.jumping) {player.vely += gravity;}

player.x += player.velx;
player.x = Math.round(player.x);   

player.y += player.vely;
player.y = Math.round(player.y);

if (player.y >= bgimg.height - player.height - 1) {
    player.y = bgimg.height - player.height - 1;
    player.vely = 0;
    player.jumping = false;
}

if (player.x > bgimg.width - player.width) {
    player.x = bgimg.width - player.width;
    player.velx = 0;
};

if (player.x < 0) {
    player.x = 0;
    player.velx = 0;
}   

if (!keys[65] && !keys[68] && (player.velx < 0.2 && player.velx > -0.2)) {player.velx = 0};

console.log(player.x,player.y)
requestAnimationFrame(playerupdate);
}

1 个答案:

答案 0 :(得分:0)

所以这是一个常见的平台引擎问题。如果您的玩家移动得太快,它会直接通过障碍物,因为当前位置和下一个位置之间不会发生碰撞测试。您的目标是尽可能少地测试碰撞,但是测试起始位置和目标之间的所有可能碰撞。此外,当您在路径中检测到碰撞时,您必须正确处理它。

安全地移动物体

要安全移动任何物体,您需要逐步移动它们,并在每一步测试碰撞。最简单的选择是一次将玩家移动1个像素,然后测试碰撞。这确实意味着要进行大量的碰撞测试。

为了改善这一点,如果你只进行箱子碰撞测试,你可以每次最多移动玩家的宽度。

处理碰撞

因此,在您的示例中,您将播放器移回1像素,具体取决于播放器的方向。如果玩家将5个像素沉入障碍物中,则您的碰撞处理机制仅将玩家移回障碍物中的4个像素。看起来好像玩家慢慢穿过障碍物。

如果您一次移动播放器1个像素,则您采取的方法有效。如果您一次移动播放器超过1个像素,则必须将播放器移回,直到它不再与障碍物重叠。类似于while(重叠)的东西 - &gt;向后移动一个像素