Slick2d collision detection with Tiles using rectangles - java

i'm quite stuck. Before I do anything, heres the code:
if(inAir&&!falling&&!jumping){
if(py<600){
if (!(isBlocked(xminusd, py) || isBlocked(xminus, py + 32 - 1))) {
falling=true;
}else{
py-=2;
inAir=false;
}
}
}
for(int g = 0;g<Map.r.size();g++){
if(rect.intersects(Map.r.get(g))||Map.r.get(g).contains(rect)||rect.contains(Map.r.get(g))||Map.r.get(g).intersects(rect)){
System.out.println("Intersecting!");
inAir= false;
hasjumped=false;
onPlat = true;
falling = false;
jumping = false;
py-=4;
break;
}else{
onPlat = false;
if(inAir==false&&!onPlat){
inAir = true;
onPlat = false;
}
}
}
Now the problem is, i'm trying to make collision detection with a certain type of tile, by creating rectangles for each tile, and if the player collides with it it stops all movement.(falling wise at least). But i've run into a problem. I've used an array list, to create all my rectangles, and i'm using a for loop to check each rectangle. Problem is, if it checks a rectangle and i'm not colliding with that rectangle currently, it immidiatly starts falling, then resetting, because it finds the rectangle i'm colliding with. The problem is im using a for loop to cycle through each rectangle... I'm really stuck on how to do collision detection with platform tiles. Anyone have any help to provide? Please be descriptive.

It doesn't look like it matters which rectangle you are colliding with so try abstracting by making a function that returns true or false if it is colliding with any block and put that in your else if statement. that way if you are still colliding it wont start falling while cycling through the rest of your blocks
Something like
...
if(colliding())
{
//stop falling
}
else
{
//start falling
}
....
boolean colliding(){
for(int g = 0;g<Map.r.size();g++){
//check for collision if true return true
}
return false;
}
EDIT:
The reason this works is because as you are going through the for loop it keeps the object falling while it determines that it should stop. By moving the falling logic away from the collision logic we can determine if it is colliding and then take the appropriate action.

Related

Jumping difficulty in Slick2D

I have researched how to implement a rudimentary gravity system in slick2d. Here is the code that I have (This is in the update function):
if (input.isKeyDown(Input.KEY_UP)) {
spressed = true; //Has the UP key been pressed?
}
if (spressed) {
if (!sjumping) {//if so, are we already in the air?
Sub_vertical_speed = -1.0f * delta;//negative value indicates an upward movement
sjumping = true;//yes, we are in the air
}
if (sjumping) { //if we're in the air, make gravity happen
Sub_vertical_speed += 0.04f * delta;//change this value to alter gravity strength
}
Sub.y += Sub_vertical_speed;
}
if (Sub.y == Sub.bottom){//Sub.bottom is the floor of the game
sjumping = false;//we're not jumping anymore
spressed = false;//up key reset
}
Here is where the problem arises. When I press the up key, the sprite jumps and comes down normally, but pressing the up key again does nothing. I originally thought it was cause I didn't reset spressed, so I added the line to set it to false, but you can still only jump once. :/
It looks like your Sub.y needs to be Clamped to your Sub.bottom so it doesn't go above it. Try:
if(Sub.y >= Sub.bottom) {
Sub.y = Sub.bottom;
sjumping = false;
spressed = false;
}
I've done something similar before, and my assumption here is that Sub.y never equals Sub.bottom. Depending on the y position and the vertical speed, the object's y position will never be exactly the value of Sub.bottom. The code below will test for this:
if (Sub_vertical_speed + Sub.y > Sub.bottom){ //new position would be past the bottom
Sub.y = Sub.bottom;
sjumping = false; //we're not jumping anymore
spressed = false; //up key reset
}

Near perfect collision in LibGdx Java

I am trying to get the collision in my game to be exactly perfect. What I am testing is if you hit a wall with the player, you come to a stop. I only implemented the collision code for when the player hits the left side of a wall(when the wall is on the right side of the player). Here is the code.
if(entityOnRight){
if(player.getPositionCorner(SquareMapTuples.BOTTOM_RIGHT).x -
ent.getPositionCorner(SquareMapTuples.BOTTOM_LEFT).x > -.9f)
player.setMovementBooleans(false, false, false, false);
else
player.setMovementBooleans(true, false, false, false);
}
Note: If I go very slow, it will stop the player where I desire it to be stopped, but going fast, it won't do the collision the way I want
Essentially, the code states if the wall is on the right side, it will check the bottom right corner of the rectangle of the player, subtract the bottom left corner of the wall, and check if the distance between the two is 0.001. 0.001 is almost an unnoticeable distance, hence why I used that value. Here is the code for player.setMovementBooleans
public void setMovementBooleans(boolean canMoveRight, boolean canMoveLeft, boolean canMoveUp, boolean canMoveDown){
this.canMoveRight = canMoveRight;
if(canMoveRight == false && moveRight)
vel.x = 0;
}
The canMoveRight boolean in the Player class (not in parameters) is what allows you to be able to move, moveRight is when you are trying to move right. Here is some code that will better explain how these booleans interact:
//If you clicked right arrow key and you're not going
//Faster then the max speed
if(moveRight && !(vel.x >= 3)){
vel.x += movementSpeed;
}else if(vel.x >= 0 && !moveRight){
vel.x -= movementSpeed * 1.5f;
System.out.println("stopping");
//Make sure it goes to rest
if(vel.x - movementSpeed * 1.5f < 0)
vel.x = 0;
}
and:
if(Gdx.input.isKeyPressed(Keys.D) && canMoveRight)
moveRight = true;
else
moveRight = false;
So to give a summary, if you click the "D" key, it allows you to start moving. However if the boolean canMoveRight is false, it won't move you. Here is an image showing what happens (The player is yellow, the wall is green)
As you can see, the player goes much further then I want it to. It should stop at this point:
Any help with figuring out how to accomplish this is extremely appreciated!
Maybe the way you tried it is a bit too complicated :-). I suggest a simpler way from scratch: make the map and the player a com.badlogic.gdx.math.Rectangle instance. Now, in the following part of the code you make a check, whether after the move the player would still be inside the map, if yes then allow the move, if not, then don't allow:
if(Gdx.input.isKeyPressed(Keys.D){
float requestedX, requestedY;
//calculate the requested coordinates
Rectangle newPlayerPositionRectangle = new Rectangle(requestedX, requestedY, player.getWidth(), player.getHeight());
if (newPlayerPositionRectangle.overlaps(map) {
//move the player
} else {
//move the player only to the edge of the map and stop there
}
}
The best way to handle those collisions would be to use a physics engine like Box2D which already comes packed with Libgdx. When a collision occurs in Box2D a event gets fired and you can easly handle that event. So you should probably take a look here.
Another alternative to achieve this without physics would be to use logical rectanlges representing the player and walls (can also be polyline) and use Intersector class of libgdx.
which is here.

Collision in 2D game

I'm trying to make a little game, where you have a little cube you can control with the arrows. When the cube intersects with another block object, I want it to go back and stop by the edge of the block object. So basically I want my block to stop when it intersects the block object, instead, it moves a bit in to it, and then when I move it again it jumps back. How can I make it so first checks if it will intersect, and if it will not move into it?
My drawing class extends JPanel and I'm painting with paintComponent.
if(keyCode == e.VK_RIGHT) {
if(xRightCollision()){
hero.x -= xVel;
}
else {
hero.x += xVel;
}
}
So let's say the cube is at the edge of the block object, but it's not intersecting it yet, so I press right and it moves into it, I press right again and it jumps back 5 pixels(xVel = 5).
public boolean xRightCollision(){
for(int i = 0; i < obstacles.size(); i++) {
if (hero.intersects(obstacles.get(i))) {
return true;
}
}
return false;
}
I've actually tried a similar thing with paint() on the JFrame, and since you have to call repaint() there, I could check first and then repaint. I don't really understand how paintComponent works since you can't control when it should be repainted.
Just use a temporary value to check, if the cube intersects with an obstacle, and reset to the original position, if necessary:
if(keyCode == e.VK_RIGHT) {
//backup of the cubes position
int tmp = hero.x;
//move the hero to the right
hero.x += xVel;
if(xRightCollision())
//cube intersects with an obstacle -> restore original position
hero.x = tmp;
}

LibGdx - Tile Game Collision Detection

I'm working on a tile 2d-side platformer game. I have done some stuff so far.
I'm working on a basic collision detection using rectangles of libgdx so considering
I have only grass block for now I made a single block world in Java (file reader is not ready)
the problem is my detection only works the first time in other words if I spawn my colliding
to a block it detects collision and do so. Although if i spawn my player top of the block
with out colliding player falls forever.
Here is the code world.update(); =>
public void update() {
Iterator<block> cb = Blocks.iterator();
while (cb.hasNext()) {
block b = cb.next();
if (b.getBounds().overlaps(player.getBounds())) {
if (player.getPosition().x >= b.getPosition().x + 32) {
//RIGHT
player.getVelocity().x = 0;
} else if (player.getPosition().x + 32 <= b.getPosition().x) {
//Left
player.getVelocity().x = 0;
}
//All Y
player.getVelocity().y = 0;
}
if (!b.getBounds().overlaps(player.getBounds())) {
player.getVelocity().y = -gravity;
}
}
}
Your while loop is applying gravity for every block your player does not intersect with. So if you have 10 blocks, and the player intersects just 1, you'll still apply gravity 9 times. You should only apply the gravity change to the player once.
Set a flag (boolean hitSomething = false) before your loop, then set it to true (hitSomething = true) if the player hits any block. Then, after the loop, if hitSomething is false, apply gravity to the player.
Stepping through the update method with a debugger is a good way to figure out what your code is doing in cases like this. It should be quicker than waiting for Stack Overflow to debug your code, too.

SIMPLE Collision Detection Java

I have checked out the following link:
http://www.ehow.com/how_12134402_detect-rectangle-collision-java.html
I have made the 2 rectangles around my player and house but am confused about what my if statement should look like, I have a boolean set on x meaning if my rectangles intersect x will return true so I know I start with
if(x=true){
//what to type in here for my collision?
}
This collision is required for my 2D state change game, I have a player that moves around with key inputs and a house on the map, I want my player not to be able to walk through the house.
Thank you in advance.
use Rectangle2D.Double rect = new Rectangle2D.Double(x,y,w,h)) to define your collision box.
Then check
rect.contains(x,y);
or
bool isCollision = rectOne.intersects(rectTwo);
Or more complete example
// returns true at the first collision
// returns false if no collision with none of the houses
Rectangle2D.Double player = new Rectangle2D.Double(x,y,w,h);
Rectangle2D.Double[] houses = map.getHouseBounds();
boolean isAnyCollision = false;
int i = 0;
while (!isAnyCollision && cnt < houses.length) {
isAnyCollision = player.intersects(houses[i]);
}
return isAnyCollision;

Categories