Im working with Box2D on LibGDX, and I'm working with bodies and collisions etc..
HERE, i had the problem of a body colliding with another, when it shouldn't do that.
Now after Knowing that i need to use ChainShapes, i started with that.
Whenever u run my project, i get an assertion error:
Assertion failed: (count >= 2), function CreateChain, file
/Users/tom/Coding/slave/workspace/libgdx-mac/extensions/gdx-box2d/gdx-box2d/jni/Box2D/Collision/Shapes/b2ChainShape.cpp,
line 62.
So i tried a small debug to print the vertex count, and the vertex out printed as 0.
Problem is that i am adding the vertices and they dont appear to be added...
Code for adding verticies:
chain = new ChainShape();
chain.setNextVertex(new Vector2((posx - size) / PPM, (posy + size) / PPM));
chain.setNextVertex(new Vector2((posx + size) / PPM, (posy + size) / PPM));
chain.setNextVertex(new Vector2((posx + size) / PPM, (posy - size) / PPM));
chain.setNextVertex(new Vector2((posx - size) / PPM, (posy - size) / PPM));
System.out.println(chain.getVertexCount());
Vertex count is printed as 0, thats why i am getting the error, I dont know how to fix it, so please help :)
Create your ChainShape in this way :
ChainShape chain=new ChainShape();
Vector2 vector[]=new Vector2[4];
vector[0]=new Vector2((posx - size) / PPM, (posy + size) / PPM);
vector[1]=new Vector2((posx + size) / PPM, (posy + size) / PPM);
vector[2]=new Vector2((posx + size) / PPM, (posy - size) / PPM);
vector[3]=new Vector2((posx - size) / PPM, (posy - size) / PPM);
chain.createChain(vector);
System.out.println(chain.getVertexCount()); // 4 on console
If still you've problem, check the value of posx, posy, size , PPM
Related
I am trying to rotate a sprite in an android app using LibGDX. I have used sprite.rotate and sprite.setRotation in an attempt to rotate the sprite, but none have worked.
public Cannon(){
cannend = new Texture("cannonend.png");
cannon = new Sprite(cannend, (Gdx.graphics.getWidth() / 2) - (cannend.getWidth() / 2) + 3, (Gdx.graphics.getHeight() / 2) + (Gdx.graphics.getHeight() / 6), (cannend.getWidth()), (cannend.getHeight()));
cannon.setPosition((Gdx.graphics.getWidth()/ 2) - (cannend.getWidth() / 2) + 3, (Gdx.graphics.getHeight() / 2) + (Gdx.graphics.getHeight() / 6));
cannon.setRotation(70);
cannon.setCenter((Gdx.graphics.getWidth()/ 2) - (cannend.getWidth() / 2), (Gdx.graphics.getHeight() / 2) + (Gdx.graphics.getHeight() / 6) - (cannend.getWidth() / 2));
}
When I draw this sprite in my Playstate class this is the code that I use.
public PlayState(GameStateManager gsm) {
super(gsm);
cannon = new Cannon();
cannontop = new Texture("Cannon.png");
man = new Man(0, (Gdx.graphics.getHeight() / 4));
bg = new Texture("background.png");
cam.setToOrtho(false, 2160, 3840);
}
//skipped some irrelevant code
#Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(bg, cam.position.x - (cam.viewportWidth / 2), 0);
sb.draw(man.getTexture(), man.getPosition().x, man.getPosition().y);
sb.draw(cannontop, (bg.getWidth()/ 2) - (cannon.getTextureWidth() / 2) - 23, (bg.getHeight() / 2) + (bg.getHeight() / 5));
sb.draw(cannon.getTexture(), (bg.getWidth()/ 2) - (cannon.getTextureWidth() / 2), (bg.getHeight() / 2) + (bg.getHeight() / 5) - (cannontop.getWidth() / 2) + 8);
sb.end();
}
I have just learnt Java, so please forgive me if some of my code is bad. I have also added and taken away single pixels for the widths and heights when drawing things - I'm not sure whether this is ok, as I normally use ratios because they dont seem to affect gameplay when screen sizes change. Anyway, what could I use to rotate the sprite a certain amount every frame? Also, what does sprite.getX() do?
Thanks.
You are not drawing sprite you are drawing texture of sprite.
sprite.draw(batch);
I am creating a rope with a series of Box2D bodies with the following code:
public void create(float length, float ropeLength){
Array<Body> bodies = new Array<Body>();
bodies.add(BodyFactory.createBox(world, position.x, position.y, length, length, BodyType.StaticBody, 0, 0, 0, "RopeMain"));
for(int i = 1; i < ropeLength; i++){
bodies.add(BodyFactory.createBox(world, position.x, position.y - (((length/2) / Core.PPM) * i),
length, length, BodyType.DynamicBody, 0, 0, 0, "RopeBody" + i));
RopeJointDef rDef = new RopeJointDef();
rDef.bodyA = bodies.get(i - 1);
rDef.bodyB = bodies.get(i);
rDef.collideConnected = true;
rDef.maxLength = (length/2)/Core.PPM;
rDef.localAnchorA.set(position.x, -((length / 2) / Core.PPM));
rDef.localAnchorB.set(position.x, ((length / 2) / Core.PPM));
world.createJoint(rDef);
}
}
Allow me to share some parameters...
For BodyFactory.createBox it requires the following:
world, xPos, yPos, width, height BodyType, density, friction, restitution, fixture user data.(length is same because it uses boxes)
Core.PPM is the pixels per meter. Also note that the position is being divided by PPM in the constructor.
Question: why do the following lines shoot to the right?
Any info is very helpful, also how will density, friction, and restitution affect the rope? Thanks!
The joint's localAnchor is relative to the center of the body and isn't an absolute value. That means that if you want to set the joint to the center-bottom of bodyA and center-top of bodyB you need to use
rDef.localAnchorA.set(0, -((length / 2) / Core.PPM));
rDef.localAnchorB.set(0, ((length / 2) / Core.PPM));
I'm currently working on a simple textured rectangle class using LWJGL (GL11). This is what I have so far in the draw method.
glEnable(GL_TEXTURE_2D);
color.bind();
glBegin(GL_QUADS);
t.bind();
if (centered)
{
glTexCoord2d(0, 0);
glVertex2d(x - (width / 2), y - (height / 2));
glTexCoord2d(t.getWidth(), 0);
glVertex2d(x + (width / 2), y - (height / 2));
glTexCoord2d(t.getWidth(), t.getHeight());
glVertex2d(x + (width / 2), y + (height / 2));
glTexCoord2d(0, t.getHeight());
glVertex2d(x - (width / 2), y + (height / 2));
}
else
{
glTexCoord2d(0, 0);
glVertex2d(x, y);
glTexCoord2d(t.getWidth(), 0);
glVertex2d(x + width, y);
glTexCoord2d(t.getWidth(), t.getHeight());
glVertex2d(x + width, y + height);
glTexCoord2d(0, t.getHeight());
glVertex2d(x, y + height);
}
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
The problem is with the second to last line (glBindTexture(GL_TEXTURE_2D, 0)). If I leave this on, the image will display for a split second (probably one frame) and then turn solid white. If I comment this out, it will display, but always displays the last texture that was loaded. Any ideas?
I think it's because you are binding your texture between the glBegin() and glEnd() calls. This is invalid. I'm guessing when you leave the glBindTexture(GL_TEXTURE_2D, 0) call off, then the binding is taking effect the next frame. Not sure why it would work for one frame, though.
You can use glGetError to see if there are any errors generated.
I'm in the process of building a isometric framework so far I've got the physical tile mapping algorithm down.
The thing is I don't want per tile collision, as in looping through all the tiles to check if my mouse is selecting a specific tile.
What I tried to accomplish is get cell index from the mouse using this.
int col = (int)(((double)mouse_x / (double)tileWidth) - ((double)mouse_y / (double)tileHeight) - 0.5);
int row = (int)(((double)mouse_y / (double)tileHeight) + ((double)mouse_x / (double)tileWidth) - 0.5);
But using this method my 0,15 is the 0,0 according to the mouse and the 0,0 is the 0,15.
So my question is how can I swap that around by editing the mouse code perhaps using offset?Even so I wouldn't know how, so my question is how.
I just went with the simple way out, instead of editing the initials equation.
I modified the outcome by:
int col = (int)(((double)mouse_x / (double)tileWidth) - ((double)mouse_y / (double)tileHeight) - 0.5);
int row = (int)(((double)mouse_y / (double)tileHeight) + ((double)mouse_x / (double)tileWidth) - 0.5);
row = mapHeight - row - 1;
This flips the outcome, and thus fixes my problem in a non-artistic equational manner.
From isometric coordinates to screen coordinates:
screenX = (isoX - isoY + isoMapMaxY) * (tileWidth / 2);
screenY = (isoX + isoY) * (tileHeight / 2);
From screen coordinates to isometric coordinates:
isoX = ( ((screenY + scrollY) / tileHeight) + ((screenX + scrollX) - (isoMapMaxY * tileWidth/2)) / tileWidth )
isoY = ( ((screenY + scrollY) / tileHeight) - ((screenX + scrollX) - (isoMapMaxY * tileWidth/2)) / tileWidth )
isoX = (screenY / 32) + (screenX - 320) / 64
isoY = (screenY / 32) - (screenX - 320) / 64
I'm just trying to code a nice looking physics game.
The ball collision looks nice but if the balls are colliding too slow, they "stick" in each other. I have no clue why they do.
Here's my collision function:
private void checkForCollision(ArrayList<Ball> balls) {
for (int i = 0; i < balls.size(); i++) {
Ball ball = balls.get(i);
if (ball != this && ball.intersects(this)) {
this.collide(ball, false);
}
}
}
public boolean intersects(Ball b) {
double dx = Math.abs(b.posX - posX);
double dy = Math.abs(b.posY - posY);
double d = Math.sqrt(dx * dx + dy * dy);
return d <= (radius + b.radius);
}
private void collide(Ball ball, boolean b) {
double m1 = this.radius;
double m2 = ball.radius;
double v1 = this.motionX;
double v2 = ball.motionX;
double vx = (m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);
v1 = this.motionY;
v2 = ball.motionY;
double vy = (m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);
if (!b)
ball.collide(this, true);
System.out.println(vx + " " + vy);
motionX = vx * BOUNCEOBJECT;
motionY = vy * BOUNCEOBJECT;
}
But this is what happens when they collide with a low speed:
So do you have an idea?
EDIT:
The update of Alnitak works very nice... but one problem is still there... if i add gravity like this:
public void physic() {
motionY += GRAVITY; // <= this part (GRAVITY is set to 0.3D)
checkForCollision(screen.balls);
keyMove();
bounceWalls();
posX += motionX;
posY += motionY;
}
They still move into each other. I think this is the wrong way to add gravity, or isn't it?
And I think I did something wrong with the collision formula, because they don't fall right:
!
and then they slowly sink into the ground.
EDIT:
found an AMAZING tutorial: http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html
This is a common problem that happens because sometimes the delta-v of the bouncing ball is insufficient to take it back out of the collision zone.
So the collision routine reverses the direction again, taking it back inside the other ball, ad-infinitum.
You should add a sufficient offset (in the direction of the collision force) to the position of the ball to ensure that the newly calculated positions are no longer colliding.
Alternatively, check whether the balls would collide once you add the new motion values:
public boolean intersects(Ball b) {
double dx = b.posX - (posX + motionX); // no need for Math.abs()
double dy = b.posY - (posY - motionY);
double d = dx * dx + dy * dy; // no need for Math.sqrt()
return d < (radius + b.radius) * (radius + b.radius);
}
but you should also change ball.intersects(this) to intersects(ball).
They may appear to collide slightly too early, but on a fast moving ball it probably won't be visible.
(m1 - m2) * v1 / (m1 + m2) + 2 * m2 * v2 / (m1 + m2);
This has an integer value 2. Please make it 2.0f or 2.0d then check it out. It must be the problem for small speeds. Becuse integer constant autocasts multiplied doubles.
If this does not work, then Alnitak 's answer would be helpful.
If you need real nice physics, you should use the force then convert it to velocity then convert it to displacement . Look at integrator techniques like Runge Kutta and Euler Integration
Force-->acceleration-->velocity-->displacement
if collision occurs, just update the force then the rest will be flowing.
----> http://codeflow.org/entries/2010/aug/28/integration-by-example-euler-vs-verlet-vs-runge-kutta/ <-----
http://www.forums.evilmana.com/game-programming-theory/euler-vs-verlet-vs-rk4-physics/
http://www.newagepublishers.com/samplechapter/001579.pdf
http://cwx.prenhall.com/bookbind/pubbooks/walker2/
Verlet integration is a point between Runge-Kutta-4 and Euler Integration preferably for molecular dynamics (a good example for bouncing balls if you ommit the electrical fields and bonds)
Just found an AMAZING tutorial:
http://www.ntu.edu.sg/home/ehchua/programming/java/J8a_GameIntro-BouncingBalls.html