libGDX: Get Specific Index of an Item from Multidimensional-Array Class - java

In My game I created Multidimensional-Array from com.badlogic.gdx.utils.Array Class as the following:
private static final Array<Array<Actor>> ARRAY_COLS = new Array<Array<Actor>>();
Now, In touchDown method from InputListener, How can I get a specific actor from ARRAY_COLS AND it Index? which all I have the known actor event.getTarget(); as the following:
InputListener listener = new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
return true;
});
EDIT: How Can I get index of this actor?
like that ARRAY_COLS.IndexOf(event.getTarget()); which the target is ARRAY_COLS.get(_col).get(_row); in the previous image case _col == 3; and _row == 4;

Um, event should return the specific actor that was clicked. If not, try setting actor's Touchable status. If it returns the Group actor that contains the one you need, you can always try using Actor#hit(float x, float y, boolean touchable), which takes local actor coordinates and should return an actor in the specific, clicked place. No need to store 2D array of actors, really.
Also, Actor has a setName method. Instead of a 2D array, you can use a ObjectMap<String, Actor> (also a lightweight LibGDX collection), give actors meaningful names and put the actors in the map during their initiation.
If you need a 2D array, you can use setUserObject to store the index values. I'm assuming you create the actor in nested for loops, so you can use a Vector2, Point or a simple class with two int variables storing the loop indexes. Then you can either serialize it to string and use as name or put as the user object and then retrieve it in the listener method.
For example:
public class IntPair { private final int x, y; /* Constructor, getters */ }
// Creation:
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
Actor actor = new Actor();
actor.setUserObject(new IntPair(x, y));
}
}
// Accessing index:
IntPair index = (IntPair) actor.getUserObject();

Related

Listener for ANY object value change?

Is there a way to create a listener (JavaFX) for any changes made to any of an object's field?
I have a coordinate object:
public class Coord {
public int x;
public int y;
public Coord(int aX, int aY) {
x = aX;
y = aY;
}
}
I have a component that creates a coordinate object when the mouse enters and destroys it when it exits. I've attached an invalidation listener:
this.setOnMouseEntered(event -> {
_hoverCoord = new SimpleObjectProperty<Coord>(getCoord(event.getX(), event.getY()));
_hoverCoord.addListener(redraw);
});
this.setOnMouseExited(event -> {
_hoverCoord = null;
});
When the mouse moves, I've been creating a new coordinate. Great, the invalidation fires because I'm replacing the coordinate. But this creates a whole bunch of these short-lived objects. I've resolved this by just calling the code I want directly in the mouse move, but it raised the following questions:
My first question is: Is that kind of rapid-fire object creation/destruction worth worrying about, generally? (I know that's a hard question to answer but I'm thinking in terms of garbage collection when creating tens of thousands of objects in a short time.)
My second question is: Is there a "listener" that just watches a POJO like Coord for field level changes?
My third question is: If not, is there a way to preserve Coord as a simple object and yet listen for specific field changes (without adding methods or changing the x and y from int)? I mean, no accessors for the fields.
My fourth question is: If not, how would I put in the accessors in Coord?
First, transform your Coord in a JavaFX Bean:
public class Coord{
private final IntegerProperty x = new SimpleIntegerProperty(this, "x");
private final IntegerProperty y = new SimpleIntegerProperty(this, "y");
public final void setX(int x){ this.x.set(x); }
public final int getX(){ return x.get(); }
public final IntegerProperty xProperty(){ return this.x; }
//Repeat for y.
}
Then, you may add an invalidation or change listener to the x property:
myCoordinate.xProperty().addListener(redraw);
myCoordinate.yProperty().addListener(redraw);
Now, there's a question: why do you need to listen the coordinates? If you need to compute something, you may use the helper Bindings, for instance, if you want to compute x*y each time the cursor moves, then you may use:
productProperty.bind(Bindings.createIntegerBinding(
()->coordinate.getX() * coordinate.getY(), //Compute x*y
coordinate.xProperty(), //dependency on x property
coordinate.yProperty()//dependency on y property
));
Or you may create your readonly property:
private final ReadOnlyIntegerWrapper product = new ReadOnlyIntegerWrapper(this, "product");
public Coord(){
init();
}
private void init(){
product.bind(Bindings.createIntegerBinding(
()->coordinate.getX() * coordinate.getY(), //Compute x*y
coordinate.xProperty(), //dependency on x property
coordinate.yProperty()//dependency on y property
));
}
public final int getProduct(){
return product.get();
}
public final ReadOnlyIntegerProperty productProperty(){
return product.getReadOnlyProperty();
}

How to manage hundreds of Entities efficiently?

OK so I am new am stuck on coming up with a good way of solving this problem. So I am creating an RPG top down survival game in Java using the slick2d. I have a problem when It comes to spawning items in the game. What is the best way to manage having hundreds of items... An example; I have a sub class of items called PickUpItems. For instance when a tree is destroyed by the player it spawns a PickUpItem which is just an Image with a Rectangle box for collision. What would be the best way to chose what Item to spawn without having to make hundreds of classes for each Interactive Item(Tree, bush, farming stuff etc). Should I have a item manager class? Given a name It will search a text file to get the parameters needed and create an Object then?
public void spawnPickUpItem(String type, int x, int y)
{
PickUpItem pickUpItem = null;
switch(type)
{
case"Log":
pickUpItem = new PickUpItem(type,logImage,x,y,this);
break;
case"Flint":
pickUpItem = new PickUpItem(type,flintImage,x,y,this);
break;
case"Rock":
pickUpItem = new PickUpItem(type,rockImage,x,y,this);
break;
}
This is my current attempt which works it spawns the necessary item but imagine running a switch statement with hundreds of cases each item you need an Item spawned in the game. I am sure some one can help.. THank you
You can follow the Factory Method pattern
Map<String, Image> imageRepository = new HashMap<>(); // to be filled
PickUpItem createItem(String type, int x, int y) {
Image itemImage = imageRepository.getOrDefault(type, yourDefaultImg);
return new PickUpItem(itemImage, x, y);
}
public void spawnPickUpItem(String type, int x, int y) {
PickUpItem pickUpItem = createItem(String type, int x, int y);
// further logic . . .
}

Creating an object of one class in another class?

I have two classses and I wonder why I always get an error when I try to create an object of class "Knoten" in a method of class "Graph".
Class Graph
public class Graph
{
static Knoten[] knotenliste;
public void punktHinzufuegen(int x, int y){
for(int i=0;i<Gui.zaehler;i++){
knotenliste[i]=new Knoten(x,y);
}
}
}
Class Knoten:
public class Knoten{
int xPos;
int yPos;
public Knoten(int x,int y){
xPos=x;
yPos=y;
}
}
Every time I call method punktHinzufuegen I get an error. Thanks for helping..
Your problem is a very easy problem to solve, so I'll give a short explanation/solution.
What your current problem is, is that you are not defining your knotenliste.
You should define it as the following field:
private static Knoten[] knotenliste = new Knoten[Gui.zaehler];
I would suggest that you do not use a static value but start working with either a fixed ArrayList (in order to index your graph points) or a Queue. Both of those can be found on the Java documentation if you're intested in reading about them.
What I would have done is the following:
public class Graph {
private final ArrayList<Knoten> knotenliste = new ArrayList<>(Gui.zaehler);
public void punktHinzufuegen(int x, int y) {
for (int i = 0; i < Gui.zaehler; i++) {
// Keep in mind that the List#add(int index, E element) will
// shift all the elements previously in the array to the right.
knotenliste.add(i, new Knoten(x, y));
}
}
}
With this you do not only stop abusing the static keyword, but you also have a more flexible Collection to save your Knoten in.
You haven't initialized your array and I think you are getting NullPointerException while adding elements. You need to initialize it before adding elements to it
static Knoten[] knotenliste = new Knoten[<SOME_INT_VALUE>];

Best way to reference multiple (unknown number of) sprites in libgdx (Android)?

Im working on a game in which multiple "notes" (sprites) are generated.
The notes are created at random. Each of them has a random velocity and are created in a different thread. The Notes class is a child of the sprite class. It has 2 properties and 1 method:
vel - a Velocity2 object holding the x and y component on the
velocity of the note object
pos - a Vector2 object holding the x and y coordinates of the note object.
changepos() - a method that changes the position based on the velocity of the object
(I cannot post the code of that class due to privacy reasons)
I currently have a static class "NoteStack", which can hold up to 64 references to Notes objects.
public class NoteStack {
public Notes[] note_array;
public int stack_len;
public NoteStack(){
note_array = new Notes[64];
stack_len = 0;
}
public void push(Notes n){
if(stack_len<64){
note_array[stack_len] = n;
stack_len++;
Gdx.app.log("push", "pushed");
}
}
public void delete_note(int pos){
if(note_array[pos] != null){
note_array[pos] = null;
for(int i = pos; i<stack_len; i++){
note_array[pos] = note_array[pos+1];
}
note_array[stack_len] = null;
stack_len = stack_len - 1;
}
}
}
Here's the code for my "update" function
public void update(float d, SpriteBatch b){
core.draw(b);
for(int i = 0; i< noteStack.stack_len; i++){
Gdx.app.log("update", "Update function running" + i);
noteStack.note_array[i].changePos(d);
noteStack.note_array[i].draw(b);
// scr_w - screen width , scr_h - screen height
if(noteStack.note_array[i].pos.x > scr_w || noteStack.note_array[i].pos.x < 0 || noteStack.note_array[i].pos.y > scr_h || noteStack.note_array[i].pos.y < 0){
noteStack.delete_note(i);
}
}
}
The issue (as you may see) is that whenever a note object from NoteStack gets removed (i.e. the delete_note method is called), other Notes objects in the array are affected.
Hence my question: What is the best way to reference multiple sprite (note) objects in LibGDX?
Generally speaking in programming, you should never implement own "classic" datastructures, only if it's really necessary and you can't use or extend a collection type, because the standard implementations are well programmed and tested, so those are safer to use.
In your case, I would use libGDX Array. That class has add, get, size methods, and if you really want to, you can extend the Array class to have an update function.
But in short, if you replace public Notes[] note_array; with public Array<Notes> note_array = new Array<>(true, 64); and use get and remove and size for iterating and managing the collection that should work.

Check if elements of different ArrayLists share position

I am programming a probe that moves through a 2D board in Java. To do this, I have two ArrayLists of Integer that contain the path that the probe has followed. The first ArrayList contains the x-coordinate, and the second one, the y-coordinate. What I would like to do is check whether the next tile of the movement has been visited or not, this is, whether the new x-coord and the new y-coord are in the corresponding ArrayList and share the same position.That way, if the new tile has been visited, I wouldn't move there. How could I possibly do this? I have tried with indexOf and lastIndexOf, but it doesn't work as each coordinate can be repeated an indefinite number of times. I also tried .contains but it didn't work either as I need that it is contained in both arrays in a specific position.
Any help would be appreciated.
First of all Java is object oriented so you should use objects. Why are you storing a coordinate in two separate arrays?
You can define your own type:
class Position implements Comparable<Position> {
public final int x;
public final int y;
Position(int x, int y) { this.x = x; this.y; }
#Override public int compareTo(Position other) { ... }
#Override public boolean equals(Object other) { ... }
#Override public int hashCode() { ... }
}
Then with this you can do whatever you want, for example
Set<Position> visited = new HashSet<Position>();
Map<Position, Integer> visitedWithSpecificPositionInPath = new HashMap<Position, Integer();
and so on.
A pretty messy approach would be to find all indexes of matching x-coordinates and for each index found check whether the y-coordinate for the given index is equal to the y in question.
So given coordinates x, y and array lists visitedX and visitedY you could do something like this:
public static boolean isVisited(int x, int y){
for(int i = 0; i < visitedX.size(), i++){
if(visitedX.get(i) == x){
if(visitedY.get(i) == y){
return true;
}
}
}
return false;
}
But as Jack has mentioned you should reconsider your data structure as looping over the complete x-coordinates list is not very efficient (though you could reduce limits of outer for loop with usage of visitedX.indexOf(x) and visitedX.lastIndexOf(x) ).

Categories