I'm working on a simple "parking type" of game where the user is driving around in a car and has to park it a specified spot.
While it was actually working, the only problem is that I need to find out in what direction the car has been parked.
I don't want the user to just randomly park the car, but the car should be facing upwards or downwards.
I tried using this check to see what rotation the car had, but this seems a bit too complex
var relativeRot = this.rotation % 360;
if((this._speed <= 0.02 && this._speed >= -0.02) && ((relativeRot <= 5 && relativeRot >= 355) || (relativeRot >= 175 && relativeRot <= 185) || (relativeRot <= -175 && relativeRot >= -185) || (relativeRot <= -5 && relativeRot >= -355))) {
Would there be an easier way to check this? There should be a small margin of 5 degrees because it doesn't have to be perfect.
You can simplify it a bit by taking modulo 90 degrees:
var relativeRot = this.rotation % 360;
if (Math.abs(this._speed) <= 0.02) {
var cornerRot = (relativeRot + 360) % 90; // should be positive
if (Math.abs(cornerRot - 45) >= 40) {
// consider car parked...
}
}
Related
I am a beginner with THREE.js and currently have a animation that spins a 3D model around its Y axis but for the website I am creating I need to rotate it back to origin during the timespan of 90 frames. I have tried using a various different code snippets but the problem is that it seems to work half the time and the other half it totally messes it up. I believe that it messes up more if I let it spin for a while.
Here is my current code for the rotation:
//angle
angle = ((room.rotation.y * 180) / Math.PI) % 360;
total_deg = room.rotation.y;
//for calculating the lap:
if(angle > 0) {
positiv = true;
} else {
positiv = false;
}
if(angle < last_angle) {
direction = "down";
} else {
direction = "up";
}
if(direction == "up" && positiv == true) {
lap = 1;
} else if(direction == "down" && positiv == true) {
lap = 2;
} else if(direction == "down" && positiv == false) {
lap = 3;
} else if(direction == "up" && positiv == false) {
lap = 4;
}
if(last_lap == 4 && lap == 1) {
room.rotation.y = 0;
}
last_angle = ((room.rotation.y * 180) / Math.PI) % 360;
//rotating it back depending on what lap it currently is on
if(lap == 4) {
room.rotation.y += -total_deg / 90;
}
if(lap == 3) {
room.rotation.y += -(Math.PI - Math.abs(total_deg)) / 90;
}
if(lap == 2) {
room.rotation.y += (Math.PI - Math.abs(total_deg)) / 90;
} else {
room.rotation.y -= total_deg / 90;
}
//reset the rotation when the room has spun a lap - don't know why this is works but seems to fix some of the rotation problems
if(last_lap == 4 && lap == 1) {
room.rotation.y = 0;
}
Have been stuck with this problem for days so any help would be appreciated
I hope I'm understanding your objective properly but to me it seems that there may be some confusion with degrees and radians as the units. Three.js uses radians, but I'm seeing 360 in your code which I'm unsure about.
Anyway this code seems like what you're trying to do, notice how it divides 2 pi (one rotation in radians) into 90 frames.
var i=0;
function update( event ) {
//angle
if(i++<90){
this.rotation.y += 2*Math.PI/90;
}
}
I figured it out using a Quaternion of the objects first rotation and rotating to that later. This example was very helpful: https://threejs.org/examples/#webgl_math_orientation_transform
Well, I tried making a camera system by just moving everything else in the opposite direction when the player gets to a certain portion of the screen, but it doesn't work. What's broken is that it's checking collisions with every single platform and then checks for the velocity to see if it's 0 or not. If it's not, then it's going to move them, but if it is, it stops, but not all of them. How do i fix this?
The white lines represent the area where the player can move freely , it's like a deadzone for the camera enter image description here
`
if(platform.position.y + platform.height > player.position.y && platform.position.y < player.position.y + player.height - 7)
{
if(player.position.x + player.width - 20 > platform.position.x && player.velocity.x > 0 && player.position.x < platform.position.x)
player.velocity.x = 0
else if(player.position.x + 20< platform.position.x + platform.width && player.velocity.x < 0 && player.position.x > platform.position.x)
player.velocity.x = 0
}
if(player.position.x > canvas.width/2 && player.velocity.x > 0)
platform.position.x -= player.speed
else if(player.position.x < canvas.width/3 && player.velocity.x < 0)
platform.position.x += player.speed
}
`
I have this code
if ($('input#grommet').is(':checked')) {
if (width <= 96) {
var grommetQTY = 4;
} else if (width > 96) {
grommetQTY = (Math.floor(width / 24));
grommetQTY = grommetQTY - 4;
grommetQTY = grommetQTY * 2;
grommetQTY = grommetQTY +4;
}
}
and I need to add 2 to the grommetQTY for each whole 24 inches (2 feet) over 96 width. Is there a way to do this?
What this is attempting to accomplish is giving the pricing for a banner. We add 2 more grommets at 2 feet intervals, but because this is custom sizing, it could be 96 feet wide, and I don't want to have to write an else if statement for each two foot interval. I am hoping there is a way to only add two to the quantity everytime the width goes another 24 inches over the standard 96 inch width so if width is 96 or less, qty is 4, at 120 its 6, at 144 its 8, etc
Rather than coming up with the equation for this, here is a for loop that will do what you need:
var grommetQTY = 0;
for(var i = 96; i < n; i++)
if(i%24 == 0)
grommetQTY += 2;
where n is the length. This is terrible inefficient and could be sped up by just doing:
var grommetQTY = 0;
for(var i = 96; i < n; i+=24)
grommetQTY += 2;
This is nicer but still not ideal. The ideal solution in your case would be an equation.
P.S - The equation is Math.floor( Math.max((n - 96), 0) / 24 ) * 2 + 4 if I understand you correctly.
You could do something like this:
var extra = width - 96
var grommetQTY = 4;
if (extra > 0) {
grommet += Math.floor((extra / 24)) * 2;
}
The variable extra holds, as the name implies, extra length that you would want to take into consideration. If it's 0 or below that means it's 96 and under.
Then, for extra > 0 you could alternatively change it to extra >= 24 as any extra value less than 24 will return 0.
Math.pow(2, grommetQTY) * (Math.floor(96 / 24))
2 to the grommetQTY for each whole 24 inches in 96. Is that what you need?
Math.pow(a, b) gives a to the power of b
Edit:
var qty = (Math.floor(n / 24)) * 2
Where n is the pixels (96 in your example).
Edit:
var qty = 4 + ((width > 96) ? ((Math.floor((width - 96) / 24) * 2) : 0);
Is that it?
I need to evenly distribute a bunch of axis-aligned sliding rectangles constrained by a maximum width/height and by some horizontal/vertical coordinates depending from the position of the sliding shapes itself. Rectangles are constrained in one direction, can slide along the other axis, may not overlap and not step over as well.
This question is based on: How to implement a constraint solver for 2-D geometry? and Spektre's well accepted proposal for a force-driven constraint solver.
The whole structure is build as usual as a graph where the rectangles represent the nodes.
Now, i need to check the size of each rectangle to get the correct force calculation and to avoid overlap, but i have some trouble to understand how a force field could be applied to a 2-D shape, and how the distance between two rectangles shall be calculated. Maybe the vertices or the sides?
Relevant code is in the function Solver.solve() below, where s.Z represent respectively the height of a shape for the horizontal ones, and the width for the vertical ones:
for(var i=0, l=sliders.length; i<l; i++) {
var si = sliders[i];
for(var j=i+1, k=sliders.length; j<k; j++) {
var sj = sliders[j];
if(si._horizontal == sj._horizontal) {
// longer side interaction
if(si._horizontal == 1) {
a0 = si.X + si.a; a1 = sj.X + sj.a;
b0 = si.X + si.b; b1 = sj.X + sj.b;
x0 = si.Y; x1 = sj.Y;
} else {
a0 = si.Y + si.a; a1 = sj.Y + sj.a;
b0 = si.Y + si.b; b1 = sj.Y + sj.b;
x0 = si.X; x1 = sj.X;
}
if(((a0 <= b1) && (b0 >= a1)) || ((a1 <= b0) && (b1 >= a0))) {
x0 = x1 - x0;
if((si.ia >= 0) && (x0 < 0.0) && ((fabs(si.x0) < si.Z) || (fabs(si.x0) > fabs(x0)))) si.x0 = -x0;
if((si.ia >= 0) && (x0 > 0.0) && ((fabs(si.x1) < si.Z) || (fabs(si.x1) > fabs(x0)))) si.x1 = -x0;
if((sj.ia >= 0) && (x0 < 0.0) && ((fabs(sj.x0) < sj.Z) || (fabs(sj.x0) > fabs(x0)))) sj.x0 = +x0;
if((sj.ia >= 0) && (x0 > 0.0) && ((fabs(sj.x1) < sj.Z) || (fabs(sj.x1) > fabs(x0)))) sj.x1 = +x0;
}
// shorter side interaction
if(si._horizontal == 1) {
a0 = si.Y - si.Z; a1 = sj.Y + sj.Z;
b0 = si.Y + si.Z; b1 = sj.Y + sj.Z;
x0 = si.X; x1 = sj.X;
} else {
a0 = si.X - si.Z; a1 = sj.X + sj.Z;
b0 = si.X + si.Z; b1 = sj.X + sj.Z;
x0 = si.Y; x1 = sj.Y;
}
if(((a0 <= b1) && (b0 >= a1)) || ((a1 <= b0) && (b1 >= a0))) {
if(x0 < x1) {
x0 += si.b; x1 += sj.a;
} else{
x0 += si.a; x1 += sj.b;
}
x0 = x1 - x0;
if(si.ia >= 0) {
var sa = this.sliders[si.ia];
if((sa.ia >= 0) && (x0 < 0.0) && ((fabs(sa.x0) < sa.Z) || (fabs(sa.x0) > fabs(x0)))) sa.x0 = -x0;
if((sa.ia >= 0) && (x0 > 0.0) && ((fabs(sa.x1) < sa.Z) || (fabs(sa.x1) > fabs(x0)))) sa.x1 = -x0;
}
if(sj.ia >= 0) {
var sa = sliders[sj.ia];
if((sa.ia >= 0) && (x0 < 0.0) && ((fabs(sa.x0) < sa.Z) || (fabs(sa.x0) > fabs(x0)))) sa.x0 = +x0;
if((sa.ia >= 0) && (x0 > 0.0) && ((fabs(sa.x1) < sa.Z) || (fabs(sa.x1) > fabs(x0)))) sa.x1 = +x0;
}
}
}
}
}
// set x0 as 1D vector to closest perpendicular neighbour before and x1 after
for(var i=0, l=sliders.length; i<l; i++) {
var si = sliders[i];
for(var j=i+1, k=sliders.length; j<k; j++) {
var sj = sliders[j];
if(si._horizontal != sj._horizontal) {
// skip ignored sliders for this
var ignore = false;
for(var n=0, m=si.ic.length; n<m; n++) {
if(si.ic[n] == j) {
ignore = true;
break;
}
}
if(ignore === true) continue;
if(si._horizontal == 1) {
a0 = si.X + si.a; a1 = sj.X - sj.Z;
b0 = si.X + si.b; b1 = sj.X + sj.Z;
x0 = si.Y;
} else {
a0 = si.Y + si.a; a1 = sj.Y - sj.Z;
b0 = si.Y + si.b; b1 = sj.Y + sj.Z;
x0 = si.X;
}
if(((a0 <= b1) && (b0 >= a1)) || ((a1 <= b0) && (b1 >= a0))){
if(si._horizontal == 1) {
a1 = sj.Y + sj.a;
b1 = sj.Y + sj.b;
} else {
a1 = sj.X + sj.a;
b1 = sj.X + sj.b;
}
a1 -= x0; b1 -= x0;
if(fabs(a1) < fabs(b1)) x0 = -a1; else x0 = -b1;
if((si.ia >= 0) && (x0 < 0.0) && ((fabs(si.x0) < si.Z) || (fabs(si.x0) > fabs(x0)))) si.x0 = +x0;
if((si.ia >= 0) && (x0 > 0.0) && ((fabs(si.x1) < si.Z) || (fabs(si.x1) > fabs(x0)))) si.x1 = +x0;
if(sj.ia < 0) continue;
var sa = sliders[sj.ia];
if((sa.ia >= 0) && (x0 < 0.0) && ((fabs(sa.x0) < sa.Z) || (fabs(sa.x0) > fabs(x0)))) sa.x0 = -x0;
if((sa.ia >= 0) && (x0 > 0.0) && ((fabs(sa.x1) < sa.Z) || (fabs(sa.x1) > fabs(x0)))) sa.x1 = -x0;
}
}
}
}
How shall be the force calculation for rectangular shapes, to get from the force field an evenly distribution, i.e. such as the distance between rectangles will be the largest possible? Think like the rectangles are really hot and must be spaced at most, with respect to their custom x/y constraints.
Any help will be greatly appreciated.
EDIT:
Sample: https://plnkr.co/edit/3xGmAKsly2qCGMp3fPrJ?p=preview
If I get this question right OP asks for set of rules for driving the sliders so the final simulation state is leading to valid solution.
So here is my approach it is really recapitulation of my solver code from linked answer in OP but it would not fit in there as I already hit the 30 KByte limit and I feel it needs a bit more explaining then just commented code so here it is:
Forces
To ensure equal spacing as much as possible you need to change the rules a bit (apart from real physics) so you are accounting only the nearest obstacle to driving Force instead of all of them as in real world. Also the force is affected only by distance and not weighted also by area of contact/overlap as most physical forces do (electrostatic included).
So during iteration of i-th slider (Yellow) find the distances to closest obstacle in all 4 directions (Red):
And compute the driving force which has to be scaled with distance. Does not really matter if linearly or not but for evenly spaced obstacles from left/right or up/down should be the resultant force zero. Scaling changes mostly the dynamics behavior. The final outcome is affected by it only in states where constrains blocks the movement to achieve even spacing. So you can use for example any of these:
F = c * (d1-d0)
F = c * (d1^2 - d0^2)
F = c * (1/d1^2 - 1/d0^2)
Where c is some magnitude coefficient and d0,d1 are the 2 closest obstacle distances in the same axis.
Now from this you will obtain 2 forces (one for each axis)
Fx - horizontal axis force
Fy - vertical axis force
In a nutshell that is it. But there is a problem with the constrains. For example selected slider (Yellow) is vertical. That means it can move only in x axis. So you put the Fx driving force to it. The Fy force should drive its parent slider (Blue) which is horizontal and can move in y axis (if not fixed of coarse).
This introduce a problem because that slider can also have its own Fy so you should always select only the strongest force from each side. That means you need to remember both distances/forces from each side and select always the smallest distance or |highest| force from each side.
That is where the x0,x1 variables come from they hold the min distance in movement able axis to nearest obstacles (from child included) and only after computation of all sliders are converted to Fx,Fy driving forces.
To detect neighbors and collisions I recognize 3 types of interaction
perpendicular which is between horizontal and vertical slider (bottom interaction on image)
wide parallel which is between two sliders of the same type contacting with its longer sides (left,right interaction on image)
short parallel which is between two sliders of the same type contacting with its shorter sides (top interaction on image)
Limits and coefficients
I also introduced some speed limits and coefficients (not just for dumping to avoid oscillations). The speed and acceleration limits affects the solution time and stability. There is also another reason to use them (I do not do) and that is to preserve the order of sliders so they do not skip through each other. That can be done by simply limiting the top speed so per single iteration any slider will not move more then the half of thickness of sliders. So in case of collision the collision routine will kick in.
I am skipping that in my code because my config is set so the order of sliders is consistent with its index number. So if I detect that any slider is on left side of some tested slider while its index is higher it means it has skipped and I handle it by restoring last position instead... This is cheap hack and will not work in complex sets where are many child sliders in chain not just one.
Feedback
Due to constraints sometimes your driving force can get lost (traveling to fixed or stuck parent slider) in case this behavior corrupts the result you should propagate opposite force the other way around too to the neighbor it caused it. For simple constructs is this not necessary as the driving force it already contain but for more complicated children chains It could pose a possible threat (but that is my wild thinking and I may be wrong in this).
In nature this is provided by integrating force from all of the neighboar objects instead of just the closest ones but that would lead to non equal spacing I think.
The code im using works fine, except for the Z position.
The maximum distance is aquired at an angle of around 53 degrees, instead of the 45 it should be.
I made my own toDegree and toRadian function, because js interprets sin and cos from a Radian points of view.
Any help?
function Bullet(I) {
I.zVelocity = Math.sin(toRadians(turretpitch)) * 5;
}
second part:
bullets.forEach(function (bullet) {
bullet.zVelocity -= 0.05;
bullet.z += bullet.zVelocity;
if (bullet.x > bgImage.width || bullet.x < 0 ||
bullet.y > bgImage.height || bullet.y < 0 ||
bullet.z < 0) {
bullet.explode();
}
}
);