首先,我将在下面发布的一些 JavaScript 代码中出现“超出最大调用堆栈大小”错误,我不确定它来自哪里。我不认为我在递归调用任何东西,而且我环顾四周找不到任何其他错误原因。我正在使用 Chrome 来执行程序,我可以从控制台中得到的唯一细节是“Vector Vector Vector Vector Vector Vector Vector...”等。我认为这意味着 Vector 函数正在递归调用自身,但是,再一次,我不知道发生在哪里。因此,首先,这是 Vector 函数:
function Vector(top,left) { //a vector constructor, with all necessary vector operations
this.top = top; //the 'top' component, which points down
this.left = left; //the 'left' component, which points right
this.in = 0; //the 'in' component, which points out of the screen
this.magnitude = Math.sqrt(this.top*this.top+this.left*this.left); //the magnitude of the vector
this.reverse = new Vector(-this.top,-this.left); //the vector that points opposite of this vector
this.unit = this.Scale(1/this.magnitude); //the unit vector pointing in this vector's direction
this.Scale = Scale; //multiplying vectors by a constant
this.Add = Add; //easier vector addition
this.Subtract = Subtract; //and subtraction
this.Dot = Dot; //a dot product operation
this.Cross = Cross; //the cross product of two planar vectors; it returns the 'in' component of the resulting vector
this.Project = Project; //the projetion of the parameter vector onto this vector
function Scale(scalar) {return new Vector(scalar*this.top,scalar*this.left);}
function Add(vector) {return new Vector(this.top+vector.top,this.left+vector.left);}
function Subtract(vector) {return new Vector(this.top-vector.top,this.left-vector.left);} //the abovedescribed methods
function Dot(vector) {return this.top*vector.top+this.left*vector.left;}
function Cross(vector) {return this.top*vector.left-this.left*vector.top;}
function Project(vector) {return this.Scale(this.Dot(vector)/Math.pow(this.magnitude,2))}
}
var zeroVector = new Vector(0,0);
这是完整的代码。随意完全忽略它,尽管也许有些东西对你来说是显而易见的,而这些东西对我来说是无可挑剔的。
<!DOCTYPE html>
<html>
<head>
<title>temp</title>
</head>
<body>
<canvas
id="canvas"
height="768px"
width="1366px"
style="position:fixed;top:0px;left:0px;"
/>
</body>
<script>
/*------------------------------------------------------------Composition Center--------------------------------------------------*/ {
window.onload = run; //it'll start running as soon as it's started up
var interval; //the interval variable for the 'run' function
function run() {
interval = setInterval(function() {
for (i=0; i!=0; i++) {
var Point = point;
var vPrime = zeroVector;
var netForce = zeroVector;
for (j=0; j!=0; j++) {
var Edge = edge;
updateCollision(Point,Edge);
}
updatePosition(Point);
updateVelocity(Point);
draw();
}
},16);
}
/*---------------------------------------------------------------------------------------------------------------------------------*/ }
/*-------------------------------------------------------------Physics Engine------------------------------------------------------*/ {
//--Constructors--//
function PointObject(mass,top,left) { //a point object
this.mass = mass; //mass
this.position = new Vector(top,left); //position
this.velocity = zeroVector; //velocity
this.near = nullEdge; //a memory tool which stores the edge the point is close to
}
function Rectangle(top,left,height,width) { //a rectangle that'll be solid, but not affected by gravity or anything
this.position = new Vector(top,left);
this.height = height; //self-explanatory
this.width = width;
}
function Edge(start,end) {
this.start = start; //the start point (vector)
this.end = end; //end point (vector)
this.vector = end.Subtract(start); //the vector pointing from the start to the end point of the edge
this.RUN = new Vector(this.vector.left,-this.vector.top).unit; //the RIGHT pointing UNIT NORMAL vector to the edge vector
this.rightPermeable = false; //whether or not the edge can be passed through from the right to the left
this.leftPermeable = true; //or from the left to the right
}
//--Objects--//
var base = new Rectangle(3/4*768,33,768/4,1300); //the main base solid
var point = new PointObject(1,base.position.top-201,1366/2); //the point object at the center of this whole ordeal
var edge = new Edge(new Vector(base.position.top,base.position.left+base.width),base.position); //a test edge. they'll be auto-assembled later
var nullEdge = new Edge(zeroVector,zeroVector);
var deltaT = .01; //standard time interval
//--Loop o' Physics--//
//Update Collision
function updateCollision(Point,edge) { //check if any points are crossing edges and deal with that
var startToPoint = Point.position.Subtract(edge.start); //the vector from the start point of the edge to the tested point
if (edge.rightPermeable && edge.vector.Cross(startToPoint) < 0) {return "Negatory.";} //if it could only approach from a permeable side, stop testing
if (edge.leftPermeable && edge.vector.Cross(startToPoint) > 0) {return "Negatory.";}
var projection = edge.vector.Project(startToPoint); //the projection of that vector onto the edge vector
if (projection.Dot(edge.vector) < 0) {return "Negatory.";} //if it's not pointing in the same dircetion as the edge vector, it's not gonna hit the edge
var distance = startToPoint.Subtract(projection); //the normal vector to the edge that points to the Point
var velocity = distance.Project(Point.velocity); //the component of the point's velocity orthogonal to the edge
if (distance.Dot(velocity) >= 0) {return "Negatory.";} //if the orthogonal velocity component is pointing 'to the point,' it won't collide
var specificT = distance.magnitude/velocity.magnitude; //the time it'll take for the point to hit the edge, if it continues with it's current velocity
if (deltaT <= specificT) {return "Negatory.";} //if the point can't move far enough to cover the distance, it won't collide
//at this point, the collision will happen
Point.near = edge; //have the point remember that it collided with this edge, so it won't have to be totally re-tested for normal forces
Point.position = Point.position.Add(Point.velocity.Scale(specificT)).Add(distance.Scale(.0001)); //move the point just a wee bit away from the edge
vPrime = Point.velocity.Add(velocity.reverse); //impulse away the velocity orthogonal to the edge
Point.velocity = Point.velocity.Scale(0); //zero the current velocity
}
//Update Position
function updatePosition(Point) {Point.position = Point.position.Add(Point.velocity.Scale(deltaT));} //d=vt, essentially
//Update Velocity
function updateVelocity(Point) { //via forces
var gravity = new Vector(20,0); //gravity... hobviously
netForce = netForce.Add(gravity); //add up all the current forces to get the right normal force
if (Point.near != nullEdge) { //calculating normal force, so it needs to be near an edge
var startToPoint = Point.position.Subtract(Point.near.start);
var projection = Point.near.vector.Project(startToPoint); //same stuff as earlier
var distance = startToPoint.Subtract(projection);
if (distance.magnitude <= .01) { //if it's very near to the edge
normalForce = distance.Project(netForce.reverse); //exert enough force to cancel anything going into the edge
if (normalForce.Dot(distance) > 0) {netForce = netForce.Add(normalForce);} //if it is indeed going into the edge
} else if (distance.magnitude > 1) {Point.near = nullEdge;} //it's not near the edge any more
}
Point.velocity = Point.velocity.Add(netForce.Scale(deltaT/Point.mass)); //v=at, essentially
}
/*---------------------------------------------------------------------------------------------------------------------------------*/ }
/*----------------------------------------------------Graphics----------------------------------------------------------------------*/ {
var c = document.getElementById("canvas").getContext("2d"); //the means for drawing all this
PointObject.prototype.Draw = function() { //the draw method for point objects
c.fillStyle = "#000000"; //a black square with the point at its center pixel
c.fillRect(this.position.left-2,this.position.top-2,5,5);
}
Rectangle.prototype.Draw = function() { //draw method for rectangles
c.fillStyle = "#c0c0c0"; //a grey rectangle; the position is the top left corner
c.fillRect(this.position.left,this.position.top,this.width,this.height);
}
function draw() { //draws everything
c.clearRect(0,0,1366,768); //clear the screen
base.Draw(); //paint stuff
point.Draw();
}
/*----------------------------------------------------------------------------------------------------------------------------------*/ }
/*------------------------------------------------------------Math Tools-------------------------------------------------------------*/ {
//--Vector Tools--//
function Vector(top,left) { //a vector constructor, with all necessary vector operations
this.top = top; //the 'top' component, which points down
this.left = left; //the 'left' component, which points right
this.in = 0; //the 'in' component, which points out of the screen
this.magnitude = Math.sqrt(this.top*this.top+this.left*this.left); //the magnitude of the vector
this.reverse = new Vector(-this.top,-this.left); //the vector that points opposite of this vector
this.unit = this.Scale(1/this.magnitude); //the unit vector pointing in this vector's direction
this.Scale = Scale; //multiplying vectors by a constant
this.Add = Add; //easier vector addition
this.Subtract = Subtract; //and subtraction
this.Dot = Dot; //a dot product operation
this.Cross = Cross; //the cross product of two planar vectors; it returns the 'in' component of the resulting vector
this.Project = Project; //the projetion of the parameter vector onto this vector
function Scale(scalar) {return new Vector(scalar*this.top,scalar*this.left);}
function Add(vector) {return new Vector(this.top+vector.top,this.left+vector.left);}
function Subtract(vector) {return new Vector(this.top-vector.top,this.left-vector.left);} //the abovedescribed methods
function Dot(vector) {return this.top*vector.top+this.left*vector.left;}
function Cross(vector) {return this.top*vector.left-this.left*vector.top;}
function Project(vector) {return this.Scale(this.Dot(vector)/Math.pow(this.magnitude,2))}
}
var zeroVector = new Vector(0,0);
/*-----------------------------------------------------------------------------------------------------------------------------------*/ }
</script>
</html>
无论如何,第二件事是关于我如何编写 Vector 构造函数的一些位,这可能会以某种方式导致我的错误。在不同的地方,我在函数的属性和方法中使用了“new Vector()”,我不知道这是否非法。我想我以前做过没有错误,但我不确定。
另外,对于“幅度”、“反向”和“单位”属性,我应该将它们改写为方法吗?我认为它们在创建时被锁定在向量的幅度/反向/单位向量中,因此如果更改顶部或左侧属性,它们将返回不正确的值。我还没有改变它们的唯一原因是它们让我印象更深的是属性而不是方法,只是在概念上。它还没有引起任何问题或任何事情;就是想。
如果你想在 JSFiddle 或其他类似的东西上这样做,我很乐意为你效劳。