How to compare variable values from multiple objectives - java

I've just started with java so bear with me if I confuse things.
Anyway, I want to create a level that contains 4 different rooms. I've done it so that every room is a seperate object which is created in the main method.
What I want to do then is to place every room inside a level of a certain size, and if a room overlaps another it will return false. Every room is basically a block of 100x100 pixels.
I've done so that every room object stores it's location on the level when placed by assigning the (x,y) cords to 2 variables defined within the room class.
But I run into trouble when placing the second room. How do I check if the second room I want to place doesn't overlap with the others? My tought was that you check all the (x,y) variable values in all the room objects and if any of them overlaps it will return false. However I don't know how to refer to all these variables, how can I check the variables in every room object?
Thank you so much for your help!

Place the rooms that are assigned to a place in an ArrayList, so you can loop through them and compare the parameters. I suppose a room does not only have x and y coordinates, but also length and width.
// using a list of rooms that are placed on level
List<Room> assignedRooms = new ArrayList<Room>();
// create a new room (x, y, width, height)
Room newRoom = new Room(0, 0, 100, 100);
assignedRooms.add(newRoom);
// create further rooms
In order to find out whether a room overlaps with another one or not, you best loop through the remaining rooms, i.e., the ones you have already placed within the whole area and check if the x and y coordinates of the newly added room are in conflict with any of the other rooms.
for (int i = 0; i < assignedRooms.size(); i++) {
Room assignedRoom = assignedRooms.get(i);
if (assignedRoom.x < roomToAdd.x && assignedRoom.x + assignedRoom.width > roomToAdd.x)
// overlap
return false;
else if (assignedRoom.y < roomToAdd.y && assignedRoom.y + assignedRoom.height > roomToAdd.y)
// overlap
return false;
}
return true;

Related

how to add two coordinates (x,y) to a arraylist

My code reads all the pixels from the screen until it finds a pixel with the RGB value that I specified, which I managed to do, however if my screen has multiple pixels of that RGB value, I want to be able select a random pixel within that RBG value, instead of only working with the first pixel that my code finds I want to work with a random one. A workaround that I made generates a random number between 1 and 100 and everytime it checks a pixel it has a 1% chance of working with it, however this isn't the best method because of the way that my code scans the screen, (top-down, left-right) that means most of the time the pixel will end up on the upper left corner with isn't exactly random. I thought a good solution would be evertime the code goes through the if statement it stores the values x,y in a arraylist then I would get a random Index from that arraylist, but I couldn't figure out how to do that.
I appreciate any suggestions and help :)
int rng = new Random().nextInt(100) + 1;
if (color.equals(iron) && rng == 5){
if (r != 215 || g != 215 || b != 215){
Robot move = new Robot();
mousemoving.mouseGlide(x,y,1250,1000);
Runecraft.randomInt(35, 481);
move.mousePress(InputEvent.BUTTON1_DOWN_MASK);
move.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println(iron);
flag = true;
break;
how to add two coordinates (x,y) to a arraylist
Check out the Point or Point2D classes. They have exactly what you want.
Then
List<Point> points = new ArrayList<>();

Random x,y coordinate within an irregular polygon given a list of x,y-points, without being on such a corner-point nor edge

I'm trying to tackle the following use-case:
Input: A list of x,y-coordinates that will form an irregular polygon (they are guaranteed valid and lines will not intersect; it can however be concaved). Input-format is irrelevant, so I'm currently using two loose int-arrays for x and y respectively.
Output: A random x,y-coordinate within this polygon, which is NOT directly on top of a corner nor edge.
Using the following code, I have been able to tackle the random x,y-coordinate within the polygon:
// Currying Function with two int-arrays as parameters and double-pair return-type
X->Y->{
// Create a Path2D object
java.awt.geom.Path2D path = new java.awt.geom.Path2D.Double();
// Start at the first coordinate given
path.moveTo(X[0], Y[0]);
// Loop over the remaining coordinates:
for(int i=1; i<X.length; i++)
// And draw lines from corner to corner
path.lineTo(X[i], Y[i]);
// After the loop, close the path to finish the polygon
path.closePath();
// Create a Rectangle that encapsulates the entire Path2D-polygon
java.awt.Rectangle rect = s.getBounds();
// The resulting x,y-coordinate, starting uninitialized
double x,y;
// Do-while the Path2D polygon does not contain the random x,y-coordinate:
do{
// Select a random x,y-coordinate within the Rectangle
x = rect.getX() + Math.random()*rect.getWidht();
y = rect.getY() + Math.random()*rect.getHeight();
}while(!path.contains(x,y));
// After which we return this random x,y-coordinate as result:
return new double[]{x,y};
}
This all works as intended. Now I want to make sure that the random x,y-coordinate is not one of the input x,y-coordinates (this is pretty easily) AND is not on an edge/line of the Path2D. This second part I'm not sure how to tackle, and a quick google search wasn't given any useful information, hence this question.
NOTE: I know the chances that the random point is exactly on top of an edge/corner are astronomical small and could probably be ignored, but this is for a challenge, hence the need to implement it regardless.
After the tip of #Andreas in the comments to use a Line2D, I've modified the do-while to:
// The resulting x,y-coordinate, starting uninitialized
double x,y;
// Flag to indicate whether the random x,y-coordinate is on a corner or edge, starting truthy
boolean flag;
// Do-while the Path2D polygon does not contain the random x,y-coordinate:
do{
// Select a random x,y-coordinate within the Rectangle
x = rect.getX() + Math.random()*rect.getWidht();
y = rect.getY() + Math.random()*rect.getHeight();
// Set the flag to false:
flag = false;
// Loop over the pair of x,y-coordinates of the input:
for(int j=0; j<X.length; )
// Create a Line2D using the current pair of x,y-coordinates:
if(new java.awt.geom.Line2D.Double(X[j],Y[j++], X[j],Y[j])
// And if it contains the random x,y-coordinate:
.contains(x,y))
// Change the flag to true
flag = true;
}while(!path.contains(x,y) || flag);

Libgdx: How to move objects on X axis without overlapping?

I have a rectangle array holding multiple objects, moving back and forth on X axis.
Iterator<Rectangle> iter = array.iterator();
while ( iter.hasNext() ) {
Rectangle obj = iter.next();
array.get(i).x += speed * Gdx.graphics.getDeltaTime() ;
if (obj.x + obj.width > 800 || obj.x < 0) {
speed = -speed;
}
}
When the speed gets bigger, you'll start noticing the first object in the array overlapping with the other objects and pushing them apart. How to fix that?
Basically each object has
Rectangle obj = new Rectangle();
obj.x = xpos;
obj.y = ypos;
obj.width = width;
obj.height = height;
xpos += width + 4;
And has a texture, image, a sqaure, a rectange, a triangle... And each object is generated at an X position xpos different than the other. All they do is keep moving on the X axis, from x=0 till 800 and back.
What happens is that when the first object gets to 0, it tries to increase its speed again and overlapping with other objects, and then time after time, all objects keep overlapping and get further apart from each other. I want the distance between the objects to stay constant at any speed.
From what you've commented, the questions appears to be "How can I make all these blocks move together, bouncing from one edge to another". The issue being that you're getting bouncing, but they stop acting as a group.
Firstly, if you want to treat them as a group - the simplest way is to consider them as one large bounding box containing lots of smaller (inconsequential) objects. Moving that as a single object from side to side will give you the behaviour you need.
That aside, the direct answer to your question is "you're changing the direction mid-way through iteration". So in any single tick, some objects have moved left and some have moved right - meaning they stop acting as a group.
How you organise it is up to you, but this is the basic idea you need:
// assume "speedForThisFrame" is a float defined outside this function
float speedForNextFrame = speedForThisFrame
// iterate through however you want
Iterator<Rectangle> iter = array.iterator();
while ( iter.hasNext() ) {
Rectangle obj = iter.next();
obj.x += speedForThisFrame * Gdx.graphics.getDeltaTime() ;
// if it's moved out of bounds, we will change direction NEXT fame
if (obj.x + obj.width > 800 || obj.x < 0) {
speedForNextFrame = -speedForThisFrame;
}
}
// now that all movement has finished, we update the speed
speedForThisFrame = speedForNextFrame
The key thing is everything must move by the same amount, in the same direction, every frame. Changing the speed mid-update will cause them to act independently.
Note, you will still have issues when your group is larger than the bounds - or when they go over the bounds in one frame and don't fully get back the next frame. These are separate issues though and can be asked in a separate question.
I think your problem is that, caused by variations in Gdx.graphics.getDeltaTime(), the rectangles exceed your 0/800 borders by different distances.
An example:
First step:
Rect #1 x=790
Rect #2 x=780
Speed=100, DeltaTime=0.11 => DeltaX=11
After this step, Rect#1 would be at 801, Rect#2 at 791, their distance is 10.
Next step:
DeltaTime=0.12 => DeltaX=12
After this step, Rect#1 is at 789, Rect#2 at 803, their distance is 14.
Your rectangles vary their distance because they travel different distances. A possible solution would be to really bounce at the borders. So you should not only invert the speed but also take the distance a rectangle exceeded the border and let it travel this distance in the opposite direction:
So Rect#1 at 790, moving 11 pixels rightwards, should not be at 801 in the end of the step but at 799 (moving 10 pixels to the right and one to the left).

How to make a hitbox?

I'm making a game similar to mario and I've got this map generated by arrays and images. But my problem is that I don't know how to make a hitbox system for all the tiles. I've tried to have a position based collision system based on your position on the map
like this
if(xpos > 10*mapX && xpos < 14 * mapX){
ypos -= 1;
}
But I don't want to that for every wall or hole.
So is there a way to check in front, below and above the character to see if there is a hitbox there and if there is you cant move that direction or fall?
Thank you
If it's a simple 2D game, I'd suggest dividing the map into square tiles. You could store the map in the memory as a two dimensional array and during each frame check tiles adjacent to the player. Of course he can occupy as much as 4 tiles during movement, but it makes you check only up to 12 positions, which can be easily done.
Further collision checking can be done easily using image position and dimension.
Remember that there is no need to check if a static object (environment) is colliding with something, you just need to check objects that have made a move since last frame, i.e. the player and sprites.
EDIT:
Let's say you've got the following section of map (variable map):
...
.pe
ooo
where
. = nothing
p = player
o = floor
e = enemy
you also have the pair (x, y) representing tile indices (not exact position) of the player. In this case you have to do something like this:
if ("o".equals(map[y + 1, x + 1]))
//floor is under
if ("e".equals(map[y, x + 1]))
//enemy is on the right
if ("o".equals(map[y - 1, x]))
//floor is above us
If any of these conditions are met, you have to check image positions and handle collisions.
Note: clicked submit way after the last post was made...
As Mateusz says a 2D array is best for this type of game:
e.g. using chars:
0123456789012
0 ==
1 * ===
2===== =======
So in this case tileMap[8][1] == '*'. You'd probably be best using an enumeration instead of chars though e.g. Tile.SPRING for a Sonic style spring board.
If your map was made up of regular sized tiles you could say:
int xInFrontOfPlayer = playerX + PLAYER_WIDTH;
int xBehindPlayer = playerX - PLAYER_WIDTH;
Tile tileInFrontOfPlayer = getTileAtWorldCoord(xInFrontOfPlayer, playerY);
Tile tileBehindPlayer = getTileAtWorldCoord(xBehindPlayer, playerY);
...
public Tile getTileAtWorldCoord(int worldX, worldY) {
return tileMap[worldX / TILE_WIDTH][worldY / TILE_HEIGHT];
}
Where TILE_WIDTH and TILE_HEIGHT are the dimensions of your tiles in pixels. Then use similar math for yAbovePlayer and yBelowPlayer.
You might then have some logic in your game loop:
if user is pressing the "go right" key:
if the tile to the right is Tile.SPACE:
move player right
else if the tile to the right is Tile.WALL:
don't do anything
if the tile below is Tile.SPACE:
fall

Swap objects in array?

I have this array ColorObject gameGrid[][] = new ColorObject[8][8]; It's a grid of sprite objects of the type ColorObject. Each object draw a circle in different colors.
I'm selecting one of them by comparing the x and y of the touch input coordinates with the positions of all objects in a loop to get the x index and y index of the selected object in the array. I then use this index values as selectedGridPositionX and selectedGridPositionY.
I also get the object like this:
selectedColorObject = gameGrid[col][row];
Finally in a method I'm trying to swap them like this:
tempColorObject = gameGrid[selectedGridPositionX + 1][selectedGridPositionY];
gameGrid[selectedGridPositionX + 1][selectedGridPositionY] = selectedColorObject;
gameGrid[selectedGridPositionX][selectedGridPositionY] = tempColorObject;
This works almost. On screen they swap, but when I touch them, they show the values from the previously object. What could I have done wrong? I hope my question isn't too unclear?

Categories