How to keep same velocity with different angle - phaser-framework

I am learning game programming with Phaser and I am currently building a simple breakout game.
When the ball hits the paddle I use the following code to determine the new x velocity of the ball:
if (ball.x < paddle.x)
{
// Ball is on the left-hand side of the paddle
diff = paddle.x - ball.x;
ball.body.velocity.x = (-10 * diff);
}
else if (ball.x > paddle.x)
{
// Ball is on the right-hand side of the paddle
diff = ball.x -paddle.x;
ball.body.velocity.x = (10 * diff);
}
else
{
// Ball is perfectly in the middle
// Add a little random X to stop it bouncing straight up!
ball.body.velocity.x = 2 + Math.random() * 8;
}
This code is originally taken I believe from stackoverflow, although I cannot remember from which post I'm afraid.
The problem with this is that when the ball goes left or right at an angle, it appears faster on screen than if it goes straight up. The more pronounced the angle, the faster it goes and appears.
Does anyone know how to solve this problem?
Regards
Crouz

The speed of the ball is given by a combination of the horizontal (x) speed and vertical (y) speed, as given by Pythagoras' theorem:
z2 = x2 + y2
where overall speed would be z.
If you increase x without decreasing y appropriately, then the overall speed will also increase.
If you want the speed to remain the same, then you need to adjust y as well. Example pseudo-code:
speed = sqrt(x^2 + y^2)
x = 2 + random()*8
y = sqrt(speed^2 - x^2)
You could incorporate this into your code by calculating speed before any adjustments are made, and then adjusting y afterwards:
// Calculate overall speed
var speed = Math.sqrt(
Math.pow(ball.body.velocity.x, 2) +
Math.pow(ball.body.velocity.y, 2)
);
if (ball.x < paddle.x)
{
// Ball is on the left-hand side of the paddle
diff = paddle.x - ball.x;
ball.body.velocity.x = (-10 * diff);
}
else if (ball.x > paddle.x)
{
// Ball is on the right-hand side of the paddle
diff = ball.x -paddle.x;
ball.body.velocity.x = (10 * diff);
}
else
{
// Ball is perfectly in the middle
// Add a little random X to stop it bouncing straight up!
ball.body.velocity.x = 2 + Math.random() * 8;
}
// Adjust y to maintain same overall speed
ball.body.velocity.y = Math.sqrt(
Math.pow(speed, 2) -
Math.pow(ball.body.velocity.x, 2)
);
This will always result in a positive y, so you might need to negate it depending on which direction (up or down) you want it to be moving.

Related

Drawing a circle with a specific start point (from degree view)

the drawing algorithm which I currently use:
a_max = Pi*2 (float)(num_segments - 1.0f)/(float)num_segments;
for (unsigned int i = 0; i<=num_segments;i++)
{
const float a = (float)i / (float)num_segments * a_max;
SetPixel(centre.x + cos(a) *radius, centre.y +sin(a) *radius);
}
Works fine, but it starts drawing at (centre.x+radius, centre.y). I would like to have it to start at the top , because I want to draw a compass and zero degree is at the top, not on the right, so that I don't have to make a hacky solution.
Try rotating 90 degrees to the left before you start drawing, this should solve it for you.
A compass not only starts at "north" instead of "east" but also goes clockwise instead of counter-clockwise.
For this case, just swap sin(a) and cos(a):
x = centre.x + sin(a) * radius
y = centre.y + cos(a) * radius

OpenSCAD: inner curved edges between 2 circles

I'm not sure what to search for or how to ask the question as I can't draw. Please bear with me.
If I have a rectangle with circular end caps. I want to remove some of the edges of the rectangle so there is a smooth path all round. Kinda like of you were to stretch the ends, the middle gets thinner.
I was trying to work out the chord of a larger, outer circle until I got stuck trying to work out where the circles should touch.
I can see some relationships for trigonometry, but my brain just won't go the extra mile.
Can anyone please help point me in the right direction.
Thanks.
Here is the answer:
// Small value for CSG
Delta = 0.01;
2Delta = 2 * Delta;
$fa=1; $fs=$fa;
module roudedArm(xl=50, yt=10, zh=5, in=2, bh=0.8) {
EndRadius = yt/2; // size of outer ends
EndSpacing = xl-yt; // distance between end point radii
ArmConcavity = in; // how much in does it go in on each side
ArmThickness = zh; // height in z
// Negative curve to narrow the Arm (calculated by pythagoras)
ArmCurveRadius = (pow((EndSpacing / 2), 2) - 2 * EndRadius * ArmConcavity + pow(ArmConcavity, 2)) / (2 * ArmConcavity);
// The orthogonal distance between the middle of the Arm the point it touches the round pillar sections
ArmSectionLength = (EndSpacing / 2) * ArmCurveRadius / (ArmCurveRadius + EndRadius);
// end points
lbxcylinder(r=EndRadius, h=ArmThickness);
translate([EndSpacing, 0, 0]) lbxcylinder(r=EndRadius, h=ArmThickness);
// inner curve
difference()
{
translate([EndSpacing / 2 - ArmSectionLength, -EndRadius -ArmThickness, 0])
translate([ArmSectionLength, (EndRadius + ArmThickness),0])
lbxcube([ArmSectionLength * 2, 2 * (EndRadius + ArmThickness), ArmThickness], bh=bh);
// Cut out Arm curve
translate([EndSpacing / 2, ArmCurveRadius + EndRadius - ArmConcavity, -Delta])
lbxcylinder(r = ArmCurveRadius, h = ArmThickness + 2Delta, bh=-bh);
translate([EndSpacing / 2, -(ArmCurveRadius + EndRadius - ArmConcavity), -Delta])
lbxcylinder(r = ArmCurveRadius, h = ArmThickness + 2Delta, bh=-bh);
}
}
module lbxcube(size, bh=0.8) {
// don't support bevelling in demo
translate([-size[0]/2, -size[1]/2, 0]) cube(size);
}
module lbxcylinder(r, h, bh=0.8) {
// don't support bevelling in demo
cylinder(r=r, h=h);
}
roudedArm(xl=50, yt=10, zh=5, in=2, bh=0.8);
Thanks to Rupert and his Curvy Door Handle on Thingiverse.

Inverse-Kinematics: How to calculate angles for servos of a robotic arm to reach all possible points in a canvas?

I have a robotic arm composed of 2 servo motors. I am trying to calculate inverse kinematics such that the arm is positioned in the middle of a canvas and can move to all possible points in both directions (left and right). This is an image of the system Image. The first servo moves 0-180 (Anti-clockwise). The second servo moves 0-180 (clockwise).
Here is my code:
int L1 = 170;
int L2 = 230;
Vector shoulderV;
Vector targetV;
shoulderV = new Vector(0,0);
targetV = new Vector(0,400);
Vector difference = Vector.Subtract(targetV, shoulderV);
double L3 = difference.Length;
if (L3 > 400) { L3 = 400; }
if (L3 < 170) { L3 = 170; }
// a + b is the equivelant of the shoulder angle
double a = Math.Acos((L1 * L1 + L3 * L3 - L2 * L2) / (2 * L1 * L3));
double b = Math.Atan(difference.Y / difference.X);
// S1 is the shoulder angle
double S1 = a + b;
// S2 is the elbow angle
double S2 = Math.Acos((L1 * L1 + L2 * L2 - L3 * L3) / (2 * L1 * L2));
int shoulderAngle = Convert.ToInt16(Math.Round(S1 * 180 / Math.PI));
if (shoulderAngle < 0) { shoulderAngle = 180 - shoulderAngle; }
if (shoulderAngle > 180) { shoulderAngle = 180; }
int elbowAngle = Convert.ToInt16(Math.Round(S2 * 180 / Math.PI));
elbowAngle = 180 - elbowAngle;
Initially, when the system is first started, the arm is straightened with shoulder=90, elbow =0.
When I give positive x values I get correct results in the left side of the canvas. However, I want the arm to move in the right side as well. I do not get correct values when I enter negatives. What am I doing wrong? Do I need an extra servo to reach points in the right side?
Sorry if the explanation is not good. English is not my first language.
I suspect that you are losing a sign when you are using Math.Atan(). I don't know what programming language or environment this is, but try and see if you have something like this:
Instead of this line:
double b = Math.Atan(difference.Y / difference.X);
Use something like this:
double b = Math.Atan2(difference.Y, difference.X);
When difference.Y and difference.X have the same sign, dividing them results in a positive value. That prevents you from differentiating between the cases when they are both positive and both negative. In that case, you cannot differentiate between 30 and 210 degrees, for example.

Rotating object relative to mouse position

At the moment I'm using the dot product of the mouse position and (0, 1) to generate radians to rotate an object, in three.js
Code below, works ok but the object 'jumps' because the radian angle skips from positive to negative when the clientX value goes between window.innerWidth / 2
onDocumentMouseMove : function(event) {
// rotate circle relative to current mouse pos
var oldPos = new THREE.Vector2(0, 1);
Template.Main.mouseCurrPos = new THREE.Vector2((event.clientX / window.innerWidth ) * 2 - 1, - (event.clientY / window.innerHeight) * 2 + 1);
Template.Main.mouseCurrPos.normalize();
//Template.Main.projector.unprojectVector(Template.Main.mouseCurrPos, Template.Main.scene);
var angle = oldPos.dot(Template.Main.mouseCurrPos);
Template.Main.mousePrevPos.x = event.clientX;
Template.Main.mousePrevPos.y = event.clientY;
if (event.clientX < window.innerWidth / 2) {
Template.Main.circle.rotation.z = -angle;
}
else {
Template.Main.circle.rotation.z = angle;
}
console.log(Template.Main.circle.rotation.z);
}
However if I add this to assign the value to oldPos:
if (event.clientX < window.innerWidth / 2) {
oldPos = new THREE.Vector2(0, -1);
}
else {
oldPos = new THREE.Vector2(0, 1);
}
Then the "jumping" goes but the effect of rotation is inverted when the mouse is on the left of the window.
I.e. mouse going up rotates anti-clockwise and vice-versa which is not desired.
It's frustrating.
Also if I keep the oldPos conditional assignment and leave out the conditional negation of the angle instead, the jumping comes back.
You can see a demo here: http://theworldmoves.me/rotation-demo/
Many thanks for any tips.
Why are you using the result of the dot product as the angle (radians)? The dot product gives you the cosine of the angle (times the magnitude of the vectors, but these are a unit vector and a normalized vector, so that doesn't matter).
You could change your angle computation to
var angle = Math.acos(oldPos.dot(Template.Main.mouseCurrPos));
However, you may get the wrong quadrant, since there can be two values of theta that satisfy cos(theta) = n. The usual way to get the angle of a vector (origin to mouse position) in the right quadrant is to use atan2():
var angle = Math.atan2(Template.Main.mouseCurrPos.y,
Template.Main.mouseCurrPos.x);
This should give the angle of the mouse position vector, going counterclockwise from (1, 0). A little experimentation can determine for sure where the zero angle is, and which direction is positive rotation.

How do I create an object boundary in Three.js / WebGL?

I'm new to graphics and was wondering how I would go about creating an object boundary for my game.
Right now I have an object following my mouse. This works fine for my boundary when my ship has a rotation.z of 0. However, when I rotate the ship, the boundary has odd behavior.
I tried getting the world position of the ship and simply checking the x and y boundaries. However, the world position seems to give me a different x and y when I rotate. How can I
go about creating a boundary that works for all the rotations of my ship.
Here's my game(collisions turned off for purpose of help): http://www.cis.gvsu.edu/~chaua/CS371/WebGLProject/home.html
The behavior I'd like occurs when you don't rotate the ship.
Rotate the ship with left/right mouse.
Relevant code snippets(in render loop):
if(mouseLeftDown)
ship.rotation.z += leanSpeed;
if(mouseRightDown)
ship.rotation.z += -leanSpeed;
....
....
targetX = ((lastMouseX / window.innerWidth) * 2 - 1) * 90;
targetY = -((lastMouseY / window.innerHeight) * 2 - 1) * 60;
var worldPosition = (new THREE.Vector3()).getPositionFromMatrix(ship.matrixWorld);
if(worldPosition.x + targetX <= (randSpawnWidth/2)-500 && worldPosition.x + targetX >= -(randSpawnWidth/2)+500)
ship.translateX(targetX);
if(worldPosition.y + targetY <= (randSpawnHeight/2)-500 && worldPosition.y + targetY >= -(randSpawnHeight/2)+500)
ship.translateY(targetY);
I would appreciate any help. Thanks!

Resources