I am developing an Android game using the libgdx box2d library in Eclipse. In the game, there's a ball that falls after touching the start button. But I get a nullpointerexception when the ball contacts the dynamic body.
On contact I want to applyLinearForce to that dynamic body. But I keep getting nullpointerexception on contact of the ball and dynamic body.
ContactHandler class:
public class ContactHandler implements ContactListener {
InputHandler input;
#Override
public void beginContact(Contact contact) {
if(contact.getFixtureA().getBody().getUserData() == "do1" && contact.getFixtureB().getBody().getUserData() == "ball"){
System.out.println("beginContact");
input = new InputHandler();
input.getBody1().applyLinearImpulse(10, 0, 0, 0, true);
}
}
InputHandler class:
public class InputHandler implements InputProcessor {
private OrthographicCamera camera;
private Ball ball;
private DragObject dragObject;
private boolean start = false;
private Vector3 touch = new Vector3();
private Vector3 dragTo = new Vector3();
public InputHandler(){
}
public InputHandler(OrthographicCamera camera, Ball ball,
DragObject dragObject) {
this.camera = camera;
this.ball = ball;
this.dragObject = dragObject;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (!start) {
for (Body body : dragObject.getBody()) {
if (touch.x > body.getPosition().x - dragObject.getWidth() - 1
&& touch.x < body.getPosition().x
+ dragObject.getWidth() + 1) {
if (touch.y > body.getPosition().y - dragObject.getHeight()
- 1
&& touch.y < body.getPosition().y
+ dragObject.getHeight() + 1) {
dragTo.set(screenX, screenY, 0);
camera.unproject(dragTo);
body.setTransform(dragTo.x, dragTo.y, 0);
touch.set(screenX, screenY, 0);
camera.unproject(touch);
}
}
}
}
return false;
}
public Body getBody1(){
return dragObject.getBody().get(0);
}
DragObject class:
public static Array<Body> bodies = new Array<Body>();
public static int count = 0;
public DragObject(){
}
public DragObject(World world, float x, float y, float width, float height) {
this.world = world;
this.width = width;
this.height = height;
initialize();
body1 = world.createBody(bodyDef1);
body1.createFixture(fixtureDef);
body1.setUserData("do1");
bodies.add(body1);
}
public Array<Body> getBody() {
return bodies;
}
Your constructor for the input handler is wrong, these lines should be removed:
public InputHandler(){
}
Because when you call this constructor here:
public void beginContact(Contact contact) {
if(contact.getFixtureA().getBody().getUserData() == "do1" && contact.getFixtureB().getBody().getUserData() == "ball"){
System.out.println("beginContact");
//You are using the wrong contructor, therefore body1 or dragObject is never initialised
input = new InputHandler();
//The null pointer exception is here, no body1 has been initialised yet
input.getBody1().applyLinearImpulse(10, 0, 0, 0, true);
}
You need to make the contructor match and create a new DragObject within the InputHandler class and as a side note it isn't very efficient initialising the class every time the body collides I am sure you can think of a better way to organise it.
Related
I am new to LibGDX library,
I am building the Snakes and ladders game with it.
I have a player class, it extends itself from Sprite class.
I want it to move when a dice is thrown.
But it becomes suddenly, I cannot see the movement.
public void updatePlayer(){
//this.setPosition(body.getPosition().x, body.getPosition().y);
game.getBatch().begin();
draw(game.getBatch());
game.getBatch().end();
}
public void updatePlayer(int dice){
if (dice > 0 && dice <= 6){
for (int i = 0; i < dice; i++){
float laterX = getX() + 48;
if (laterX > GameInfo.WIDTH - 20){
//setPosition(3, getY() + 5f);
translateY(5);
updatePlayer();
}else {
translateX(5);
//setPosition(getX() + 5, getY());
updatePlayer();
}
}
}
}
You cannot see movement 'cause you set the position. Use translate to move it.
doc
Sprite#setPosition() //Sets the position where the sprite will be drawn
Sprite#translate() //Sets the position relative to the current position where the sprite will be drawn.
My loop class:
public class Game extends ScreenAdapter {
private static String worldName;
private EntityPlayer player;
private FlatWorld flatWorld;
public static World world;
// private Box2DDebugRenderer debugRenderer;
private static boolean pauseGame;
public Game(String worldName){
world = new World(new Vector2(0, 0), false);
//this.debugRenderer = new Box2DDebugRenderer();
this.worldName = worldName;
this.player = PlayerDiskUtils.readPlayerFromDisk(this.worldName);
this.flatWorld = FlatWorldUtils.loadFlatWorld(this.worldName);
this.player.setCamera(this.flatWorld.getWorldSize());
this.flatWorld.setBlocksCourt(FlatWorldUtils.readBlocksCourt(this.flatWorld.getWorldSize().getWidth(), this.flatWorld.getWorldSize().getHeight(), this.worldName));
Gdx.input.setInputProcessor(new GameInputAdapter());
}
#Override
public void render(float delta) {
world.step(1/60f, 6, 2);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
this.flatWorld.getBlocksCourt().renderWorld(player.getCamera());
this.player.update(this.flatWorld, this.flatWorld.getWorldSize().getWidth(), this.flatWorld.getWorldSize().getHeight());
this.flatWorld.blocks.renderBlocks(this.player.getCamera());
this.player.renderInventory();
this.player.playerHud.render(this.player.states.getHealth(), this.player.states.getHungry(), this.player.states.getThirsty());
}
#Override
public void dispose() {
this.pause();
world = null;
worldName = null;
this.flatWorld.blocks.disposeBlocks();
}
#Override
public void pause() {
super.pause();
PlayerDiskUtils.writePlayerToDisk(this.worldName, this.player);
FlatWorldUtils.saveFlatWorld(this.worldName, this.flatWorld);
}
public static String getWorldName() { return worldName; }
public static boolean isPauseGame() { return pauseGame; }
public static void setPauseGame(boolean pauseGame) { Game.pauseGame = pauseGame; }
/**
* This is the input adapter of the player.
* Here keys and input event are set
*/
private class GameInputAdapter extends InputAdapter{
#Override //Mouse moving
public boolean mouseMoved(int screenX, int screenY) { return player.rotatePlayerToMouse(); }
#Override //Keys
public boolean keyDown(int keycode) {
if(keycode == Input.Keys.ESCAPE){ if(player.inventoryOpen) player.inventoryOpen = false;}
if(keycode == Input.Keys.E){ player.inventoryOpen = !player.inventoryOpen; }
return true;
}
#Override //Mouse buttons
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Vector3 mouseCords3 = player.getCamera().unproject(new Vector3(screenX, screenY, 0));
return onBodyClick(new Vector2(mouseCords3.x, mouseCords3.y), button);
}
private boolean onBodyClick(Vector2 mouseCords, int button){
if(player.inventoryOpen) return false;
final Body[] body = new Body[1];
//Save inside body[0] the body which has been clicked
world.QueryAABB(fixture -> {
if(fixture.testPoint(mouseCords)){
body[0] = fixture.getBody();
}
return true;
}, mouseCords.x, mouseCords.y, mouseCords.x + 0.5f, mouseCords.y + 0.5f);
if(body[0] == null){
if(button == Input.Buttons.RIGHT){
player.onPlayerRightClick(flatWorld, mouseCords);
}
}else{
if(button == Input.Buttons.RIGHT){
((Block)body[0].getUserData()).onBlockClicked(player);
}else if(button == Input.Buttons.LEFT){
player.onPlayerBlockDestroying(flatWorld, (Block)body[0].getUserData(), mouseCords);
}
}
return true;
}
}
}
My code about player moving(it is 3d model, but it coult help you):
public void move(FlatWorld flatWorld, int worldWidth, int worldHeight) {
int x = 0, y = 0;
if (Gdx.input.isKeyPressed(Input.Keys.W))
y = 1;
if (Gdx.input.isKeyPressed(Input.Keys.S))
y = -1;
if (Gdx.input.isKeyPressed(Input.Keys.A))
x = -1;
if (Gdx.input.isKeyPressed(Input.Keys.D))
x = 1;
if(x != 0 || y != 0) {
if (this.canPlayerMove(flatWorld, new Vector3(x, y, 0), worldWidth, worldHeight)) {
this.modelInstance.transform.translate(x, y, 0);
this.moveCamera(worldWidth, worldHeight);
}
}
this.renderModel(null);
}
As you can see, I translate my model without call setPosition()
Class FirstTower:
public class FirstTower extends Sprite {
private Map map;
private Texture texture;
private float transfer = 1000;
private float hp;
private float radius;
public FirstTower(Map map) {
this.texture = new Texture("square.png");
this.map = map;
this.hp = 100;
radius = 40;
}
#Override
public void render(SpriteBatch batch) {
batch.draw(texture, Gdx.input.getX() - radius, transfer - Gdx.input.getY() - radius);
}
#Override
public void updade(float dt) {
}
}
I need simple to create example of this class (object of FirstTower) with mouse click on gamefield.
How can I do this?
Try to search, but not find anything useful.
Image of object follow with my cursor.
Here is screen when app is running:
You need to set the GDX InputProcessor. This is done by executing the following:
Replace MyClass with the class you wish to create (FirstTower I believe)
Gdx.input.setInputProcessor(new InputProcessor() {
public boolean touchDown(int x, int y, int point, int button) {
if (button == Input.Buttons.LEFT) {
new MyClass();
return true;
}
return false;
}
});
Note: I have excluded the other methods when creating a new InputProcessor to keep this answer tidy, but you will need to implement those methods.
I am using the Android Studio IDE, with the libGDX framework to develop a game. It is a clone of the Pac-Man game with a similar gameplay to flappy bird. The concept is that the pac man moves through the planks while avoiding the ghosts coming from the right direction, that are moving off straight into the left direction (not chasing the position of the player). I am not sure how I create a 'for loop' for the ghost animations, I want the ghosts to consistently reposition and re-appear from the right side after a few seconds, with the exception that they completely gone off the screen initially.
The class for one of the Ghosts.
public class Blinky {
private Vector3 position; //x y and z axis
private Rectangle bounds;
private Texture texture1;
private Animation blinkyAnimLeft;
public Blinky(int x, int y) {
position = new Vector3(x, y, 0);
Texture texture1 = new Texture("blinkyLeft.png");
blinkyAnimLeft = new Animation(new TextureRegion(texture1), 2, 0.5f);
//bounds = new Rectangle(x,y,texture1.getWidth() / 2, texture1.getHeight());
}
public void update(float dt) {
blinkyAnimLeft.update(dt);
//bounds.setPosition(position.x, position.y);
}
public Vector3 getPosition() {
return position;
}
public TextureRegion getTexture() {
return blinkyAnimLeft.getFrame();
}
//public Rectangle getBounds() {
return bounds;
}
public void dispose() {
texture1.dispose();
}
}
Ghosts and Player initialised in the GamePlayState Class
public class GamePlayState extends State {
//Variables
private float timePassed = 0;
private Texture background;
public static final int WALK = 1;
public static final double GHOST_WALK = 0.5;
private static final int PLANKS_SPACING = 125; //gap betwen the planks
private static final int PLANK_COUNT = 4;
private Array<Obstacle> planks;
private Player player;
private Blinky blinky;
private Inky inky;
private Texture missile;
public GamePlayState(GameStateManager gsm) {
super(gsm);
player = new Player(50, 100);
blinky = new Blinky(400, 220);
inky = new Inky(400, 240);
// missile = new Texture("missile.png");
background = new Texture("black.jpg");
cam.setToOrtho(false, PacMan.WIDTH/2, PacMan.HEIGHT/2);
planks = new Array<Obstacle>();
for (int i = 1; i<= PLANK_COUNT; i++) {
planks.add(new Obstacle(i * (PLANKS_SPACING + Obstacle.PLANK_WIDTH)));
}
}
#Override
public void handleInput() {
}
#Override
public void update(float dt) {
handleInput();
player.update(dt);
blinky.update(dt);
inky.update(dt);
cam.position.x = player.getPosition().x + 80; //update the position of the camera with the bird
//update when pacman cam viewport has passed plank
//make cam follow the player
for (Obstacle plank: planks) {
if (cam.position.x - (cam.viewportWidth/1) > plank.getPosTopPlank().x + plank.getTopPlank().getWidth()) {
plank.respositionPlanks(plank.getPosTopPlank().x + ((Obstacle.PLANK_WIDTH + PLANKS_SPACING * PLANK_COUNT )));
}
if (plank.collision (player.getBounds()))
gsm.set(new GamePlayState(gsm));
}
cam.update();
}
#Override
public void render(SpriteBatch sb) {
sb.setProjectionMatrix(cam.combined);
sb.begin();
sb.draw(background, cam.position.x - (cam.viewportWidth/2), 0);
timePassed += Gdx.graphics.getDeltaTime();
//Moving Inky
sb.draw(inky.getTexture(), inky.getPosition().x, inky.getPosition().y);
inky.getPosition().x -= GHOST_WALK;
//Moving Blinky
sb.draw(blinky.getTexture(), blinky.getPosition().x, blinky.getPosition().y);
blinky.getPosition().x -= GHOST_WALK;
You should get x, y( and z) position from Vector3.
Then check for borders
if (inky.getPosition().x < 0){
Thread.sleep(/*a few sdeconds*/2000);/*Android studio would ask you about wrapping it with try - catch*/
inky.setPostion( x + /*screen x size*/,
inky.getPosition().y,inky.getPosition().z)/*add setter in ghost class*/
}
In fact, this is not the best way to do it, but the simplest one
I want to draw a texture on a body, which is a box.
How do I convert the coordinates of the body to screen coordinates?
I know that the other way around is with camera.unproject(pos), is it similar to this?
I see a lot of people using constants such as WORLD_TO_SCREEN = 32, but I currently don't have that in my game. Is that a problem, and how can I implement it now? Because it seems like people that are using these factors can convert world to screen positions easily. I currently have a camera and an ExtendViewport
camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
viewport = new ExtendViewport(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, camera);
camera.position.set(VIEWPORT_WIDTH/2, VIEWPORT_HEIGHT/2, 0f);
Viewport width and height are set to this
public static final int VIEWPORT_WIDTH = 20;
public static final int VIEWPORT_HEIGHT = 22;
I don't really know what I'm doing, I read documentation and read some tutorials, but if someone could give some explanation about these variables and the world_to_screen factor that would really help me out.
I also set APP_WIDTH=1280, APP_HEIGHT = 720
Do viewport width and height mean that for box2d my screen is 20 meters wide and 22 meters high?
(asking it again because I added a lot the question and I would really like to know these things)
[EDIT]
So I'm trying to draw a ground picture on the ground body
float x = stage.getGround().getX();
float y = stage.getGround().getY();
float w = stage.getGround().getWidth();
float h = stage.getGround().getHeight();
stage.act(delta);
stage.draw();
stage.updateCamera();
Texture texture = new Texture(Gdx.files.internal("ground.png"));
Sprite sprite = new Sprite(texture);
sprite.setSize(w, h);
sprite.setPosition(x-sprite.getWidth()/2, y-sprite.getHeight()/2);
But I don't see it anywhere
[EDIT 2]
Stage Class
public class Mission1Stage extends Stage{
public static final int VIEWPORT_WIDTH = 20;
public static final int VIEWPORT_HEIGHT = 22;
private World world;
private Ground ground;
private LeftWall leftWall;
private Rocket rocket;
private static final float TIME_STEP = 1 / 300f;
private float accumulator = 0f;
private OrthographicCamera camera;
private Box2DDebugRenderer renderer;
private Viewport viewport;
private SpriteBatch spriteBatch = new SpriteBatch();
private Vector3 touchPoint;
private ShapeRenderer shapeRenderer;
private Button boostButton;
private Skin boostSkin;
private Button boostLeftButton;
private Skin boostLeftSkin;
private Button boostRightButton;
private Skin boostRightSkin;
private Button resetButton;
private Skin resetSkin;
private Game game;
private boolean isTouched = false;
public Mission1Stage(Game game) {
setUpWorld();
renderer = new Box2DDebugRenderer();
shapeRenderer = new ShapeRenderer();
setupCamera();
setUpButtons();
addActor(new Background(ground));
}
private void setUpWorld() {
world = WorldUtils.createWorld();
setUpGround();
setUpRocket();
}
private void setUpGround() {
ground = new Ground(WorldUtils.createGround(world));
addActor(ground);
}
private void setUpLeftWall() {
leftWall = new LeftWall(WorldUtils.createLeftWall(world));
}
private void setUpRocket() {
rocket = new Rocket(WorldUtils.createRocket(world));
addActor(rocket);
}
private void setupCamera() {
camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
viewport = new ExtendViewport(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, camera);
camera.position.set(VIEWPORT_WIDTH/2, VIEWPORT_HEIGHT/2, 0f);
camera.update();
}
private void setUpButtons() {
boostSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
boostButton = new Button(boostSkin);
boostButton.setSize(80,80);
boostButton.setPosition(Gdx.graphics.getWidth()-boostButton.getWidth()*2,0);
boostButton.setTransform(true);
boostButton.scaleBy(0.5f);
Gdx.input.setInputProcessor(this);
addActor(boostButton);
boostLeftSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
boostLeftButton = new Button(boostLeftSkin);
boostLeftButton.setSize(100, 100);
boostLeftButton.setPosition(0, 0);
addActor(boostLeftButton);
boostRightSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
boostRightButton = new Button(boostRightSkin);
boostRightButton.setSize(100, 100);
boostRightButton.setPosition(boostLeftButton.getWidth(), 0);
addActor(boostRightButton);
resetSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
resetButton = new Button(resetSkin);
resetButton.setSize(100, 100);
resetButton.setPosition(Gdx.graphics.getWidth()-100, Gdx.graphics.getHeight()-100);
addActor(resetButton);
}
#Override
public void act(float delta) {
super.act(delta);
handleInput();
accumulator += delta;
while(accumulator >= delta) {
world.step(TIME_STEP, 6, 2);
accumulator -= TIME_STEP;
}
}
#Override
public void draw() {
super.draw();
renderer.render(world, camera.combined);
float x = getGround().getBody().getPosition().x;
float y = getGround().getBody().getPosition().y;
float w = getGround().getWidth() * 2;
float h = getGround().getHeight() * 2;
spriteBatch.setProjectionMatrix(getCamera().combined);
Texture texture = new Texture(Gdx.files.internal("ground.png"));
Sprite sprite = new Sprite(texture);
sprite.setSize(w, h);
sprite.setPosition(x-sprite.getWidth()/2, y-sprite.getHeight()/2);
spriteBatch.begin();
sprite.draw(spriteBatch);
spriteBatch.end();
}
public void handleInput() {
if(boostButton.isPressed()) {
rocket.boost();
}
if(boostLeftButton.isPressed()) {
rocket.turnLeft();
}
if(boostRightButton.isPressed()) {
rocket.turnRight();
}
if(resetButton.isPressed()) {
}
}
public boolean resetScreen() {
if(resetButton.isPressed()) return true;
return false;
}
public void updateCamera() {
}
public Ground getGround() {
return ground;
}
public void resize(int width, int height) {
viewport.update(width, height);
camera.position.x = VIEWPORT_WIDTH / 2;
camera.position.y = VIEWPORT_HEIGHT /2;
}
private void translateScreenToWorldCoordinates(int x, int y) {
getCamera().unproject(touchPoint.set(x, y, 0));getCamera();
}
}
Screen class
public class Mission1Screen implements Screen{
private Game game;
private Mission1Stage stage;
private SpriteBatch spriteBatch = new SpriteBatch();
private Skin boostSkin;
private Button boostButton;
public Mission1Screen(Game game) {
this.game = game;
stage = new Mission1Stage(game);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(stage.resetScreen()) {
game.setScreen(new Mission1Screen(game));
}
stage.act(delta);
stage.draw();
stage.updateCamera();
}
#Override
public void resize(int width, int height) {
stage.resize(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
[EDIT 3]
public class Main extends Game {
#Override
public void create () {
this.setScreen(new Mission1Screen(this));
}
#Override
public void render () {
super.render();
}
#Override
public void dispose () {
}
}
We mostly use Pixel to meter conversion because box2d best works in meters (0-10) but you can avoid this conversion by using small worldwidth and height of your viewport. I mostly prefer 48 and 80 as viewport width and height.
You can use unproject(vector3) method of camera that translate a point given in screen coordinates to world space. I am using this method in touchdown because I get screen coordinate as parameter then I need to convert it into camera world space so that I can generate object at a particular position in world.
public class MyGdxTest extends Game implements InputProcessor {
private SpriteBatch batch;
private ExtendViewport extendViewport;
private OrthographicCamera cam;
private float w=20;
private float h=22;
private World world;
private Box2DDebugRenderer debugRenderer;
private Array<Body> array;
private Vector3 vector3;
#Override
public void create() {
cam=new OrthographicCamera();
extendViewport=new ExtendViewport(w,h,cam);
batch =new SpriteBatch();
Gdx.input.setInputProcessor(this);
world=new World(new Vector2(0,-9.8f),true);
array=new Array<Body>();
debugRenderer=new Box2DDebugRenderer();
vector3=new Vector3();
BodyDef bodyDef=new BodyDef();
bodyDef.type= BodyDef.BodyType.StaticBody;
bodyDef.position.set(0,0);
Body body=world.createBody(bodyDef);
ChainShape chainShape=new ChainShape();
chainShape.createChain(new float[]{1,1,55,1});
FixtureDef fixtureDef=new FixtureDef();
fixtureDef.shape=chainShape;
fixtureDef.restitution=.5f;
body.createFixture(fixtureDef);
chainShape.dispose();
}
#Override
public void render() {
super.render();
Gdx.gl.glClearColor(0,1,1,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(1/60f,6,2);
batch.setProjectionMatrix(cam.combined);
batch.begin();
world.getBodies(array);
for (Body body:array){
if(body.getUserData()!=null) {
Sprite sprite = (Sprite) body.getUserData();
sprite.setPosition(body.getPosition().x-sprite.getWidth()/2, body.getPosition().y-sprite.getHeight()/2);
sprite.setRotation(body.getAngle()*MathUtils.radDeg);
sprite.draw(batch);
}
}
batch.end();
debugRenderer.render(world,cam.combined);
}
#Override
public void resize(int width, int height) {
super.resize(width,height);
extendViewport.update(width,height);
cam.position.x = w /2;
cam.position.y = h/2;
cam.update();
}
private void createPhysicsObject(float x,float y){
float sizeX=2,sizeY=2;
BodyDef bodyDef=new BodyDef();
bodyDef.position.set(x,y);
bodyDef.type= BodyDef.BodyType.DynamicBody;
Body body=world.createBody(bodyDef);
PolygonShape polygonShape=new PolygonShape();
polygonShape.setAsBox(sizeX,sizeY);
FixtureDef fixtureDef=new FixtureDef();
fixtureDef.shape=polygonShape;
fixtureDef.restitution=.2f;
fixtureDef.density=2;
body.createFixture(fixtureDef);
body.setFixedRotation(false);
polygonShape.dispose();
Sprite sprite=new Sprite(new Texture("badlogic.jpg"));
sprite.setSize(2*sizeX,2*sizeY);
sprite.setPosition(x-sprite.getWidth()/2,y-sprite.getHeight()/2);
sprite.setOrigin(sizeX,sizeY);
body.setUserData(sprite);
}
#Override
public void dispose() {
batch.dispose();
debugRenderer.dispose();
world.dispose();
}
#Override
public boolean keyDown(int keycode) {
return false;
}
#Override
public boolean keyUp(int keycode) {
return false;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
vector3.set(screenX,screenY,0);
Vector3 position=cam.unproject(vector3);
createPhysicsObject(vector3.x,vector3.y);
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
}
I have created the following custom actor to draw lines on libgdx
public class LineWidget extends Actor implements Disposable {
private Position posA;
private Position posB;
public final Vector2 _A;
public final Vector2 _B;
private TextureRegion lineTexture;
private final TextureRegion lineTextureGreen = Assets.instance.Images.lineGreen;
private final TextureRegion lineTextureOrange = Assets.instance.Images.lineOrange;
private final TextureRegion lineTextureRed = Assets.instance.Images.lineRed;
public LineWidget(Position A, Position B) {
this._A = A.getPositionVector();
this._B = B.getPositionVector();
this.posA = A;
this.posB = B;
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
setLineColor(posA, posB);
float xdif = _B.x-_A.x;
float ydif = _B.y-_A.x;
float l2 = xdif*xdif+ydif*ydif;
float invl = (float)(1/Math.sqrt(l2));
//dif is vector with length linewidth from first to second vertex
xdif*=invl*5;
ydif*=invl*5;
float floatBits = batch.getColor().toFloatBits();
//draw quad with width of linewidth*2 through (x1, y1) and (x2, y2)
float[] verts = new float[]{_A.x+ydif, _A.y-xdif, floatBits, lineTexture.getU(), lineTexture.getV(),
_A.x-ydif, _A.y+xdif, floatBits, lineTexture.getU2(), lineTexture.getV(),
_B.x-ydif, _B.y+xdif, floatBits, lineTexture.getU2(), lineTexture.getV2(),
_B.x+ydif, _B.y-xdif, floatBits, lineTexture.getU(), lineTexture.getV2()};
batch.draw(lineTexture.getTexture(), verts, 0, 20);
}
#Override
public void setSize(float width, float height) {
super.setSize(width, height);
}
#Override
public void dispose() {
}
private void setLineColor(Position A, Position B) {
if(A.get_value() != null && B.get_value() != null) {
if(A.get_value() == 1 || B.get_value() == 1) {
lineTexture = lineTextureGreen;
return;
}else {
lineTexture = lineTextureRed;
}
} else {
lineTexture = lineTextureRed;
}
}
}
When I create the actor memory consumption keeps going up but I cannot detect where this leak is happening. How can I fix this actor to stop leaking memory?
EDIT: I am drawing this actor inside another actor which extends Group Actor class. Group actor class does not leak memory and the only thing it is doing for now is draw LineWidget by calling addActor(). This actor is then added to a stage inside a screen. I dont think this information is important but just adding it in case. I have tested all this actors and the memory leak begins when I draw LineWidget Actor.