Snake size not increasing after eating food? - javascript

Relevant code:
if (food.x === snake[0].x && food.y === snake[0].y) {
// increase the size of the snake
snake.push({
x: snake[snake.length - 1].x,
y: snake[snake.length - 1].y
});
where snake is an array of objects. Each object is x and y coordinates of snake position and food is an object with x and y coordinates randomly placed.
I've tried to first unshift then pop the array snake, but it didn't work.

Related

Collision check between vectors - moving vectors - HTML, JS, P5

I have created the collision check function for my player to every time when the object (in this case vector - circle) touches the player (also a vector - circle) the game is over.
I have managed to create a logic and there is a collision check working, however it's not calculating the actual distance between elements (instead of ending game when they actually touch its ending when they are some distance from each other.
Both objects are moving - obstacle is moving x+=6 and the player is following the coursor so the speed varies.
I have tried adjusting distance slightly and I have managed to end the game when the x of obstacle is touch x of the player but could not managed actually to when boarders touch. I attach the code I have below;
class Player {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(500, 500);
this.mag = 3;
this.velLerp = 0.1;
}
update() {
let mouse = createVector(mouseX - width / 2,
mouseY - height / 2);
mouse.setMag(this.mag);
this.vel.lerp(mouse, this.velLerp);
this.pos.add(this.vel);
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
console.log("GAME OVER");
return true;
}
The issue is caused by the fact that the movement of the circles is 3 (this.mag) pixel. You just get the exact point of contact by chance. Most time they are intersecting.
If a collision is detected, change the player's position slightly by an offset of this.r + obstacle.r - d:
collisionCheck(obstacle) {
let d = p5.Vector.dist(this.pos, obstacle.pos);
if (d < this.r + obstacle.r) {
let shift = p5.Vector.sub(this.pos, obstacle.pos);
shift.setMag(this.r + obstacle.r - d);
this.pos.add(shift);
console.log("GAME OVER");
return true;
}
}

Math to account for winner in RouletteWheel

I'm going to be honest with you all. Since high school ended and I've had a year away from school a lot of the math has been faded out. I am creating this roulettewheel for the page I'm doing at the moment and now I have to calculate the winner from where the ball stops.
The ball has a position of
x = Math.cos(alpha) * radius;
y = Math.sin(alpha) * radius;
Where each slice of the wheel is drawn as following.
var slice = {startAngle: deg2rad(deg), stopAngle: deg2rad(deg+sliceDeg), deg: deg};
ctx.arc(centerX, centerY, width/2, slice.startAngle, slice.stopAngle);
Where the slices are drawn as following
function drawAll(){
ctx.clearRect(0, 0, width, width); //Clear the canvas
for(var i=0; i < locations.length; i++){
drawSlice(deg, color[i]);
deg += sliceDeg;
}
}
So what I am basically trying to understand is how I am to check whether in which of the slices bounds the ball is when it stops. My thesis is that I have to check it as following.
If the angle of the ball(alpha) is within the angle created by slices[i].startAngle and -||-.stopAngle. Get that slice and alert this item. Where I am lost is basically when I am to compare the radians that the slice is represented with the x and y position that the ball is represented with. All help is greatly appreciated.
You can use the function Math.atan2(y, x) to convert cartesian coordinates back into radians.
For instance, Math.atan2(1, 1) yields 0.7853981633974483, which is 45 degrees.
You may need to fiddle with the signs of y and x, if the results seem wrong.
The ball angle is given by
atan2(Y - Cx, X - Cy)
in radians. If the angle is negative, add 2π to be in range [0, 2π).
Then floor(Angle / sliceRad) tells you the slice index.

bug when rotating vectors, creating new vectors with adjust rotation

I'm having a strange bug in the following code. Scroll down to see images for reference to this question. The program found in the images below is drawn in canvas using javascript, so please be aware that the x and y coordinates are all positive, so the y coordinates are upside down relative to the graph.
let rotateVectors = (vs, t) => {
return sortVectors(Object.keys(vs).map(v => {
console.log(vs[v].vector.direction);
let rateOfRotation = -.01 * (Math.random() * (5-1)+1);
let vector = vs[v].vector
let p = vector.magnitude;
let c = vector.coords;
let x = c.x*Math.cos(rateOfRotation) - c.y*Math.sin(rateOfRotation);
let y = c.x*Math.sin(rateOfRotation) + c.y*Math.cos(rateOfRotation);
return vector(cartesian2dCoordinate(x,y))
}));
}
The above method is called on a loop to slowly rotate vectors by some random amount, the map function returns a new vector which takes an x,y coordinate, or the 2d cartesian pair describing the rise and run of the vector.
rotateVectors returns a sorted list of all vectors (sorted by angle in degrees) in the vs object.
let vectorDirection = (c) => {
//THE ZERO VECTOR
if(c.x === 0 && c.y === 0) return 0;
//cardinal directions, vertical and horizontal
else if(c.x === 0) return c.y > 0 ? .5 : 1.5;
else if(c.y === 0) return c.x > 0 ? 0:Math.PI;
//q3
else if(c.x< 0 && c.y < 0) return (1+ (Math.atan(-1*((c.y * -1) / c.x))));
//q2
else if(c.x < 0 && c.y > 0) return (Math.PI / 180)*(180 + toDegrees(Math.atan((c.y * -1)/c.x)));
//q4
else if(c.y < 0 && c.x > 0) return (Math.PI / 180)*(toDegrees(Math.atan((c.y * -1)/c.x)));
//q1
else return Math.atan(c.y*-1/c.x);
}
This function returns a radian of the angle of a vector based on its quadrant.
Traversal zone 1
In image one, any given vector will rotate from the x plane marked in red, all the way around to the -y vertical column. S->E.
traversal zone 2, reversed direction
In image two, the vector magically teleports from the E plane to the S plane, and travels in the opposite direction. S->E, whereupon the vector teleports back to the -X plane "S" in image1.
I'm relatively new to drawing stuff with vectors. I remember a bit of trig from school, but I haven't used it in a very long time. Does anyone have an idea wwhat may be happening here? Why are my vectors teleporting, changing direction, and why do no vectors travers the null zone to the left of S of image 2, and down from S of image 1?
Thanks to samgak for the answer in the comments. I replaced the original vectorDirection function with this code. It works as expected. Vectors rotate in the direction expected, and at the rate expected.
let vectorDirection = (c) => {
//THE ZERO VECTOR
if(c.x === 0 && c.y === 0) return undefined;
else return Math.atan2(-1*c.y,c.x)
}

Moving object from A to B smoothly across canvas

I am trying to move an object smoothly from point A to point B using HTML canvas and regular javascript.
Point A is a set of coordinates
Point B is in the case the cursor location.
I made a jsfiddle of what I have so far: https://jsfiddle.net/as9fhmw8/
while(projectile.mouseX > projectile.x && projectile.mouseY < projectile.y)
{
ctx.save();
ctx.beginPath();
ctx.translate(projectile.x, projectile.y);
ctx.arc(0,0,5,0,2*Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
ctx.stroke();
ctx.restore();
if(projectile.mouseX > projectile.x && projectile.mouseY < projectile.y)
{
var stepsize = (projectile.mouseX - projectile.x) / (projectile.y - projectile.mouseY);
projectile.x += (stepsize + 1);
}
if(projectile.mouseY < projectile.y)
{
var stepsize = (projectile.y - projectile.mouseY) / (projectile.mouseX - projectile.x);
projectile.y -= (stepsize + 1);
}
}
Essentially what I can't figure out to do is to make the while loop slower (so that it appears animated in stead of just going through every iteration and showing the result).
I also can't figure out how to prevent the Arc from duplicating so that it creates a line that is permanent, instead of appearing to move from point a to point b.
Smooth animation here is really about determining how far to move your object for each iteration of the loop.
There is a little math involved here, but it's not too bad.
Velocity
Velocity in your case is just the speed at which your particles travel in any given direction over a period of time. If you want your particle to travel 200px over the course of 4 seconds, then the velocity would be 50px / second.
With this information, you can easily determine how many pixels to move (animate) a particle given some arbitrary length of time.
pixels = pixelsPerSecond * seconds
This is great to know how many pixels to move, but doesn't translate into individual X and Y coordinates. That's where vectors come in.
Vectors
A vector in mathematics is a measurement of both direction and magnitude. For our purposes, it's like combining our velocity with an angle (47°).
One of the great properties of vectors is it can be broken down into it's individual X and Y components (for 2-Dimensional space).
So if we wanted to move our particle at 50px / second at a 47° angle, we could calculate a vector for that like so:
function Vector(magnitude, angle){
var angleRadians = (angle * Math.PI) / 180;
this.magnitudeX = magnitude * Math.cos(angleRadians);
this.magnitudeY = magnitude * Math.sin(angleRadians);
}
var moveVector = new Vector(50, 47);
The wonderful thing about this is that these values can simply be added to any set of X and Y coordinates to move them based on your velocity calculation.
Mouse Move Vector
Modeling your objects in this way has the added benefit of making things nice and mathematically consistent. The distance between your particle and the mouse is just another vector.
We can back calculate both the distance and angle using a little bit more math. Remember that guy Pythagoras? Turns out he was pretty smart.
function distanceAndAngleBetweenTwoPoints(x1, y1, x2, y2){
var x = x2 - x1,
y = y2 - y1;
return {
// x^2 + y^2 = r^2
distance: Math.sqrt(x * x + y * y),
// convert from radians to degrees
angle: Math.atan2(y, x) * 180 / Math.PI
}
}
var mouseCoords = getMouseCoords();
var data = distanceAndAngleBetweenTwoPoints(particle.x, particle.y, mouse.x, mouse.y);
//Spread movement out over three seconds
var velocity = data.distance / 3;
var toMouseVector = new Vector(velocity, data.angle);
Smoothly Animating
Animating your stuff around the screen in a way that isn't jerky means doing the following:
Run your animation loop as fast as possible
Determine how much time has passed since last time
Move each item based on elapsed time.
Re-paint the screen
For the animation loop, I would use the requestAnimationFrame API instead of setInterval as it will have better overall performance.
Clearing The Screen
Also when you re-paint the screen, just draw a big rectangle over the entire thing in whatever background color you want before re-drawing your items.
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
Putting It All Together
Here is a Fiddle demonstrating all these techniques: https://jsfiddle.net/jwcarroll/2r69j1ok/3/

Particles "run away" from mouse

Im creating a simple particle experiment on canvas. Now i want them to "run away" from mouse coursor over canvas. detecting the distance from the mouse is not a problem, but how to code their behaviour?
each particle is created as following:
var particle = {
x: Math.floor(Math.random() * width),
y: Math.floor(Math.random() * height),
xVel: Math.random() * 10 - 5,
yVel: Math.random() * 10 - 5,
}
so i assume i should also save the direction somehow, and if the distance from pointer is < x, reverse the direction? maybe also save old speed, and decrease it slowly while moving away?
how to detect the direction?
Velocity (xVel, yVel, together) is a 2D vector. And so is the distance between the mouse and the particles. A vector contains both direction and magnitude. So you want a vector that is the difference between the mouse position and the particle position.
var posRelativeToMouse = {
x: particle.x - mousPosX,
y: particle.y - mousPosY
};
So small numbers of x and y mean the the particle is close to the mouse, and big mean it's far away.
Next we need to figure out how these numbers should affect the velocity of the particle. So we need 2 things.
What direction do we push them in?
We already have this, mostly. posRelativeToMouse is a vector that has the direction we want. We just normalize it, which means to set the length of the vector to 1. To do that, we divide each component by the current length of the vector. The length of this vector is always the distance to from the particle to the mouse.
var distance = Math.sqrt(
posRelativeToMouse.x * posRelativeToMouse.x +
posRelativeToMouse.y * posRelativeToMouse.y
);
var forceDirection = {
x: posRelativeToMouse.x / distance,
y: posRelativeToMouse.y / distance,
};
How hard do we push the particles?
This is an inverse of the distance. Close means a big push, far means a little push. So lets reuse our distance we calculated above.
// distance past which the force is zero
var maxDistance = 1000;
// convert (0...maxDistance) range into a (1...0).
// Close is near 1, far is near 0
// for example:
// 250 => 0.75
// 100 => 0.9
// 10 => 0.99
var force = (maxDistance - distance) / maxDistance;
// if we went below zero, set it to zero.
if (force < 0) force = 0;
Ok we have a direction, and we have the force. All that's left is to apply this to the particle velocity.
particle.xVel += forceDirection.x * force * timeElapsedSinceLastFrame;
particle.yVel += forceDirection.y * force * timeElapsedSinceLastFrame;
And assuming you are animating your position each frame by that xVel/yVel, you should now have particles being pushed away by the mouse.
you can obtain a vector v by subtracting the position of particle from position of mouse,
then you can find the magnitude of this vector my taking sqrt(x^2 + y^2)
by dividing v by magnitude, you obtain a unit vector in the direction you want your particles to go.
for instance.
suppose I have 10 particles in a list U, each has an x and y field.
I can obtain it's vector from each particle v by setting v = (xpart - mousepart, ypart - mousepart)
then you need to find the magnitude vmag by taking sqrt(vx^2 + vy^2)
then you obtain vunit = (vx / vmag, vy / vmag)
This is the vector "away from the mouse".
the rest can be left to detemining speed you want to move at, and ensuring you bounce of walls and such.
I have a similar project at github open source:
https://github.com/dmitrymakhnin/JavaParticleSystem/blob/master/Main.java

Categories