我正在编写一个简单的 2D 游戏引擎,因为我想复习我的学校数学知识。我知道也许很多人已经回答了类似的问题(我阅读了很多关于这个主题的问题和答案),但我无法管理为什么我的方法不起作用。在这个例子中,我们可以看到一个“房间”,里面有一个摄像头和两条根据摄像头方向改变方向的光线。这些光线应该代表相机视野的左右边界,并且应该与相机前面的墙壁相交。问题是当相机移动和旋转时(使用“UP”、“DOWN”、“LEFT”、“RIGHT”),有时光线会消失,即相交功能失败。有人可以帮我找到解决方案吗?这里有代码的相关部分:
function Player(x,y,angle) {
this.x = x;
this.y = y;
this.z = 30;
this.fieldOfView = {
degrees : 60,
rads : Game.utils.degree2Rad(60),
set : function (deg) {
var self = this;
self.fieldOfView.degrees = deg;
self.fieldOfView.rads = Game.utils.degree2Rad(rads);
}
};
this.angleDeg = angle;
this.angleRads = Game.utils.degree2Rad(angle);
this.rotate = function () {
/* Handle rotation and position
of the camera depending on the button pressed */
}
this.draw = function (canvas1,canvas2) {
var self = this;
var ctx1 = canvas1.getContext('2d');
var ctx2 = canvas2.getContext('2d');
/*Draw a circle on canvas1 at Game.player.x Game.player.y*/
// CODE
/*Draw a circle on canvas2 at the center of canvas*/
// CODE
/*Angles of the two rays in radians (FOV is 60°).
Add 30° to player's angle and find one,
Substract 30° to player's angle and find the other
*/
var rad1 = Game.utils.degree2Rad(Game.player.angleDeg+30);
var rad2 = Game.utils.degree2Rad(Game.player.angleDeg-30);
/*
The two Rays, defined with a point (player.x and player.y)
and a vector
*/
var _rad1 = new Ray2D(self.x,self.y,new Vector2D(Math.cos(rad1),Math.sin(rad1)));
var _rad2 = new Ray2D(self.x,self.y,new Vector2D(Math.cos(rad2),Math.sin(rad2)));
var _w = Game.walls;
var ps = [];
for(var i=0;i<_w.length;i++)
{
//FIND THE INTERSECTION POINTS
var j = _w[i];
var p =_rad1.intersectionWall(j);
if(p) {
ps.push(p);
}
var p2 = _rad2.intersectionWall(j);
if(p2) {
ps.push(p2);
}
}
if(ps.length>1)
{
// DRAW THE TWO INTERSECTION POINTS
ctx1.beginPath();
ctx1.moveTo(self.x,self.y);
ctx1.lineTo(ps[0].x,ps[0].y);
ctx1.stroke();
ctx1.beginPath();
ctx1.moveTo(self.x,self.y);
ctx1.lineTo(ps[1].x,ps[1].y);
ctx1.stroke();
//CODE
}
else {
console.log(_rad1,_rad2);
//console.log('non-p',ps[0]);
}
/*ctx1.beginPath();
ctx1.arc(self.x,self.y,2,0,Game.GLOBAL.CIRCLE);
ctx1.stroke();
ctx1.closePath();*/
},
this.update = function () {
this.rotate();
}
}
function Wall (x1,y1,x2,y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.update = function (context1,context2,player) {
};
this.draw = function (context1,context2,player) {
//CODE
}
}
function Vector2D (x,y) {
this.x = x;
this.y = y;
this.dot = function (v) {
//Dot product
return v.x*self.x+v.y*self.y;
}
this.cross = function (v) {
//cross product
return self.x*v.y-self.y*v.x;
}
}
function StraightLine2D (xo,yo,v) {
if(!(v instanceof(Vector2D)))
{
throw new Error('Invalid Argument supplied for constructor "StraightLine2D"');
}
this.xo = xo;
this.yo = yo;
this.v = v;
this.calc = function (t) {
var self = this;
return {
x : t*self.v.x + self.xo,
y : t*self.v.y + self.yo
}
}
this.intersectionLine = function (R) {
var self = this;
var x1 = R.xo;
var y1 = R.yo;
var v1 = R.v;
var _cross = self.v.cross(v1);
if(_cross == 0)
{
return null;
}
switch(true) {
case self.v.x == 0:
var t = (self.xo-x1)/v1.x;
return R.calc(t);
break;
case self.v.y == 0:
var t = (self.yo-y1)/v1.y;
return R.calc(t);
break;
default:
var t = (self.v.y*(self.xo-x1)+self.v.x*(y1-self.yo))/(-_cross);
//var t = (t1*(v1.x)+x1-self.xo)/self.v.x;
return R.calc(t);
break;
}
}
}
function Ray2D (xo,yo,v) {
if(!(v instanceof(Vector2D)))
{
throw new Error('Invalid Argument supplied for constructor "StraightLine2D"');
}
this.xo = xo;
this.yo = yo;
this.v = v;
this.calc = function (t) {
var self = this;
if(t<0) {
return null;
}
return {
x : t*self.v.x + self.xo,
y : t*self.v.y + self.yo
}
}
this.intersectionLine = function (R) {
var self = this;
var x1 = R.xo;
var y1 = R.yo;
var v1 = R.v;
var _cross = self.v.cross(v1);
if(_cross == 0.0)
{
return null;
}
switch(true) {
case self.v.x == 0:
var t = (self.xo-x1)/v1.x;
return t > 0 ? R.calc(t) : null;
break;
case self.v.y == 0:
var t = (self.yo-y1)/v1.y;
return t > 0 ? R.calc(t) : null;
break;
default:
var t1 = ((y1-self.yo)*self.v.x+self.v.y*(self.xo-x1))/(v1.x*self.v.y-v1.y*self.v.x);
var t = (t1*R.v.x+R.xo-self.xo)/self.v.x;
return t >= 0 ? self.calc(t) : null;
break;
}
}
this.intersectionWall = function (W) {
var self = this;
var R = new StraightLine2D(W.x1,W.y1,new Vector2D(W.x1-W.x2,W.y1-W.y2));
var point = self.intersectionLine(R);
if(point &&
point.x <= Math.max(W.x1,W.x2) && point.x >= Math.min(W.x1,W.x2) &&
point.y <= Math.max(W.y1,W.y2) && point.y >= Math.min(W.y1,W.y2))
{
return point;
}
return null;
}
}
编辑:我试图删除代码的不相关部分。综合不是我的素质之一,我希望现在更具可读性。