Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 基于画布平铺的游戏有一个困难的碰撞错误_Javascript_Css_Html_Canvas_Tiles - Fatal编程技术网

Javascript 基于画布平铺的游戏有一个困难的碰撞错误

Javascript 基于画布平铺的游戏有一个困难的碰撞错误,javascript,css,html,canvas,tiles,Javascript,Css,Html,Canvas,Tiles,我是一个游戏开发的初学者,一直在努力在一组瓷砖和一个玩家矩形之间完成碰撞。这个游戏的特点是跳跃和重力。首先,碰撞可以工作,但非常笨重。有时,当玩家最终到达一块瓷砖的顶部并稍微靠近边缘时,它会立即传送到右侧或左侧(取决于边缘/角落),然后掉落。当与瓷砖底部碰撞时也会发生这种情况;玩家将立即传送到侧面,并进一步向上移动。据我所知,磁贴碰撞检测器会将碰撞与一侧或另一侧混淆,因为当玩家撞击磁贴边缘时,检测器会将其视为与两侧碰撞,并根据最高坐标速度(也称为speedX和speedY)决定将玩家放置在其他位

我是一个游戏开发的初学者,一直在努力在一组瓷砖和一个玩家矩形之间完成碰撞。这个游戏的特点是跳跃和重力。首先,碰撞可以工作,但非常笨重。有时,当玩家最终到达一块瓷砖的顶部并稍微靠近边缘时,它会立即传送到右侧或左侧(取决于边缘/角落),然后掉落。当与瓷砖底部碰撞时也会发生这种情况;玩家将立即传送到侧面,并进一步向上移动。据我所知,磁贴碰撞检测器会将碰撞与一侧或另一侧混淆,因为当玩家撞击磁贴边缘时,检测器会将其视为与两侧碰撞,并根据最高坐标速度(也称为speedX和speedY)决定将玩家放置在其他位置。我通过设置speedY=0来解决这个问题,每次它碰到一块瓷砖的顶部,这就解决了这个问题,但是又出现了另一个问题。现在,如果玩家在一块瓷砖的上面,然后摔倒,很快又向后扫射,它不会与瓷砖的侧面碰撞,但会很快再次回到瓷砖的上面

我只是需要一些关于如何解决这个问题的建议,因为我尝试的每件事都会导致另一个问题。我听说这是开发基于2D瓷砖的游戏时的一个常见错误

下面是一个JSFIDLE,代码正在运行:

下面是我全部代码的显示:

function startGame() { //Starts after all assets have finished loading into the browser
    gameArea.start();
    actor = new player(32, 32, "green", 32, 32);
}

var mapArray = [
    [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,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],
    [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,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],
    [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,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],
    [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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
    [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,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,0,0,0,0,0,1,0,0,0,0,0,1,1,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,1,1,1,0,0,0,1,1,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]

];

function TileCollisionManager() {
    let tileSize = 32;
    let baseCol = Math.floor(actor.x / tileSize);
    let baseRow = Math.floor(actor.y / tileSize);
    let colOverlap = actor.x % tileSize;
    let rowOverlap = actor.y % tileSize;

    if (actor.speedX > 0) { //horizontal collision detection
        if ((mapArray[baseRow][baseCol + 1] && !mapArray[baseRow][baseCol]) ||
            (mapArray[baseRow + 1][baseCol + 1] && !mapArray[baseRow + 1][baseCol] && rowOverlap)) {
            actor.x = baseCol * tileSize;
        }
    }

    if (actor.speedX < 0) {
        if ((!mapArray[baseRow][baseCol + 1] && mapArray[baseRow][baseCol]) ||
            (!mapArray[baseRow + 1][baseCol + 1] && mapArray[baseRow + 1][baseCol] && rowOverlap)) {
            actor.x = (baseCol + 1) * tileSize;
        }
    }



    if (actor.speedY > 0) { //vertical collision detection
        if ((mapArray[baseRow + 1][baseCol] && !mapArray[baseRow][baseCol]) || //Collision with the top of a tile
            (mapArray[baseRow + 1][baseCol + 1] && !mapArray[baseRow][baseCol + 1] && colOverlap)) {
            actor.y = ((baseRow) * tileSize);
            actor.jumping = false;
            actor.speedY = 0;
        }
    }

    if (actor.speedY < 0) { //Collision with the bottom of a tile
        if ((!mapArray[baseRow + 1][baseCol] && mapArray[baseRow][baseCol]) ||
            (!mapArray[baseRow + 1][baseCol + 1] && mapArray[baseRow][baseCol + 1] && colOverlap)) {
            actor.y = (baseRow + 1) * tileSize;
        }
    }
}

var levelRows = 20;
var levelCols = 20;
var gameArea = {
    canvas : document.getElementById('canvas'),

    start : function() {
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, document.body.childNodes[0]);
        requestAnimationFrame(updateGameArea);
        window.addEventListener('keydown', function (e) {
            gameArea.keys = (gameArea.keys || []);
            gameArea.keys[e.keyCode] = true;
        });

        window.addEventListener('keyup', function (e) {
            gameArea.keys = (gameArea.keys || []);
            gameArea.keys[e.keyCode] = false;
        })
    },

    clear : function(){
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    },
    render : function() {
        context = this.canvas.getContext("2d");
        var tileSize = 32;
        for(i=0;i<levelRows;i++){
            for(j=0;j<levelCols;j++){
                if(mapArray[i][j]==1){
                    context.fillStyle = "gray";
                    context.fillRect(j*tileSize,i*tileSize,tileSize,tileSize);
                }
            }
        }
    }
};

function updateGameArea() { //loop function
    gameArea.clear();
    gameArea.render();
    actor.update();
    actor.newPos();
    actor.speedX = 0;
    actor.speedY += actor.gravity;

    if (gameArea.keys && gameArea.keys[39]) {
        actor.speedX = 4;
    }
    if (gameArea.keys && gameArea.keys[37]) {
        actor.speedX = -4;
    }
    if (gameArea.keys && gameArea.keys[32]) { //jump
        if (!actor.jumping) {
            actor.jumping = true;
            actor.speedY = -actor.speed * 3;
        }
    }
    TileCollisionManager();
    if (!TileCollisionManager) {
        actor.speedY += actor.gravity;
    }

    requestAnimationFrame(updateGameArea);
}

function player (width, height, color, x, y) { //player component

    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;
    this.speedX=0;
    this.speedY=0;
    this.gravity=0.3;
    this.speed=3;
    this.jumping=false;
    this.color = color;

    this.update = function () {
        ctx = gameArea.context;
        ctx.fillStyle = this.color;
        ctx.fillRect(
            this.x,
            this.y,
            this.width, this.height);

    };
    this.newPos = function () {
        this.x += this.speedX;
        this.y += this.speedY;

    };
}
函数startGame(){//在所有资源都加载到浏览器后启动
gameArea.start();
演员=新玩家(32,32,“绿色”,32,32);
}
变量映射数组=[
[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,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],
[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,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],
[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,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],
[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,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[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,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,0,0,0,0,0,1,0,0,0,0,0,1,1,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,1,1,1,0,0,0,1,1,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]
];
函数TileCollisionManager(){
让tileSize=32;
让baseCol=Math.floor(actor.x/tileSize);
让baseRow=Math.floor(actor.y/tileSize);
让colOverlap=actor.x%tileSize;
让rowOverlap=actor.y%tileSize;
如果(actor.speedX>0){//水平碰撞检测
if((mapArray[baseRow][baseCol+1]&&!mapArray[baseRow][baseCol])||
(mapArray[baseRow+1][baseCol+1]&&!mapArray[baseRow+1][baseCol]&&rowOverlap)){
actor.x=baseCol*tileSize;
}
}
如果(actor.speedX<0){
if((!mapArray[baseRow][baseCol+1]&&mapArray[baseRow][baseCol])||
(!mapArray[baseRow+1][baseCol+1]&&mapArray[baseRow+1][baseCol]&&rowOverlap)){
actor.x=(baseCol+1)*tileSize;
}
}
如果(actor.speedY>0){//垂直碰撞检测
如果((mapArray[baseRow+1][baseCol]&&!mapArray[baseRow][baseCol])||//与平铺顶部碰撞
(mapArray[baseRow+1][baseCol+1]&&!mapArray[baseRow][baseCol+1]&&colOverlap)){
actor.y=((基线)*tileSize);
actor.jumping=false;
actor.speedY=0;
}
}
如果(actor.speedY<0){//与平铺底部碰撞
if((!mapArray[baseRow+1][baseCol]&&mapArray[baseRow][baseCol])||
(!mapArray[baseRow+1][baseCol+1]&&mapArray[baseRow][baseCol+1]&&colOverlap)){
actor.y=(基线+1)*tileSize;
}
}
}
var levelRows=20;
var levelCols=20;
var游戏区={
canvas:document.getElementById('canvas'),
开始:函数(){
this.context=this.canvas.getContext(“2d”);
document.body.insertBefore(this.canvas,document.body.childNodes[0]);
requestAnimationFrame(updateGameArea);
window.addEventListener('keydown',函数(e){
gameArea.keys=(gameArea.keys | | |[]);
gameArea.keys[e.keyCode]=true;
});
window.addEventListener('keyup',函数(e){
gameArea.keys=(gameArea.keys | | |[]);
gameArea.keys[e.keyCode]=false;
})
},
清除:函数(){
this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
},
render:function(){
context=this.canvas.getContext(“2d”);
var tileSize=32;

对于(i=0;我建议尝试Unity3d游戏引擎。与用JS构建游戏相比,学习如何使用它所需的时间更少。我知道unity更适合制作。但是,我对这个游戏的目的是从从头开始编程中学习。也许我可以阅读unity代码的工作原理,并从中汲取一些想法。我建议尝试Unity3d游戏引擎。学习如何使用它所需的时间比在JS中构建游戏所需的时间要少。我知道unity更适合制作。但是,我对这个游戏的目的是从从头开始编程中学习。也许我可以阅读unity代码的工作原理,并从中汲取一些想法。