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()
Related
I'm making a game similar to agar.io where a blob goes around and eats dots. I'm making it on my phone and you control the blob with your finger to collect the dots. I noticed that when I collect a single dot some random other dots dissappearing as well. I debugged some and found out that unless you collected the dots in the order that they were added to the array, any dot with a lower array order would be destroyed. Example: if you collected the dot added to the array 7th then dots 0-6 would dissappear, bit if you collected 1 then 2 and so on then no other dots would dissappear randomly. I created another simpler example to explore this problem. Now it's a simple screen with 5 circles. You can pick up and drag and drop any circle. I noticed the same problem where you drag a circle and other circles randomly dissappear even though there is no code to make them dissappear. My code is as follows:
// Drag n' Drop //
Objects[] box;
int objCount = 5;
void setup() {
box = new Objects[objCount];
for (int i = 0; i < objCount; i++){
box[i] = new Objects(random(displayWidth),random(displayHeight),200);
}
}
void draw() {
background(170);
for (Objects boxes : box) {
boxes.display();
boxes.dragging();
}
}
class Objects {
float x, y;
float s;
Objects(float tempX, float tempY, int tempS) {
x = tempX;
y = tempY;
s = tempS;
}
void display() {
ellipse(x, y, s, s);
}
void dragging() {
if (dist(x, y, mouseX, mouseY) < 500) {
x = mouseX;
y = mouseY;
s = 300;
}
}
}
I believe my problem may lie in the loop I use to call the display function of the box object, but I cannot find out any other way to make it work. Any help us very much appreciated. Thank you for your time. PS Im using processing to run this code.
Kelton
Firstly, I'd like to thank you for I have never played with Processing before and you inspired me to download it!
There are quite a few things wrong that I'd like to point out and maybe steer you in the right direction. The main issue lies within your dragging() method you are not actually removing the objects you are just moving them to your mouse position, giving you the illusion they are being removed!
Anyway, as you said you were creating the game Agar.io, I would assume that you yourself should have your own Blob. For the sake of my Java brain I have switched what you called Objects to Blobs.
First off, the setup.
import java.util.*;
public static final int BLOB_COUNT = 10;
List<Blob> blobs = new ArrayList<Blob>();
// this is our blob, the one that displays in the middle of the screen
Blob myBlob = new Blob(mouseX, mouseY, 50);
void setup() {
size(1000, 500);
for (int i = 0; i < BLOB_COUNT; i++){
blobs.add(new Blob(random(displayWidth/2),random(displayHeight/2),50));
}
}
Notice how I am using ArrayLists rather than an array, this will make it easier for you to add and remove from the List.
Next, the draw() so this happens each frame.
void draw() {
background(170);
// refreshes the players blob wherever the cursor is!
myBlob.setX(mouseX);
myBlob.setY(mouseY);
myBlob.display();
// display the other blobs on the screen
for (Blob boxes : blobs) {
boxes.display();
boxes.dragging();
}
}
Notice, we want to update our blob to the current position of the mouse!
Lastly, the Blob class!
class Blob {
float x, y;
float size;
Blob(float tempX, float tempY, int size) {
this.x = tempX;
this.y = tempY;
this.size = size;
}
void display() {
ellipse(x, y, size, size);
}
void dragging() {
if (dist(x, y, mouseX, mouseY) < myBlob.getSize()/2) {
myBlob.setBlobSize(25);
this.x = random(displayWidth/2);
this.y = random(displayHeight/2);
}
}
void setX(float x){
this.x = x;
}
void setY(float y) {
this.y = y;
}
void setBlobSize(float size) {
this.size += size;
}
float getSize() {
return this.size;
}
}
So now, we check in the dragging() method whether the blob is close to our blob, and if it is we want to consume that blob (which increases our mass) and then we want that blob to re-spawn to another location, well that's how most Agar.io games work, but of course this is entirely up to you. There is also much more accurate ways to calculate the area of the blob and determine whether two blobs are within touching distance, but I'll leave the maths to you.
Rotating Asteroids ( Polygons )
I am trying to rotate asteroids(polygons) so that they look nice. I am doing this through multiple mathematical equations. To start I give the individual asteroid a rotation velocity:
rotVel = ((Math.random()-0.5)*Math.PI/16);
Then I create the polygon shape,
this.shape = new Polygon();
Followed by generating the points,
for (j = 0; j < s; j++) {
theta = 2 * Math.PI / s * j;
r = MIN_ROCK_SIZE + (int) (Math.random() * (MAX_ROCK_SIZE - MIN_ROCK_SIZE));
x = (int) -Math.round(r * Math.sin(theta)) + asteroidData[0];
y = (int) Math.round(r * Math.cos(theta)) + asteroidData[1];
shape.addPoint(x, y);
}
Finally, in a loop a method is being called in which it attempts to move the polygon and its points down as well as rotating them. (I'm just pasting the rotating part as the other one is working)
for (int i = 0; i < shape.npoints; i++) {
// Subtract asteroid's x and y position
double x = shape.xpoints[i] - asteroidData[0];
double y = shape.ypoints[i] - asteroidData[1];
double temp_x = ((x * Math.cos(rotVel)) - (y * Math.sin(rotVel)));
double temp_y = ((x * Math.sin(rotVel)) + (y * Math.cos(rotVel)));
shape.xpoints[i] = (int) Math.round(temp_x + asteroidData[0]);
shape.ypoints[i] = (int) Math.round(temp_y + asteroidData[1]);
}
now, the problem is that when it prints to the screen the asteroids appear to 'warp' or rather the x and y positions on some of the polygon points 'float' off course.
I've noticed that when I make 'rotVel' be a whole number the problem is solved however the asteroid will rotate at mach speeds. So I've concluded that the problem has to be in the rounding but no matter what I do I can't seem to find a way to get it to work as the Polygon object requires an array of ints.
Does anyone know how to fix this?
Currently your asteroids rotate around (0 , 0) as far as i can see. Correct would be to rotate them around the center of the shape, which would be (n , m), where n is the average of all x-coordinates of the shape, and m is the average of all y-coordinates of the shape.
Your problem is definitely caused by rounding to int! The first improvement is to make all shape coordinates to be of type double. This will solve most of your unwanted 'effects'.
But even with double you might experience nasty rounding errors in case you do a lot of very small updates of the coordinates. The solution is simple: Just avoid iterative updates of the asteroid points. Every time, you update the coordinates based on the previous coordinates, the rounding error will get worse.
Instead, add a field for the rotation angle to the shape and increment it instead of the points themselves. Not until drawing the shape, you compute the final positions by applying the rotation to the points. Note that this will never change the points themselves.
You can extend this concept to other transformations (e.g. translation) too. What you get is some kind of local coordinate system for every shape/object. The points of the shape are defined in the local coordinate system. By moving and rotating this system, you can reposition the entire object anywhere in space.
public class Shape {
// rotation and position of the local coordinate system
private double rot, x, y;
// points of the shape in local coordinate system
private double[] xp, yp;
private int npoints;
// points of the shape in world coordinates
private int[][] wxp, wyp;
private boolean valid;
public void setRotation(double r) { this.rot = r; valid = false; }
public void setPosition(double x, double y) { this.x = x; this.y = y; valid = false; }
public void addPoint(double x, double y) {
// TODO: add point to xp, yp
valid = false;
}
public void draw(...) {
if (!valid) {
computeWorldCoordinates(wxp, wyp);
valid = true;
}
// TODO: draw shape at world coordaintes wxp and wyp
}
protected void computeWorldCoordinates(int[] xcoord, int[] ycoord) {
for (int i = 0; i < npoints; i++) {
double temp_x = xp[i] * Math.cos(rot) - yp[i] * Math.sin(rot);
double temp_y = xp[i] * Math.sin(rot) + yp[i] * Math.cos(rot);
xcoord[i] = (int) Math.round(x + temp_x);
ycoord[i] = (int) Math.round(y + temp_y);
}
}
}
For a JOGL game I get very low fps, now with some testing I found out the problem is not in the JOGL part, but in pure Java calculations. I need to define a lot of float variables, which takes up 90% of the time.
I have tested for 45 float variables, where only 16 get an initial value. The rest is just float z1; float z2;, etc. This took around 5-10 milliseconds, according to System.currentTimeMillis().
But this code with the 45 floats is in a method called by a double loop. In total this method is called 49 times (7*7). All this is inside the JOGL method to draw the game in a JFrame, but because of this many float variables it takes a total of 100ms, which means only 10fps.
So basically the problem is that I have to initialize 45*49=2205 floats. Is there any way to optimize this to get a better fps?
For example, would a double be faster than a float? Or would it help to define the variables first outside the loop, and give them their value inside the loop? Does anyone know a way to make this code run faster? Thanks a lot in advance.
EDIT
As requested, here is the source code:
for (int x = -4; x < 3; x++) { // Loops 7 times
for (int y = -4; y < 3; y++) { // Loops 7 times
long t1 = System.currentTimeMillis();
float z0 = terrain.getHeight(x-1, y-1); // Simple method, but takes up about half of the time
float z1 = terrain.getHeight(x , y-1);
float z3 = terrain.getHeight(x+1, y-1);
float z4 = terrain.getHeight(x+2, y-1);
float z5 = terrain.getHeight(x-1, y );
float z6 = terrain.getHeight(x , y );
float z7;
float z8;
float z9;
float z10 = terrain.getHeight(x+1, y );
float z11 = terrain.getHeight(x+2, y );
float z12;
float z13;
float z14;
float z15;
float z16;
float z17;
float z18;
float z19;
float z20;
float z21;
float z22;
float z23;
float z24;
float z25;
float z26;
float z27;
float z28;
float z29;
float z30;
float z31;
float z32;
float z33 = terrain.getHeight(x-1, y+1);
float z34 = terrain.getHeight(x , y+1);
float z35;
float z36;
float z37;
float z38 = terrain.getHeight(x+1, y+1);
float z39 = terrain.getHeight(x+2, y+1);
float z40 = terrain.getHeight(x-1, y+2);
float z41 = terrain.getHeight(x , y+2);
float z43 = terrain.getHeight(x+1, y+2);
float z44 = terrain.getHeight(x+2, y+2);
t1 = System.currentTimeMillis() - t1;
// Some other code where I use these variables.
// Takes between 0-1 ms in total.
}
}
EDIT
I now tested the getHeight() method, and it takes up about half of the time. The seven variables which use this method add up to about 5 ms, where the total is 10. The following is the code used in getHeight():
public float getHeight(float x, float y) {
long t1 = System.currentTimeMillis();
Coordinate c = new Coordinate(x, y);
for (Entry<Coordinate, Float> e : heightMap.entrySet()) { // heightMap = HashMap<Coordinate, Float>
if (e.getKey().x == c.x && e.getKey().y == c.y) {
System.out.println("getHeight: " + (System.currentTimeMillis() - t1) + " ms");
return e.getValue();
}
}
return 0f;
}
Coordinate is a class I made myself, it has a constructor with two float parameters for x and y, and saves them public, globally in the class itself.
The reason why I am not using heightMap.get(c), is because this always throws a NullPointerException, while the code given above never reaches the last line of return 0f;.
EDIT
Found the solution to the problem in this [link] (Why are custom objects not equivalent keys for a HashMap?) question, namely that I had to add public boolean equals(Object other) and public int hashCode() to my custom Coordinate class. Now the getHeight method can work with heightMap.get(c), which removes the loop in there and makes the program a lot faster. The total (with 49 loops) takes around 1 ms now.
Please note that Full Screen Exclusive Mode must be used for some operating systems to give you enough resources.
Defining variables outside of the loop will not help, as Java optimizes your code and defining variables inside a loop actually gives Java hints to increase performance. What I think (and I can only guess, since you posted no code) is, that you may consider using an array of longs. They are very effective to work with in a loop and they're also allocated one after another in your memory, so cache can be used effectively.
To me, fillings 2025 Longs takes slightly above one millisecond, including calls to random.nextLong() method.
public Long fillLongs(int numberofLongs) {
long[] longs = new long[numberofLongs];
Random r = new Random();
long start = System.currentTimeMillis();
for (long l : longs) {
l = r.nextLong();
}
long end = System.currentTimeMillis();
return end - start;
}
Using parallel stream, this task takes even less time. Often under 1 ms.
public Long fillLongs(int numberofLongs) {
Long[] longs = new Long[numberofLongs];
List<Long> longList = Arrays.asList(longs);
Random r = new Random();
long start = System.currentTimeMillis();
longList.parallelStream().forEach(l -> {
l = r.nextLong();
});
long end = System.currentTimeMillis();
return end - start;
}
For high-performance computing in Java you might consider usi JNI (Java Native Interface) - though it requires C++ knowledge. For a quick start take a look here.
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));
Awhile back I asked a question to see if I was able to find a pair of specific points in a path; however, this time I want to know if there is a way to know all points in a path? (I couldn't find a method that did so, which is unfortunate because Java provides a way to do this, just not Android?)
The reason I ask this is because I have multiple geometric graphs and I want to compare the points to see where they intersect.
I appreciate any helpful responses
You can use PathMeasure to get coordinates of arbitrary point on the path.For example this simple snippet(that I saw here) returns coordinates of the point at the half of the path:
PathMeasure pm = new PathMeasure(myPath, false);
//coordinates will be here
float aCoordinates[] = {0f, 0f};
//get point from the middle
pm.getPosTan(pm.getLength() * 0.5f, aCoordinates, null);
Or this snippet returns an array of FloaPoints.That array involves coordinates of 20 points on the path:
private FloatPoint[] getPoints() {
FloatPoint[] pointArray = new FloatPoint[20];
PathMeasure pm = new PathMeasure(path0, false);
float length = pm.getLength();
float distance = 0f;
float speed = length / 20;
int counter = 0;
float[] aCoordinates = new float[2];
while ((distance < length) && (counter < 20)) {
// get point from the path
pm.getPosTan(distance, aCoordinates, null);
pointArray[counter] = new FloatPoint(aCoordinates[0],
aCoordinates[1]);
counter++;
distance = distance + speed;
}
return pointArray;
}
In above snippet,FloatPoint is a class that encapsulate coordinates of a point:
class FloatPoint {
float x, y;
public FloatPoint(float x, float y) {
this.x = x;
this.y = y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}
References:
stackoverflow
Animating an image using Path and PathMeasure – Android
If you have created a Path that means that in some point of your code, you know the exact (Geo)point. Why don't you put this point(s) on a ArrayList or something similar?
So for example before doing:
path.lineTo(point.x, point.y);
you can do:
yourList.add(point);
path.lineTo(point.x, point.y);
And later you can get all your points from the ArrayList.
Note you that you can take advantage of the Enhanced For Loop Syntax of ArrayList that execute up to three times faster.