i really need help with figuring out a velocity equation to launch a player from one X Y Z location to another. from looking at other threads i created the following code (the code doesn't work)
public void vJump(Entity entity, Location loc, double time)
{
this.entity = entity;
entity.setVelocity(getV(entity.getLocation(), loc, time));
}
private Vector getV(Location p1, Location p2, double t)
{
double x = p2.getX() - p1.getX();
double y = p2.getY() - p1.getY();
double z = p2.getZ() - p1.getZ();
double gravity = -14.266;
return new Vector(getVelocity(x,gravity,t), getVelocity(y,gravity,t), getVelocity(z,gravity,t));
}
private double getVelocity(double d, double a, double t)
{
a*=-.5;
a*=Math.pow(t,2);
d-=a;
return d/t;
}
i do not know the gravity in Minecraft nor do i know the movement friction. the problem with the code above is that it doesn't go in the right direction nor does it create the parabola effect i was looking for.
based on Nick Rhodes answer i removed gravity for all but the y (in minecraft, up and down is y). and then i doubled the velocity for all planes by 2 and it ended up working! here is the code. also i found out that gravity was actually 0.1.
public void vJump(Entity entity, Location loc, double time)
{
this.entity = entity;
entity.setVelocity(getV(entity.getLocation(), loc, time));
}
private Vector getV(Location p1, Location p2, double t)
{
double x = p2.getX() - p1.getX();
double y = p2.getY() - p1.getY();
double z = p2.getZ() - p1.getZ();
double gravity = 0.1;
return new Vector(getVelocity(x,0,t), getVelocity(y,gravity,t), getVelocity(z,0,t));
}
private double getVelocity(double d, double a, double t)
{
a*=-.5;
a*=Math.pow(t,2);
d-=a;
return 2*(d/t);
}
Part of the problem lies in the fact that gravity will only come into play for the z vector. There will be no gravitational force in the x or y directions. This may explain why your code produces movement in another direction than expected.
try (assuming that t is defined as the total time of transit):
return new Vector(getVelocity(x,0,t), getVelocity(y,0,t), getVelocity(z,gravity,t));
Related
I've created a very simple form of a Cubic Bézier in Java in order to retrieve the Y value of the point retrieved given the time (t). In my implementation My first (P1) and last (P4) points are always (0, 0) and (1, 1) respectively, and I'm only going to be manipulating P1 and P2. The purpose of this is to create a modifiable curve used to retrieve a value that will be used to multiply and manipulate other values, like a difficulty ramp in video games.
I've tested my implementation using P2=(0.1, 0.1) and P3=(0.9,0.9), so the curve should effectively be a straight line, and whatever my input value (t) is, the output should mimic:
Here is my CubicBezier class:
#AllArgsConstructor
public class CubicBezier {
private static final Point P1 = new Point(0, 0);
private static final Point P4 = new Point(1, 1);
private Point p2;
private Point p3;
public double getValue(double t) {
double dt = 1d - t;
double dt2 = dt*dt;
double t2 = t*t;
Point temp = p2.copy();
return P1.copy()
.scale(dt2 * dt)
.add(temp.scale(3 * dt2 * t))
.add(temp.set(p3).scale(3 * dt * t2))
.add(temp.set(P4).scale(t2 * t))
.getY();
}
}
And my Point class:
#Data
#AllArgsConstructor
public class Point {
private double x;
private double y;
public Point(Point point) {
this.x = point.x;
this.y = point.y;
}
public Point copy() {
return new Point(this);
}
public Point set(Point point) {
this.x = point.x;
this.y = point.y;
return this;
}
public Point add(double scalar) {
this.x += scalar;
this.y += scalar;
return this;
}
public Point add(double x, double y) {
this.x += x;
this.y += y;
return this;
}
public Point add(Point point) {
return add(point.x, point.y);
}
public Point scale(double scalar) {
this.x *= scalar;
this.y *= scalar;
return this;
}
public Point scale(double x, double y) {
this.x *= x;
this.y *= y;
return this;
}
public Point scale(Point point) {
return scale(point.x, point.y);
}
}
My main method:
public static void main(String[] args) {
CubicBezier bezier = new CubicBezier(new Point(0.1d, 0.1d), new Point(0.9d, 0.9d));
double value = 0.4;
System.out.println(value + ": " + bezier.getValue(value));
}
Expected output should be:
0.4: 0.4
However, the output I receive is:
0.4: 0.36640000000000006
And I can't understand why. My getValue method is modelled using the Cubic Bézier explicit form specified on Wikipedia. Am I missing something?
Note: I'm using Lombok to remove some boilerplate. I can specify this boilerplate if necessary.
EDIT:
So it appears that my bezier curve is actually working as it should, and that I've been mistaking t as a value on the x axis, assuming that the y value of the calculated bezier curve will be in relation to the x axis. The functionality I want is that, with the resulting curve, given a value x, return the y value in relation. So in the screenshot above, where the curve is a straight line, x should equal y.
I figured out the answer to my question. There was never anything wrong with my code, the error was a lack of understanding. I had assumed that because P1, p2, p3 and P4 were all points that lay on a straight line between 0 and 1 on both the x and y axes, that no matter where they were positioned on that line, time would reflect progression identically, i.e. x would equal y.
However, because p2 and p3 are closer to P0 and P4 respectively, the progression along the curve is stretched out relative to the time.
In order for a Cubic Bézier curve to have the same progression (y) value as the time (t) value where P1 = (0, 0) and P4 = (1, 1), both inside points must be spread evenly along the curve on both axes. So p2 must be (0.33333, 0.33333) and p3 must be (0.66666, 0.66666).
An example of this problem is shown in this video here. When the points are spread apart, the resulting value is affected.
I'm trying to implement the Graham’s Scan algorithm for a convex hull in Java, and have trouble sorting the points by polar angle with respect to the point with lowest y-value.
I have found this answer and understand how to calculate the polar angle but not how to sort the points.
I have seen implementations were Collections.sort() is being used but none of them seem to work with the Point2D class which I want to use because I want to be able to have doubles as coordinates.
Basically I want to be able to sort an ArrayList<Point2D> by their polar angle to the point with the lowest y-value in the same ArrayList.
Could someone please help me with this? Thanks.
I modified the last answer to this question.
Define a new class for Point:
class Point {
private long x, y;
Point(long x, long y) {
this.x = x;
this.y = y;
}
Point() {
x = 0;
y = 0;
}
public long getX() {
return x;
}
public long getY() {
return y;
}
}
Define a new function for calculating the cross product of two vectors:
public long cross(long x1, long y1, long x2, long y2) {
return x1 * y2 - x2 * y1;
}
Let's assume that initial is the Point which has the lowest Y coordinate. Also, let's assume that List<Point> points is a list with all the other points available, but it does NOT contain the initial point.
In order to sort the list, we can use Collections.sort with the comparator:
Collections.sort(points, (a, b) -> {
long cr = cross(a.getX() - initial.getX(), a.getY() - initial.getY(), b.getX() - initial.getX(), b.getY() - initial.getY());
if (cr > 0)
return 1;
else
return -1;
});
In this solution, we used the cross product to check whether two vectors are positioned clockwise or counter-clockwise.
This solution has two benefits:
It's more precious when our coordinates are integer numbers. When we calculate angles in other solutions, we may have some errors in floating point calculations.
In other solutions we may have "division by zero", but we don't have this problem here.
Let's assume that initial is the Point2D which has the lowest Y coordinate. Also, let's assume that List<Point2D> points is a list with all the other points available, but it does NOT contain the initial point.
In order to sort the list, we can use Collections.sort with the comparator:
Collections.sort(points, (a, b) -> {
double cotanA = -(a.getX() - initial.getX()) / (a.getY() - initial.getY());
double cotanB = -(b.getX() - initial.getX()) / (b.getY() - initial.getY());
if (cotanA - cotanB < 0) {
return 1;
}
return -1;
});
Edit:
This solution might encounter a division by zero. One way to overcome this is to use a cross product. See this answer from Erfan Alimohammadi.
We are working on creating object and driver classes. I have an object class that does various things to a moving exploratory robot.
What I need to do now is create a method that returns the largest distance that the robot moved in one single move command. I also need to return the time that it took to move that distance.
Here's the relevant code for that so far:
{
private int xcoord, ycoord; //Cartesian coordinates of the robot
private int identification; //Identification number of the robot
private double rate; //Rate at which the robot explores
private double traveled; //Distance the robot has travelled
private double timeSpent; //Time spent travelling
private double longestLeg; //Longest leg of the journey
private double longestLegTime; //Time on the longest leg
//Sets up a robot with the given ID number and beginning x and y coordinates
public Robot (int id, int x, int y)
{
identification = id;
xcoord = x;
ycoord = y;
traveled = 0;
rate = 5.0;
}
//Has the robot travel to the set coordinates
public double setDestination (int x, int y)
{
double distance = Math.pow(x - xcoord, 2) + Math.pow(y - ycoord, 2);
traveled += Math.sqrt(distance);
xcoord = x;
ycoord = y;
timeSpent += Math.sqrt(distance)/rate;
return traveled;
}
//Gets the time spent travelling
public double getTimeSpent()
{
return timeSpent;
}
//Sets the rate at which the robot travels
public void setRate(double setrate)
{
rate = setrate;
}
//Returns longest leg of the robot's travels
public int getLongestLeg()
{
return longestLeg;
}
//Returns time of longest leg
public double getLongestLegTime()
{
return longestLegTime;
}
I'm not allowed to use if statements or loops yet, so it will have to be using Math.max I'm guessing. I tried using it, but it gave me an error saying that it required an int but I supplied a double.
Any suggestions would be awesome. Thanks!
If you are able, I have one final problem with the code as well. I need to create a method that would get the distance between two Robot objects. I'm not even sure how to start this one since we haven't really worked with it yet. A suggestion on how to even start this would be great. Thanks again.
To avoid casting, this should work:
longestLeg = Math.max(distance, longestLeg);
If you are getting an error about requiring an int, it probably means one of your parameters was an int when it shouldn't be. Can't be sure without seeing exactly how you were calling it, but I suspect it may have been to do with the fact getLongestLeg() is returning longestLeg as an int when it's actually a double. I would suggest changing that method to:
//Returns longest leg of the robot's travels
public double getLongestLeg()
{
return longestLeg;
}
In terms of your second question, to calculate the distance between another robot, the calcDist() method should probably look something like this:
public double calcDist(Robot other)
{
return Math.sqrt(Math.pow(this.getX() - other.getX(), 2) + Math.pow(this.getY() - other.getY(), 2));
}
If i got your question right you just wanted to use the Math.max() with Integers.
Try
(int) Math.max()
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to create simple objects, branching out from a single point object, into a line object (two points), and then into a triangle object (three points). I understood how to create the point class, though when trying to branch into the line class, I got a bit confused with how to actually go into writing a line class or triangle class using the initial point class. I need some help with going from a single point class into
I can post some code that I have done so far.
I also have read that there are already java geometry classes out there, but I want to actually create these classes to practice with OOP.
edit --- Added code below
class Point
{
private double x;
private double y;
public Point()
{
x = 0.0;
y = 0.0;
}
public Point(double x, double y)
{
this.x = x;
this.y = y;
}
public double getX()
{
return this.x;
}
public double getY()
{
return this.y;
}
public void setX(double x)
{
this.x = x;
}
public void setY(double y)
{
this.y = y;
}
public double distance(Point p)
{
return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y)
* (this.y - p.y));
}
public String toString()
{
String s = "(" + x + ", " + y + ")";
return s;
}
public boolean equals(Point p)
{
double delta = 1.0e-18;
return (Math.abs(this.x - p.x) < delta)
&& (Math.abs(this.y - p.y) < delta);
}
//-----------------Line Class--------------------//
class Line
{
private Point p1;
private Point p2;
public Line()
{
p1 = new Point (0,0);
p2 = new Point (1,1);
}
public Line(double x1, double y1, double x2, double y2)
{
p1 = new Point (x1, y1);
p2 = new Point (x2, y2);
}
public Line(Point p, Point q)
{
p1 = new Point(p.getX(), p.getY());
p2 = new Point(q.getX(), q.getY());
}
public Point getP1()
{
return this.p1;
}
public Point getP2()
{
return this.p2;
}
public void setP1(double x, double y)
{
Point p1 = new Point(x, y);
this.p1 = p1;
}
public void setP2(double x, double y)
{
Point p2 = new Point(x, y);
this.p2 = p2;
}
public boolean isParallelY()
{
double delta = 1.0e-18;
return (Math.abs(p1.getX() - p2.getX()) < delta);
}
public boolean isParallelX()
{
double delta = 1.0e-18;
return (Math.abs(p1.getY() - p2.getY()) < delta);
}
public boolean isParallel (Line line)
{
if (this.Slope() == line.Slope())
return true;
else
return false;
}
public double Slope()
{
double inf = Double.POSITIVE_INFINITY;
if(isParallelY())
return inf;
return ((p2.getY() - p1.getY()) / (p2.getX() - p1.getX()));
}
public double xIntercept()
{
return -(p1.getY() / Slope() - p1.getX());
}
public double yIntercept()
{
return p1.getY() - (Slope() * p1.getX());
}
I am still adding methods to the line class right now and have not started on the triangle class (though I was thinking of creating a triangle with 3 points rather than 3 lines. And sorry about the branching confusion, I am relatively new.
A Line has 2 Points, so any Line class will have 2 Point-attributes
Any Triangle has 3 Points, so any Triangle class will have 3 Point-attributes
You can create the constructor of these classes to ensure correct objects.
public Line(Point point1, Point point2)
{
this.point1 = point1;
this.point2 = point2;
}
and for the Triangle class
public Triangle(Line line1, Line line2, Line line3)
{
this.point1 = line1.firstpoint();
this.point2 = line2.firstpoint();
this.point3 = line3.firstpoint();
}
or
public Triangle(Point point1, Point point2, Point point3)
{
this.point1 = point1;
this.point2 = point2;
this.point3 = point3;
}
Since each class contains the right attributes you can calculate with them.
If you really want to do OOP, think about what objects exist in your domain, and what messages they understand - that's all Mr Kay ever talked about :)
In your case, you've found Points. Seems you are thinking in a 2D point, and that's why you've just used x and y coordinates. In a 2D world, what would we like to ask to a Point? It's position/coordinates, right - we already have them. What else? A distance to another Point, right. That seems to be pretty much everything a Point can do by now.
Wait - we can ask it to join another Point, creating a Line. So, maybe, doing aPoint.lineTo(anotherPoint) isn't that bad. But, hey, the important thing is we are actually creating Lines.
They consist in a pair of dots. What would we like to ask to a Line? It's lenght, of course. It's clearly the same as the distance between its points. We can ask it the distance to a Point (some mathematicians already defined it, yeah). We can ask a Line if it's parallel with another one, or if they cross. We can ask it at which point they cross. We can ask the angle formed by two lines. And, then, again, we can ask it to join with a third point, to create a Triangle.
Then we'll have a convex shape, so new fun things as area, perimeter, internal angles, external angles.
Try to think of things, concepts and definitions, and implement them as simply as you can. Try to make code as nearly as possible to the colloquial definitions of the concepts it represents. And construct new abstractions based on the previous ones.
Besides all of this, there's one thing you shall not forget: programming is modeling. Models are abstractions. OOP is about using objects to model the portion of the reality we are interested in. If you don't define the scope of what things you wish to model (as this case is just an educational activity, with no real requirements), you can spend your hole life adding methods to your objects, without much sense. Think in advance what things you would like to be able to do with your Points, Lines, Triangles, etc, and limit yourself to them.
Happy hacking :)
OK, so I'm trying to make a simple asteroids clone. Everything works fine, except for the collision detection.
I have two different versions, the first one uses java.awt.geom.Area:
// polygon is a java.awt.Polygon and p is the other one
final Area intersect = new Area();
intersect.add(new Area(polygon));
intersect.intersect(new Area(p.polygon));
return !intersect.isEmpty();
This works like a charm... if you don't care about 40% CPU for only 120 asteroids :(
So I searched the net for the famous separating axis theorem, since I'm not thaaaaaat good a the math I took the implementation from here and converted it to fit my Java needs:
public double dotProduct(double x, double y, double dx, double dy) {
return x * dx + y * dy;
}
public double IntervalDistance(double minA, double maxA, double minB,
double maxB) {
if (minA < minB) {
return minB - maxA;
} else {
return minA - maxB;
}
}
public double[] ProjectPolygon(double ax, double ay, int p, int[] x, int[] y) {
double dotProduct = dotProduct(ax, ay, x[0], y[0]);
double min = dotProduct;
double max = dotProduct;
for (int i = 0; i < p; i++) {
dotProduct = dotProduct(x[i], y[i], ax, ay);
if (dotProduct < min) {
min = dotProduct;
} else if (dotProduct > max) {
max = dotProduct;
}
}
return new double[] { min, max };
}
public boolean PolygonCollision(Asteroid ast) {
int edgeCountA = points;
int edgeCountB = ast.points;
double edgeX;
double edgeY;
for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) {
if (edgeIndex < edgeCountA) {
edgeX = xp[edgeIndex] * 0.9;
edgeY = yp[edgeIndex] * 0.9;
} else {
edgeX = ast.xp[edgeIndex - edgeCountA] * 0.9;
edgeY = ast.yp[edgeIndex - edgeCountA] * 0.9;
}
final double x = -edgeY;
final double y = edgeX;
final double len = Math.sqrt(x * x + y * y);
final double axisX = x / len;
final double axisY = y / len;
final double[] minMaxA = ProjectPolygon(axisX, axisY, points, xp,
yp);
final double[] minMaxB = ProjectPolygon(axisX, axisY, ast.points,
ast.xp, ast.yp);
if (IntervalDistance(minMaxA[0], minMaxA[1], minMaxB[0], minMaxB[1]) > 0) {
return false;
}
}
return true;
}
It works... kinda. Actually it seems that the "collision hull" of the asteroids is too big when using this code, it's like 1.2 times the size of the asteroid. And I don't have any clue why.
Here are two pictures for comparison:
http://www.spielecast.de/stuff/asteroids1.png
http://www.spielecast.de/stuff/asteroids2.png
As you can hopefully see, the asteroids in picture one are much denser than the ones in picture 2 where is use the SAT code.
So any ideas? Or does anyone knows a Polygon implementation for Java featuring intersection tests that I could use?
It looks like your second result is doing collision detection as if the polygons were circles with their radius set to the most distant point of the polygon from the center. Most collision detection stuff I've seen creates a simple bounding box (either a circle or rectangle) into which the polygon can fit. Only if two bounding boxes intersect (a far simpler calculation) do you continue on to the more detailed detection. Perhaps the appropriated algorithm is only intended as a bounding box calculator?
EDIT:
Also, from wikipedia
The theorem does not apply if one of the bodies is not convex.
Many of the asteroids in your image have concave surfaces.