我目前正在开发一款小平台游戏。但碰撞检测并不是很好。我已经看了很多这方面的教程,但似乎无法理解它。这是我的代码:
var ctx = document.getElementById("canvas").getContext("2d");
var rightPressed =false;
var spacePressed =false;
var leftPressed=false;
var gravity = 1;
//Player object
var player = {
x:50,
y:370,
dy:0,
dx:0,
width:10,
height:10,
speed:10,
jumping:false
};
//Box object
var box ={
x:200,
y:350,
width:50,
height:50
};
document.addEventListener("keydown", keyDown);
document.addEventListener("keyup", keyUp);
function keyDown(e) {
if(e.keyCode ==39){
rightPressed=true;
}
if (e.keyCode ==32){
spacePressed=true;
}
if (e.keyCode ==37){
leftPressed =true;
}
}
function keyUp(e) {
if(e.keyCode ==39){
rightPressed=false;
}
if (e.keyCode ==32){
spacePressed=false;
}
if (e.keyCode ==37){
leftPressed =false;
}
}
//Draw the ball
function drawBall(){
ctx.beginPath();
ctx.arc(player.x,player.y,10,0,Math.PI*2);
ctx.fillStyle="red";
ctx.fill();
}
//Draw the box
function drawBox() {
ctx.fillRect(box.x,box.y,box.width,box.height);
}
//The main function that calls the other functions and handles the logic
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
drawBall();
drawBox();
if (rightPressed){
//Right speed of the ball
player.x+=5;
}
if(leftPressed){
//Left speed of the ball
player.x-=5;
}
if(spacePressed){
if(!player.jumping){
//The hight of the jump
player.dy=-player.speed * 2;
player.jumping = true;
}
}
player.dy+=gravity;
player.x+=player.dx;
player.y+=player.dy;
if(player.y >= 390){
player.y = 390;
player.jumping = false;
}
//Box collision logic
window.requestAnimationFrame(draw)
}
window.requestAnimationFrame(draw);

canvas {border:1px solid black;}

<canvas id="canvas" width="400px" height="400px"> </canvas>
&#13;
答案 0 :(得分:1)
我认为这是您正在寻找的行为。以下代码完成所有魔术:
(请参阅下面的代码片段了解工作演示)
//CHECK COLLISION
var collisionObjects = [rect.box, rect.wall];
for (var i=0,count=collisionObjects.length; i<count; ++i) {
var obj = collisionObjects[i];
var playerLeft=x-player.width, playerRight=x+player.width, playerTop=y-player.height, playerBottom=y+player.height;
var objectLeft=obj.x, objectRight=obj.x+obj.width, objectTop=obj.y, objectBottom=obj.y+obj.height;
//check if player is either touching or within the object-bounds
if (playerRight>=objectLeft && playerLeft<=objectRight && playerBottom>=objectTop && playerTop<=objectBottom) {
if (player.y+player.height==objectTop || player.y-player.height==objectBottom) {y=player.y;} //player is already colliding with top or bottom side of object
else if (player.x+player.width==objectLeft || player.x-player.width==objectRight) {x=player.x;} //player is already colliding with left or right side of object
else if (playerRight>objectLeft && playerLeft<objectRight && playerBottom>objectTop && playerTop<objectBottom) {
//check on which side the player collides with the object
var sides = {left:Math.abs(playerRight-objectLeft), right:Math.abs(playerLeft-objectRight), top:Math.abs(playerBottom-objectTop), bottom:Math.abs(playerTop-objectBottom)};
var side = Math.min(sides.left, sides.right, sides.top, sides.bottom); //returns the side with the smallest distance between player and object
if (side==sides.top) {y=objectTop-player.height;} else if (side==sides.left) {x=objectLeft-player.width;} //first check top, than left
else if (side==sides.bottom) {y=objectBottom+player.height;} else if (side==sides.right) {x=objectRight+player.width;} //first check bottom, than right
}
}
}
但为了实现这一点,我不得不改变其他一些事情:
player.x
和player.y
,而是必须在绘制开始时创建变量x
和y
,而只在更新{{1 }}。player.x=x, player.y=y
应该被复制,我认为是保存。但是不要盲目地复制它,我也做了一些其他的改动,主要是为了我自己对你的脚本的理解和可读性。做你想要的......你喜欢它,复制它,你不要,留下它:
draw()
更改为player.speed
和player.speedx
。这些属性也在player.speedy
中使用,因此请小心。draw()
和floor
,以限制球离开画布。end
值更改为地球上的重力值。gravity
更改为var box
,这是一个包含所有矩形形状的对象。如果您想要放置一个新的矩形,只需在var rect
对象中添加一个新的矩形即可。rect
我将draw()
更改为drawBox();
,这是一个绘制for (key in rect) {if (rect.hasOwnProperty(key)) {drawRect(rect[key]);}}
对象内所有对象的循环。rect
是一个数组,其中包含应该触发与玩家发生碰撞的所有对象
正如您在演示中看到的那样,黄色var collisionObjects = [rect.box, rect.wall];
不会触发碰撞,因为它不在阵列中。shelf
添加到collisionObjects-array中,大约半秒后球仍然会掉下来,我还没弄清楚原因。我认为它与宽度有关(代码中shelf
),但不是这样。出于某种原因,如果对象没有碰到地板,那么球最终会落空。) 代码段:
height
&#13;
var ctx = document.getElementById("canvas").getContext("2d");
//OBJECTS====================
var player = {x:50,y:100, dx:0,dy:0, width:10,height:10, speedx:5,speedy:10, jumping:false, color:"red"};
var rect = {
box: {x:150,y:350, width:50,height:50, color:"blue"},
shelf: {x:220,y:250, width:60,height:5, color:"gold"},
wall: {x:360,y:300, width:10,height:100, color:"green"}
};
//VARS====================
var rightPressed = false;
var spacePressed = false;
var leftPressed = false;
var gravity = 0.98;
var floor = canvas.height-player.height;
var end = canvas.width-player.width;
//KEY-HANDLERS====================
document.addEventListener("keydown",function(e) {
if (e.keyCode==39) {rightPressed=true;} //RIGHT
if (e.keyCode==37) {leftPressed=true;} //LEFT
if (e.keyCode==32) {spacePressed=true;} //JUMP
});
document.addEventListener("keyup",function(e) {
if (e.keyCode==39) {rightPressed=false;} //RIGHT
if (e.keyCode==37) {leftPressed=false;} //LEFT
if (e.keyCode==32) {spacePressed=false;} //JUMP
});
//DRAW====================
//OBJECTS--------------------
function drawPlayer() {
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x,player.y,10,0,Math.PI*2);
ctx.fill();
}
function drawRect(obj) {
ctx.fillStyle = obj.color;
ctx.fillRect(obj.x,obj.y,obj.width,obj.height);
}
//SCENE--------------------
function draw() {
ctx.clearRect(0,0,canvas.width,canvas.height);
drawPlayer(); //draw player
for (key in rect) {if (rect.hasOwnProperty(key)) {drawRect(rect[key]);}} //draw all objects in 'rect'
//MOVE PLAYER
var x=player.x, y=player.y;
if (rightPressed) {x = x+player.speedx;} //right
if (leftPressed) {x = x-player.speedx;} //left
if (spacePressed && !player.jumping) { //jump
player.jumping = true;
player.dy = -player.speedy * 2; //jump-factor
}
x = x+player.dx;
if (x <= player.width) {x=player.width;}
if (x >= end) {x=end;}
player.dy += gravity;
y = y+player.dy;
if (y >= floor) {y=floor; player.jumping=false;}
//CHECK COLLISION
var collisionObjects = [rect.box, rect.wall];
for (var i=0,count=collisionObjects.length; i<count; ++i) {
var obj = collisionObjects[i];
var playerLeft=x-player.width, playerRight=x+player.width, playerTop=y-player.height, playerBottom=y+player.height;
var objectLeft=obj.x, objectRight=obj.x+obj.width, objectTop=obj.y, objectBottom=obj.y+obj.height;
//check if player is either touching or within the object-bounds
if (playerRight>=objectLeft && playerLeft<=objectRight && playerBottom>=objectTop && playerTop<=objectBottom) {
if (player.y+player.height==objectTop || player.y-player.height==objectBottom) {y=player.y;} //player is already colliding with top or bottom side of object
else if (player.x+player.width==objectLeft || player.x-player.width==objectRight) {x=player.x;} //player is already colliding with left or right side of object
else if (playerRight>objectLeft && playerLeft<objectRight && playerBottom>objectTop && playerTop<objectBottom) {
//check on which side the player collides with the object
var sides = {left:Math.abs(playerRight-objectLeft), right:Math.abs(playerLeft-objectRight), top:Math.abs(playerBottom-objectTop), bottom:Math.abs(playerTop-objectBottom)};
var side = Math.min(sides.left, sides.right, sides.top, sides.bottom); //returns the side with the smallest distance between player and object
if (side==sides.top) {y=objectTop-player.height;} else if (side==sides.left) {x=objectLeft-player.width;} //first check top, than left
else if (side==sides.bottom) {y=objectBottom+player.height;} else if (side==sides.right) {x=objectRight+player.width;} //first check bottom, than right
player.jumping=false;
}
}
}
//SET PLAYER POSITION
player.x=x, player.y=y;
//NEXT FRAME--------------------
requestAnimationFrame(draw)
} draw();
&#13;
canvas {border:1px solid black;}
&#13;
答案 1 :(得分:0)
所以我知道这不会帮助你修复你的代码,但如果你看一下首页上的演示,我强烈建议你查看http://wickeditor.com/(点击查看第4个)你会看到它提供了很好的碰撞检测,你可以从网站下载项目,它应该使它非常容易复制,以满足你的需求。