dispose() and detachChild - java

First, I apologize for my poor english.
i am creating a game where i have to throw balls. After a timer i want the ball disapear. So i try to detach it and dispose it. The ball become invisible but is still in my scene because the player is blocked when he's walking on it.
Have you an idea about why the ball is not completly destroy?
private void fire() {
ballon = new Sprite(this.player.getX() + 15, this.player.getY() -5, resourcesManager.ballon_region,vbom);
ballon.setScale(2f);
BallonBody = PhysicsFactory.createCircleBody(this.physicsWorld, ballon, BodyType.DynamicBody, mFixtureDef);
this.physicsWorld.registerPhysicsConnector(new PhysicsConnector(ballon, BallonBody, true, true));
final Vector2 speed = Vector2Pool.obtain(20, 0);
BallonBody.setLinearVelocity(speed);
Vector2Pool.recycle(speed);
attachChild(ballon);
engine.registerUpdateHandler(new TimerHandler(1.6f, new ITimerCallback()
{
public void onTimePassed(final TimerHandler pTimerHandler)
{
//ballon.dispose();
ballon.detachSelf();
ballon=null;
}
}));
}
Edit : Ok , I've found the problem. I just have to destroy the body too.

Related

LibGDX Tiled (TMX) Maps + Scene2D, bugs when rendering both

So I've recently started tinkering with LibGDX (desktop only, at the moment) in Java. I'm mildly experienced with other type of OGL libraries in other languages (namely SFML in C++) and quite experienced with the Java language itself, so I tackled LibGDX pretty confidently; and while the results were mostly positive, there's a bug that I just can't figure out.
What I want to achieve is simple: draw a map (Tiled .tmx), draw a Sprite (soon-to-be "player") inbetween layers 1 and 2, and render a couple of GUI widgets on top of all that, using a scene2D stage. I've managed to achieve this partially.
Here's my Game class, it's pretty messy from so much switching things around just to try, but it's pretty clear what it attempts to do:
public class Game extends ApplicationAdapter
{
private SpriteBatch batch;
private Texture img;
private Sprite playerSprite;
private TiledMap tiledMap;
private OrthographicCamera camera;
private OrthogonalTiledMapRenderer tiledMapRenderer;
private Stage stage;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("trchar000.png");
playerSprite = new Sprite(img, 0, 0, 32, 48);
playerSprite.setPosition(32, 192);
InputHandler.init();
Gdx.input.setInputProcessor(new InputHandler());
stage = new TestStage(playerSprite);
// inputs
InputMultiplexer im = new InputMultiplexer(stage, new InputHandler());
Gdx.input.setInputProcessor(im);
// tiles
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
tiledMap = new TmxMapLoader().load("map2.tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap);
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
tiledMapRenderer.setView(camera);
int[] groundLayers = {0};
int[] topLayers = {1};
// render layer1 -> player -> layer 2
// the .tmx map doesn't have any other layers (just those 2)
tiledMapRenderer.render(groundLayers);
// removing these 3 lines solves the issue, but doesn't render the player
// I've also tried using my regular SpriteBatch instance; same results
// Also, I tried creating a class that extends OrthogonalTiledMapRenderer and overriding the render() method, so that it would draw the player inbetween layers, but again, same results.
tiledMapRenderer.getBatch().begin();
tiledMapRenderer.getBatch().draw(playerSprite, playerSprite.getX(), playerSprite.getY());
tiledMapRenderer.getBatch().end();
tiledMapRenderer.render(topLayers);
batch.begin();
// just to try, I'm rendering the stage here (not calling it's draw() method). Removing this for loop solves the issue, but doesn't render the GUI
for(Actor a : stage.getActors())
a.draw(batch, 1);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
img.dispose();
tiledMapRenderer.dispose();
stage.dispose();
}
}
Also, here's my TestStage class:
public class TestStage extends Stage {
private Skin skin;
private BitmapFont newDefaultFont;
public TestStage(Sprite player)
{
super(new ScreenViewport());
// skin
FreeTypeFontGenerator freeTypeFontGenerator = new FreeTypeFontGenerator(Gdx.files.internal("segoeui.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 14;
newDefaultFont = freeTypeFontGenerator.generateFont(parameter);
skin = new Skin();
skin.add("default-font", newDefaultFont, BitmapFont.class);
FileHandle fileHandle = Gdx.files.internal("uiskin.json");
FileHandle atlasFile = fileHandle.sibling("uiskin.atlas");
if (atlasFile.exists()) {
skin.addRegions(new TextureAtlas(atlasFile));
}
skin.load(fileHandle);
final TextButton button = new TextButton("This is a Button", skin, "default");
button.setPosition(250, 250);
button.setWidth(150);
button.setHeight(40);
final Label lbl = new Label("Test", skin);
this.addActor(lbl);
this.addActor(button);
}
}
Now here's the deal; this is what it looks like if a try to render everything (as shown in my Game class' render() method):
Image 1
The player, GUI, and layer 2 are rendered correctly, but the layer 1 is all bugged out, and I can't figure out why.
Now, here's how it looks like if a don't render the player, removing the line
tiledMapRenderer.getBatch().draw(playerSprite, playerSprite.getX(), playerSprite.getY());
Image 2
Everything renders fine.
Also, here's what it looks like if I decide not to render the stage actors, commenting this loop:
for(Actor a : stage.getActors())
a.draw(batch, 1);
Image 3
Again, everything renders fine.
The only other classes in my project are the default DesktopLauncher class, and an InputProcessor which I'm sure has nothing to do with this.
This is my first question here ever; I just can't figure this out.
Thanks in advance.

Libgdx: SetScreen Issues

Hello the following code is from my main class trying to call another class i made which implements screen.
if (grumpface.whiteballoon.getBoundingRectangle().overlaps(spriterect)) {
System.out.println("hey");
setScreen(new GameOverScreen());
}
;
here is the class i am calling.
class GameOverScreen implements Screen{
private Stage stage;
// Called automatically once for init objects
#Override
public void show() {
stage = new Stage();
float delta = Gdx.graphics.getDeltaTime();
stage.setDebugAll(true); // Set outlines for Stage elements for easy debug
BitmapFont white = new BitmapFont(Gdx.files.internal("hazey.fnt"), false);
LabelStyle headingStyle = new LabelStyle(white, Color.WHITE);
Label gameoverstring = new Label("game ovaaaa!", headingStyle);
gameoverstring.setPosition(100, 100);
stage.addActor(gameoverstring);
}
// Called every frame so try to put no object creation in it
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
System.out.println("hey");
stage.act(delta);
stage.draw();
}
even though i am not returning any stack errors, my program still will not switch screen whenever the event is performed. i can tell the gameoverscreen class is getting called, because whenever the event happens the System.out.println("hey"); is triggered and starts in the console. however, there is no color clear or label drawing like there should be.
Don't use Show() like that. You should initialize your objects in your constructor. maybe try to set screen like that :
((com.badlogic.gdx.Game) Gdx.app.getApplicationListener())
.setScreen(new GameScreen());
We need to see more code to help you
ps i can't comment, but the link : https://code.google.com/p/libgdx-users/wiki/ScreenAndGameClasses is outdated, check it : https://github.com/libgdx/libgdx/wiki

AndEngine, PhysicsWorld not updating?

I'm not entirely sure what I'm doing wrong. I have written this code multiple times before without problems. The problem is that the physics world just does not seem to be updating and I don't know why! Right now I have a gameScene class which extends a normal scene, this is the onCreate method:
#Override
public void create() {
ParallaxBackground background = new ParallaxBackground(0, 0, 0);
background.attachParallaxEntity(new ParallaxEntity(0, new Sprite(0, 0, res.BasicBackground, res.vbom)));
this.setBackground(background);
test = new Sprite(0, 0, res.GrassRegion, res.vbom);
FixtureDef fix = PhysicsFactory.createFixtureDef(10f, 0f, 10f);
Body bod = PhysicsFactory.createBoxBody(physicsWorld, test, BodyType.DynamicBody, fix);
attachChild(test);
physicsWorld = new PhysicsWorld(new Vector2(SensorManager.GRAVITY_EARTH, SensorManager.GRAVITY_EARTH), false);
physicsWorld.registerPhysicsConnector(new PhysicsConnector(test, bod, true, true));
this.registerUpdateHandler(physicsWorld);
}
(I removed a lot of the unnecessary things) I just have a basic test sprite to make sure that the physics is working (which it is not). The app runs without any errors, its just that the sprite will not move, leading me to think that its a problem with the physics world being update.
As you can see, I'm setting the gravity to be accelerating in both the X and Y directions. I did this because I thought maybe it wasn't working in one direction for some reason. I'm thinking that maybe I have to set the scene to update in the main activity? But I don't remember having to do that with any of my other apps. Any help is appreciated thank you :)
No, this.registerUpdateHandler(physicsWorld); will do just fine. Try adding this:
physicsWorld = new PhysicsWorld(new Vector2(0, AHC.WORLD_GRAVITY), false) {
#Override
public void onUpdate(float pSecondsElapsed) {
super.onUpdate(pSecondsElapsed);
}
};
And put a breakpoint or Log.i(TAG, "hey"); inside onUpdate to check if it hits it
EDIT:
Try registering a "normal" UpdateHandler, you can do it in 2 ways:
public class YourGameActivity implements IUpdateHandler{
...
private void yourSetupMethod(){
registerUpdateHandler(this);
}
#Override
public void reset() {}
#Override
public void onUpdate(float pSecondsElapsed) {
Log.i(TAG, "hey");
}
}
or you can create a class that implements IUpdateHandler and then:
public class YourGameActivity{
private MyClassThatImplementsIUpdateHandler mInstance;
...
private void yourSetupMethod(){
registerUpdateHandler(mInstance);
}
}
It's the same.
Try it and see if it logs something, if for some reason you can't see the log use a breakpoint just to be sure.

jMonkeyEngine multiple collision events for single collision

I have implemented and added a PhysicsCollisionListener to register when a projectile hits a player. But when a projectile hits a player. multiple events are triggered.
I add my listener with bulletAppState.getPhysicsSpace().addCollisionListener(collisionListener) in my simpleInitApp() method. I remove the projectile after the collision.
What I need to do to get only one event for each projectile?
Here is my code:
public void collision(PhysicsCollisionEvent event) {
//nodeA is a projectile
if(event.getNodeA().getName().startsWith("Projectile")) {
//projectile hits player
if(event.getNodeB().getName().startsWith("Player")) {
onHit(event.getNodeA(), event.getNodeB().getParent().getUserData("player");
}
//projectile hits projectile
else if(event.getNodeB().getName().startsWith("Projectile")) {
return;
}
//in any case, remove projectile
projectileNode.detachChild(event.getNodeA());
bulletAppState.getPhysicsSpace().remove(event.getNodeA());
}
//nodeB is a projectile
if(event.getNodeB().getName().startsWith("Projectile")) {
//projectile hits player
if(event.getNodeA().getName().startsWith("Player")) {
onHit(event.getNodeB(), event.getNodeA().getParent().getUserData("player");
}
//in any case, remove projectile
projectileNode.detachChild(event.getNodeB());
bulletAppState.getPhysicsSpace().remove(event.getNodeB());
}
}
The problem is that the underlying jBullet engine runs in a different thread at a fixed framerate. If the state of the PhysicsSpace is altered from outside, changes are not immediately recognized.
To quote the jME Wiki:
http://hub.jmonkeyengine.org/wiki/doku.php/jme3:advanced:physics_listeners#physics_tick_listener
Applying forces or checking for overlaps only has an effect right at a physics update cycle, which is not every frame. If you do physics interactions at arbitrary spots in the simpleUpdate() loop, calls will be dropped at irregular intervals, because they happen out of cycle.
The solution is to remove the physics object from within a PhysicsTickListener which synchronizes the call with the framerate of jBullet. It's also somewhat described in the wiki. This implementation will only produce one collision event:
private class ProjectileCollisionControl extends GhostControl implements PhysicsTickListener {
public ProjectileCollisionControl(CollisionShape shape) {
super(shape);
}
public void prePhysicsTick(PhysicsSpace space, float tpf) {}
// Invoked after calculations and after events have been queued
public void physicsTick(PhysicsSpace space, float tpf) {
for(PhysicsCollisionObject o : getOverlappingObjects()) {
Spatial other = (Spatial) o.getUserObject();
// I just hit a player, remove myself
if(other.getName().startsWith("Player"))
{
space.remove(this);
space.removeTickListener(this);
}
}
}
}
The projectiles now need a ProjectileCollisionControl. Setup like this:
public void simpleInitApp() {
BulletAppState state = new BulletAppState();
getStateManager().attach(state);
PhysicsSpace space = state.getPhysicsSpace();
space.addCollisionListener(new PhysicsCollisionListener()
{
public void collision(PhysicsCollisionEvent event) {
// Same code but without bulletAppState.getPhysicsSpace().remove()
}
});
Material mat = new Material(getAssetManager(), "Common/MatDefs/Misc/ShowNormals.j3md");
CollisionShape collisionShape = new BoxCollisionShape(new Vector3f(5, 5, 5));
ProjectileCollisionControl ctrlA = new ProjectileCollisionControl(collisionShape);
Box a = new Box(new Vector3f(0.4f, 0, 0), 1, 1, 1);
Geometry boxGeomA = new Geometry("Box A", a);
boxGeomA.setMaterial(mat);
boxGeomA.addControl(ctrlA);
ProjectileCollisionControl ctrlB = new ProjectileCollisionControl(collisionShape);
Box b = new Box(new Vector3f(-0.4f, 0, 0), 1, 1, 1);
Geometry boxGeomB = new Geometry("Box B", b);
boxGeomB.setMaterial(mat);
boxGeomB.addControl(ctrlB);
getRootNode().attachChild(boxGeomA);
getRootNode().attachChild(boxGeomB);
space.add(ctrlA);
space.add(ctrlB);
space.addTickListener(ctrlA);
space.addTickListener(ctrlB);
}

libgdx not displaying anything

Hey everyone I am really new to libgdx and Open GL so I am having trouble with this sample project I have to do. Here is my code it should be simply displaying a three buttons from a .batch file any help is greatly appreciated. After going through the debugger the only thing I could see was that the call to get draw able returned object[o] but if it didn't find anything why didn't it error out?
public MainScreen() {
spriteBatch = new SpriteBatch();
stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false, spriteBatch);
font = new BitmapFont(Gdx.files.internal("assets/font.fnt"),
Gdx.files.internal("assets/font.png"), false);
buttons = new TextureAtlas("assets/GameButtons.pack");
images = new Skin();
images.addRegions(buttons);
SFXButton = new Button(images.getDrawable("sfxButton"));
SFXButton.setPosition(295, 310);
APIButton = new Button(images.getDrawable("apiButton"));
APIButton.setPosition(405, 310);
GameButton = new Button(images.getDrawable("gameButton"));
GameButton.setPosition(515, 310);
SFXClick = Gdx.audio.newSound(Gdx.files.internal("assets/button_click.wav"));
}
#Override
public void dispose() {
spriteBatch.dispose();
stage.dispose();
}
#Override
public void render(float delta) {
stage.act(delta);
stage.draw();
stage.addActor(SFXButton);
stage.addActor(APIButton);
stage.addActor(GameButton);
spriteBatch.begin();
font.setColor(Color.RED);
font.draw(spriteBatch, "PennyPop", 455 - font.getBounds("PennpyPop").width/2,
460 + font.getBounds("PennyPop").height/2);
if (SFXButton.isPressed())
SFXClick.play();
spriteBatch.end();
}
OUCH! No way you want to add buttons to your stage every render, with 60 FPS and 3 buttons, that would add 180 buttons to your stage per second, and for every second, until you close your app.
public void render(float delta) {
stage.act(delta);
stage.draw();
stage.addActor(SFXButton); //problem here
stage.addActor(APIButton); //and here
stage.addActor(GameButton); //and here
Move the buttons adding to the constructor, see if it will solve the problem.

Categories

Resources