如果你只是想您的播放器停止時達到一堵牆,你可以應用一些數學:
例如:假設您的播放器是由10px的矩形和右牆的X位置10px的是200
矩形右側的X位置計算如下:
var playerRightSide = player.x + player.width;
您可以測試玩家已經達到了這樣的牆:
if(playerRightSide >= 200)
如果用戶試圖將他們的播放器推到牆壁之外,您可以使用播放器的X位置將播放器放在牆的左邊。
if(playerRightSide >= 200) { player.x = 190; }
190是牆的X位置(200)減去玩家的寬度(10)。
如果您有興趣進行更高級的碰撞測試,請進一步閱讀。
許多基本遊戲衝突可分爲3種類型:
這裏有一個圖如何檢測這些常見碰撞中的每一個。
假設你確定了一個圓是這樣的:
var circle1={
x:30,
y:30,
r:10
};
假設你定義一個矩形這樣的:
var rect1={
x:20,
y:100,
w:20,
h:20
};
您可以檢測圈VS圈的碰撞是這樣的...
...使用這個圈VS圈碰撞測試代碼:
// return true if the 2 circles are colliding
// c1 and c2 are circles as defined above
function CirclesColliding(c1,c2){
var dx=c2.x-c1.x;
var dy=c2.y-c1.y;
var rSum=c1.r+c2.r;
return(dx*dx+dy*dy<=rSum*rSum);
}
您可以檢測矩形VS矩形碰撞是這樣的...
...使用此矩形與矩形碰撞測試代碼:
// return true if the 2 rectangles are colliding
// r1 and r2 are rectangles as defined above
function RectsColliding(r1,r2){
return !(r1.x>r2.x+r2.w || r1.x+r1.w<r2.x || r1.y>r2.y+r2.h || r1.y+r1.h<r2.y);
}
您可以檢測矩形VS圈的碰撞是這樣的...
...使用這個矩形VS圈碰撞測試代碼:
// return true if the rectangle and circle are colliding
// rect and circle are a rectangle and a circle as defined above
function RectCircleColliding(rect,circle){
var dx=Math.abs(circle.x-(rect.x+rect.w/2));
var dy=Math.abs(circle.y-(rect.y+rect.y/2));
if(dx > circle.r+rect.w2){ return(false); }
if(dy > circle.r+rect.h2){ return(false); }
if(dx <= rect.w){ return(true); }
if(dy <= rect.h){ return(true); }
var dx=dx-rect.w;
var dy=dy-rect.h
return(dx*dx+dy*dy<=circle.r*circle.r);
}
例如,可以使用這些碰撞測試來響應玩家觸摸上電立方體:
// create a circular player object
// that's located at [30,30] and has a radius of 10px
var player={x:30,y:30,r:10};
// create a rectangular power-up at position [200,30]
var powerup={x:200, y:30, w:20, h:20};
// Let's say the user keys the player to coordinate [200,35]
// (touching the power-up)
player.x = 220;
player.y = 35;
// you can test if the circular player is touching the rectangular power-up
if(RectCircleColliding(powerup,player) ) {
// the player has collided with the power-up, give bonus power!
player.power += 100;
}
這裏是代碼和一個小提琴:http://jsfiddle.net/m1erickson/u6t48/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
window.requestAnimFrame = (function(callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000/60);
};
})();
ctx.fillStyle="lightgray";
ctx.strokeStyle="skyblue";
// top collision circle vs circle
var circle1={x:30,y:30,r:10};
var circle2={x:70,y:40,r:10};
var circle3={x:100,y:30,r:10};
var direction1=1;
// middle collision rect vs rect
var rect1={x:20,y:100,w:20,h:20};
var rect2={x:50,y:110,w:20,h:20};
var rect3={x:90,y:100,w:20,h:20};
var direction2=1;
// bottom collision rect vs circle
var circle4={x:30,y:200,r:10};
var rect4={x:50,y:205,w:20,h:20};
var circle5={x:100,y:200,r:10};
var direction3=1;
function drawAll(){
ctx.clearRect(0,0,canvas.width,canvas.height);
drawCircle(circle1);
drawCircle(circle2);
drawCircle(circle3);
drawCircle(circle4);
drawCircle(circle5);
drawRect(rect1);
drawRect(rect2);
drawRect(rect3);
drawRect(rect4);
}
function drawCircle(c){
ctx.beginPath();
ctx.arc(c.x,c.y,c.r,0,Math.PI*2,false);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
function drawRect(r){
ctx.beginPath();
ctx.rect(r.x,r.y,r.w,r.h);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
// return true if the 2 circles are colliding
function CirclesColliding(c1,c2){
var dx=c2.x-c1.x;
var dy=c2.y-c1.y;
var rSum=c1.r+c2.r;
return(dx*dx+dy*dy<=rSum*rSum);
}
// return true if the 2 rectangles are colliding
function RectsColliding(r1,r2){
return !(r1.x>r2.x+r2.w || r1.x+r1.w<r2.x || r1.y>r2.y+r2.h || r1.y+r1.h<r2.y);
}
// return true if the rectangle and circle are colliding
function RectCircleColliding(rect,circle){
var dx=Math.abs(circle.x-(rect.x+rect.w/2));
var dy=Math.abs(circle.y-(rect.y+rect.h/2));
if(dx > circle.r+rect.w/2){ return(false); }
if(dy > circle.r+rect.h/2){ return(false); }
if(dx <= rect.w){ return(true); }
if(dy <= rect.h){ return(true); }
var dx=dx-rect.w;
var dy=dy-rect.h
return(dx*dx+dy*dy<=circle.r*circle.r);
}
var fps = 15;
function animate() {
setTimeout(function() {
requestAnimFrame(animate);
// circle vs circle
circle2.x = circle2.x+direction1;
if(CirclesColliding(circle2,circle1) || CirclesColliding(circle2,circle3) ){
direction1=-direction1;
}
// rect vs rect
rect2.x = rect2.x+direction2;
if(RectsColliding(rect2,rect1) || RectsColliding(rect2,rect3)){
direction2=-direction2;
}
// rect vs circle
rect4.x = rect4.x+direction3;
if(RectCircleColliding(rect4,circle4) || RectCircleColliding(rect4,circle5)){
direction3=-direction3;
}
drawAll();
}, 1000/fps);
}
animate();
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
嘿,我知道這個話題是舊的,但我又遇到問題時,我已經設置了塊之間的碰撞,其中如果「播放器」擊中「目標」, 「玩家」停在「對象」的左側。 但我希望「玩家」能夠從任何一邊(左,上,下,右)擊中相同的「對象」,並適當停止。任何指針爲newby? 哦,我忘了提及,謝謝你的迴應:) – user2582299
我發佈的碰撞函數將處理來自各方的碰撞。看看這個小提琴:http://jsfiddle.net/m1erickson/EKCRJ/ – markE
Thankyou爲您的快速回復!我正在閱讀你評論的鏈接,我可能是錯的,但我不確定這正是我想要做的。我有一個問題,從今天早些時候解釋自己更好,如果你不介意看一下? http://stackoverflow.com/questions/17932679/how-do-i-create-2d-object-collision-from-每-sidetop,左右下角,prope – user2582299