libgdx: Adding Table to Stage causes Actors that aren't children of the Table to not render, despite not having overlapping coordinates - libgdx

So, I have a Game Screen that I have set to 800x480, and at the top of that screen I'm trying to create a Table that contains some information. I've set the table bounds to x = 0, y = 380, width = 800, height = 100, and when the screen renders, the table shows up at the top of the screen just like I want. However, below that table, I want to render additional Actors that I've added to my stage. Problem is, they aren't rendering. If I comment out the line where I add the table to the stage, everything renders just fine - its only when I add the table that the issue occurs, even though the non-Table Actors don't overlap screen coordinates with the Table. For the purpose of this question, I cut out all of the Actors other than the one called "Field", which is a game board with coordinates of x=0, y=0, width=500, height=300.
Why is the inclusion of the Table obfuscating the rendering of my other Actors?
Here's my code (first GameScreen, then Field):
public GameScreen(MyGame game) {
// TODO Auto-generated constructor stub
this.game = game;
log = "Starting game";
plyscore = 0;
oppscore = 0;
stage = new Stage(new StretchViewport(800,480));
gameskin = new Skin(Gdx.files.internal("uiskin.json"));
gametable = new Table();
background = new TextureRegionDrawable(new TextureRegion(AssetLoader.background));
field = new Field();
score = new Label(plyscore+" - "+oppscore, gameskin);
logarea = new TextArea(log, gameskin);
logarea.setPrefRows(3);
logscroll = new ScrollPane(logarea, gameskin);
logscroll.setForceScroll(false, true);
logscroll.setFlickScroll(false);
gametable.setBounds(0, 380, 800, 100);
gametable.add(score).width(390);
gametable.add(logscroll).width(390).row();
stage.addActor(gametable);
stage.addActor(field);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0.0f, 0.5f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.draw();
}
public class Field extends Actor {
public Field() {
setBounds(getX(), getY(), AssetLoader.field.getRegionWidth(),
AssetLoader.field.getRegionHeight());
}
#Override
public void draw(Batch batch, float alpha){
batch.draw(AssetLoader.field,this.getX(),getY());
}
}

Related

LIBGDX Framebuffer is drawn as a black box

We figured out the issue. I was disposing the framebuffer before using it.
I recently queried about how to use the Libgdx Framebuffer correctly.
Summed up, i am making a tile-based game and i wanted to understand how to setup and use a
framebuffer object to eventually start experimenting with shaders. I wanted to exclude the
"water tiles" from the normal draw cycle and instead have them be rendered to a framebuffer.
Then render the framebuffer to the screen.
(I am not using any "Scene2d" or "Tiled" classes)
Link to previous question: How to use LIBGDX FrameBuffer correctly.
Even though the answer i accepted did not work in my particular program, it did work
when i tried it out on a smaller more contained program (shown below).
This works:
public void render() {
float dt = Gdx.graphics.getDeltaTime();
Cam.instance.getCamera().translate(direction.x*speed*dt, direction.y*speed*dt,0);
Cam.instance.update();
// clear the screen, set batch's projection matrix
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(Cam.instance.getCamera().combined);
// draw texture as layer 0
batch.begin();
batch.draw(green,606,306);
batch.flush(); // No need to call batch.end() / batch.begin()
// Storing the original values of the batch before changing it.
originalMatrixTemp.set(batch.getProjectionMatrix());
int originalBlendSrcFunc = batch.getBlendSrcFunc();
int originalBlendDstFunc = batch.getBlendDstFunc();
// Sorcery as far as i am concerned. "Ensures alpha is preserved in case of overlapping translucent sprites"
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);
frameBuffer.begin(); // initialize framebuffer
// clear the colors of the batch
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.draw(red,256,0); // Draw another texture, now unto the framebuffer texture
batch.flush(); // flush batch
frameBuffer.end(); // end framebuffer
// "Ensure we're drawing the frame buffer texture without modifying its color"
batch.setColor(Color.WHITE);
// I think we are setting the projection to "default" (-1,1,2,-2)
batch.setProjectionMatrix(IDENTITY);
// draw the framebuffers texture across all the screen (layer 1)
batch.draw(frameBuffer.getColorBufferTexture(),-1, 1, 2, -2);
batch.flush();
// restoring the original state
batch.setProjectionMatrix(originalMatrixTemp);
batch.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
// drawing arbitrary layer 2
batch.draw(green,300,300);
batch.end(); // end of cycle
}
and it shows (Red square is the framebuffer texture):
The cycle is: Begin -> Draw something -> Draw, using buffer -> Draw something -> end.
So my question is then, why does this not work:
private void renderFbo(int layer) {
batch.flush();
originalMatrixTemp.set(batch.getProjectionMatrix());
int originalBlendSrcFunc = batch.getBlendSrcFunc();
int originalBlendDstFunc = batch.getBlendDstFunc();
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);
fbo.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Drawing the layer unto the framebuffer:
for (DrwDat dat: layers.get(layer)) { dat.draw(batch); }
batch.flush();
fbo.end();
batch.setColor(Color.WHITE);
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
batch.setProjectionMatrix(IDENTITY);
// Halving the output texture to see the issue clearer. whole screen: (-1, 1, 2, -2)
batch.draw(fbo.getColorBufferTexture(), -0.5f, 0.5f, 1f, -1f);
batch.flush();
batch.setProjectionMatrix(originalMatrixTemp);
batch.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
}
With this being the immediate context:
public void draw() {
Gdx.gl.glClearColor(1, 1, 1, 1); // clearing with WHITE to see the framebuffer texture
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (int i = 0; i < NUM_LAYERS; i++) {
if (RENDER[i]) {
if (SORT[i]) Collections.sort(layers.get(i));
//for (DrwDat dat: layers.get(i)) { dat.draw(batch);}
if (i==1) { renderFbo(i); } // calling the framebuffer-using method for "water layer"
else{
for (DrwDat dat: layers.get(i)) {
dat.draw(batch);
}
}
}
}
Instance variables in the "draw class" :
public class DrwHandler {
private static final String TAG = DrwHandler.class.getName();
public static DrwHandler instance = new DrwHandler();
private final Matrix4 originalMatrixTemp = new Matrix4();
private static final Matrix4 IDENTITY = new Matrix4();
private Map<Integer, ArrayList<DrwDat>> layers;
private OrthographicCamera camera;
private FrameBuffer fbo;
private SpriteBatch batch;
private static final int NUM_LAYERS = 8;
private static final boolean[] RENDER = new boolean[NUM_LAYERS];
private static final boolean[] SORT = new boolean[NUM_LAYERS];
private DrwHandler() {
fbo = new FrameBuffer(Pixmap.Format.RGBA8888, Settings.SCREEN_W,Settings.SCREEN_H,false);
batch = new SpriteBatch();
layers = new HashMap<>();
layers.put(0,new ArrayList<>());
layers.put(1,new ArrayList<>());
layers.put(2,new ArrayList<>());
layers.put(3,new ArrayList<>());
layers.put(4,new ArrayList<>());
layers.put(5,new ArrayList<>());
layers.put(6,new ArrayList<>());
layers.put(7,new ArrayList<>());
}
It shows:
The "black box" is the framebuffer texture (redused in size). The white background is the clear color.
and the green is a foreground layer.
It is black regardless of changing the Gdx.gl.glClearColor(0, 0, 0, 0) within the context of the framebuffer rendering to some other color.
without the renderFbo() method, it renders normally like this:
Now i have heard Static references can cause issues with OpenGL-related objects:
"If you will be building for Android, never use static references to any OpenGL-related objects unless you have an expert understanding of the LibGDX lifecycle. Even then, it is an error-prone practice. People come on here to ask about black textures pretty frequently and 99% of the time it has to do with some static reference being used incorrectly."
I am not building for android. And since my previous question i have removed static objects.
just to be sure.
But i do use statics in a few select classes like this (example):
public class Cam {
public static Cam instance = new Cam();
private OrthographicCamera camera;
private Cam() {
camera = new OrthographicCamera(Settings.SCREEN_W, Settings.SCREEN_H);
}
(including my Assets class and Draw class):
Trying to think about what else.. I guess we will try with this first. Se if something sticks out to you.
Really could need some help right about now. Been banging my head against the wall for a while. Thank you.
Here is a link to some source files that could be relevant:
Source

TextureMapObject is not shown on isometric Tiled Map

In my code I'm using the following code to load the .tmx map. I also use IsometricTiledMapRenderer.
I would like to add a unit upon touch event on tile.
assetManager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
assetManager.load("maps/grass_and_water.tmx", TiledMap.class);
assetManager.finishLoading();
map = assetManager.get("maps/grass_and_water.tmx");
renderer = new IsometricTiledMapRenderer(map, 1f / 64f);
Gdx.input.setInputProcessor(new GestureDetector(new MapGestureListener(camera, jetFlyingSprite, map)));`
In the touchDown I'm trying to add TextureMapObject on click.
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
Gdx.app.log(TAG, "touchDown gesture");
flinging = false;
scale = camera.zoom;
//return false;
Vector3 clickCoordinates = new Vector3(x,y,0);
Vector3 position = camera.unproject(clickCoordinates);
Texture texture = new Texture("jet_flying.png");
TextureRegion textureRegion = new TextureRegion(texture,400,400);
MapLayer mapLayer = map.getLayers().get("objects");
mapLayer.setVisible(true);
TextureMapObject textureMapObject = new TextureMapObject(textureRegion);
textureMapObject.setName("plane");
textureMapObject.setX((float)position.x);
textureMapObject.setY((float)position.y);
mapLayer.getObjects().add(textureMapObject);
textureMapObject.setX((float)position.x);
textureMapObject.setY((float)position.y);
return true;
}
When running nothing happens when I click.
Any clues/?
I am guessing your "objects" layer is a Object layer, the implementation of that is left blank in BatchTiledMapRenderer which IsometricTiledMapRenderer inherits from. This means object layers are rendered.
BatchTiledMapRenderer renderMapLayer method which calls renderObject which looks like this:
#Override
public void renderObject (MapObject object) {
}
You could subclass IsometricTiledMapRenderer and implement renderObject yourself.

LibGDX Label scaling on Stage

I'm trying to show a label on the Stage with virtual 16:9 size:
public class MyGdxGame extends ApplicationAdapter {
private Stage stage;
#Override
public void create () {
stage = new Stage(new FillViewport(16, 9));
Label label = new Label("What's wrong with labels?",
new Label.LabelStyle(new BitmapFont(), Color.WHITE));
label.setBounds(0, 0, 16, 9);
stage.addActor(label);
Gdx.input.setInputProcessor(stage);
}
#Override
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
}
#Override
public void dispose () {
stage.dispose();
}
}
The font looks huge and can't fit screen bounds:
Then I try to set font scale and word wrapping:
stage = new Stage(new FillViewport(16, 9));
Label label = new Label("What's wrong with labels?",
new Label.LabelStyle(new BitmapFont(), Color.WHITE));
label.setBounds(0, 0, 16, 9);
label.setFontScale(0.1f);
label.setWrap(true);
stage.addActor(label);
And getting messed completely:
Tried settings viewport size in pixels, like 1080:1920. In this case label is shown small, as expected. But I'd like to have my world size (16:9) work with labels. Can you suggest me how to scale down the font properly?

LibGDX making a rectangle move on its own

public class gameMain implements Screen {
final main game;
SpriteBatch batch;
Texture img;
private Texture alexTexture;
private Rectangle alex;
private Texture cTex;
private Texture dropper;
private Texture ender;
private Texture partsImg;
private Texture toy;
private OrthographicCamera camera;
private Array<Rectangle> part; // ******
private long lastDropTime;
private int beltSpeed = 100; // ******
//Score Keeper
private int score;
private String scoreName;
//basically a create method
public gameMain(final main gam){
this.game = gam;
// load images into memory
dropper = new Texture("android/assets/dropper.png");
ender = new Texture("android/assets/endOfBelt.png");
partsImg = new Texture("android/assets/unmadeToyParts.png");
toy = new Texture("android/assets/toymade.png");
cTex = new Texture("android/assets/conveyerBeltBackground.png");
alexTexture = new Texture(Gdx.files.internal("android/assets/alexAlpha2.png"));
// set the game window resolution
camera = new OrthographicCamera();
camera.setToOrtho(false, 1080,720);
// Alex's position / hitbox
alex = new Rectangle();
alex.x = 250;
alex.y = 150;
alex.width = 126;
alex.height = 75;
// part stuff
part = new Array<Rectangle>();
spawnPart();
// score handler
score = 0;
scoreName = "Toys Made: ";
}
private void spawnPart(){ // *******
Rectangle parts = new Rectangle();
parts.x = 0;
parts.y = 210;
parts.width = 52;
parts.height = 60;
part.add(parts);
lastDropTime = TimeUtils.nanoTime();
} //********
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
// load alex sprite
game.batch.setProjectionMatrix(camera.combined);
// begin drawing to screen
game.batch.begin();
batch.draw(cTex, -5, 200); // draw conveyer background
batch.draw(dropper, 0, 210); // draw the dropper
batch.draw(ender, 600, 200); // draw the ender
game.batch.draw(alexTexture, alex.x, alex.y); // draw alex
for(Rectangle parts: part){
game.batch.draw(partsImg, parts.x, parts.y); // draw part
}
game.font.draw(game.batch, scoreName, 25, 100); // draw scoreboard
game.batch.end(); // end drawing to screen
//******************************************************************************
//HERE IS WHERE I AM TRYING TO PUT IT
part.x += beltspeed;
if (part.rectangle overlaps ender.rectangle){
despawn part;
}
//******************************************************************************
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void dispose() {
}
}
Hello I am very new to LibGDX, and after doing some research I decided to make a game where you are a factory worker named Alex and you build toys. I will gladly take any feedback you have to make my code more orginized or work better. I highlighted everything I believe to be relevant to my question with some asterisks.
But my question is: How do you make a 'rectangle' such as my 'part' move on its own. I added a beltspeed and a spawn zone, and once the hitbox for it goes over the 'ender' hitbox I would like to despawn it.
Also I haven't gotten this far yet, but when the 'part' hitbox passes over 'Alex' hitbox I would like a little minigame to appear where you have to press up, down, left, right (randomly) to build the toy. If you have any suggestions on how I should handle that, I would be very appreciative.
"C:\Program Files\Java\jdk1.7.0_79\jre\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\desktop;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\core;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx\1.9.2\e641cb91bec06bc64d9ddf7a7d7062caceec73cd\gdx-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d\1.9.2\b78eaa90aaaf7830e6dffff587ea6e859c2787b2\gdx-box2d-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype\1.9.2\3609253d14edb1b3ca5aacff4e06989edde75be4\gdx-freetype-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-lwjgl\1.9.2\d710a8704ed584ec2ba9ca52e3a6a5885dd759cc\gdx-backend-lwjgl-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-platform\1.9.2\dde4cf7e9ce61c24042f512203aed87657496639\gdx-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d-platform\1.9.2\497cbfbf81e7e8b1e8433b19291c5af4bbc2ec66\gdx-box2d-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-tools\1.9.2\37d8e3009ae0febdf93717b21980c67c8cadac07\gdx-tools-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype-platform\1.9.2\1e1afb0b6c9e8aeb7d495cb8f55c353d3da58cf0\gdx-freetype-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl\2.9.2\a9d80fe5935c7a9149f6584d9777cfd471f65489\lwjgl-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl_util\2.9.2\4b9e37300a87799856e0bd15ed81663cdb6b0947\lwjgl_util-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.jlayer\jlayer\1.0.1-gdx\7cca83cec5c1b2f011362f4d85aabd71a73b049d\jlayer-1.0.1-gdx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.jcraft\jorbis\0.0.17\8872d22b293e8f5d7d56ff92be966e6dc28ebdc6\jorbis-0.0.17.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-headless\1.9.2\813e6020de85cd831f02cb5e9060fd7ea8cb208e\gdx-backend-headless-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\510c7d317f5e9e700b9cfaac5fd38bdebf0702e0\lwjgl-platform-2.9.2-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d276cdf61fe2b516c7b7f4aa1b8dea91dbdc8d56\lwjgl-platform-2.9.2-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d55b46b40b40249d627a83a7f7f22649709d70c3\lwjgl-platform-2.9.2-natives-osx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput\2.0.5\39c7796b469a600f72380316f6b1f11db6c2c7c4\jinput-2.0.5.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jutils\jutils\1.0.0\e12fe1fda814bd348c1579329c86943d2cd3c6a6\jutils-1.0.0.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\7ff832a6eb9ab6a767f1ade2b548092d0fa64795\jinput-platform-2.0.5-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\385ee093e01f587f30ee1c8a2ee7d408fd732e16\jinput-platform-2.0.5-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\53f9c919f34d2ca9de8c51fc4e1e8282029a9232\jinput-platform-2.0.5-natives-osx.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.rafiredog.game.desktop.DesktopLauncher
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.rafiredog.game.gameMain.render(gameMain.java:97)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.rafiredog.game.main.render(main.java:45)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:223)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Process finished with exit code 0
Lastly, I am now getting this error. I moved some code around near the 'batch.draw'. However that might not be the cause of the error? I am a little lost right now. But I will gladly screenshot what I have of the game now once the errors are resolved.
Thank you for any insight you have on fixing up this game.
You need to do game updates and then rendering on each cycle of the game loop. The game update part of your code can iterate through your objects to do stuff to them.
For example, your render method would look like this. You need to explicitly use an Iterator for your for loop because you otherwise could not remove items from the list while iterating.
#Override
public void render(float delta) {
//Update game
Iterator<Rectangle> iterator = parts.iterator();
while (iterator.hasNext()){
Rectangle part = iterator.next();
part.x += beltSpeed * delta; //distance = speed * time
if (part.rectangle.overlaps(ender.rectangle)){
iterator.remove(); //removes rectangle from the list
}
}
//This is also where you would update movement for anything else,
//such as a character jumping, or counting down a timer and spawning
//something when it reaches zero, for example.
//Draw everything
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
//...
game.batch.end();
}
If you spawn and "despawn" a lot of objects, you will probably need to use pooling to avoid stutters from memory deallocation. You can do this by replacing new Rectangle() with Pools.obtain(Rectangle.class) and adding the line Pools.free(part) right after iterator.remove().
I also noticed you have counter-intuitive usage of the words "part" and "parts" by swapping plural and singular. Make sure that doesn't trip you up.
As for your NullPointerException, read here.
Piggy backing onto Tenfour04's answer and attempting to answer your question in the comments. I'd suggest looking at this link: https://github.com/libgdx/libgdx/wiki/The-life-cycle

Libgdx ScrollPane adding space at the top

I'm creating a store for my game and I'm having issues with the libgdx ScrollPane. It seems to be moving the table within it down by 155px. The effect it's having is that the table appears roughly 155px down from the top, and the last button is off the screen no matter how far down I scroll.
Here is the window when the "Store" first appears.
As you can see the top of the table is quite a bit below the top of the window. Code below, but the table only has 10px of padding.
Here is the window when I've scrolled down as far as I could go - sorry, the scroll pars disappeared before I could grab the screenshot.
You can see that the "Main Menu" button is about half way off the screen.
Here is the code that lays out the "Store".
table = new Table();
table.setFillParent(true);
table.defaults().expandX().fill().space(5f);
table.pad(10f);
// characters
table.add(new Label("Characters: ", skin, "default")).left().colspan(2);
table.row();
ButtonGroup characterGroup = new ButtonGroup();
characterGroup.setMaxCheckCount(1);
Button boyButton = createImageTextButton("Plain Boy", boyTexture);
Button catButton = createImageTextButton("Cat Girl", catTexture);
Button hornButton = createImageTextButton("Horn Girl", hornTexture);
Button pinkButton = createImageTextButton("Pink Girl", pinkTexture);
Button queenButton = createImageTextButton("Queen", queenTexture);
float minHeight = 130f; // only used to force scrolling.
table.add(boyButton).minHeight(minHeight);
table.add(catButton).minHeight(minHeight).row();
table.add(hornButton).minHeight(minHeight);
table.add(pinkButton).minHeight(minHeight).row();
table.add(queenButton).minHeight(minHeight).colspan(2);
table.row();
characterGroup.add(boyButton, catButton, hornButton, pinkButton, queenButton);
characterGroup.setChecked("Plain Boy");
// drills
ButtonGroup drillGroup = new ButtonGroup();
Button flappyButton = createImageTextButton("Flappy", null);
Button tappyButton = createImageTextButton("Tappy", null);
Button tiltyButton = createImageTextButton("Tilty", null);
table.add(new Label("Drills:", skin, "default")).left().padTop(20).colspan(2);
table.row();
table.add(flappyButton).minHeight(minHeight);
table.add(tappyButton).minHeight(minHeight).row();
table.add(tiltyButton).minHeight(minHeight);
drillGroup.add(flappyButton, tappyButton, tiltyButton);
drillGroup.setChecked("Flappy");
// main menu button
table.row();
Button mainMenuButton = createImageTextButton("Main Menu", null);
table.add(mainMenuButton).minHeight(minHeight).padTop(40).padBottom(10f).colspan(2);
ScrollPane scrollPane = new ScrollPane(table, skin);
scrollPane.setBounds(0, 0, stage.getWidth(), stage.getHeight());
addActor(scrollPane);
I debugged the desktop version and saw that the table's y position was set to -155 before I scroll, and set to 0 after I scroll to the bottom. However, even when it's set to 0, the last button is always partly off the screen.
As requested here is the code where I create the viewport and camera:
package com.example;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.viewport.ExtendViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.example.stages.GameStage;
public class MainGame extends ApplicationAdapter {
public static final int MIN_WIDTH = 480;
public static final int MIN_HEIGHT = 800;
public static SpriteBatch batch;
public static GameStage game;
public static Skin skin;
public static Viewport viewport;
public static Stage stage;
#Override
public void create() {
viewport = new ExtendViewport(MIN_WIDTH, MIN_HEIGHT);
batch = new SpriteBatch();
initSkin();
game = new GameStage(viewport, batch, skin);
setStage(game);
}
#Override
public void dispose() {
super.dispose();
game.dispose();
skin.dispose();
}
public void initSkin() {
skin = new Skin(Gdx.files.internal("skins/uiskin.json"));
}
#Override
public void render() {
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override
public void resize(int width, int height) {
viewport.update(width, height, true);
}
public Skin getSkin() {
return skin;
}
public static void setStage(Stage stage) {
MainGame.stage = stage;
Gdx.input.setInputProcessor(stage);
}
}
Ok, finally figured it out. Turns out the Table within the ScrollPane cannot be set to fill parent.
table.setFillParent(true);
Causes the issue. Not sure why it's doing that, but removing the setFillParent(true) fixes the issue.