Box2D crashes when destroying body (Expression: m_bodyCount < m_bodyCapacity) - java

Expression: m_bodyCount < m_bodyCapacity
That is the error I'm getting. The entire game crashes when I get this error. Now, here's the thing: I only get the error on certain I try to destroy, more specifically, bodies that were made during the game. What I mean is at the beginning of the game, I load the level and create all the bodies for each piece of the level. But, there are items that are made as the game runs, such as bullets, cannons, and coins. I can destroy any of the bodies created when the level is loaded, but when I try to destroy bodies created afterwards, I get the above error.
Here's an example. I spawn a CannonBall with my Cannon:
Cannon.class
if(reloadProgress >= RELOAD_TIME) {
CannonBall cannonBall = new CannonBall();
cannonBall.setXDirection(xDirection);
cannonBall.setYDirection(yDirection);
cannonBall.position.set(cannonBallPos);
Box2DHelper.makeFixture(cannonBall, BodyType.KinematicBody, origin, WorldController.b2world,
true, false);
Level.cannonBalls.add(cannonBall);
reloadProgress -= RELOAD_TIME;
} else {
reloadProgress += deltaTime;
}
Where Box2DHelper.makeFixture() is:
public static void makeFixture(GameObject object, BodyType type,
Vector2 origin, World b2world, boolean addUserData, boolean isMonster) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.position.set(object.position);
Body body = b2world.createBody(bodyDef);
if(addUserData)
body.setUserData(object);
object.body = body;
PolygonShape polygonShape = new PolygonShape();
origin.x = object.bounds.width / 2.0f;
origin.y = object.bounds.height / 2.0f;
polygonShape.setAsBox(object.bounds.width / 2.0f,
object.bounds.height / 2.0f, origin, 0);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
if(isMonster) fixtureDef.filter.groupIndex = Constants.GROUP_MONSTER;
body.createFixture(fixtureDef);
polygonShape.dispose();
}
So now I've created my CannonBall and set its body. Now, after 10 seconds, if it hasn't hit anything, I destroy it:
CannonBall.class
if (existanceDuration >= CANNON_BALL_EXISTANCE_DURATION) {
//Destroy cannon ball
CollisionHandler.bodiesToRemoveList.add(this.body);
}
Now that I have added the body into the list, I have to remove it:
CollisionHandler.class:
public static void removeSpecifiedBodies() {
Iterator<Body> i = bodiesToRemoveList.iterator();
while (i.hasNext()) {
Body desBod = i.next();
removeObjectFromList(desBod); //This is just to remove the object as well
WorldController.b2world.destroyBody(desBod);
if (perCharHitAction == true) {
performCharacterDeathAction(Level.character);
perCharHitAction = false;
}
i.remove();
}
bodiesToRemoveList.clear();
}
But now, I need to actually call this method. I do this in my main update method, right after b2world.step():
WorldController.class:
public void update(float deltaTime) {
...
b2world.step(deltaTime, 8, 3);
if (CollisionHandler.bodiesToRemoveList.size() > 0)
CollisionHandler.removeSpecifiedBodies();
Now, like I stated before, this method works fine when I destroy objects made at the loading of the level, but on objects I later create, it doesn't.
Why does my game keep crashing after trying to destroy box2d bodies later created in my game?
Edit: I call this method right after the level has loaded for creating the object's bodies:
private void initPhysics() {
if (b2world != null)
b2world.dispose();
b2world = new World(new Vector2(0, -9.81f), true);
Vector2 origin = new Vector2();
b2world.setContactListener(new CollisionHandler());
// Create Box2D Fixtures
for (Grass grass : Level.grasses)
Box2DHelper.makeEdgeChain(grass, BodyType.StaticBody, origin,
b2world, true);
// Bricks
for (Brick brick : Level.bricks)
// Box2DHelper.makeFixture(brick, BodyType.KinematicBody, origin,
// b2world, true);
Box2DHelper.makeEdgeChain(brick, BodyType.StaticBody, origin,
b2world, true);
// Item Boxes
for (ItemBox box : Level.itemBoxes)
Box2DHelper.makeFixture(box, BodyType.KinematicBody, origin,
b2world, true, false);
//Enemies
for (Goomba goomba : Level.goombas)
Box2DHelper.makeFixture(goomba, BodyType.DynamicBody, origin,
b2world, true, true);
for (Koopa koopa : Level.koopas)
Box2DHelper.makeFixture(koopa, BodyType.DynamicBody, origin,
b2world, true, true);
// Cannons
for (Cannon cannon : Level.cannons)
Box2DHelper.makeFixture(cannon, BodyType.KinematicBody, origin,
b2world, true, true);
// Character
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(Level.character.position);
Body body = b2world.createBody(bodyDef);
body.setUserData(Level.character);
Level.character.body = body;
CircleShape polygonShapeHead = new CircleShape();
origin.x = Level.character.circleBoundOrigin.x * 2.0f;
origin.y = Level.character.circleBoundOrigin.y * 3.0f;
// polygonShapeHead.setAsBox(level.character.circleBoundOrigin.x,
// level.character.circleBoundOrigin.y, origin, 0);
polygonShapeHead.setPosition(origin);
polygonShapeHead.setRadius(Level.character.circleBoundOrigin.x);
FixtureDef fixtureDefHead = new FixtureDef();
fixtureDefHead.shape = polygonShapeHead;
fixtureDefHead.friction = Level.character.friction.x;
body.createFixture(fixtureDefHead);
polygonShapeHead.dispose();
PolygonShape polygonShapeBod = new PolygonShape();
origin = Level.character.rectBoundOrigin;
polygonShapeBod.setAsBox(Level.character.rectBoundOrigin.x,
Level.character.rectBoundOrigin.y, origin, 0);
FixtureDef fixtureDefBod = new FixtureDef();
fixtureDefBod.shape = polygonShapeBod;
fixtureDefBod.friction = Level.character.friction.x;
body.createFixture(fixtureDefBod);
polygonShapeBod.dispose();
}
Maybe the issue when creating bodies later in the game is the b2world?

I had the same Error - I figured out, that it happens if you destroy the same body multiple times.
In my case I put the body into a list in the contact listener.. but I didn't make sure it was in the list only once.
That also explains why your problem was fixed once you worked with a boolean flag, that also made sure the same body was only destroyed once.
In short: You get this error if you try to destroy the same body over and over again.

Related

Java Libgdx weird Error with Textures and Arraylists

I'm pretty much a beginner when it comes to game development, especially with Libgdx, so far I made it so I can load any .tmx map or save it, I'm probably going to try and see how procedurally generating terrains works but right now I'm getting this weird error when I delete a block (that block consists of a TiledMapTile and a box2d body), I'm deletting it and after the deletion I'm creating a smaller entity that will also be a body, that represents the block I just deleted, as a drop for the player, this is the error I'm getting when I click a block, it only happens after the first block is deleted, so, one block is deleted and a small entity is created, but if I try to do it a second time, the game breaks and this appears:
A fatal error has been detected by the Java Runtime Environment:
EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffb8ecd9f58, pid=6580, tid=0x0000000000002474
JRE version: Java(TM) SE Runtime Environment (8.0_121-b13) (build 1.8.0_121-b13)
Java VM: Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode windows-amd64 compressed oops)
Problematic frame:
C [ntdll.dll+0x39f58]
Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
An error report file with more information is saved as:
C:\Libgdx Projects Fedora\WINDOWS\Generator Test\core\assets\hs_err_pid6580.log
If you would like to submit a bug report, please visit:
http://bugreport.java.com/bugreport/crash.jsp
The crash happened outside the Java Virtual Machine in native code.
See problematic frame for where to report the bug.
[error occurred during error reporting , id 0xc0000005]
This is the error log:
http://pastebin.com/a8iUH8Rz
This is where I delete the blocks:
public void destroyTerrain( ArrayList<Block> terrain, ArrayList<BlockDrop> blockDropsList ) {
int x = Gdx.input.getX() / 32;
int y = ( Gdx.graphics.getHeight() - Gdx.input.getY() ) / 32;
Iterator<Block> iterator = terrain.iterator();
while ( iterator.hasNext() ) {
Block block = iterator.next();
if ( x == ( int ) block.getBody().getPosition().x && y == ( int ) block.getBody().getPosition().y ) {
PolygonShape shape = ( PolygonShape ) block.getBody().getFixtureList().get( 0 ).getShape();
world.destroyBody( block.getBody() );
iterator.remove();
TiledMapTileLayer.Cell cell = ( ( TiledMapTileLayer ) map.getLayers().get( 0 ) ).getCell( x, y );
Texture tex = cell.getTile().getTextureRegion().getTexture();
// this is where the error is happening, when I'm creating a second blockDrop
BlockDrop blockDrop = new BlockDrop( screen, x, y, shape.getRadius() * 16, shape.getRadius() * 16 );
blockDrop.setTexture( tex );
blockDropsList.add( blockDrop );
cell.setTile( null );
}
}
}
This is the BlockDrop class:
public class BlockDrop extends Entity {
public BlockDrop( PlayGame screen, int x, int y, float width, float height ) {
super( screen );
posX = x;
posY = y;
type = BodyDef.BodyType.DynamicBody;
density = 0.2f;
friction = 0.4f;
shape = new PolygonShape();
( ( PolygonShape ) shape ).setAsBox( width, height, new Vector2( ( x / 32 ) + width * 2, ( y / 32 ) + height * 2 ), 0 );
createBody();
}
}
And this is the Entity:
abstract public class Entity {
private PlayGame screen;
float posX, posY;
private Body body;
Shape shape;
BodyDef.BodyType type;
float density;
float friction;
SpriteBatch batch;
Sprite sprite;
Entity( PlayGame screen ) {
this.screen = screen;
batch = new SpriteBatch();
sprite = new Sprite();
}
void createBody( ) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.position.set( posX, posY );
body = screen.getWorld().createBody( bodyDef );
body.setUserData( this );
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = density;
fixtureDef.friction = friction;
body.createFixture( fixtureDef );
dispose();
}
public void setTexture(Texture tex){
sprite.setTexture( tex );
}
public void render( ) {
sprite.setBounds( posX, posY, shape.getRadius(), shape.getRadius() );
batch.begin();
sprite.draw( batch );
batch.end();
}
public String toString( ) {
return getClass().getSimpleName();
}
public Body getBody( ) {
return body;
}
public void dispose( ) {
shape.dispose();
batch.dispose();
}
}
Any help would be greatly appreciated, it might just be a simple dumb thing and the code might be a mess right now, but I can't seem to get around this
This error usually happens when an object is being used after you disposed it.
You are using a shape that was disposed:
iterator.remove();
...
BlockDrop blockDrop = new BlockDrop( screen, x, y, shape.getRadius() * 16, shape.getRadius() * 16 );
It's better to create and remove physics body in separate loop.
Create List of item that you want to create and another list that you want to remove and also keep in mind that creation and deletion must be performed when physics World is unlocked.
private World physicsWorld;
if(!physicsWorld.isLocked()) {
removeBodyFromWorld();
addBodyIntoWorld();
}
In removeBodyFromWorld() method remove your desired entity and create new body in addBodyIntoWorld() method.

Java use a method multiple times but with changed parameters

I have a method reads coordinates from a file and uses them to render a GameObject at the specified coordinates writen on the file, this code looks like this:
public void ProcessText()
{
String file_name = "C:/Users/Server/Desktop/textText.txt";
try
{
ProcessCoords file = new ProcessCoords(file_name);
String[] aryLines = file.OpenFile();
int i;
for (i = 0; i < aryLines.length; i++)
{
System.out.println(aryLines[i]);
if(aryLines[i].startsWith("makeGrass:")) {
String Arguments = aryLines[i].substring(aryLines[i].indexOf(":")+1, aryLines[i].length());
String[] ArgArray = Arguments.substring(1, Arguments.length() - 2).split(" ");
this.makeGrass(Double.parseDouble(ArgArray[0]),
Double.parseDouble(ArgArray[1]),
Double.parseDouble(ArgArray[2]));
}
}
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
and my text file would only have one line:
makeGrass:(x y z) // for example makeGrass:(1.22334 0.0 9.66678)
this all works fine now.. but there's no point in making this for only one single object. What I want to be able to do is have as many objects as I want from multiple coordinates, so my text file might look like this:
makeGrass:(0.0 1.0 5.0)
makeGrass:(8.0 1.0 2.0)
makeGrass:(4.0 1.0 7.0)
makeGrass:(0.0 1.0 2.0)
makeGrass:(2.0 1.0 7.0)
makeGrass:(5.0 1.0 6.0)
at the moment I use the code this.makeGrass only once and like that my grass model is only placed at those coordinates of the first line (the other lines cause a graphical glitch where they are just being put ontop of each other)
My question here is how I have to write the code so it gives me this.makeGrass multiple times: I want to render the grass model at the respective makeGrass coordinates as many times as there are makeGrass coordinates provided in the text file, how can I do that?
Thanks for any help!
edit: I was asked for more information.. here it is:
public class Vegetation extends GameComponent
{
private Game game;
GameObject grassLeaf1 = new GameObject();
Mesh grassLeaf1mesh = new Mesh("grassLeaf1.obj");
Material grassLeaf1material = new Material
(new Texture("GrassUVTex.png"), 1, 8, new Texture("GrassUVTex_NRM.jpg"), new Texture("GrassUVTex_DISP.jpg"), 0.008f, -0.5f);
MeshRenderer grassLeaf1Renderer = new MeshRenderer(grassLeaf1mesh, grassLeaf1material);
public Vegetation(Game game)
{
this.game = game;
}
public void makeGrass(double posX, double posY, double posZ)
{
grassLeaf1.AddComponent(grassLeaf1Renderer);
grassLeaf1.GetTransform().GetPos().Set((float)posX, (float)posY, (float)posZ);
grassLeaf1.GetTransform().SetScale(new Vector3f (2, 2, 2));
grassLeaf1.GetTransform().SetRot(new Quaternion(new Vector3f(0, 1, 0), (float) Math.toRadians(0)));
game.AddObject(grassLeaf1);
}
public void ProcessText()
{
grassLeaf1.AddComponent(new SaveGrass());
grassLeaf1.AddComponent(new ObjectManipulator(4.0f));
String file_name = "C:/Users/Server/Desktop/textText.txt";
try
{
ProcessCoords file = new ProcessCoords(file_name);
String[] aryLines = file.OpenFile();
int i;
for (i = 0; i < aryLines.length; i++)
{
System.out.println(aryLines[i]);
if(aryLines[i].startsWith("makeGrass:")) {
String Arguments = aryLines[i].substring(aryLines[i].indexOf(":")+1, aryLines[i].length());
String[] ArgArray = Arguments.substring(1, Arguments.length() - 2).split(" ");
this.makeGrass(Double.parseDouble(ArgArray[0]),
Double.parseDouble(ArgArray[1]),
Double.parseDouble(ArgArray[2]));
}
}
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
}
The Vegetation Class handles creating a grass model and reading the coordinates of it from a text file. This here is said text file:
makeGrass:(0.6 1.0 2.8)
makeGrass:(5.6 1.0 9.8)
makeGrass:(2.6 1.0 4.8)
makeGrass:(7.6 1.0 3.8)
makeGrass:(0.6 1.0 2.8)
makeGrass:(0.6 1.0 4.8)
makeGrass:(2.6 1.0 2.8)
makeGrass:(0.6 1.0 0.8)
Now this should enable me to render 8 grass models at different positions but when I hit run all I can see is this:
http://www.pic-upload.de/view-27752444/Untitled.png.html
the grass is also super shiny because all other grass models are being placed also at this location.. something went wrong..
Okay I've found the mistake my make grass function was messed up, it needs to be like this:
public void makeGrass(double posX, double posY, double posZ)
{
GameObject grassLeaf1 = new GameObject();
Mesh grassLeaf1mesh = new Mesh("grassLeaf1.obj");
Material grassLeaf1material = new Material
(new Texture("GrassUVTex.png"), 1, 8, new Texture("GrassUVTex_NRM.jpg"), new Texture("GrassUVTex_DISP.jpg"), 0.008f, -0.5f);
MeshRenderer grassLeaf1Renderer = new MeshRenderer(grassLeaf1mesh, grassLeaf1material);
grassLeaf1.AddComponent(grassLeaf1Renderer);
grassLeaf1.GetTransform().GetPos().Set((float)posX, (float)posY, (float)posZ);
grassLeaf1.GetTransform().SetScale(new Vector3f (2, 2, 2));
grassLeaf1.GetTransform().SetRot(new Quaternion(new Vector3f(0, 1, 0), (float) Math.toRadians(0)));
game.AddObject(grassLeaf1);
}
only strange that once I've added the code into the makeGrass method I lost my input methods.. strange but not that of a problem for now..
I'm getting almost exactly what I wanted now.. here's the final result and the basis of my world editor. Thank you all very much, you've really helped me!
Here's my ShowOff picture: http://www.pic-upload.de/view-27752521/ShowOff.png.html
I'm sure I'll be back for more soon enough but at the moment I know everything and can extend this world editor on my own, thanks a lot to all who have helped me so far, hopefully I can return the favour some time!

Sprites don't follow bodies movements. PhysicsConnector + Update Rotation

I am using:
physicsWorld.registerPhysicsConnector(new PhysicsConnector(sprite, body, true, true));
When the body interact with another it moves correctly, but the sprite moves oddly.
The image show this situation.
How I correct that?
--
Code:
Sprite sp = new Sprite(x, y, resourcesManager.box_region, vbom);
Body body = PhysicsFactory.createBoxBody(physicsWorld, sp, BodyType.DynamicBody, FIXTURE_DEF);
physicsWorld.registerPhysicsConnector(new PhysicsConnector(sp, body, true, true));

Rotate an image while it is being used

I am creating a car game and I want to rotate my car ( Image ) when I'm using the car but I don't know how. I've tried a few things that don't work. Here is what I have:
g2d.drawImage(DEFAULT_CAR_SKIN, DEFAULT_BOX.x, DEFAULT_BOX.y, null);
DEFAULT_BOX.setLocation(DEFAULT_BOX.x + 1, DEFAULT_BOX.y);
if (Game.rotateFront == true) {
AffineTransform identity = new AffineTransform();
AffineTransform trans = new AffineTransform();
trans.setTransform(identity);
trans.rotate(Math.toRadians(Game.Angle));
g2d.drawImage(DEFAULT_CAR_SKIN, trans, this);
}
But this code draws a new image but with the characteristics that I want.

Scaling an image with LibGDX SpriteBatches

I have my image (for the sake of explaining, lets call it Image.png) and I'm trying to get it to scale to properly fit in my Bodies I have drawn. The bodies and everything work with the debug but I'm not a fan of it.. I'm using a SpriteBatch to draw the background image onto the screen(it would be nice to scale that too). How would I scaleImage.png to the same size/position as a Dynamic body that has been rendered?
EDIT:
While drawing the images, I cant get them to match up with the debug render Bodies..
Creating Body:
BodyDef bodydef2 = new BodyDef();
bodydef2.type = BodyType.DynamicBody;
bodydef2.position.set(camera.viewportWidth + 30.0f, (int)(Math.random()*camera.viewportHeight)%(LastPlatformY+5)+20);
//System.out.println(bodydef2.position.y + " " + LastPlatformY);
Body block = world.createBody(bodydef2);
PolygonShape Shape2 = new PolygonShape();
Shape2.setAsBox(750*WORLD_TO_BOX, 200*WORLD_TO_BOX);
FixtureDef fixtureDef2 = new FixtureDef();
fixtureDef2.shape = Shape2;
fixtureDef2.density = 1000.0f;
fixtureDef2.friction = 0.0f;
fixtureDef2.restitution = 0;
block.setLinearVelocity(new Vector2((float) (Platform_Velocity*-1), 0));
block.createFixture(fixtureDef2);
//Lock 'block' to X-Axis, Relative to floor.
PrismaticJointDef jointDef = new PrismaticJointDef();
jointDef.collideConnected = true;
jointDef.initialize(block, groundBody, block.getWorldCenter(), new Vector2(1, 0));
world.createJoint(jointDef);
Platforms.add(block);
Platforms_Created++;
LastPlatformY = (int)bodydef2.position.y;
Drawing Image:
sp.draw(platforms, (float)(Platforms.get(i).getPosition().x), (float)(Platforms.get(i).getPosition().y), 75,20);
EDIT #2:
turns out that if your camera is smaller than the size of your screen you have to do some compensation to account for that variation in positions.. Problem solved, thanks!
Just save the size of your body in two variables while creating your body and then call the appropriate draw method.
To get the position of your object call body.getPosition().
For example
Texture t = assetManager.get("your texture", Texture.class);
BodyDef bodyDef = new BodyDef();
body.type = BodyType.DynamicBody
float width = 64 * WORLD_TO_BOX;
float height = 64 * WORLD_TO_BOX;
Shape shape = new PolygonShape();
float[] points = new float[]{0,0,width,0,width,height,0, height};
shape.set(points);
FixtureDef def = new FixtureDef();
def.shape = shape;
...
body.createFixture(def);
shape.dispose();
And later when you want to draw
public void render(Spritebatch batch) {
batch.draw(t, body.getPosition().x * BOX_TO_WORLD, body.getPosition().y * BOX_TO_WORLD, width * BOX_TO_WORLD, height * BOX_TO_WORLD);
}

Categories