checking if 2 rectangles WILL overlap - java

I have been trying to do player intersection with a small project i'm doing, and I can't seem to make it work. I got the Intersection to work with the player and the wall, but it's very buggy, by buggy I mean, it draws the player in the wall then moves him back instantly. (Check Gyazo for gif of this). I'm pretty sure the problem is that it only checks if the player is in the wall, and not WILL be in the wall, but I can't seem to figure out how to check this. This is what I have so far:
public void intersectsBox2(Rectangle r, Rectangle r2) {
P1 = new Point((int) r.getMinX(), (int) r.getMinY());
P2 = new Point((int) r.getMaxX(), (int) r.getMaxY());
P3 = new Point((int) r2.getMinX(), (int) r2.getMinY());
P4 = new Point((int) r2.getMaxX(), (int) r2.getMaxY());
if ((P2.y < P3.y || P1.y > P4.y || P2.x < P3.x || P1.x > P4.x)
&& !intersectsBox(playerRectangle(), noWalls[0])) {
isInsideWalls = true;
}
}
// Gets the players rectangle
public Rectangle playerRectangle() {
return new Rectangle(9 + dx, 23 + dy, 54, 90);
}
This is to make the player Move:
public void playerMovement() {
if (isInsideWalls) {
System.out.println("YOU ARE IN THE BOX!");
if (animation == down) {
dy -= moveSpeed;
isInsideWalls = false;
} else if (animation == up) {
dy += moveSpeed;
isInsideWalls = false;
} else if (animation == left) {
dx += moveSpeed;
isInsideWalls = false;
} else if (animation == right) {
dx -= moveSpeed;
isInsideWalls = false;
}
} else {
// Moves the player
if (moving == downMove) {
dy += moveSpeed;
moving = 0;
} else if (moving == upMove) {
dy -= moveSpeed;
moving = 0;
} else if (moving == leftMove) {
dx -= moveSpeed;
moving = 0;
} else if (moving == rightMove) {
dx += moveSpeed;
moving = 0;
}
}
This is to check for the intersection:
//Checks for intersection
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
intersectsBox2(walls[i][j], playerRectangle());
}
}
Not really sure if this is needed but heres the full Game.java if you need to see this: http://pastebin.com/GrDy689d
Also here is the Gif of the problem: http://i.gyazo.com/1f31f739897af78f81e61cf22ac772db.mp4
P.S: It's on purpose I can only go into 1 box at the moment for testing purposes.

You could move the player, then check to see if it is in a wall and, if it is, undo the move (or better, calculate a new location as the result of a move, check it, and if it is good, only then move the player there). Note that this assumes a single move can't put you all the way on the other side of a wall, but then it looks like your code does, too.

Related

Java LibGDX Multi Touch Issue

for (byte i = 0; i < 20; i++) {maxDistance = 10 * Gdx.graphics.getDeltaTime();
if (Gdx.input.isTouched(i) && Gdx.input.getY()<= 400) {
player1TouchPosition.set(Gdx.input.getX(i), Gdx.input.getY(i), 0);
camera.unproject(player1TouchPosition);
}
player1Tmp.set(player1TouchPosition.x, player1TouchPosition.y).sub(player1Rectangle.x, player1Rectangle.y);
if (player1Tmp.len() <= maxDistance) {
player1Rectangle.x = player1TouchPosition.x;
player1Rectangle.y = player1TouchPosition.y;
} else {
player1Tmp.nor().scl(maxDistance);
player1Rectangle.x += player1Tmp.x;
player1Rectangle.y += player1Tmp.y;
}
if (Gdx.input.isTouched(i) && Gdx.input.getY() >= 401) {
player2TouchPosition.set(Gdx.input.getX(i), Gdx.input.getY(i), 0);
camera.unproject(player2TouchPosition);
}
player2Tmp.set(player2TouchPosition.x, player2TouchPosition.y).sub(player2Rectangle.x, player2Rectangle.y);
if (player2Tmp.len() <= maxDistance) {
player2Rectangle.x = player2TouchPosition.x;
player2Rectangle.y = player2TouchPosition.y;
} else {
player2Tmp.nor().scl(maxDistance);
player2Rectangle.x += player2Tmp.x;
player2Rectangle.y += player2Tmp.y;
}
}
Hello I'm using this code to move to touch position. But I need multi touch. It's not working. When I add player2, it doesn't work. I didn't understand how is multi touch. How can I fix it?
Why do you not use InputProcessor?
One example of one method from the interface
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if(pointer =< 2){
touches.get(pointer).touchX = screenX;
touches.get(pointer).touchY = screenY;
touches.get(pointer).touched = true;
}
return true;
}
In the above example you can use maximum 2 touches.
Actually 1 pointer is 1 touch.
Documentation
screenX and screenY are the touch position. Be aware you have to scale this position compared to your orthographic camera. A pointer is the pointer for the event.
If you create the InputProcessor you can launch it with
Gdx.input.setInputProcessor(/*Your class*/);
EDIT:
Example from the comments:
for (Button button : /*ArrayList*/{
if (positionX >= button1.getX() && positionX <= button1.getX() + button1.getWidth() &&
positionY >= button1.getY() && positionY <= button1.getY() + button1.getHeight()){
//Update the position from the specific button
}
You use this code inside the method from the interface touchDragged().

Game rope swing physics acting weird

I'm trying to implement rope swinging in my platformer, following this tutorial. Instead of swing on the rope, the player looks like he's sliding down a slope: he moves very slowly towards the bottom.
This is what it looks like now:
Instead, I want the player to have more natural movement, like he's really swinging on the rope.
This is the update method from my player class:
#Override
public final void update() {
setPosition(getNextPosition());
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
if (direction == Direction.RIGHT && moving) {
getVelocity().x = WALK_SPEED;
} else if (getVelocity().x > 0) {
getVelocity().x *= COEF_FRIC;
}
checkAsleep();
animations.update();
if (ropePoint != null) {
//getCenter() returns the center position of the player
if (getCenter().toPoint().distanceSq(ropePoint) > ROPE_LENGTH * ROPE_LENGTH) {
final Vec2D oldPosition = getCenter();
final Vec2D oldVelocity = getVelocity();
final Vec2D ropePosition = new Vec2D(ropePoint);
setCenter((oldPosition.subtract(ropePosition).unit().multiply(ROPE_LENGTH).add(ropePosition)));
setVelocity(oldPosition.subtract(getCenter()).unit().multiply(oldVelocity));
}
}
}
This is my implementation of getNextPosition(), if it is needed.
public final Vec2D getNextPosition() {
final int currCol = (int) (getX() / Tile.SIZE);
final int currRow = (int) (getY() / Tile.SIZE);
final double destX = getX() + moveData.velocity.x;
final double destY = getY() + moveData.velocity.y;
double tempX = getX();
double tempY = getY();
Corners solidCorners = getCornersAreSolid(getX(), destY);
boolean topLeft = solidCorners.topLeft;
boolean topRight = solidCorners.topRight;
boolean bottomLeft = solidCorners.bottomLeft;
boolean bottomRight = solidCorners.bottomRight;
framesSinceLastTopCollision += 1;
framesSinceLastBottomCollision += 1;
framesSinceLastLeftCollision += 1;
framesSinceLastRightCollision += 1;
if (moveData.velocity.y < 0) {
if (topLeft || topRight) {
moveData.velocity.y = 0;
tempY = currRow * Tile.SIZE;
framesSinceLastTopCollision = 0;
} else {
tempY += moveData.velocity.y;
}
} else if (moveData.velocity.y > 0) {
if (bottomLeft || bottomRight) {
moveData.velocity.y = 0;
tempY = (currRow + 1) * Tile.SIZE - moveData.collisionBox.getHeight() % Tile.SIZE - 1;
framesSinceLastBottomCollision = 0;
} else {
tempY += moveData.velocity.y;
}
}
solidCorners = getCornersAreSolid(destX, getY());
topLeft = solidCorners.topLeft;
topRight = solidCorners.topRight;
bottomLeft = solidCorners.bottomLeft;
bottomRight = solidCorners.bottomRight;
if (moveData.velocity.x < 0) {
if (topLeft || bottomLeft) {
moveData.velocity.x = 0;
tempX = currCol * Tile.SIZE;
framesSinceLastLeftCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
if (moveData.velocity.x > 0) {
if (topRight || bottomRight) {
moveData.velocity.x = 0;
tempX = (currCol + 1) * Tile.SIZE - moveData.collisionBox.getWidth() % Tile.SIZE - 1;
framesSinceLastRightCollision = 0;
} else {
tempX += moveData.velocity.x;
}
}
return new Vec2D(tempX, tempY);
}
What should I change in this code to get natural movement?
My first guess is that the problem lies in that first if statement:
if (direction == Direction.LEFT && moving) {
getVelocity().x = -WALK_SPEED;
} else if (getVelocity().x < 0) {
getVelocity().x *= COEF_FRIC;
}
If the first thing is true, you're going to constantly be setting the velocity to walking pace, which doesn't make sense when your guy is swinging on a rope. He should be speeding up as he goes down and slowing down on the way up.
If the first thing is false, then since he is going left, you're definitely going to go into the else if statement, and he'll be slowed down by friction. I don't see where you set that, but it seems to still be the friction he has on the ground, which would seem to explain why he's all stuttery and looks more like he's sliding than falling.
You might want to add different states instead of just "moving", (perhaps jumping, swinging, walking, running, stopped) and vary how he behaves while doing each of those things.

Java Program emits an error beep sound when key combination is pressed

I have code that generates projectiles corresponding to different directions of a boat sailing on the ocean. The direction is determined by the speeds of the object, looping clockwise where 0 is north through 7 as North West. In My keyPressed function, I can move around with the arrow keys just fine. Furthermore, If I press the space button to activate the cannons, everything works well, except if I'm heading north west. In this case, no bullet is fired, and my java program emits a little beep.
The keyPressed code
public void keyPressed(KeyEvent e) { //TODO switch to keyBindings to remove pause after the initial key press
// if the key is pressed, move up
if(e.getKeyCode() == KeyEvent.VK_DOWN){
//move the board down.
dy = speed;
}
if(e.getKeyCode() == KeyEvent.VK_UP){
// move spaceship upwards
dy = -speed;
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
dx = -speed;
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
dx = speed;
}
dir = myShip.getDirection(dx, dy); // determine direction so that the draw function can draw the correct sprite.
if(e.getKeyCode() == KeyEvent.VK_I){ // info key.
System.out.println(getCurrentTile().getClass().getName());
Tile t = getCurrentTile();
if(t.isDockTile()){
Docks d = (Docks) t;
System.out.println(d.getName());
}
}
if(e.getKeyCode() == KeyEvent.VK_M && getCurrentTile().isDockTile()){
if(getCurrentTile().isDockTile()){
mission = new Mission(); // create a new mission.
Docks d = (Docks) getCurrentTile();
mission.init(d); // initialize using the dock's name.
isMissionAssigned = true; // yay! we have a Mission!
} else {
System.out.println("You can't get a mission if you're not at a port!");
}
}
// fire a bullet
if(e.getKeyCode() == KeyEvent.VK_SPACE){ // TODO - NW seems to be broken.
bullet = new Projectile(bulletSpeed, dir, 10);
System.out.println("Created a bullet with direction " + dir);
bullet2 = new Projectile(bulletSpeed, myShip.getOppDir(dir), 10);
}
}
And my two functions for getting the Direction of the ship.
public int getOppDir(int d){
// since there are 4 directions, add 4 to get opposite.
// use opposite to move back to 0 if > than 8
for(int i = 0; i < 4; i++){
d++;
if(d >= 8){
d = 0;
}
}
return d;
}
public int getDirection(int dx, int dy){ // determines the direction the ship is facing based on speeds.
// 0 = N, 1 = ne, 2 = e, 3 = se, 4 = s, 5 = sw, 6 = w, 7 = nw
int tempDir = 0;
if( dx == 0 && dy < 0){
// north
tempDir = 0;
} else if(dx == 0 && dy > 0){
// south
tempDir = 4;
} else if(dx > 0 && dy == 0){
// east
tempDir = 2;
} else if(dx > 0 && dy < 0){
// ne
tempDir = 1;
} else if( dx > 0 && dy > 0) {
// se
tempDir = 3;
} else if(dx < 0 && dy == 0){
// west
tempDir = 6;
} else if (dx < 0 && dy < 0){
//northWest
tempDir = 7;
} else if(dx < 0 && dy > 0){
//south west
tempDir = 5;
}
return tempDir;
}
Thanks in advance for any help!
EDIT : I think this turned out to be a hardware problem. Shifting to ASDW controlls instead of the Arrow keys solved the problem.

Collision bug in a 2D platform game

I'm new to java, and game programming and I'm starting my first big project which is a 2D platform puzzle game.
This is my player movement code
if (speedX > 0 && centerX <= 400){
centerX += speedX;
}
if (speedX < 0 && centerX >= 400){
centerX += speedX;
}
if (speedX > 0 && centerX >= 400){
bg1.setSpeedX(-MOVESPEED);
bg2.setSpeedX(-MOVESPEED);
}
if (speedX < 0 && centerX <= 400){
bg1.setSpeedX(MOVESPEED);
bg2.setSpeedX(MOVESPEED);
}
if (speedX == 0){
bg1.setSpeedX(0);
bg2.setSpeedX(0);
}
if(movingRight == true && movingLeft == true ){
bg1.setSpeedX(0);
bg2.setSpeedX(0);
}
// Handles Jumping
if (jumped == true) {
speedY += 1;
}
// Prevents going beyond X coordinate of 0
if (centerX + speedX <= 60) {
centerX = 61;
}
rect.setRect(centerX - 47, centerY - 65, 32, 87);
centerY += speedY;
}
public void moveRight() {
speedX = MOVESPEED;
}
public void moveLeft() {
speedX = -MOVESPEED;
}
public void stopRight() {
movingRight = false;
stop();
}
public void stopLeft() {
movingLeft = false;
stop();
}
private void stop() {
if (movingRight == false && movingLeft == false) {
speedX = 0;
}
if (movingRight == false && movingLeft == true) {
moveLeft();
}
if (movingRight == true && movingLeft == false) {
moveRight();
}
}
public void jump() {
if (jumped == false) {
speedY = JUMPSPEED;
jumped = true;
}
}
and this is the collision code
public void checkCollision(Rectangle rect){
if (rect.intersects(r)){
if(Player.movingRight){
Player.centerX = tileX + 11;
Player.speedX =0;
}
if(Player.movingLeft){
Player.centerX = tileX + 89;
Player.speedX = 0;
}
if(Player.speedY > 0){
Player.centerY = tileY - 25;
Player.speedY = 0;
Player.jumped = false;
}
}
}
There are two problems.The first one is that if I press one of the movement keys when landing the character "teleports" to the right or left.
I know this happens because I programmed it that if the character intersects with the ground while movingRight or movingLeft are true he moves right or left.(I made it this way so the horizonal collision will work) and I cant think of any other way to do it or how to fix it.
The second problem is that if the character moves of a platfrom he does not fall down.
I tryed to fix it by adding to the collision method
else{
speedY += 1;
}
But it made the character disappear for some reason.
Thanks a lot!
This code was originally written in C++ for a 3D platformer. I rewrote it, but there might be some bugs. I can draw a picture later if it's difficult to understand.
public void checkCollision(Rectangle rect){
if(player.intersects(rect)) {
//the rectangles intersect, time to move the player out of the block
if(rect.y+rect.height >= player.y && rect.y+rect.height-0.7f < player.y) { //if the player is at most 0.7 units (you should change this!) below top side
player.y = rect.y+rect.height; //set player to stand on top
speed.y = 0f; //stop the movement
onGround = true;
} else if(rect.y+rect.height > player.y && rect.y < player.y+player.height) { //if the playeer is on the side, but not below
float xEscMinus = (float)Math.abs((rect.x+rect.width)-player.x); //find the distance to the side
float xEscPlus = (float)Math.abs(rect.x-(player.x+player.width));
if(xEscMinus<xEscPlus) {
player.x = rect.x+rect.width;
} else {
player.x = rect.x-player.width;
}
}
}
}

Canvas OnDraw method

I am currently creating a maze using a pair of boolean array (horizontal and vertical) in order to draw lines for the maze.
The maze only every displays 5 bools from the array at one time. Then, I have an user who is always centered and as he moves through the maze the next set of bools are drawn. This is working as it should.
The issue that I am having is: when the user moves to a certain part of the maze the for loop drawing the lines becomes higher than the bool array and therefore crashes the app. Please find below some code snippets.
The onDraw:
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, width, height, background);
int currentX = maze.getCurrentX(),currentY = maze.getCurrentY();
int drawSizeX = 6 + currentX;
int drawSizeY = 6 + currentY;
currentX = currentX - 2;
currentY = currentY - 2;
for(int i = 0; i < drawSizeX - 1; i++) {
for(int j = 0; j < drawSizeY - 1; j++) {
float x = j * totalCellWidth;
float y = i * totalCellHeight;
if(vLines[i + currentY][j + currentX]) {
canvas.drawLine(x + cellWidth, //start X
y, //start Y
x + cellWidth, //stop X
y + cellHeight, //stop Y
line);
}
if(hLines[i + currentY][j + currentX]) {
canvas.drawLine(x, //startX
y + cellHeight, //startY
x + cellWidth, //stopX
y + cellHeight, //stopY
line);
}
}
//draw the user ball
canvas.drawCircle((2 * totalCellWidth)+(cellWidth/2), //x of center
(2 * totalCellHeight)+(cellWidth/2), //y of center
(cellWidth*0.45f), //radius
ball);
}
EDIT 1 - The Move -
public boolean move(int direction) {
boolean moved = false;
if(direction == UP) {
if(currentY != 0 && !horizontalLines[currentY-1][currentX]) {
currentY--;
moved = true;
}
}
if(direction == DOWN) {
if(currentY != sizeY-1 && !horizontalLines[currentY][currentX]) {
currentY++;
moved = true;
}
}
if(direction == RIGHT) {
if(currentX != sizeX-1 && !verticalLines[currentY][currentX]) {
currentX++;
moved = true;
}
}
if(direction == LEFT) {
if(currentX != 0 && !verticalLines[currentY][currentX-1]) {
currentX--;
moved = true;
}
}
if(moved) {
if(currentX == finalX && currentY == finalY) {
gameComplete = true;
}
}
return moved;
}
If there is anything else that I need to clarify please let me know.
Thanks in advance.
drawSizeX/Y indexes over the array when currentX/Y is high enough (length-6)
So limit the values to Math.min(current + 6, array.length)

Categories