gpt4 book ai didi

javascript - Sprites HTML5 Canvas 下的边界矩形

转载 作者:行者123 更新时间:2023-11-29 19:31:13 24 4
gpt4 key购买 nike

我已经上传了几张图片作为 2D HTML5 Canvas 汽车游戏的 Sprite 。我一直在尝试仅使用 Sprite 的坐标来进行碰撞检测,但它工作不顺利。我以前听说过边界矩形,据我所知,它们是 sprite 下的不可见矩形,有助于碰撞检测(如果我错了请纠正我)。

我在网上看到了一些东西,比如 Element.getBoundingClientRect()。谁能帮我在我的 Sprite 下面放一些边界矩形,因为我一无所知,而且我在网上找不到任何基本教程。

Js代码:Jsbin链接:http://jsbin.com/muzulutaci/2/edit

var canvas = document.getElementById('background');
var context = canvas.getContext('2d');

//================
//ENTER: USER CAR
//================

//Uploading car sprite
var usercar = new Image();
usercar.src = "http://www.iconshock.com/img_jpg/BETA/communications/jpg/128/car_icon.jpg";

//Setting properties of car
var x = 450;
var y = 730;
var speed = 10;
var angle = -90;
var mod = 0;

function drawUserCar() {
context.clearRect(0, 0, canvas.width, canvas.height);

context.save();
context.translate(x, y);
context.rotate(Math.PI / 180 * angle);
context.drawImage(usercar, -(usercar.width / 2), -(usercar.height / 2));
context.restore();

obstacleCar1();
}

//Interval for animation
var moveInterval = setInterval(function () {
drawUserCar();
}, 30);

//=====================
//ENTER: OBSTACLE CAR 1
//=====================

//Uploading obstacle car
var obstcar = new Image();
obstcar.src = "http://www.iconshock.com/img_jpg/BETA/communications/jpg/128/car_icon.jpg";

//Setting properties of obstacle car
var x1 = 450;
var y1 = 300;
var speed1 = 5;
var angle1 = 90;
var mod1 = 0;

function obstacleCar1() {

x1 += (speed1 * mod1) * Math.cos(Math.PI / 180 * angle1);
y1 += (speed1 * mod1) * Math.sin(Math.PI / 180 * angle1);

context.save();
context.translate(x1, y1);
context.rotate(Math.PI / 180 * angle1);
context.drawImage(obstcar, -(obstcar.width / 1), -(obstcar.height / 1));
context.restore();

}

最佳答案

旋转矩形之间的碰撞检测在数学上很复杂,有多种形式:

检测2个旋转的矩形是否相交(碰撞)

要检测 2 个旋转的矩形是否发生碰撞(但不检测它们发生碰撞的位置),您可以使用分离轴定理。这里有一个很好的解释:http://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169

检测旋转的矩形在哪里发生碰撞并对矩形应用回弹

要在 2 个旋转的矩形发生碰撞时应用回弹需要一些复杂的物理学。也许最简单的方法是使用像 Box2dJS 这样的物理库。这是一个很好的 Box2dJS 演示,显示了碰撞的矩形:http://box2d-js.sourceforge.net/index2.html

示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var BB=canvas.getBoundingClientRect();
var offsetX=BB.left;
var offsetY=BB.top;

var isDown=false;
var startX;
var startY;

var PI=Math.PI;

var car1Rect,car2Rect;
var cars=[];

var Closure=(function(){
// ctor
function Closure(x,y,imageObject){
var iw=imageObject.width;
var ih=imageObject.height;
this.img=imageObject;
this.x=x;
this.y=y;
this.w=iw;
this.h=iw;
this.cx=x+iw/2;
this.cy=y+ih/2;
this.radius=Math.sqrt(iw*iw+ih*ih)/2;
this.rotation=0;
this.corners=[];
this.isDragging=false;
this.collisionType=0;

// corner angles
var w2=iw/2;
var h2=ih/2;
this.negHalfWidth=-w2;
this.negHalfHeight=-h2;
this.cornerAngles=[
Math.atan2(-h2,-w2), // top-left
Math.atan2(h2,-w2), // top-right
Math.atan2(h2,w2), // bottom-right
Math.atan2(-h2,w2) // bottom-left
];

this.rotateTo(0);

}
//
Closure.prototype.draw=function(){
this.drawImage();
this.drawBB(true);
this.drawBoundingCircle(true);
};
Closure.prototype.moveBy=function(dx,dy){
this.cx+=dx;
this.cy+=dy;
};
Closure.prototype.rotateTo=function(angle){
this.rotation=angle;
this.setCorners();
};
Closure.prototype.setCorners=function(){
this.corners.length=0;
for(var i=0;i<this.cornerAngles.length;i++){
var a=this.cornerAngles[i]+this.rotation;
var x=this.radius*Math.cos(a);
var y=this.radius*Math.sin(a);
this.corners.push({x:x,y:y});
}
};
Closure.prototype.drawBB=function(withStroke){
var p=this.corners;
var cx=this.cx;
var cy=this.cy;
ctx.beginPath();
ctx.moveTo(cx+p[0].x,cy+p[0].y);
for(var i=1;i<p.length;i++){
ctx.lineTo(cx+p[i].x,cy+p[i].y);
}
ctx.closePath();
if(withStroke){
switch(this.collisionType){
case 0:ctx.strokeStyle='gray';break;
case 1:ctx.strokeStyle='green';break;
case 2:ctx.strokeStyle='red';break;
}
ctx.stroke();
}
};
Closure.prototype.drawBoundingCircle=function(withStroke){
var p=this.corners;
var cx=this.cx;
var cy=this.cy;
ctx.beginPath();
ctx.arc(this.cx,this.cy,this.radius,0,PI*2);
ctx.closePath();
if(withStroke){
switch(this.collisionType){
case 0:ctx.strokeStyle='gray';break;
case 1:ctx.strokeStyle='red';break;
case 2:ctx.strokeStyle='red';break;
}
ctx.stroke();
}
};
Closure.prototype.drawImage=function(){
ctx.globalAlpha=0.50;
ctx.translate(this.cx,this.cy);
ctx.rotate(this.rotation);
ctx.drawImage(this.img,this.negHalfWidth,this.negHalfHeight);
ctx.setTransform(1,0,0,1,0,0);
ctx.globalAlpha=1.00;
};
// Closure.prototype.=function(){};
return(Closure);
})();


function calculateCollisionType(r1,r2){

// rough but fast circular bounds hit-test
var dx=r2.cx-r1.cx;
var dy=r2.cy-r1.cy;
var rr=r1.radius+r2.radius;
if(dx*dx+dy*dy>rr*rr){
r1.collisionType=0; // no collision
r2.collisionType=0; // no collision
return(false);
}

// hit-test the bounding rectangles
if(RectanglesIntersect(r1,r2)){
r1.collisionType=2; // bounding rectangles collide
r2.collisionType=2;
}else{
r1.collisionType=1; // circular bounds collide
r2.collisionType=1;
}

return(true);
}


$car1Angle=$('#car1Angle');
$car2Angle=$('#car2Angle');
$car1Angle.val(0);
$car2Angle.val(0);

var carCount=2;
var car1=new Image();
car1.onload=start;
car1.src="https://dl.dropboxusercontent.com/u/139992952/multple/car1.png";
var car2=new Image();
car2.onload=start;
car2.src="https://dl.dropboxusercontent.com/u/139992952/multple/car2.png";
function start(){

if(--carCount>0){return;}

car1Rect=new Closure(50,100,car1);
cars.push(car1Rect);
car2Rect=new Closure(50,250,car2);
cars.push(car2Rect);

$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUpOut(e);});
$("#canvas").mouseout(function(e){handleMouseUpOut(e);});

$car1Angle.change(function(){
car1Rect.rotateTo($(this).val()*PI/180);
draw();
});
$car2Angle.change(function(){
car2Rect.rotateTo($(this).val()*PI/180);
draw();
});

calculateCollisionType(car1Rect,car2Rect);
draw();

$('#testCollision').click(function(){
log(RectanglesIntersect(car1Rect,car2Rect));
});

}

function draw(){
ctx.clearRect(0,0,cw,ch);
car2Rect.draw();
car1Rect.draw();
}



function handleMouseDown(e){
e.preventDefault();
e.stopPropagation();

startX=parseInt(e.clientX-offsetX);
startY=parseInt(e.clientY-offsetY);

isDown=false;
for(var i=0;i<cars.length;i++){
var c=cars[i];
c.drawBB(false);
if(ctx.isPointInPath(startX,startY)){
c.isDragging=true;
isDown=true;
}
}
}

function handleMouseUpOut(e){
e.preventDefault();
e.stopPropagation();

isDown=false;
for(var i=0;i<cars.length;i++){
cars[i].isDragging=false;
}
}

function handleMouseMove(e){
if(!isDown){return;}

e.preventDefault();
e.stopPropagation();

mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);

var dx=mouseX-startX;
var dy=mouseY-startY;
startX=mouseX;
startY=mouseY;

for(var i=0;i<cars.length;i++){
var c=cars[i];
if(c.isDragging){ c.moveBy(dx,dy); }
}

calculateCollisionType(car1Rect,car2Rect);
draw();

}


///////////////////////////////////////
// Attribution for RectanglesIntersect() & isProjectedAxisCollision()
// https://github.com/jozefchutka/YCanvas/blob/master/YCanvasLibrary/libs/yoz/sk/yoz/math/FastCollisions.as
//

function RectanglesIntersect(r1,r2){

// rotated rectangle hit-test
var cx,cy,c;
//
cx=r1.cx;
cy=r1.cy;
c=r1.corners;
//
var r1p1x=cx+c[0].x;
var r1p2x=cx+c[1].x;
var r1p3x=cx+c[2].x;
var r1p4x=cx+c[3].x;
//
var r1p1y=cy+c[0].y;
var r1p2y=cy+c[1].y;
var r1p3y=cy+c[2].y;
var r1p4y=cy+c[3].y;
//
cx=r2.cx;
cy=r2.cy;
c=r2.corners;
//
var r2p1x=cx+c[0].x;
var r2p2x=cx+c[1].x;
var r2p3x=cx+c[2].x;
var r2p4x=cx+c[3].x;
//
var r2p1y=cy+c[0].y;
var r2p2y=cy+c[1].y;
var r2p3y=cy+c[2].y;
var r2p4y=cy+c[3].y;

//
if(!isProjectedAxisCollision(r1p1x, r1p1y, r1p2x, r1p2y,
r2p1x, r2p1y, r2p2x, r2p2y, r2p3x, r2p3y, r2p4x, r2p4y))
return false;

if(!isProjectedAxisCollision(r1p2x, r1p2y, r1p3x, r1p3y,
r2p1x, r2p1y, r2p2x, r2p2y, r2p3x, r2p3y, r2p4x, r2p4y))
return false;

if(!isProjectedAxisCollision(r2p1x, r2p1y, r2p2x, r2p2y,
r1p1x, r1p1y, r1p2x, r1p2y, r1p3x, r1p3y, r1p4x, r1p4y))
return false;

if(!isProjectedAxisCollision(r2p2x, r2p2y, r2p3x, r2p3y,
r1p1x, r1p1y, r1p2x, r1p2y, r1p3x, r1p3y, r1p4x, r1p4y))
return false;
//
return true;
}

function isProjectedAxisCollision( b1x, b1y, b2x, b2y, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y){
var x1, x2, x3, x4;
var y1, y2, y3, y4;
if(b1x == b2x){

x1 = x2 = x3 = x4 = b1x;
y1 = p1y;
y2 = p2y;
y3 = p3y;
y4 = p4y;

if(b1y > b2y)
{
if((y1 > b1y && y2 > b1y && y3 > b1y && y4 > b1y) ||
(y1 < b2y && y2 < b2y && y3 < b2y && y4 < b2y))
return false;
}
else
{
if((y1 > b2y && y2 > b2y && y3 > b2y && y4 > b2y) ||
(y1 < b1y && y2 < b1y && y3 < b1y && y4 < b1y))
return false;
}
return true;
}
else if(b1y == b2y){

x1 = p1x;
x2 = p2x;
x3 = p3x;
x4 = p4x;
y1 = y2 = y3 = y4 = b1y;

}else{

var a = (b1y - b2y) / (b1x - b2x);
var ia = 1 / a;
var t1 = b2x * a - b2y;
var t2 = 1 / (a + ia);

x1 = (p1y + t1 + p1x * ia) * t2;
x2 = (p2y + t1 + p2x * ia) * t2;
x3 = (p3y + t1 + p3x * ia) * t2;
x4 = (p4y + t1 + p4x * ia) * t2;

y1 = p1y + (p1x - x1) * ia;
y2 = p2y + (p2x - x2) * ia;
y3 = p3y + (p3x - x3) * ia;
y4 = p4y + (p4x - x4) * ia;
}

if(b1x > b2x){

if((x1 > b1x && x2 > b1x && x3 > b1x && x4 > b1x) ||
(x1 < b2x && x2 < b2x && x3 < b2x && x4 < b2x))
return false;

}else{

if((x1 > b2x && x2 > b2x && x3 > b2x && x4 > b2x) ||
(x1 < b1x && x2 < b1x && x3 < b1x && x4 < b1x))
return false;
}

return true;
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Red car angle:&nbsp<input id=car1Angle type=range min=0 max=360 value=0><br>
Gold car angle:&nbsp<input id=car2Angle type=range min=0 max=360 value=0><br>
<h4>Use sliders above to rotate cars.<br>Drag cars closer.<br>Bounding Circles turn green if they collide.<br>Bounding Rectangles turn green if they collide.</h4>
<br>
<canvas id="canvas" width=400 height=500></canvas>

上面的演示最好在全屏模式下观看

关于javascript - Sprites HTML5 Canvas 下的边界矩形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27454313/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com