My player for some reason is able to walk through objects it shouldn't. I am using a 2d boolean array and if the position to the players left is true in the grid, then he shouldn't be able to move and same goes for right. I know for a fact the collision handler is working because all it does is check if there is something to the left or right and if there is it writes player.setCanMoveLeft or right to false and the code was working in previous builds. When there is something to the left or right of the player I print out something so I know the collision handler is doing it's job. I just don't understand what is happening here is my Entity update method which player extends,
if(!wantsToMoveLeft && !wantsToMoveRight)
velocity.x = 0;
if(velocity.x > 1){
velocity.x = 1;
}if(velocity.x<-1)
velocity.x = -1;
position.x += velocity.x;
spritePosition.x += velocity.x;
position.y += velocity.y;
spritePosition.y += velocity.y;
and here is my players update method,
if(wantsToMoveRight && canMoveRight)
velocity.x = 1;
if(wantsToMoveLeft && canMoveLeft)
velocity.x = -1;
if(wantsToJump && canJump){
canFall = true;
velocity.y += 1f;
if(lastLeft){
jumpLeft = true;
jumpRight = false;
}else{
jumpRight = true;
jumpLeft = false;
}
}else if(canJump == false){
jumpLeft = false;
jumpRight = false;
}
super.update();
Here is my input listener class too
#Override
public boolean keyDown(int keycode) {
if(keycode == Keys.A){
player.setLastLeft(true);
player.setLastRight(false);
player.setWantsToMoveLeft(true);
player.setWantsToMoveRight(false);
}
if(keycode == Keys.D){
player.setLastRight(true);
player.setLastLeft(false);
player.setWantsToMoveRight(true);
player.setWantsToMoveLeft(false);
}
if(keycode == Keys.W){
player.setWantsToJump(true);
}
return false;
}
#Override
public boolean keyUp(int keycode) {
if(keycode == Keys.A){
player.setLastLeft(true);
player.setLastRight(false);
player.setWantsToMoveLeft(false);
}
if(keycode == Keys.D){
player.setLastRight(true);
player.setLastLeft(false);
player.setWantsToMoveRight(false);
}
if(keycode == Keys.W){
player.setWantsToJump(false);
}
return false;
}
If anyone could help me with this I would be extremely appreciative because I am at a complete loss. If you need any additional information ask for it in the comments. Thank *you!!
Update - If I walk right near the object (before hitting it) and stop (let go of key) then try to repress it it won't let me move(i.e it works if I do this)
Note - That this code I believe worked before I switched to using an InputListener this may be false though I can't quite remember but I know for sure it hasn't worked since I switched from using Gdx.input in players update to communicating through an InputListener
The simple solution that I missed has to do with not executing a stop when told he can't move. I can't explain why it was working before and now I need this line of code but here it is, I placed these lines of code in my players update and method and it works beautifully now.
if(!canMoveLeft) {
if(!wantsToMoveRight) {
velocity.x = 0;
} else {
velocity.x = 1;
}
}
if(!canMoveRight) {
if(!wantsToMoveLeft) {
velocity.x = 0;
} else {
velocity.x = -1;
}
}
Sorry for anyone who may have gotten confused about this, I got it thanks to anyone who tried to help!
Related
The following code I wrote does what I want, a touch on the left or right side of the screen to move the sprite left or right and stop at the edge of the phone screen. The issue I'm having is when you do a fast motion of touching the right side of the screen, letting go while using another finger to touch the left side of the screen to change direction will yield a result of the sprite still moving to the right side of the screen despite you wanting to move left. In order to fix this, you need to let go completely for at least 0.5sec then press the other direction to start moving in that direction, which I don't want to have to live with. If anyone has any tips/help for this, please let me know!
MAIN ACTIVITY CLASS METHOD:
public boolean onTouchEvent(MotionEvent event){
int x = (int)event.getX();
switch(event.getAction()) {
case (MotionEvent.ACTION_DOWN):
CharacterSprite.touchedX = x;
break;
case (MotionEvent.ACTION_UP):
CharacterSprite.touchedX = 0;
break;
}
return super.onTouchEvent(event);
}
CHARACTERSPRITE CLASS METHOD:
public void update() {
if (touchedX != 0) {
if (touchedX < screenWidth / 2) {
if (!(xVelocity < 0)) {
xVelocity = xVelocity * -1;
}
if (!(x > 0)) {
touchedX = 0;
return;
}
x += xVelocity;
}
if (touchedX > screenWidth / 2) {
if (!(xVelocity > 0)) {
xVelocity = xVelocity * -1;
}
if (!(x < screenWidth - image.getWidth())) {
touchedX = 0;
return;
}
x += xVelocity;
}
}
}
The way you handling MotionEvent will not work for multitouch events. Each finger (action pointer) data stored as an array and you need to handle each entry separately. Here is the lesson on handling multitouch events:
https://developer.android.com/training/gestures/multi
Assuming that the below method is hooked up to a main method that creates a circle in a window and that I want this circle to move left about 100 pixels and then move right 100 pixels and so on.
I can't figure out the code to do it.
private void moveBall()
{
boolean moveRight = true;
if(moveRight == true)
{
x = x + 1;
}
else
{
x = x - 1;
}
if(x == 300)
{
moveRight = false;
}
}
The reason the ball is continually moving right is because when it hits the if statement to set moveRight to false it resets it back to true at the start of the method. You need to pull moveRight to be a class variable if you want it to work like you think it should.
What about trying it like this?
//set the moveRight variable as a class variable
private boolean moveRight = true;
private void moveBall() {
//move right or left accordingly
x = moveRight ? x + 1 : x - 1;
//if x == 300 we want to move left, else if x == 100 im assuming you want to move right again
if (x == 300) {
moveRight = false;
} else if(x == 100){
moveRight = true;
}
}
What I mean is that when I collide with the side of an entity and want to jump, I cannot move right/left as I have a flag which prevents this when I collide with the entity on the right/left side, like so:
This is code code I use to detect collision:
public void onCollision(Wrapper wrapper) {
if (horizontal_velocity == 0 && vertical_velocity == 0) {
return;
}
Entity e1 = wrapper.thisEntity; //the object we are controlling
Entity e2 = wrapper.otherEntity; //the object we are impacting with
Rectangle rect1 = wrapper.thisEntityRectangle;
Rectangle rect2 = wrapper.otherEntityRectangle;
int e1y = (int) rect1.getY(), e1x = (int) rect1.getX(), e1w = (int) rect1.getWidth(), e1h = (int) rect1.getHeight();
int e2y = (int) rect2.getY(), e2x = (int) rect2.getX(), e2w = (int) rect2.getWidth(), e2h = (int) rect2.getHeight();
e1x += e1w / 2;
e1w /= 2;
e1y += e1h / 2;
e1h /= 2;
//horizontal interaction -- x
/* ---+\\\\\\+---
* |------|
* | |
* e1 | e2 | e1
* | |
* |------|
* ---+\\\\\\+---
*/
boolean touchingSide = false;
if(e1y > e2y && e1y < e2y + e2h) {
//touchingSide = true;
if(e1x > e2x - e1w && e1x < e2x) { //going right || hitting left side
collisionsHappening.put(wrapper.otherEntity.getID(), "right");
canMoveRight = false;
horizontal_velocity = 0;
setX(e2x - e1w*2);
}
if(e1x < e2x + e2w + e1w && e1x > e2x) { //going left || hitting right side
collisionsHappening.put(wrapper.otherEntity.getID(), "left");
canMoveLeft = false;
horizontal_velocity = 0;
setX(e2x + e2w);
}
}
//vertical interaction -- y
/*
* \| e1 |\
* \+--+------+--+\
* \\\\| |\\\\
* \\\\| e2 |\\\\
* \\\\| |\\\\
* \+--+------+--+\
* \| e1 |\
*
*/
if(e1x > e2x - e1w && e1x < e2x + e2w && !touchingSide) {
if(e1y + e1h > e2y && e1y < e2y) { //going down || hitting top side
collisionsHappening.put(wrapper.otherEntity.getID(), collisionsHappening.get(wrapper.otherEntity.getID()) + "|top");
setY(e2y - e1h * 2);
vertical_velocity = 0;
//readyNextTurn = true;
isFalling = false;
onGround = true;
}
if(e1y - e1h < e2y + e2h && e1y > e2y) { //going up || hitting bottom side
collisionsHappening.put(wrapper.otherEntity.getID(), collisionsHappening.get(wrapper.otherEntity.getID()) + "|bottom");
setY(e2y + e2h + e1h);
vertical_velocity = 0;
//readyNextTurn = true;
isFalling = false;
onGround = true;
}
}
}
..and where the code is affected by the canMoveRight and canMoveLeft flags:
public void key(int keyCode) {
try {
onEdge();
switch (keyList.get(keyCode)) {
...
case MOVE_RIGHT:
for(Entity e : objectsCollidingWith) { //check if still colliding, if not, reset variable canMoveLeft inorder to not impair movement
if(collisionsHappening.get(e.getID()) == "right") {
canMoveRightNextFrame = true;
}
}
canMoveLeft = true;
if (!canMoveRight && !canMoveRightNextFrame) break;
if(canMoveRightNextFrame) {
canMoveRightNextFrame = false;
System.out.println(canMoveRightNextFrame);
}
if (horizontal_velocity == 0) {
horizontal_velocity = getXDisplacement();
}
changeX(horizontal_velocity);
direction = "right";
//horizontal_velocity = 0;
break;
case MOVE_LEFT:
for(Entity e : objectsCollidingWith) { //check if still colliding, if not, reset variable canMoveLeft inorder to not impair movement
if(collisionsHappening.get(e.getID()) == "left") {
canMoveLeftNextFrame = true;
}
}
canMoveRight = true;
if (!canMoveLeft && !canMoveLeftNextFrame) {
break;
}
canMoveLeftNextFrame = canMoveLeftNextFrame ? true : false; //if true, make false
if (horizontal_velocity == 0) {
horizontal_velocity = getXDisplacement();
}
changeX(-horizontal_velocity);
direction = "left";
//horizontal_velocity = 0;
break;
case JUMP:
jump();
}
} catch (NullPointerException e) {
//ignore - a key with no action pressed
}
}
What I have tried
When I look for collisions - not react to them as shown in the above code - I tried to implement a HashMap in which I put a String - either "left" or "right" - to the key Entity.getID() which returns a unique name, like so (after the lines of code that are relevant are // <<<) :
public Wrapper[] collisions(Entity thisEntity) {
ArrayList<Wrapper> wrappers = new ArrayList<Wrapper>();
Player p = null;
boolean isPlayer = thisEntity instanceof Player;
boolean onGround = false;
if (isPlayer) {
p = (Player) thisEntity;
}
try {
for (Entity e : getLevel().getEntities()) {
if (!thisEntity.equals(e)) {
collisionsHappening.put(e.getID(), ""); // <<<
objectsCollidingWith.add(e); // <<<
if (thisEntity.getRect().intersects(e.getRect())) {
wrappers.add(new Wrapper(thisEntity, e, thisEntity.getRect(), e.getRect(),
thisEntity.getRect().intersection(e.getRect())));
onGround = true;
//collisionsHappening.put(e.getID(), true);
//System.out.println("collision between " + e.getID() + " + " + thisEntity.getID());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (isPlayer) {
p.isTouching = onGround;
if (onGround) {
//System.out.println(onGround);
}
}
//Entity[] result = list.toArray(new Entity[1]);
return wrappers.toArray(new Wrapper[0]);
}
This system relies on keeping a flag 1 frame after the collision ceases in-order to remove the flags canMoveRight or canMoveLeft in the lines of code
for(Entity e : objectsCollidingWith) { //check if still colliding, if not, reset variable canMoveLeft inorder to not impair movement
if(collisionsHappening.get(e.getID()) == "left") {
canMoveLeftNextFrame = true;
}
}
canMoveRight = true;
if (!canMoveLeft && !canMoveLeftNextFrame) {
break;
}
if(canMoveLeftNextFrame) {
canMoveLeftNextFrame = false; //if true, make false
}
...
...and same for the canMoveRight flag...
However, this does not work, and I still cannot move mid-jump after I "scrape" the edge of an Entity unless I move in the opposite direction to "reset" the flag for the desired direction (line: case MOVE_RIGHT: ... canMoveLeft = true; and case MOVE_LEFT: ... canMoveRight = true;), as seen in the animation.
So, to conclude:
How can I make this system work?
Is there a more efficient/better way of doing this kind of thing?
Do you recommend I redo my collision?
Thanks.
It is actually impossible to approach this problem in such an event driven way for a game more advanced then Snake. I recommend that you focus on a simple update loop which updates each entity. Each entity then updates their own velocity and then position. Then check for collision and handle response. The key event handlers should not have any logic and be simply changing flags which the entities can poll.
As for the the collision and response part, that is where the meat of a simple platform game engine lies, and there are many different approaches. In the modern world of off the shelf physics engines, e.g. Box2D, you could simply let the physics system handle things. But from the sounds of things, you are not looking for that and what you want is what I call logic based physics.
If your world and entities consist of axis aligned boxes, you can separate horizontal and vertical motion into two discrete steps, for each entity. For each axis, each object tries to move as far as it can for (depending on velocity and collisions) if the object hits something, generate a collision event and set the velocity to zero on that axis. Repeat for the other axis and you will have a simple platform game engine. For this method you will need to handle the state of two objects touching carefully due to floating point numerical error. I recommend doing collision detection with integers (in the scale of the screen coordinates).
If you are looking to have an environment and entities which are not restricted to the axis aligned boxes, then you will have to get more complex and no longer rely on simply handling X then Y movement to give you things like a box sliding on the floor or down a wall. In this case I suggest you keep track of what surface your entity is standing or walking on so that you can handle their movement differently in each state. When they are in the air, normal movement, but when they are on some surface, the movement is constrained to horizontal movement and the vertical position is adjusted to keep them on the surface. You then will need to detect when they change states.
I hope you find this helpful. It turns out that it is not an easy topic to Google. (Update loops, collision detection, physics of motion, numerical integration and the geometry of collision response are all easy to Google). Most programmers seem to just take the approach of keep fiddling with it till it works, and so it never gets documented well.
P.S. Implicit Euler integration method is fine for most games.
So basically i'm currently working on a small project where the player will be able to fight stuff through move but the gravity is giving me kind of a problem. So basically, i got this method, checkGravity() which will check if isGravityApplicable() return true (does the entity's bottom collider(a Line2D) collide with one of the foothold?(another line2D))
If isGravityApplicable() returns true, then the gravity should be applied but the problem that i have is that anything above 1 pixel Y is way too quickly and even, moving the character by one pixel is extremely fast. I'm not sure whether i should fix my game loop or what?
public boolean isGravityApplicable() {
for (Line2D line : frame.getMap().getFootholds()) {
/*Does the bottom collider intersect the foothold?*/
/*v THIS CHECK DOESN'T WORK CORRECTLY FOR SOME REASONS v*/
if (!GraphicHelper.getLineCameraRelative(getBottomCollider(), frame.getCam()).intersectsLine(line)) {
return true;
}
/*Above check returned false, if the velocity.y is above 1, then it might
skip the line since it would be skipping 5 pixels for example at once.
this check should resolve that.*/
if (velocity.y > 0) {
Line2D collider = getPositionToVelocityCollider();
if (!collider.intersectsLine(line)) {
position.y = (int) line.getY1(); //Y1 or Y2, same sh*t.
return true;
}
}
}
return false;
}
public void checkGravity() {
if (isGravityApplicable()) {
if (isJumping) { //Player has jumped
velocity.y += 1;
velocity.y = velocity.y > TERMINAL_ACCELERATION ? (int) TERMINAL_ACCELERATION : velocity.y;
if (velocity.y < 0) {
isFalling = true;
}
} else if (isFalling) { //Player is currently falling but not from jumping. Most likely just spawned
velocity.y = 1;
/*Anything higher than 1 is WAY too quickly...*/
//velocity.y += 1;
//velocity.y = velocity.y > TERMINAL_VELOCITY ? (int) TERMINAL_VELOCITY : velocity.y;
} else if (isJumping && isFalling) { //Player has jumped and has reached its highest point, falling back down
velocity.y = 1;
/*Anything higher than 1 is WAY too quickly...*/
//velocity.y += 1;
//velocity.y = velocity.y > TERMINAL_VELOCITY ? (int) TERMINAL_VELOCITY : velocity.y;
} else { //Player hasn't jumped and has not started falling, he most likely just spawned
isFalling = true;
velocity.y = 1;
}
} else {
isFalling = false;
isJumping = false;
}
}
Thanks in advance. Oh and if there is anything i could of done better like the collisions which consist of simple lines all around the entities, please tell me. :) Thanks.
Nevermind guys, for some reason the update/tick method was called twice in the loop for some reasons. I guess i had a brain fart or something.
I am working on an Android game similar to the Rush Hour/Traffic Jam/Blocked puzzle games. The board is a square containing rectangular pieces. Long pieces may only move horizontally, and tall pieces may only move vertically. The object is to free the red piece and move it out of the board. This game is only my second ever programming project in any language, so any tips or best practices would be appreciated along with your answer.
I have a class for the game pieces called Pieces that describes how they are sized and drawn to the screen, gives them drag-and-drop functionality, and detects and handles collisions.
I then have an activity class called GameView which creates my layout and creates Pieces objects to add to a RelativeLayout called Board. I have considered making Board its own class, but haven't needed to yet.
Here's what my work in progress looks like:
My Question:
Most of this works perfectly fine except for my collision handling. It seems to be detecting collisions well but instead of pushing the pieces outside of each other when there is a collision, it frantically snaps back and forth between (what seems to be) where the piece is being dragged to and where it should be. It looks something like this:
Another oddity: when the dragged piece collides with a piece to its left, the collision handling seems to work perfectly. Only piece above, below, and to the right cause problems.
Here's the collision code:
#Override
public boolean onTouchEvent(MotionEvent event){
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height)){
initialX=x;
initialY=y;
break;
}else{
return false;
}
case MotionEvent.ACTION_MOVE:
//determine if piece should move horizontally or vertically
if(width>height){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//if next to another piece,
//do not allow to move any further towards said piece
if(eventX<x&&(x==piece.right+1)){
return false;
}else if(eventX>x&&(x==piece.x-width-1)){
return false;
}
//move normally if no collision
//if collision, do not allow to move through other piece
if(collides(this,piece)==false){
x = (eventX-(width/2));
}else if(collidesLeft(this,piece)){
x = piece.right+1;
break;
}else if(collidesRight(this,piece)){
x = piece.x-width-1;
break;
}
}
break;
}else if(height>width){
for (Pieces piece : aPieces) {
if(piece==this){
continue;
}else if(collides(this,piece)==false){
y = (eventY-(height/2));
}else if(collidesUp(this,piece)){
y = piece.bottom+1;
break;
}else if(collidesDown(this,piece)){
y = piece.y-height-1;
break;
}
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:
// end move
if(this.moves()){
GameView.counter++;
}
initialX=x;
initialY=y;
break;
}
// parse puzzle
invalidate();
return true;
}
This takes place during onDraw:
width = sizedBitmap.getWidth();
height = sizedBitmap.getHeight();
right = x+width;
bottom = y+height;
My collision-test methods look like this with different math for each:
private boolean collidesDown(Pieces piece1, Pieces piece2){
float x1 = piece1.x;
float y1 = piece1.y;
float r1 = piece1.right;
float b1 = piece1.bottom;
float x2 = piece2.x;
float y2 = piece2.y;
float r2 = piece2.right;
float b2 = piece2.bottom;
if((y1<y2)&&(y1<b2)&&(b1>=y2)&&(b1<b2)&&((x1>=x2&&x1<=r2)||(r1>=x2&&x1<=r2))){
return true;
}else{
return false;
}
}
private boolean collides(Pieces piece1, Pieces piece2){
if(collidesLeft(piece1,piece2)){
return true;
}else if(collidesRight(piece1,piece2)){
return true;
}else if(collidesUp(piece1,piece2)){
return true;
}else if(collidesDown(piece1,piece2)){
return true;
}else{
return false;
}
}
As a second question, should my x,y,right,bottom,width,height variables be ints instead of floats like they are now?
Also, any suggestions on how to implement things better would be greatly appreciated, even if not relevant to the question! Thanks in advance for the help and for sitting through such a long question!
Update:
I have gotten it working almost perfectly with the following code (this doesn't include the code for vertical pieces):
#Override
public boolean onTouchEvent(MotionEvent event){
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height)){
initialX=x;
initialY=y;
break;
}else{
return false;
}
case MotionEvent.ACTION_MOVE:
//determine if piece should move horizontally or vertically
if(width>height){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//check if there the possibility for a horizontal collision
if(this.isAllignedHorizontallyWith(piece)){
//check for and handle collisions while moving left
if(this.isRightOf(piece)){
if(eventX>piece.right+(width/2)){
x = (int)(eventX-(width/2)); //move normally
}else{
x = piece.right+1;
}
}
//check for and handle collisions while moving right
if(this.isLeftOf(piece)){
if(eventX<piece.x-(width/2)){
x = (int)(eventX-(width/2));
}else{
x = piece.x-width-1;
}
}
break;
}else{
x = (int)(eventX-(width/2));
}
The only problem with this code is that it only detects collisions between the moving piece and one other (with preference to one on the left). If there is a piece to collide with on the left and another on the right, it will only detect collisions with the one on the left. I think this is because once it finds a possible collision, it handles it without finishing looping through the array holding all the pieces. How do I get it to check for multiple possible collisions at the same time?
My best guess is that the dragged piece is dragged into the other piece, then moved back so it is no longer colliding, then dragged into the other piece again. At least that is what I would expect if collision response happens after drawing.
On a side note, the following code makes me wonder a bit:
//if next to another piece,
//do not allow to move any further towards said piece
if(eventX<x&&(x==piece.right+1)){
return false;
}else if(eventX>x&&(x==piece.x-width-1)){
return false;
}
Checking for equality (==) on floats is generally a very bad idea, see zillions of "floating point precision" topics. Alternative a) use ints instead of floats. b) use ranged comparisions (>=, etc.). Don't use (a) though, there are many drawbacks with tiny (time) steps and such.
Try using the same approach as with the touch detection instead:
//check if touch is on piece
if (eventX > x && eventX < (x+width) && eventY > y && eventY < (y+height))
You should be able to do this more simply :)
Note that I made some assumptions on how you store the direction of movement, which you may have to adjust to your likings.
Also note that I treat piece1 as the moving piece we are concerned with, and piece2 simply as an object it collides with. So piece1 is repositioned, piece2 is not.
// Horizontal:
if( piece1.isMovingLeft )
piece1.x += Math.max( 0, piece2.right - piece1.x );
else if( piece1.isMovingRight )
piece1.x -= Math.max( 0, piece1.right - piece2.x );
// Vertical:
if( piece1.isMovingUp )
piece1.y -= Math.max( 0, piece2.bottom - piece1.y );
else if( piece1.isMovingDown )
piece1.y += Math.max( 0, piece1.bottom - piece2.y )
What I do here is as follows:
If the piece is moving in a certain direction, we move it back (a little bit) in the opposite direction to compensate for (possible) collision. We need to move it back by exactly the amount of overlapping pixels.
The amount of overlap, when moving left, for instance, is the right side of the second object minus the left side of the first object. (Negative means no overlap.)
The Math.max( 0, overlap ) ensures that said negative values become 0, i.e. no collision leads to no compensation.
The compensation is then applied in the direction opposite of movement, effectively taking piece1 out of piece2. (You can then choose to invert its movement direction or respond in any further way.)
You can apply this simple routine to every possible combination of two pieces, and they will no longer penetrate.
I hope this helps you out!
In reply to your second question:
The only problem with this code is that it only detects collisions between the moving piece and one other (with preference to one on the left). If there is a piece to collide with on the left and another on the right, it will only detect collisions with the one on the left.
There is a break statement within your loop - specifically, in the left collision check. ;)
I made a few changes and, so far, it has been working perfectly. Here is my new code:
case MotionEvent.ACTION_MOVE:
//determine if piece should move horizontally or vertically
if(width>height){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//check if there the possibility for a horizontal collision
if(this.isAllignedHorizontallyWith(piece)){
//check for and handle collisions while moving left
if(this.isRightOf(piece)){
if(eventX>piece.right+(width/2)){
x = (int)(eventX-(width/2)); //move normally
continue;
}else{
x = piece.right+1;
}
}else if(this.isLeftOf(piece)){ //check for and handle collisions while moving right
if(eventX<piece.x-(width/2)){
x = (int)(eventX-(width/2));
continue;
}else{
x = piece.x-width-1;
}
}else{
continue;
}
break;
}else{
x = (int)(eventX-(width/2));
}
}
}
if(height>width){
for (Pieces piece : aPieces) {
//if object equals itself in array, skip to next object
if(piece==this){
continue;
}
//check if there the possibility for a vertical collision
if(this.isAllignedVerticallyWith(piece)){
//check for and handle collisions while moving up
if(this.isBelow(piece)){
if(eventY>piece.bottom+(height/2)){
y = (int)(eventY-(height/2)); //move normally
continue;
}else{
y = piece.bottom+1;
}
}else if(this.isAbove(piece)){ //check for and handle collisions while moving down
if(eventY<piece.y-(height/2)){
y = (int)(eventY-(height/2));
continue;
}else{
y = piece.y-height-1;
}
}else{
continue;
}
break;
}else{
y = (int)(eventY-(height/2));
}
}
}
invalidate();
break;
And these are the methods I use:
private boolean isLeftOf(Pieces piece) {
int r1 = this.right;
int x2 = piece.initialX;
boolean bool = false;
if (r1<=x2){
for(Pieces piece2: aPieces){
if (piece2==piece || piece2==this){
continue;
}
if (this.isAllignedHorizontallyWith(piece2) && r1<=piece2.initialX){
if (piece.x>piece2.x){
bool = false;
break;
}else{
bool = true;
continue;
}
}else{
bool = true;
}
}
}else{
bool = false;
}
return bool;
}
private boolean isRightOf(Pieces piece) {
//True means that "this" is right of "piece" and "piece" is farther right than other possible pieces
int x1 = this.initialX;
int r2 = piece.right;
boolean bool = false;
if (x1>=r2){
for(Pieces piece2: aPieces){
if (piece2==piece || piece2==this){
continue;
}
if (this.isAllignedHorizontallyWith(piece2) && x1>=piece2.right){
if (piece.x<piece2.x){
bool = false;
break;
}else{
bool = true;
continue;
}
}else{
bool = true;
}
}
}else{
bool = false;
}
return bool;
}
private boolean isBelow(Pieces piece){
int y1 = this.initialY;
int b2 = piece.bottom;
boolean bool = false;
if (y1>=b2){
for(Pieces piece2: aPieces){
if (piece2==piece || piece2==this){
continue;
}
if (this.isAllignedVerticallyWith(piece2) && y1>=piece2.bottom){
if (piece.y<piece2.y){
bool = false;
break;
}else{
bool = true;
continue;
}
}else{
bool = true;
}
}
}else{
bool = false;
}
return bool;
}
private boolean isAbove(Pieces piece){
int y2 = piece.initialY;
int b1 = this.bottom;
boolean bool = false;
if (b1<=y2){
for(Pieces piece2: aPieces){
if (piece2==piece || piece2==this){
continue;
}
if (this.isAllignedVerticallyWith(piece2) && b1<=piece2.y){
if (piece.y>piece2.y){
bool = false;
break;
}else{
bool = true;
continue;
}
}else{
bool = true;
}
}
}else{
bool = false;
}
return bool;
}
private boolean isAllignedHorizontallyWith(Pieces piece) {
int y1 = this.y;
int b1 = this.bottom;
int y2 = piece.y;
int b2 = piece.bottom;
if((y1>=y2&&y1<=b2)||(b1>=y2&&b1<=b2)){
return true;
}else{
return false;
}
}
private boolean isAllignedVerticallyWith(Pieces piece) {
int x1 = this.x;
int r1 = this.right;
int x2 = piece.x;
int r2 = piece.right;
if((x1>=x2&&x1<=r2)||(r1>=x2&&r1<=r2)){
return true;
}else{
return false;
}
}
This could be commented better and probably done much simpler, but I am leaving it here for reference.
Nothing just get the your imageviews Left,right,top,bottom, and intersect with current x and y and find this solution more about this go to this link its also help i hop you got a right answer on this link
/technical/game-programming/collision-detection-algorithm-r754">http://www.gamedev.net/page/resources//technical/game-programming/collision-detection-algorithm-r754