Random movement angular - javascript

I'm currently working on a game which is based on a svg canvas as shown
and what I'm trying to do now is to allow the ball to move at random once the game starts, but I'm having difficulties coding out the random movement.
function createBall() {
const svg = document.getElementById("canvas")!,
ball = new Elem(svg, 'circle') #create the ball
.attr("cx",300).attr("cy",300)
.attr("r",8)
.attr('fill','grey');
Observable.interval(10).takeUntil(Observable.interval(4000)) #10 milliseconds until 4000 milliseconds
.subscribe( () => ball.attr("cx", 2 + Number(ball.attr("cx")))); #I'm having issue here when i subscribe as i can only allow the ball to move to the right at the moment, aside from being random
}

I think you would need a constant velocity towards a certain direction in x and y coordinates.
My suggestion would be to create two random integer values for x_velocity and y_velocity. You could try to use Math.random() and Math.floor():
function getRandomInt(min, max) {
return Math.floor((Math.random() + min) * Math.floor(max));
}
Then you will need to determine the direction, if it is negative (go left) or positive (go right):
function getDirection() {
return this.getRandomInt(0, 2) === 0? -1 : 1;
}
Use these two functions to set your x_velocity and y_velocity. The ball should now be able to go to the left, right, up, or down:
directionX = this.getDirection();
directionY = this.getDirection();
x_velocity = directionX * this.getRandomInt(1,8); // the number will be between -8 and 8 excluding 0
y_velocity = directionY * this.getRandomInt(1,8); // same here
Observable.interval(10).takeUntil(Observable.interval(4000))
.subscribe( () => {
ball.attr("cx", x_velocity + Number(ball.attr("cx"))); // the ball should go towards the left or the right
ball.attr("cy", y_velocity + Number(ball.attr("cy"))); // the ball should go up or down
);
Happy Coding! :)

Related

How to always rotate an element clockwise with normalized angle and transition?

I am trying to make a simple game in which you can rotate each element by 90 degrees on each click with some transition like 500ms. When it passes from 270 to 0 it goes in opposite direction. It is possible to achieve this by keeping incrementing the value to +Infinity, but what if I want to keep the angle normalized, from 0 to 359? How do I tell browser to use closest path to rotate an object basically going from 270 to 360 and not from 270 to 0. What if someday I exceed the integer limit and it brakes? Is it even possible? Here is an example of how it works right now.
const images = document.querySelectorAll("img")
for(const image of images) {
let rotation = 0;
image.style.transition = 'transform 500ms';
image.addEventListener('click', function() {
rotation = (rotation + 90) % 360
image.style.transform = `rotate(${rotation}deg)`
})
}
No need to mod the angle by 360. Integer limit in JS is about 9007199254740991. So if you rotate 100 times per second, it's still would last 100,000 years or so.
const images = document.querySelectorAll("img")
for(const image of images) {
let rotation = 0;
image.style.transition = 'transform 500ms';
image.addEventListener('click', function() {
rotation = (rotation + 90)
image.style.transform = `rotate(${rotation}deg)`
})
}
<img src="https://picsum.photos/200">

HTML Video currentTime not being set correctly

I have a video being used as a background of a mobile device to show a reactive animation for when the phone is rotated its works (sort of) but when the rotation requires it to loop from start to end or end to start it does not loop and I have no clue why as the value it's trying to be set as should work.
this is the function that subscribes to the gyroscope and updates the angle with some maths
this.gyroscope.watch(this.options)
.subscribe((orientation: GyroscopeOrientation) => {
// need delta time to correctly calculate angle per update
this.time.now = new Date().getTime();
this.time.delta = this.time.now - this.time.last;
if (this.videoLoaded) {
// convert radians/sec to degree/sec and times by deltaTime
const degree = 180 / Math.PI * orientation.z;
this.targetAngle -= (this.time.delta / 1000) * degree;
// lerp target angle no clipping applied
this.angle = (1 - .1) * this.angle + .1 * this.targetAngle;
// convert lerped angle into clipped 0-360
let displayAngle = this.angle % 360;
if (displayAngle < 0) { displayAngle = 360 + displayAngle; }
// convert angle to time of video round to tenths dec
this.frame = Math.round((displayAngle * this.axeVideo.duration / 360) * 10) / 10;
// set video time
this.axeVideo.currentTime = this.frame;
} else {
// clear angle as gyro spits out large values at first
this.angle = this.targetAngle = 0;
}
// update last time for deltaTime calc
this.time.last = this.time.now;
});
this is all correct maths and logically works however when testing the video is going to either edge and locking up no matter how many rotations the phone does and to "unlock" it i must rotate the phone back the same amount.
Screen Capture of issue recording is a little laggy but normally super smooth (hence why i use this solution).
It is the ion-range that has [(ngModel)] on it overriding the set time.

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)
}

Turning objects so they reset their y-rotation in Three.js

Using three.js, I'm creating a game with cars that move in a specific direction, depending on their y-rotation. An example would be 90 degrees. I use object.translateZ() to move them forward but I've run into a problem.
I'm using physijs to simulate the cars. Cars that run into each other may change their y-rotation (because of the crash) and I want to find a way for the cars to slowly change their rotation back to the original rotation like they are turning to get back on the road. Without this my city is very chaotic.
Here's the code that I'm already using (this is just part of it):
var targetRotation = 90
var rotation = car.mesh.rotation.y * 180 / Math.PI //to convert to degrees
I want to find a way to slowly change the car's rotation so it's the same as the target rotation.
Any help is appreciated! (but some sort of function would be perfect)
I've done stuff like this before in other systems (2D, not Three.js), and essentially all you want to do is gradually increment the angle until you reach something close enough to the target angle. Usually this means the float is less than the turning speed you're incrementing by (so you don't "overshoot" the value).
The amount of the increment depends on how quickly you want them to turn.
You also want to check if it's better to increase the angle or decrease (do you turn clockwise or counterclockwise) depending on if you're closer to 360 or 0. This prevents the car from turning the "long way" around. You can find this out by seeing if the difference is greater/less than 180.
We can use the modulus operator to get the "real" angle between -360/360.
var currentAngle = car.mesh.rotation.y * 180 / Math.PI; //car's angle in degrees
var targetAngle = 90; //preferred angle *this time* ;)
var turningSpeed = 1; //one degree per update (wayyy to high for real stuff, usually)
currentAngle = currentAngle % 360; //get the 0-360 remainder
if ( Math.abs(targetAngle - currentAngle) >= turningSpeed) {
var addto = 0
if (targetAngle - currentAngle < 0) {
addto = 360
}
if ( targetAngle - currentAngle + addto <= 180 ) {
currentAngle += turningSpeed;
}
else {
currentAngle -= turningSpeed;
}
}
else { currentAngle = targetAngle; } //we're close enough to just set it
car.mesh.rotation.y = ( currentAngle * Math.PI ) / 180; // back to radians!

increase speed on "bouncing" object

I don't know a lot about JS, but i have to do assignments with it. right now i have a ball that bounces from one side of the screen to the other. with every bounce the colour of the screen and the ball change. but i'd like a slight increase of speed with every bounce as well(or a random speed every time it bounces if that's easier). this is the code I have for moving, the bouncing and the colour changing now:
fill(r,g,b);
ellipse(circleX, circleY, circleSize, circleSize);
circleX += moveX;
if (circleX > width - circleSize / 2 || circleX < circleSize / 2) {
moveX = -moveX;
r = random(255);
g = random(255);
b = random(255);
}
moveX is always 5 now and changes to -5 when turning back. but i'd like it if it turned into -6 and then +7 when going forward again. or something like that at least.
I thank you guys in advance for helping me and please explain it like you're explaining it to a child.
First, lets make a function which takes a number and returns +1 for non-negative numbers (positive or 0) and -1 for negative numbers, i.e. it's sign
function sign(x) {
if (x < 0) return -1;
return 1;
}
A full implementation of sign would have a special case for 0, and is available natively in ES6
Next, when it becomes time to change moveX separate it's magnitude (absolute value) and sign, increment it's magnitude and put the two pieces back together again before flipping the sign over
moveX = -sign(moveX) * (Math.abs(moveX) + 1);
You'll want to add another test inside your collision detection code to increase the speed. If the velocity is positive, then you want to add 1. If the velocity is negative, you want to subtract 1. Your code would look something like this...
...
moveX = -moveX
if (moveX < 0) {
--moveX;
} else {
++moveX;
}
...
Keep track of how many times the circle has "bounced" and add it to the speed.
var base_speed = 5;
var bounces = 0;
var direction = 1; //positive for moving right, negative for moving left
var moveX = base_speed + bounces * direction;
circleX += moveX;
if (circleX > width - circleSize / 2 || circleX < circleSize / 2) {
direction = -direction;
bounces++;
r = random(255);
g = random(255);
b = random(255);
}

Categories