Hello :) I'm totally lost. I have two balls on the screen, floating. Also I have a method that checks is there is a collision and a method name 'collide' that collides :)
When both balls goes in a straight line on each other it collides well. The problem is shown on the picture:
So, the methods are:
public final float ball_radius = 2.4f; // ball image has 48 width
public boolean isColliding(Ball ball)
{
distance = Math.sqrt((ball.image_center_x - this.image_center_x)*(ball.image_center_x - this.image_center_x)+(ball.image_center_y - this.image_center_y)*(ball.image_center_y - this.image_center_y));
if(distance <= 2*ball_radius)
return true;
/*
float sumRadius = 9.6f;
float sqrRadius = sumRadius * sumRadius;
float distSqr = (xd * xd) + (yd * yd);
if (distSqr <= sqrRadius)
{
return true;
}*/
return false;
}
void Collide(Ball ball1, Ball ball2)
{
double dx = (ball1.x - ball2.x) + dt * (ball1.vx - ball2.vx);
double dy = (ball1.y - ball2.y) + dt * (ball1.vy - ball2.vy);
// if collision swap velocities
if (Math.sqrt(dx * dx + dy * dy) <= 2*ball_radius) {
double tempx = ball1.vx;
double tempy = ball1.vy;
ball1.vx = ball2.vx;
ball1.vy = ball2.vy;
ball2.vx = tempx;
ball2.vy = tempy;
}
}
private void moveBalls(){
for (int i = 0; i < balls.size(); i++) {
Ball ball1 = balls.get(i);
for (int a = i + 1; a < balls.size(); a++) {
Ball ball2 = balls.get(a);
if(ball1.isColliding(ball2)) {
ball1.Collide(ball1, ball2);
checkHealthAndChangeColor(ball1, ball2);
}
//catchMP.start();
}
}
for (int i = 0; i < balls.size(); i++) {
balls.get(i).step();
}
}
Related
I am currently generating an isometric map which should allow some sprites to move randomly within its bounds. My sprites, or 'humans' do move within a specified constraint however it is not the correct boundaries I wish to set it to. Below is my code.
public class Human implements Entity {
private int[][] map;
public static final int TILE_WIDTH = 34;
public static final int TILE_HEIGHT = 34;
private int min = 100;
private int max = 200;
private Texture img;
// position variable
private Vector2 pos;
private float time;
public Human() {
img = new Texture(Gdx.files.internal("humanFF.png"));
// coordinates of human initial position
pos = new Vector2(9, 220);
// for locking movement if need be.
time = 2;
map = randomGenerator();
}
#Override
public void render(SpriteBatch batch) {
batch.draw(img, pos.x, pos.y);
}
#Override
public void update(float delta) {
time += delta;
Random rand = new Random();
int upperbound = 2;
double double_random = rand.nextDouble(upperbound);
// lock human, can only move once every 2 secs.
if (time > 0) {
move();
time = 0;
}
}
private void move() {
/** Calculation **/
for (int row = map.length - 1; row >= 0; row--) {
for (int col = map.length - 1; col >= 0; col--) {
float x = (col - row) * (TILE_WIDTH / 2f - 2);
float y = (col + row) * (TILE_HEIGHT / 4f);
}
}
// after calculation, mapWidth is 525 pixels.
int mapWidth = map.length * (TILE_WIDTH / 2 - 2);
// after calculation, mapHeight is 280 pixels.
int mapHeight = map.length * (TILE_HEIGHT / 4);
// Calculate the minimum and maximum x-coordinates.
float minX = 0;
float maxX = mapWidth - TILE_WIDTH;
if (maxX < 0) {
maxX = 0;
}
// max-x coordinate is 491.0. min-x coordinate is 0.0.
// Calculate the minimum and maximum y-coordinates.
float minY = 0;
float maxY = mapHeight - TILE_HEIGHT;
if (maxY < 0) {
maxY = 0;
}
// check the position of human against map boundaries
if (pos.x < minX) {
pos.x = minX;
} else if (pos.x > maxX) {
pos.x = maxX;
}
if (pos.y < minY) {
pos.y = minY;
} else if (pos.y > maxY) {
pos.y = maxY;
}
// min-y coordinate is 0.0, max-y coordinate is 246.0.
// a variable to store a random generated value between 100 and 200.
int a = (int) (Math.random() * (max - min + 1) + min);
float newX = pos.x;
float newY = pos.y;
// move up
if (a <= 125) {
newX -= 15;
newY += 8.5;
}
// move down
else if (a <= 150 && a > 125) {
newX += 15;
newY -= 8.5;
}
// move left
else if (a <= 175 && a > 150) {
newX -= 15;
newY -= 8.5;
}
// move right
else if (a <= 200 && a > 175) {
newX += 15;
newY += 8.5;
}
if (newX >= minX && newX <= maxX && newY >= minY && newY <= maxY) {
pos.x = newX;
pos.y = newY;
}
}
public int[][] randomGenerator() {
Random r = new Random();
int Size = r.nextInt(35, 36);
int[][] map = new int[Size][Size];
for(int row = 0; row < map.length; row++) {
for(int col = 0; col < map.length; col++) {
int Number = r.nextInt(10);
if(Number == 0) {
map[row][col] = 0;
} else if (Number == 1) {
map[row][col] = 1;
}
else if (Number == 2) {
map[row][col] = 2;
}
else if (Number == 3) {
map[row][col] = 3;
}
else if (Number == 4) {
map[row][col] = 4;
}
else if (Number == 5) {
map[row][col] = 5;
}
else if (Number < 8) {
map[row][col] = 6;
}
else {
map[row][col] = 7;
}
}
}
map[0][0] = 1;
return map;
}
}
Based on the above, I am generating a random value which defines the movement of my 'humans' thus adding or subtracting from their x and y positions. In my attempt to tackle the problem of these sprites moving outside of my isometric map, I tried to calculate my mapWidth, mapHeight, min-x, max-x, min-y and max-x and then checking the position of my human against these boundaries to determine their movement.
Although these sprites now move within a constraint, it is not same dimension as my isometric map, but are now constrained to a rectangular-shaped boundary. How do I modify my code so that the sprites only move within the isometric map I have generated?
Below is a photo for visualisation.
The coordinate system you use for Human enties is ordinary orthogonal, you don't map these coordinates to an isometric view but you -have to- map them onto the isometric background. Screen coordinate system is basically different from the isometric one. When you render you need to map coordinates so that
(0,0)-> left corner
(0,maxY)->top corner
(maxX,maxY)->right corner
(maxX,0)->bottom corner
See here for to and back(map screen touch events to the map etc) conversion LibGdx render a sprite on top of a isometric tile
can anyone tell me what i'm doing wrong? i'm trying to get the circles to bounce off each other but they don't seem to be working.i keep making changes to fix the issue but that only makes more issues, whilst the main issue isn't resolved. have i used the wrong math's algorithm to check for collisions? or is it right and i have just made an error i cant seem to find? any help would be appreciated.
public float[][] CreateDots() {
if (first == true) {
for (int i = 0; i < dotNumber; i++) {
do{
dotX = r.nextInt(300);
dotY = r.nextInt(300);
dotWidth = r.nextFloat() * 50;
dotRadius = dotWidth / 2;
dotMass = r.nextFloat() / 10;
dotCentreX = dotX + dotRadius;
dotCentreY = dotY + dotRadius;
dotVelocityX = r.nextFloat();
dotVelocityY = r.nextFloat();
dots[i][0] = dotX;
dots[i][1] = dotY;
dots[i][2] = dotVelocityX;
dots[i][3] = dotVelocityY;
dots[i][4] = dotRadius;
dots[i][5] = dotCentreX;
dots[i][6] = dotCentreY;
dots[i][7] = dotMass;
dots[i][8] = dotWidth;
}while(collision == true);
}
first = false;
} else {
for (int i = 0; i < dotNumber; i++) {
dots[i][0] = dots[i][0] + dots[i][2];
dots[i][1] = dots[i][1] + dots[i][3];
if (dots[i][0] + dots[i][8] >= wallX) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] + dots[i][8] >= wallY) {
dots[i][3] = -dots[i][3];
}
if (dots[i][0] < 0) {
dots[i][2] = -dots[i][2];
}
if (dots[i][1] < 0) {
dots[i][3] = -dots[i][3];
}
}
}
repaint();
return dots;
}
public void bounce() {
collisionDot = false;
for (int i = 0; i < dotNumber; i++) {
for (int a = i + 1; a < dotNumber; a++) {
// difference between the x and y velocity of two dots
float xVelDiff = dots[i][2] - dots[a][2];
float yVelDiff = dots[i][3] - dots[a][3];
//difference between the centre x and y of two dots
float xDist = dots[i][5] - dots[a][5];
float yDist = dots[i][6] - dots[a][6];
System.out.println(xVelDiff + " * " + xDist + " + " + yVelDiff + " * " + yDist + " = "+ (xVelDiff * xDist + yVelDiff * yDist));
//not quite sure yet
if (xVelDiff * xDist + yVelDiff * yDist <= 0) {
angleCollision = (float) -Math.atan2(dots[a][0] - dots[i][0], dots[a][1] - dots[i][1]);
float mass = (dots[i][7] + dots[a][7]);
float mass2 = (dots[i][7] - dots[a][7]);
// x and y velocity and angle of collision for the two dots
float[] u1 = rotate(dots[i][2], dots[i][3], (float) angleCollision);
float[] u2 = rotate(dots[a][2], dots[a][3], (float) angleCollision);
//Velocity of dot 1
float[] v1 = new float[2];
v1[0] = u1[0] * mass2 / mass + u2[0] * 2 * dots[a][7] / (mass);
v1[1] = u1[1];
// velocity of dot 2
float[] v2 = new float[2];
v2[0] = u2[0] * mass2 / mass + u1[0] * 2 * dots[a][7] / (mass);
v2[1] = u2[1];
// final velocity of two colliding dots is:
float[] vFinal1 = rotate(v1[0], v1[1], (float) -angleCollision);;
float[] vFinal2 = rotate(v2[0], v2[1], (float) -angleCollision);;
if (a != i && !(dots[a][0] == 0 && dots[a][1] == 0)) {
// if the x and y distance between the two dots centres is less than their radii combined then the dots have collided
boolean thisCollision = Math.pow(xDist, 2) + Math.pow(yDist, 2) <= Math.pow((dots[a][4] + dots[i][4]), 2);
//if the dots collided, create new final velocity's from the angle of collision and the x and y velocitys at collision
if (thisCollision) {
collisionDot = true;
dots[i][2] = vFinal1[0];
dots[i][3] = vFinal1[1];
dots[a][2] = vFinal2[0];
dots[a][3] = vFinal2[1];
return;
}
}
}
}
}
}
public float[] rotate(float velocityX, float velocityY, float angle) {
float x1 = (float) (velocityX * Math.cos(angle) - velocityY * Math.sin(angle));
float y1 = (float) (velocityX * Math.sin(angle) - velocityY * Math.cos(angle));
float vel[] = new float[2];
vel[0] = x1;
vel[1] = y1;
return vel;
}
I have a set of methods in my platformer in progress to detect and resolve collisions between entities and the tilemap, but they are doing a bad job of it.
The bottom method is the one being called, like this:
player.velocity = player.velocity.add(getFinalCollisionVector());
where player.velocity is a Vec2D.
private List<Rectangle2D> getCollidingTiles(){
List<Rectangle2D> collidingTiles = new ArrayList<Rectangle2D>();
for(int x = (int) (this.getX()/Tile.SIZE); x <= (int) (this.getX()/Tile.SIZE) + this.getRect2D().getWidth()/Tile.SIZE; x++){
for(int y = (int) (this.getX()/Tile.SIZE); y <= (int) (this.getX()/Tile.SIZE) + this.getRect2D().getHeight()/Tile.SIZE; y++){
if(map.getTileAt(x, y).getAttribute(Attribute.SOLID))
if(map.getCollisionBoxAt(x,y).isColliding(this.collisionBox))
collidingTiles.add(new Rectangle2D.Double(x, y, Tile.SIZE, Tile.SIZE));
}
}
return collidingTiles;
}
private List<Vec2D> getAllTileCollisionVectors(){
List<Rectangle2D> collidingTiles = getCollidingTiles();
List<Vec2D> collisionVectors = new ArrayList<Vec2D>();
for(Rectangle2D rec : collidingTiles){
collisionVectors.add(getCorrectionVector(rec));
}
return collisionVectors;
}
private Vec2D getCorrectionVector(Rectangle2D target)
{
Vec2D ret = new Vec2D();
double x1 = (this.getX() + this.getSize().x) - target.getX();
double x2 = this.getX() - (target.getX() + target.getWidth());
double y1 = (this.getY() + this.getSize().y) - target.getY();
double y2 = this.getY() - (target.getY() + target.getHeight());
// calculate displacement along X-axis
if (x1 < x2)
{
ret.x = x1;
}
else if (x1 > x2)
{
ret.x = x2;
}
// calculate displacement along Y-axis
if (y1 < y2)
{
ret.y = y1;
}
else if (y1 > y2)
{
ret.y = y2;
}
return ret;
}
protected Vec2D getFinalCollisionVector(){
List<Vec2D> collisionVectors = getAllTileCollisionVectors();
if(collisionVectors.size() < 1)
return new Vec2D(0,0);
Vec2D finalVector = new Vec2D();
for(Vec2D vec : collisionVectors){
finalVector = finalVector.add(vec);
}
return finalVector;
}
What am I doing wrong in my code? This is the behavior that the player shows, where he falls (due to gravity) to that point, and then he freezes.
OP here:
Since there are no other answers, I've posted my own.
I've abandonded the old implementation,started from the ground up, and it works now. This is the new implementation:
public Corners getCornersAreSolid(double x, double y) {
int leftTile = (int)(x / Tile.SIZE);
int rightTile = (int)((x + moveData.collisionBox.getWidth()) / Tile.SIZE);
int topTile = (int)(y / Tile.SIZE);
int bottomTile = (int)((y + moveData.collisionBox.getHeight()) / Tile.SIZE);
boolean topLeft = hasAttribute(map, Attribute.SOLID, topTile, leftTile);
boolean topRight = hasAttribute(map, Attribute.SOLID, topTile, rightTile);
boolean bottomLeft = hasAttribute(map, Attribute.SOLID, bottomTile, leftTile);
boolean bottomRight = hasAttribute(map, Attribute.SOLID, bottomTile, rightTile);
Corners solidCorners = new Corners();
solidCorners.topLeft = topLeft;
solidCorners.topRight = topRight;
solidCorners.bottomRight = bottomRight;
solidCorners.bottomLeft = bottomLeft;
return solidCorners;
}
private boolean hasAttribute(GameMap map, Attribute attribute, int tileY, int tileX) {
boolean result = false;
if (tileX >= 0 && tileX < map.getWidthInTiles() && tileY >= 0 && tileY < map.getHeightInTiles()) {
result = map.getTileAt(tileX, tileY).getAttribute(attribute);
}
return result;
}
public Vec2D getNextPosition() {
int currCol = (int) (getX() / Tile.SIZE);
int currRow = (int) (getY() / Tile.SIZE);
double destX = getX() + moveData.velocity.x;
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;
this.framesSinceLastCollision += 1;
if(moveData.velocity.y < 0) {
if(topLeft || topRight) {
moveData.velocity.y = 0;
tempY = currRow * Tile.SIZE;
this.framesSinceLastCollision = 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 ;
this.framesSinceLastCollision = 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;
this.framesSinceLastCollision = 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 ;
this.framesSinceLastCollision = 0;
}
else {
tempX += moveData.velocity.x;
}
}
return new Vec2D(tempX, tempY);
}
private static class Corners{
public boolean topLeft, topRight;
public boolean bottomLeft, bottomRight;
public Corners(){
topLeft = false;
topRight = false;
bottomLeft = false;
bottomRight = false;
}
}
I currently loop through all my sprites checking if they intersect with each other like this:
for (Sprite s : sprites) {
if (s.dead) {
dead.add(s);
}
for (Sprite sprite : sprites) {
if (!sprite.equals(s)) {
s.collide(sprite, maxX, maxY);
}
}
s.run();
}
and the sprite checks using the Rect.intersects() method like so:
if (getRect().intersects(s.getRect()))
But sometimes it just completely ignores a collision, and the objects just pass through each other.
Any ideas?
You should try changing the code to
if(getRect().intersects(s.getRect()) || s.getRect().intersects(getRect()))
{
// They have intersected
}
The reason for this being, the intersection method check is unique for each rectangle. Performing an intersection check to see if rectangle a intersects rectangle b, is different than performing an intersection check to see if rectangle b intersects rectangle a.
Other than this, can you give me more information on your rectangles? Are they rotating? How fast are they moving? How large are they? Other information would be use full as well, I can try to think of other reasons for why they are not colliding.
I fixed it by making it create a rectangle for the area that it covers between frames like so:
private void checkForNextCollision() {
double boundsWidth = width + dX ;
if(dX < 0){
boundsWidth= width - dX ;
}
double boundsHeight = height + dY ;
if(dY < 0){
boundsHeight = height - dY ;
}
double boundx = xWorld + dX ;
double boundy = yWorld + dY ;
betweenRect = new Rectangle((int)(boundx),(int)(boundy),(int)(boundsWidth), (int)(boundsHeight));
}
This rectangle is then checked against the rectangle created in the other sprites to check if there should be a collision in the next frame:
public void collide(Sprite s, int maxX, int maxY) {
maxWX = maxX;
maxWY = maxY;
//check for collision with borders
if (xWorld <= 0) {
dX = -dX;
xWorld += 2;
if(xWorld < -1000){
dX = 0;
xWorld += 10;
}
}
if (yWorld <= 0) {
dY = -dY;
yWorld += 2;
if(yWorld < -1000){
dX = 0;
yWorld += 10;
}
}
if (xWorld + width >= maxX) {
dX = -dX;
xWorld -= 2;
if(xWorld+width > maxX + 1000){
dX = 0;
xWorld -= 10;
}
}
if (yWorld + height >= maxY) {
dY = -dY;
yWorld -= 2;
if(yWorld+height > maxY + 1000){
dY = 0;
yWorld -= 10;
}
}
//check for collision with borders
if(betweenRect.intersects(s.betweenRect)){
willIntersect = true;
}else{
willIntersect = false;
}
// Use all checks to see if they should collide
if (getRect().intersects(s.getRect()) || s.getRect().intersects(getRect()) || willIntersect || (xWorld + width > s.xWorld && xWorld < s.xWorld + s.width && yWorld < s.yWorld+s.height && yWorld + height > s.yWorld) ) {
double lastDy = dY;
double lastsDy = s.dY;
double lastDx = dX;
double lastsDx = s.dX;
dY = (((weight - s.weight) / (weight + s.weight)) * lastDy)
+ (((2.0 * s.weight) / (weight + s.weight)) * lastsDy);
s.dY = (((s.weight - weight) / (weight + s.weight)) * lastsDy)
+ (((2.0 * weight) / (weight + s.weight)) * lastDy);
dX = (((weight - s.weight) / (weight + s.weight)) * lastDx)
+ (((2.0 * s.weight) / (weight + s.weight)) * lastsDx);
s.dX = (((s.weight - weight) / (weight + s.weight)) * lastsDx)
+ (((2.0 * weight) / (weight + s.weight)) * lastDx);
if(willIntersect){
willIntersect = false;
//s.willIntersect = false;
}
}
}
Ok i know this is sort of a non specific question but i am making a verlet integration physics engine for a game similar to, for example angry birds. I am writing a practice engine just to get the jist of it (credits for simpler c++ version go to Benedikt Bitterli) and no matter what i do i cant figure out how to implement friction. I posted the main collision and caluculation methods below if someone could at least tell me where or in which method i should add something and the name of the techneque or somthing.
private void updateVerlet() {
float tempX;
float tempY;
for (int b = 0; b < bodies.size(); b++) {
for (int i = 0; i < bodies.get(b).vertices.size(); i++) {
Vertex v = bodies.get(b).vertices.get(i);
tempX = v.x;
tempY = v.y;
v.x += v.x - v.ox + v.accx * timestep * timestep;
v.y += v.y - v.oy + v.accy * timestep * timestep;
v.ox = tempX;
v.oy = tempY;
}
}
}
private void updateEdges() {
for (int b = 0; b < bodies.size(); b++) {
for (int i = 0; i < bodies.get(b).edges.size(); i++) {
Edge e = bodies.get(b).edges.get(i);
float distX = e.v2.x - e.v1.x;
float distY = e.v2.y - e.v1.y;
float dist = (float)Math.hypot(distX, distY);
float diff = dist - e.length;
float len = 1f / (float)Math.hypot(distX, distY);// Normalize with (float)Math.hypot(distX, distY); again????
distX *= len;
distY *= len;
e.v1.x += distX * diff * 0.5;
e.v1.y += distY * diff * 0.5;
e.v2.x -= distX * diff * 0.5;
e.v2.y -= distY * diff * 0.5;
}
}
}
private void iterateCollisions() {
for (int iteration = 0; iteration < iterations; iteration++) {
// Temporary solution to prevent bodies from falling out of the screen
for (int b = 0; b < bodies.size(); b++) {
for (int i = 0; i < bodies.get(b).vertices.size(); i++) {
bodies.get(b).vertices.get(i).x = Math.max(Math.min(bodies.get(b).vertices.get(i).x, (float)screenWidth), 0.0f);
bodies.get(b).vertices.get(i).y = Math.max(Math.min(bodies.get(b).vertices.get(i).y, (float)screenHeight), 0.0f);
}
}
updateEdges();
for (int b = 0; b < bodies.size(); b++) {
bodies.get(b).calculateCenter();
}
for (int b1 = 0; b1 < bodies.size(); b1++) {
for (int b2 = 0; b2 < bodies.size(); b2++) {
if (bodies.get(b1) != bodies.get(b2)) {
if (bodiesOverlap(bodies.get(b1), bodies.get(b2))) {
if (detectCollision(bodies.get(b1), bodies.get(b2))) {
processCollision();
}
}
}
}
}
}
}
private boolean bodiesOverlap(PhysicsBody b1, PhysicsBody b2) {
return
(b1.minX <= b2.maxX) &&
(b1.minY <= b2.maxY) &&
(b1.maxX >= b2.minX) &&
(b2.maxY >= b1.minY);
}
private boolean detectCollision(PhysicsBody b1, PhysicsBody b2) {
float minDistance = 10000.0f;
Edge e;
for (int i = 0; i < b1.edges.size() + b2.edges.size(); i++) {
if (i < b1.edges.size()) {
e = b1.edges.get(i);
} else {
e= b2.edges.get(i - b1.edges.size());
}
if (!e.boundary)
continue;
axis.x = e.v1.y - e.v2.y;
axis.y = e.v2.x - e.v1.x;
float len = 1f / (float)Math.hypot(axis.x, axis.y);
axis.x *= len;
axis.y *= len;
MinMax dataA = b1.projectToAxis(axis);
MinMax dataB = b2.projectToAxis(axis);
float distance = intervalDistance(dataA, dataB);
if (distance > 0f)
return false;
else if (Math.abs(distance) < minDistance) {
minDistance = Math.abs(distance);
CollisionInfo.normalX = axis.x;
CollisionInfo.normalY = axis.y;
CollisionInfo.e = e;
}
}
CollisionInfo.depth = minDistance;
if (CollisionInfo.e.parent != b2) {
PhysicsBody temp = b2;
b2 = b1;
b1 = temp;
}
float diffX = b1.centerX - b2.centerX;
float diffY = b1.centerY - b2.centerY;
float mult = CollisionInfo.normalX * diffX + CollisionInfo.normalY * diffY;
if (mult < 0) {
CollisionInfo.normalX = 0 - CollisionInfo.normalX;
CollisionInfo.normalY = 0 - CollisionInfo.normalY;
}
minDistance = 10000.0f;
for (int i = 0; i < b1.vertices.size(); i++) {
diffX = b1.vertices.get(i).x - b2.centerX;
diffY = b1.vertices.get(i).y - b2.centerY;
float distance = CollisionInfo.normalX * diffX + CollisionInfo.normalX * diffY;
if (distance < minDistance) {
minDistance = distance;
CollisionInfo.v = b1.vertices.get(i);
}
}
return true;
}
private void processCollision() {
Vertex v1 = CollisionInfo.e.v1;
Vertex v2 = CollisionInfo.e.v2;
float collisionVectorX = CollisionInfo.normalX * CollisionInfo.depth;
float collisionVectorY = CollisionInfo.normalY * CollisionInfo.depth;
float t;
if (Math.abs(v1.x - v2.x) > Math.abs(v1.y - v2.y)) {
t = (CollisionInfo.v.x - collisionVectorX - v1.x) / (v2.x - v1.x);
}
else {
t = (CollisionInfo.v.y - collisionVectorY - v1.y) / (v2.y - v1.y);
}
float lambda = 1.0f / (t * t + (1 - t) * (1 - t));
float edgeMass = t * v2.parent.mass + (1f - t) * v1.parent.mass;
float invCollisionMass = 1.0f / (edgeMass + CollisionInfo.v.parent.mass);
float ratio1 = CollisionInfo.v.parent.mass * invCollisionMass;
float ratio2 = edgeMass*invCollisionMass;
v1.x -= collisionVectorX * ((1 - t) * ratio1 * lambda);
v1.y -= collisionVectorY * (( 1 - t) * ratio1 * lambda);
v2.x -= collisionVectorX * (t * ratio1 * lambda);
v2.y -= collisionVectorY * (t * ratio1 * lambda);
CollisionInfo.v.x += collisionVectorX * ratio2;
CollisionInfo.v.y += collisionVectorY * ratio2;
}
try this code, friction on the bottom world boundary
for every particle, limit horizontal movement.
if(Particle.Y >= world_height) { Particle.OldX = Particle.OldX - (Particle.OldX - Particle.X)/2; }