I have a method which takes in 4 floats and modifies the value. Now I would like to set the floats of the parent class to the value that the method took in. Some code:
public void influence(float x, float y, float w, float h){
x += 5; y += 5; w += 5; h += 5;
}
Now that would be called from the parent class like this:
float x = 5, y = 5, w = 5, h = 5;
influence(x, y, w, h);
I would like to set the floats in the parent to the modified method. I know I could return a float[] and then manually set the floats of the parent class to that array but is there a better way to do this? I could also use a class like Rect but that would be like an array.
Java does not have a way to pass a reference to a primitive. However, in your situation it would probably be better to avoid it anyway: it appears that the four variables are related to each other.
When several variables are related, they should be instance variables of a single object. Your object probably looks like a rectangular box that has the origin of (x, y), height h, and width w. Make a class for it, and let the method change that class, or return a new instance:
class Rect {
private final float x, y, w, h;
public float getX() { return x; }
public float getY() { return y; }
public float getW() { return w; }
public float getH() { return h; }
public Rect(float x, float y, float w, float h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
Then you can write a method returning a new Rect
public Rect influence(Rect inputRect) {
...
}
or make Rect mutable, and let influence modify its values.
You can't change primitives in Java like that because everything in Jave is passed by value - but you can store the value in an array and pass it:
public void influence(float[] arr){
for (int i=0; i<arr.length; i++){
arr[i] += 5;
}
}
Related
So I have the code below but it caused java.lang.StackOverFlowError.
I guess maybe creating an new object inside the second constructor may
have caused an infinite loop or something. But I don't fully understand
why this happened. Could someone explain it to me? I'd appreciate it!
private double x;
private double y;
private double z;
private double[] elements;
/**
* Creates a 3D vector from an array
* #param v array containing 3 components of the desired vector
*/
public Vector3(double[] v) {
this(v[0], v[1], v[2]);
}
/**
* Creates a 3D vector from 3 numeric scalar components
* #param x x coordinate
* #param y y coordinate
* #param z z coordinate
*/
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
/**
* Clones an existing vector
* #param old an existing Vector3 object
*/
public Vector3(Vector3 old) {
x = old.x;
y = old.y;
z = old.z;
elements = new double[3];
elements[0] = x;
elements[1] = y;
elements[2] = z;
}
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
I'm not sure what you're up to do, but it seems you're calling the Vector3 constructor in itself. This is causing the infinite loop.
In the constructor
public Vector3(double x, double y, double z) {
this(new Vector3(x, y, z));
}
you are calling the same constructor again and again (i.e. new Vector3(x, y, z)). That causes the SOE. This happens before the copy constructor with the call to this(...) even has a chance.
Assuming the following class
public class Vector3 {
// No need for an array. Or if you want an array, discard the doubles.
double x;
double y;
double z;
public double getX() { return x; }
public double getY() { return y; }
public double getZ() { return z; }
}
the correct way to build up constructors is the following:
1) Start with a constructor that builds up a whole instance with all elementary data:
public Vector3(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
2) If you want to add some other convenience constructors, do it his way:
public Vector3(double[] elements) {
this(elements[0], elements[1], elements[2]);
}
3) A copy constructor can be handled the same way:
public Vector3(Vector3 origin) {
this(origin.getX(), origin.getY(), origin.getZ());
}
All the other constructors can be built by calling the first constructor!
I have a class
public class Coordinates {
public int x,y,z;
public Coordinates (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
}
In another class' method I want to get access on the coordinates, but I have to do the same long code for each coordinate x,y and z. Is there a way to use variables for the parameters such as :
Coordinates coords0 = new Coordinates(1, 2, 3);
Coordinates coords1 = new Coordinates(4, 1, 3);
Coordinates coords2 = new Coordinates(5, 1, 3);
Coordinates coords3 = new Coordinates(1, 1, 3);
Coordinates coords4 = new Coordinates(1, 2, 0);
Set<Coordinates> set = new HashSet<Coordinates>();
set.add(coords0);
set.add(coords1);
set.add(coords2);
set.add(coords3);
set.add(coords4);
int sum = 0;
for (int i = 0; i < 3; i++) {
String param = "";
if(i == 0) param = "x";
if(i == 1) param = "y";
if(i == 2) param = "z";
Iterator<Coordinates> it = set.iterator();
while(it.hasNext()) {
Coordinates currentCoords = it.next();
sum += currentCoords.param;
}
}
This does not work obviously, but is there a way to achieve something similar to this ?
As far as I understand, the problem is that you must apply the same code to a collection of coordinates, and this same code must be done for all the x of the coordinates, then to all the y of the coordinates, then for all the z of the coordinates.
So you probably need a method looking like this:
private void complexCode(Collection<Coordinates> collection, ToIntFunction<Coordinates> axisAccessor) {
// ...
for (Coordinates c : collection) {
int axis = axisAccessor.applyAsInt(c);
//...
}
// ...
}
You would then call your function three times using
complexCode(collection, coordinates -> coordinates.x);
complexCode(collection, coordinates -> coordinates.y);
complexCode(collection, coordinates -> coordinates.z);
Your current attempt is pretty close, only you don't need a param variable, println (and based on a comment, eliminate the i value). Like,
Coordinates coords = new Coordinates(1, 2, 3);
System.out.println("Coordinate x is " + coords.x);
System.out.println("Coordinate y is " + coords.y);
System.out.println("Coordinate z is " + coords.z);
or format it a little differently, and override toString() in Coordinates. Oh, and fix the constructor.
public class Coordinates {
public int x, y, z;
public Coordinates(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
#Override
public String toString() {
return String.format("x=%d, y=%d, z=%d", x, y, z);
}
}
Then you could print it like
Coordinates coords = new Coordinates(1, 2, 3);
System.out.println("Coordinate " + coords);
What you want is a getter method. It is a good idea to create setter methods as well. Heres what they look like for x. You'll need to make similar methods for y and z.
public int getX(){
return x;
}
public void setX(int newX){
x = newX;
}
you create these in your Coordinates class then from your other class you can do
if(i == 0) param = coords.getX();
You can use reflection like this:
int paramInt = Coordinates.class.getField(param).getInt(coords);
System.out.println("Coordinate "+param+" is "+paramInt);
Don't.
Here's the code for the class GameObject.java:
package com.badlogic.androidgames.gamedev2d;
import com.badlogic.androidgames.framework.math.Rectangle;
import com.badlogic.androidgames.framework.math.Vector2;
public class GameObject {
public final Vector2 position;
public final Rectangle bounds;
public GameObject(float x, float y, float width, float height) {
this.position = new Vector2(x,y);
this.bounds = new Rectangle(x-width/2, y-height/2, width, height);
}
}
Code for Rectangle.java:
package com.badlogic.androidgames.framework.math;
public class Rectangle {
public final Vector2 lowerLeft;
public float width, height;
public Rectangle(float x, float y, float width, float height) {
this.lowerLeft = new Vector2(x,y);
this.width = width;
this.height = height;
}
}
Code snippet for Vector2.java:
package com.badlogic.androidgames.framework.math;
public Vector2(float x, float y) {
this.x = x;
this.y = y;
}
And a code snippet for SpatialhashGrid.java:
package com.badlogic.androidgames.gamedev2d;
import java.util.ArrayList;
import java.util.List;
import android.util.FloatMath;
public class SpatialHashGrid {
List<GameObject>[] dynamicCells;
List<GameObject>[] staticCells;
int cellsPerRow;
int cellsPerCol;
float cellSize;
int[] cellIds = new int[4];
List<GameObject> foundObjects;
public int[] getCellIds(GameObject obj) {
int x1 = (int)FloatMath.floor(obj.bounds.lowerLeft.x / cellSize);
int y1 = (int)FloatMath.floor(obj.bounds.lowerLeft.y / cellSize);
int x2 = (int)FloatMath.floor((obj.bounds.lowerLeft.x + obj.bounds.width) / cellSize);
int y2 = (int)FloatMath.floor((obj.bounds.lowerLeft.y + obj.bounds.height) / cellSize);
if(x1 == x2 && y1 == y2) {
if(x1 >= 0 && x1 < cellsPerRow && y1 >= 0 && y1 < cellsPerCol)
cellIds[0] = x1 + y1 * cellsPerRow;
else
cellIds[0] = -1;
cellIds[1] = -1;
cellIds[2] = -1;
cellIds[3] = -1;
}
Whenever I read any Java book they always mention the Law of Demeter. Isn't the line :
int x1 = (int)FloatMath.floor(obj.bounds.lowerLeft.x / cellSize);
violating this law? Since I never used convention like this, I can't seem to understand what does this line mean? How can 3 objects be used in the same line with the dot(.) operator?
int x1 = (int)FloatMath.floor(obj.bounds.lowerLeft.x / cellSize);
The above line is an assimilation line of the following:
Rectangle bounds1 = obj.bounds;
Vector2 lowerLeft1 = bounds1.lowerLeft;
float xtemp = lowerLeft1.x;
int x1 = (int)FloatMath.floor(xtemp / cellSize);
Instead of declaring separate variables, the developer chose to cascade them into one line. Since they are public variables, they can be accessed via the dot operator, viz. object.variable.
It might be that Information hiding is not quite a requirement in the example.
class A {
public int b;
}
A a = new A();
int c = a.b;
The dots mean access the member named. In my case access the member b of the object a.
It's rarely seen because it involves directly accessing the member variable of an object, which is almost always bad practice.
In short, Law of Demeter suggests that you should only "talk to your immediate friends; don't talk to strangers."
In your example, the statement obj.bounds.lowerLeft.x breaks this principle, because there instead of only accessing properties of the obj variable, also a distant variable in the object graph (x) is read directly.
This is possible because Java supports chaining calls to member variables (and non-void methods). However, "talking to strangers" like this is an anti-pattern because it makes refactoring your code difficult; small changes like renaming variables can break code in other classes that use the variable directly
I have created a custom Path2D class to draw an H-shaped "calliper" on screen, for a project I am doing. I want to drag and eventually resize the calliper on screen. I have managed to get the Path2D set up so I can draw the calliper, and the code looks like this:
Declaration and Constructor:
public class Calliper extends Path2D.Double
{
// X and Y coordinates of all six points on Calliper
double cX1, cX2, cX3, cX4, cX5, cX6;
double cY1, cY2, cY3, cY4, cY5, cY6;
// Width and Height
double cWidth;
double cHeight;
public Calliper(double x, double y, double w, double h)
{
cWidth = w;
cHeight = h;
cX1 = x;
cY1 = y;
cX2 = x;
cY2 = y + (h/2);
cX3 = x;
cY3 = y + h;
cX4 = x + w;
cY4 = y;
cX5 = cX4;
cY5 = cY4 + (h /2);
cX6 = cX4;
cY6 = cY4 + h;
build();
}
build() method (used to draw the path) and setCalliper() method, used to redefine the coordinates, or width, height:
private void build()
{
// Draw the path for the calliper
moveTo(cX1, cY1);
lineTo(cX2, cY2);
lineTo(cX3, cY3);
moveTo(cX2, cY2);
lineTo(cX5, cY5);
moveTo(cX4, cY4);
lineTo(cX6, cY6);
}
public void setCalliper(double x, double y, double w, double h)
{
// Rebuild the calliper using different x,y coordinates, or
// different width/height
cWidth = w;
cHeight = h;
cX1 = x;
cY1 = y;
cX2 = x;
cY2 = y + (h/2);
cX3 = x;
cY3 = y + h;
cX4 = x + w;
cY4 = y;
cX5 = cX4;
cY5 = cY4 + (h /2);
cX6 = cX4;
cY6 = cY4 + h;
build();
}
I have created a class to draw this calliper on the screen, which it will do, however if I try to drag the calliper around the screen, it doesn't erase the original shape as I drag, so I get a long trail of shapes left behind. I thought I had omitted super.paintComponent(g) from my paintComponent(Graphics g) method, but even with it in there the code still does not work.
My drag method looks like this:
#Override
public void mouseDragged(MouseEvent ev)
{
double mx = ev.getX();
double my = ev.getY();
if (dragging)
{
calX = mx - offsetX;
calY = my - offsetY;
cal = setCalliper(calX, calY, calW, calH);
repaint();
}
}
If I change the line cal = setCalliper(calX, calY, calW, calH); above to read cal = new Calliper(calX, calY, calW, calH); then it works, but I have been told I shouldn't do it this way.
Any ideas why it doesn't work as expected?
The setCalliper() directly calls the build method, a method which appends new points to all the previous points added to the Path2D - so each time mouseDragged is called more points are added to the Path. Try calling reset() before calling build() (or call reset in the build method before the moveTo/lineTo calls).
I need a method to get the points of the circle, I have one that I found online but unfortunately I'd like to add a boolean filled to it:
public static Location[] getCylinderAt(Location loc, int r, int height) {
ArrayList<Location> list = new ArrayList<>();
int cx = loc.getBlockX();
int cy = loc.getBlockY();
int cz = loc.getBlockZ();
World w = loc.getWorld();
int rSquared = r * r;
for (int x = cx - r; x <= cx + r; x++) {
for (int y = cy - height; y <= cy + height; y++) {
for (int z = cz - r; z <= cz + r; z++) {
if ((cx - x) * (cx - x) + (cz - z) * (cz - z) <= rSquared) {
list.add(new Location(w, x, y, z));
}
}
}
}
return list.toArray(new Location[list.size()]);
}
I can't really get my head around the maths involved in this and have been searching through non minecraft sources to create my own but to no avail.
Ideally I'd like to be able to change the method to this:
public static Location[] getCylinderAt(Location loc, boolean filled, int r, int height)
Thanks guys! If you like I can remove all of the minecraft references, but I didn't think it'd be necessary as a Location is basically a Vector with a few added minecraft only variables!
Thanks for reading :)
Are you looking for a way to compute pixels on the rim of a circle, as opposed to those inside, for the case where filled is false? If so, have a look at the midpoint circle algorithm. It describes how a circle can be drawn in a raster image.