Collision Detection Glitches - java

Thanks in advance. I am trying to make a scrolling 2d game with perfect collision detections on the corners of the player. The problem I am having is that if you go left or down on a wall, it works just fine, but on the right or up, it seems to infinitely detect collisions and glitch you to a corner.
I have tried resetting the motion, reverting to old location, subtracting pixels from the position after the translation, and also changing the variables.
package me.Rigidity.Apocalypse;
public class Entity extends Tile {
private float x, y, xm, ym;
public Entity(String name, float r, float g, float b, float x, float y, float size) {
super(name, r, g, b);
this.size = size;
this.x = x;
this.y = y;
}
public void move(float x, float y) {
this.x += x;
this.y += y;
}
public void position(float x, float y) {
this.x = x;
this.y = y;
}
public void factor(float x, float y) {
this.xm *= x;
this.ym *= y;
}
public void motion(Map map) {
motionX(map);
motionY(map);
}
public void motionX(Map map) {
x += xm;
if (collision(map)) {
if (left(map)) {
x = rightX();
}
if (right(map)) {
x = leftX();
}
}
}
public void motionY(Map map) {
y += ym;
if (collision(map)) {
if (top(map)) {
y = bottomY();
return;
}
if (bottom(map)) {
y = topY();
}
}
}
public void motion(float x, float y) {
xm += x;
ym += y;
}
public float x() {
return x;
}
public float y() {
return y;
}
public void x(float x) {
this.x = x;
}
public void y(float y) {
this.y = y;
}
public float xm() {
return xm;
}
public float ym() {
return ym;
}
public Tile bottomleft(Map map) {
return map.getAbsoluteTile(leftX(), bottomY());
}
public Tile bottomright(Map map) {
return map.getAbsoluteTile(rightX(), bottomY());
}
public Tile topleft(Map map) {
return map.getAbsoluteTile(leftX(), topY());
}
public Tile topright(Map map) {
return map.getAbsoluteTile(rightX(), topY());
}
public int leftX() {
return (int)(((int)(x/Tile.BASIC.size()))*Tile.BASIC.size()+Tile.BASIC.size()-size);
}
public int rightX() {
return (int)(((int)(x/Tile.BASIC.size()))*Tile.BASIC.size()+Tile.BASIC.size());
}
public int topY() {
return (int)(((int)(y/Tile.BASIC.size()))*Tile.BASIC.size()+Tile.BASIC.size());
}
public int bottomY() {
return (int)(((int)(y/Tile.BASIC.size()))*Tile.BASIC.size()+Tile.BASIC.size()-size);
}
public boolean top(Map map) {
return topleft(map) instanceof Solid || topright(map) instanceof Solid;
}
public boolean bottom(Map map) {
return bottomleft(map) instanceof Solid || bottomright(map) instanceof Solid;
}
public boolean left(Map map) {
return topleft(map) instanceof Solid || bottomleft(map) instanceof Solid;
}
public boolean right(Map map) {
return topright(map) instanceof Solid || bottomright(map) instanceof Solid;
}
public boolean collision(Map map) {
return bottomleft(map) instanceof Solid || topleft(map) instanceof Solid || bottomright(map) instanceof Solid || topright(map) instanceof Solid;
}
}
There is no error message, however the result isn't as expected on the right or top collision. Left and bottom work as expected with clean collision, as well as the sliding motion.

Related

I have problem with class that creates rectangle based on a test

Ok so i have rectangle that should be created based on: method point that will crete coordinates of it center and values of hight and width, all value are based on this test
public void testRectangle1() {
Point center = new Point(20, 30);
Rectangle rect = new Rectangle(center, 20, 20);
assertAll(
() -> assertEquals(10, rect.getTopLeft().getX()),
() -> assertEquals(20, rect.getTopLeft().getY()),
() -> assertEquals(30, rect.getBottomRight().getX()),
() -> assertEquals(40, rect.getBottomRight().getY()),
() -> assertEquals(20, rect.getWidth()),
() -> assertEquals(20, rect.getHeight())
);
}
I have prewritten class point that i will add here for overall clarity
package net.thumbtack.school.figures.v1;
public class Point {
private int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point() {
this(0, 0);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void moveTo(int newX, int newY) {
x = newX;
y = newY;
}
public void moveRel(int dx, int dy) {
x += dx;
y += dy;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
And this is class for creating rectangle
package net.thumbtack.school.figures.v1;
public class Rectangle {
public int width;
public int height;
public Point center;
public int xCenter;
public int yCenter;
private Point point;
public Rectangle(Point center, int width, int height) {
this.width=width;
this.height=height;
this.center=center;
}
public Point getTopLeft() {
Point point = getCenter();
point.moveRel(- width / 2, - height / 2);
return point;
}
public Point getBottomRight() {
Point point = getCenter();
point.moveRel(width / 2, height / 2);
return point;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Point getCenter() {
Point center = new Point(xCenter, yCenter);
return center;
}
So problem is in constructor public Rectangle(Point center, int width, int height) when i run the test it returns wirng values
expected: <10> but was: <-10>
Comparison Failure:
Expected :10
Actual :-10
expected: <20> but was: <-10>
Comparison Failure:
Expected :20
Actual :-10
expected: <30> but was: <10>
Comparison Failure:
Expected :30
Actual :10
expected: <40> but was: <10>
Comparison Failure:
Expected :40
Actual :10
I dont this that the problem is into other methods becouse when i use them in different but simmilar constrictors everything works.
As maloomeister mentioned you must init xCenter or yCenter before used,or the value of xCenter and yCenter is 0.
modify getCenter() method:
public Point getCenter() {
Point point = new Point(center.getX(), center.getY());
return point;
}

I need constructor that will create rectangle using coordinates of the centers, high (X axis) and width (y axis)

So i code consist of 3 parts 2 classes and test.
This is code for test
#Test
public void testRectangle1() {
Point center = new Point(20, 30);
Rectangle rect = new Rectangle(center, 20, 20);
assertAll(
() -> assertEquals(10, rect.getTopLeft().getX()),
() -> assertEquals(20, rect.getTopLeft().getY()),
() -> assertEquals(30, rect.getBottomRight().getX()),
() -> assertEquals(40, rect.getBottomRight().getY()),
() -> assertEquals(20, rect.getWidth()),
() -> assertEquals(20, rect.getHeight())
);
}
Class Point works fine, and i am ading it just for clarity
public class Point {
private int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public Point() {
this(0, 0);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void moveTo(int newX, int newY) {
x = newX;
y = newY;
}
public void moveRel(int dx, int dy) {
x += dx;
y += dy;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + x;
result = prime * result + y;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Point other = (Point) obj;
if (x != other.x)
return false;
if (y != other.y)
return false;
return true;
}
}
This is class for Rectangle itself, and it includes both constructor and aditional methods.
public class Rectangle {
public int width = 0;
public int height = 0;
public Point center;
public Rectangle(Point center, int width, int height) {
int x = 0;
int y = 0;
width=x;
height=y;
}
public Point getTopLeft() {
Point point = new Point(center.getX(), center.getY());
point.moveRel(- width / 2, height / 2);
return point;
}
public Point getBottomRight() {
Point point = new Point(center.getX(), center.getY());
point.moveRel(width / 2, - height / 2);
return point;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
}
Main problem is that this code return only zeroes in tests, i guess problem is in rectangle class in constructor, or aditionalmethods.
Your constructor for Rectangle is always setting width and height to 0. I think the constructor should look something like...
public Rectangle(Point center, int width, int height) {
int x = 0;
int y = 0;
this.width=width;
this.height=height;
this.center=center;
}

Finding if the x and y coordinate is within a view is enclosed by two intersecting rectangles, in java

Say I have this view with two subviews A and B, A and B has a color property mColor,
I want a function in the parent view that has this signature: int getColor(int x, int y), which for any given x and y coordinate, return the color at that position, if the x and y coordinates land and the two shapes are overlapped, return the average color of A and B
The problem I am running into is i see myself doing a lot of conditional checks, checking if A is left of B or if A is right of B etc. I feel like I am missing some key intuition
I have a Point class that handles the coordinates"
public class Point {
private final int mX;
private final int mY;
public Point(int mX, int mY) {
this.mX = mX;
this.mY = mY;
}
public int getX() {
return mX;
}
public int getY() {
return mY;
}
}
Here is my subview class:
public class Chart {
private int mColor;
private Point mTopLeft;
private Point mBottomRight;
public Point getTopLeft() {
return mTopLeft;
}
public Point getBottomRight() {
return mBottomRight;
}
public Chart(int mColor, Point topLeft, Point bottomRight) {
this.mColor = mColor;
this.mTopLeft = topLeft;
this.mBottomRight = bottomRight;
}
public int getColor() {
return mColor;
}
public Point getTopRightCorner() {
return new Point(getBottomRight().getX(), getTopLeft().getY());
}
public Point getBottomLeftCorner() {
return new Point(getTopLeft().getX(), getBottomRight().getY());
}
}
My parent view class:
public class View {
private Chart mChartA;
private Chart mChartB;
public View(Chart chartA,
Chart chartB) {
mChartA = chartA;
mChartB = chartB;
}
public boolean doChartsOverlap() {
boolean isOverlapped = true;
if(isChartALeftOfChartBInX() || isChartARightOfChartBInX()) {
isOverlapped = false;
}
if(isChartABottomOfChartBInY() || isChartATopOfChartBInY()) {
isOverlapped = false;
}
return isOverlapped;
}
public final boolean isChartALeftOfChartBInX() {
return mChartA.getBottomRight().getX() <= mChartB.getTopLeft().getX();
}
public final boolean isChartARightOfChartBInX() {
return mChartA.getTopLeft().getX() >= mChartB.getBottomRight().getX();
}
public final boolean isChartATopOfChartBInY() {
return mChartA.getBottomRight().getY() <= mChartB.getTopLeft().getY();
}
public final boolean isChartABottomOfChartBInY() {
return mChartA.getTopLeft().getY() >= mChartB.getBottomRight().getY();
}
public void setChartA(Chart mChartA) {
this.mChartA = mChartA;
}
public void setChartB(Chart mChartB) {
this.mChartB = mChartB;
}
}
Logically, you want to test if the point is in both rectangles; so test if it is in one rectangle and also in the other rectangle. Everything else about whether one rectangle is above, below, left or right of the other is a red herring.
Add this method to the Chart class (use < instead of <= if you only want to paint the interiors):
public boolean contains(Point p) {
return mTopLeft.getX() <= p.getX() && p.getX() <= mBottomRight.getX()
&& mTopLeft.getY() <= p.getY() && p.getY() <= mBottomRight.getY();
}
And this method to the View class:
public int getColor(Point p) {
boolean inA = mChartA.contains(p), inB = mChartB.contains(p);
if(inA && inB) {
// ...
} else if(inA) {
// ...
} else if(inB) {
// ...
} else {
// ...
}
}
You can then overload public int getColor(int x, int y) to return getColor(new Point(x, y)).
Rectangle r1 = new Rectangle(x1, y1, width1, height1 );
Rectangle r2 = new Rectangle(x2, y2, width2, height2);
if ( r1.contains( x3, y3 ) && r2.contains( x3, y3 ) ) {
// (x3,y3) is in both rectangles
}

How to handle the collision between two arraylist objects?

I have a problem with my code here. I want to make a game with thow ball on each side of screen, on ball being controlled by the user and the other one by the computer. Both ball shoot to each other, and if the bullets intersects one with another, i need to make something happen. I managed to do some thing here, and I have two class, one for the player bullets, and the other one for the enemies bullets, and the bullets are created trough arraylists. All works fin until now, but if I try ti make them collision with each other,it doesnt work at all. I've tried a lot of things but none of it worked, and I would really appreciate if someone could help me.
That is the Player Projectile class:
import java.awt.Rectangle;
public class Projectiles {
private int x, y, speedX;
private boolean visible;
private int width = 10;
private int height = 10;
private Rectangle r;
public Projectiles(){
}
public Projectiles(int startX, int startY) {
x = startX;
y = startY;
speedX = 1;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update(){
x += speedX;
r.setBounds(x, y, width, height);
if (x > 800){
visible = false;
r = null;
}
if (x < 800){
checkCollision();
}
}
private void checkCollision() {
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public Rectangle getR() {
return r;
}
public void setR(Rectangle r) {
this.r = r;
}
}
And this one is the Enemy_Projectile class:
import java.awt.Rectangle;
public class Enemy_Projectiles {
private int x, y, speedX;
private boolean visible;
private int width = 30;
private int height = 20;
public static Rectangle r;
Projectiles p1;
public Enemy_Projectiles(int startX, int startY) {
x = startX;
y = startY;
speedX = 1;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update() {
x -= speedX;
r.setBounds(x, y, width, height);
if (x < 0) {
visible = false;
r = null;
}
if (x > 0){
checkCollision();
}
}
private void checkCollision() {
if(r.intersects(p1.getR())){
visible = false;
System.out.println("Coliziune!!");
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
}
Do not check intersection after the frame has been drawn. Let's say you have a slow computer and your bullets intersect, but they have moved out of intersection in one frame.
You need to apply high school physics/geometry. Calculate where the bullet will be well before you render it. Then, calculate where the ball will be, and construct a line segment for each from where they are now, to where they will be on the next frame. Check if these segments intersect. Then you will have a fool-proof method of checking for intersection.
This method is similar to how physics and intersections between objects are handled inside of a game engine like Unity.

mass change values of arraylist

I have array list of circles, whitch are drawing by canvas. And everything is OK. But I need change all X,Y coordinates of circles, by during the program.
static ArrayList<Circle> mCircles;
private static void createCircles() {
if (mCircles == null) {
mCircles = new ArrayList<Circle>();
}
int rana = 66/(koeficient);
mCircles.add(new Circle(80, 200, rana));
}
public static void AddCircle() {
int rana = 66/(koeficient);
mCircles.add(new Circle(80, 200, rana));
}
private void Drawing(Canvas canvas) {
for (Circle c : mCircles) {
canvas.drawCircle(c.getCurrentX(), c.getCurrentY(), c.getRadius(),
mMalovani);
}
}
public static Circle findCircleClosestToTouchEvent(float x, float y) {
Circle c = mCircles.get(mCircles.size() - 1);
return c;
}
public class Circle extends Shape {
final float mRadius;
public Circle(float x, float y, float r) {
super(x, y);
mRadius = r;
}
final float getRadius() {
return mRadius;
}
}
public class Shape extends Activity {
protected float mStartX = 0f;
protected float mStartY = 0f;
public float mCurrentX = 30f;
public float mCurrentY = 30f;
protected float mActionDownX;
protected float mActionDownY;
protected float mActionMoveOffsetX;
protected float mActionMoveOffsetY;
// x y coordinate of a move action
public Shape (float x, float y) {
mStartX = x;
mStartY = y;
mCurrentX = x;
mCurrentY = y;
}
public void setStartX(float x) { mStartX = x; }
public void setStartY(float y) { mStartY = y; }
public float getCurrentX() { return mCurrentX; }
public float getCurrentY() { return mCurrentY; }
public void setCurrentX(float x) { mCurrentX = x;
}
public void setCurrentY(float y) { mCurrentY = y; }
public void setActionMoveOffsetX(float x) { mActionMoveOffsetX = x; }
public void setActionMoveOffsetY(float y) { mActionMoveOffsetY = y; }
public float getActionMoveOffsetX() { return mActionMoveOffsetX; }
public float getActionMoveOffsetY() { return mActionMoveOffsetY; }
public void setActionDownX(float x) { mActionDownX = x; }
public void setActionDownY(float y) { mActionDownY = y; }
public float getActionDownX() { return mActionDownX; }
public float getActionDownY() { return mActionDownY; }
public void restoreStartPosition() {
mCurrentX = mStartX;
mCurrentY = mStartY;
}
}
Assuming you have setCurrentX and setCurrentY methods opposite the getter methods, just loop through the list of circles.
private void changeCoordinates(List<Circle> circles, int x, int y){
for(Circle c:circles){
c.setCurrentX(x);
c.setCurrentY(y);
}
}

Categories

Resources