How to detect collisions properly? - java

This is my first time making a game with LibGDX and I'm trying to increase the score in my game when two things collide, but it doesn't register the collision at all.
This is what I have in the Player class:
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.EdgeShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.World;
import com.mygdx.summative.MyGdxGame;
import com.mygdx.summative.Screens.PlayScreen;
public class Player extends Sprite {
public World world;
public Body b2dbody;
private TextureRegion peteStand;
public Player(World world, PlayScreen screen ){
super(screen.getAtlas().findRegion("goomba"));
this.world = world;
definePlayer();
peteStand = new TextureRegion(getTexture(), 227,1,16,16);
setBounds(227,1,16/ MyGdxGame.PPM,16/MyGdxGame.PPM);
setRegion(peteStand);
}
public void update (float dt ){
setPosition(b2dbody.getPosition().x - getWidth() /2, b2dbody.getPosition().y - getHeight()/2);
}
public void definePlayer (){
BodyDef bdef = new BodyDef();
bdef.position.set(32 / MyGdxGame.PPM,32 /MyGdxGame.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2dbody = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(6/MyGdxGame.PPM);
fdef.shape = shape;
b2dbody.createFixture(fdef);
EdgeShape body = new EdgeShape(); // used for collision dectection
body.set(new Vector2(-1/MyGdxGame.PPM,7/MyGdxGame.PPM), new Vector2(1/MyGdxGame.PPM,7/MyGdxGame.PPM)); // sets up borders for collision on player
fdef.shape = body ;
fdef.isSensor = true;
b2dbody.createFixture(fdef).setUserData("body"); // used to identify collisions to see if one if the player
}
}
When cloud hits, I want to increase the score, so I wrote this in the Object class:
public class Cloud extends InteractiveTileObject {
public Cloud(World world, TiledMap map, Rectangle bounds) {
super(world, map, bounds);
fixture.setUserData(this);
}
#Override
public void onBodyHit() {
Gdx.app.log("Cloud" , "Collision");
Hud.addScore(200);
}
}
What am I missing? This is contact methods in the ContactListener class:
#Override
public void beginContact(Contact contact) { // when to things start to collide
// figures out with fixture is which in a collision of two objects
Fixture fixA = contact.getFixtureA();
Fixture fixB = contact.getFixtureB();
// checks of one is players body
if (fixA.getUserData() == "body" || fixB.getUserData() == "body"){
Fixture body = fixA.getUserData() == "body" ? fixA : fixB;
Fixture object = body == fixA ? fixB : fixA;
// checks if the object the player collided with is a interactive object
if (object.getUserData() instanceof InteractiveTileObject) {
((InteractiveTileObject) object.getUserData() ).onBodyHit();
}
}
}

Generally, fixA.getUserData() == "body" is wrong because you are comparing the equality of references. To check if a String is equal to another in terms of the content, i.e. lexicographically you should do fixA.getUserData().equals("body") or a safer way "body".equals(fixA.getUserData()).
On a side note, the "player" identifier may be more suitable, as technically speaking everything in the physics world is a body.

Related

Libgdx + Box2d working with 2 cameras

Recently I have read that you can work with 2 cameras whenever you involve Box2d, which only works in meters.
In my Renderer class, I receive all the entities in the game and then draw them.
I work with ashley library so all my entities are a formed by components.
Now, in my renderer method I check if the current Entity has BodyComponent. If true, then it draws the Sprite in the physicsCam, who has a Viewport of meters. Otherwise, it will just draw the Sprite in sceneCam, which has a Viewport of pixels.
My problem is I try to draw the Sprite according to the Body's position in meters, but it is drawn not exactly where the body is.
NOTE: I also have PhysicsDebugSystem which basically just call the DebugRenderer.render() method.
Here is my RenderSystem class:
package engine.systems;
import com.badlogic.ashley.core.Component;
import com.badlogic.ashley.core.ComponentMapper;
import com.badlogic.ashley.core.Entity;
import com.badlogic.ashley.core.Family;
import com.badlogic.ashley.systems.IteratingSystem;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.Array;
import engine.Values;
import engine.components.BodyComponent;
import engine.components.SpriteComponent;
import engine.components.TransformComponent;
public class RenderSystem extends IteratingSystem{
private SpriteBatch batch;
private Array<Entity> renderQueue;
private OrthographicCamera sceneCam;
private OrthographicCamera physicsCam;
private ComponentMapper<SpriteComponent> txt;
private ComponentMapper<TransformComponent> trs;
#SuppressWarnings("unchecked")
public RenderSystem(SpriteBatch batch) {
super(Family.all(TransformComponent.class, SpriteComponent.class).get());
txt = ComponentMapper.getFor(SpriteComponent.class);
trs = ComponentMapper.getFor(TransformComponent.class);
sceneCam = new OrthographicCamera(Values.WIDTH, Values.HEIGHT);
sceneCam.setToOrtho(false);
physicsCam = new OrthographicCamera(Values.WIDTH, Values.HEIGHT);
physicsCam.setToOrtho(false);
renderQueue = new Array<Entity>();
this.batch = batch;
}
#Override
public void update(float deltaTime) {
super.update(deltaTime);
Gdx.gl.glClearColor(230/255f, 242/255f, 242/255f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sceneCam.update();
physicsCam.update();
batch.enableBlending();
batch.begin();
for (Entity entity : renderQueue) {
Component comp = entity.getComponent(BodyComponent.class);
if(comp == null) {
batch.setProjectionMatrix(sceneCam.combined);
} else {
batch.setProjectionMatrix(physicsCam.combined);
}
SpriteComponent texture = txt.get(entity);
TransformComponent transform = trs.get(entity);
if (texture.region == null || transform.isHidden) {
continue;
}
texture.region.setPosition(transform.position.x, transform.position.y);
texture.region.setRotation(transform.rotation);
texture.region.setScale(transform.scale.x, transform.scale.y);
texture.region.draw(batch);
}
batch.end();
renderQueue.clear();
}
#Override
protected void processEntity(Entity entity, float deltaTime) {
renderQueue.add(entity);
}
public OrthographicCamera getCamera() {
return sceneCam;
}
}
In my GameWorld class I construct the ball in this method:
public void initBall() {
Entity entity = new Entity();
float x = Values.WIDTH/2*Values.PPM;
float y = Values.HEIGHT*Values.PPM;
SpriteComponent txt = new SpriteComponent();
txt.region = skin.getSprite("soccerball");
txt.region.setSize(Values.BALL_WIDTH, Values.BALL_HEIGHT);
entity.add(txt);
TransformComponent trs = new TransformComponent();
trs.isHidden = false;
trs.position.x = x;
trs.position.y = y;
entity.add(trs);
BodyComponent bc = new BodyComponent();
BodyDef bodyDef = new BodyDef();
// Set our body to dynamic
bodyDef.type = BodyDef.BodyType.DynamicBody;
// Set our body's starting position in the world
bodyDef.position.set(x, y+Values.BALL_HEIGHT/2);
bc.body = world.createBody(bodyDef);
bc.body.applyAngularImpulse(50f, true);
CircleShape circle = new CircleShape();
circle.setRadius(Values.BALL_WIDTH/2f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 20f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f;
bc.body.createFixture(fixtureDef);
circle.dispose();
entity.add(bc);
engine.addEntity(entity);
}
Here's the screenshot I took during the simulation:
The reason your ball sprite seems to be rendered offset from your box2d body is because your texture's anchor is it's bottom left corner, which means that when you set your texture's position you basically set the position of it's bottom left corner. To properly position your ball you'll need to subtract it's half-width and half-height from it's position:
final float halfWidth = texture.region.getRegionWidth() * 0.5f;
final float halfHeight = texture.region.getRegionHeight() * 0.5f;
texture.region.setPosition(transform.position.x - halfWidth, transform.position.y - halfHeight);
I'll also urge you to read this box2d blog post since, from the code you posted, you don't seem to scale your box2d entites which means that that ball you have is Values.BALL_WIDTH METERS wide. Judging from the screenshot it looks like it's ~2.5m radius. That's one huge ball!

Shaking single tile in java (libgdx + TiledMap)

I'm making a clone of old Super Mario and I am trying to shake the brick tile when mario in his little form hits it from below. The concept is taken from a great libgdx tutorial by Brent Aureli and everything he wrote/shown works, however when I made this (seemingly small) modification, the modification itself behaves strange.
Namely, when little mario hits the tile (any brick tile) ALL tiles of this kind get this offset. From my understanding, the access is getCell().getTile().setOffsetY(value) which should mean
get a single cell -> get tile in that cell -> set offset to this one tile that is in the given cell.
Documentation also suggests it should work like that:
https://libgdx.badlogicgames.com/nightlies/docs/api/
replacing tile with null when big mario hits the tile works as intended, so I don't understand why the approach with getCell.getTile doesn't.
Finally, I'm aware that cells are immobile, all I want is a purely cosmetic shift of the actual texture for half a second or so - and that is possible, but in the current state it offsets ALL similar tiles.
For the fun of it I
public class Brick extends InteractiveTile {
private static TiledMapTileSet tileSet;
public Brick(PlayScreen screen, MapObject object) {
super(screen, object);
tileSet = screen.getMap().getTileSets().getTileSet("tileset_gutter");
fixture.setUserData(this);
setCategoryFilter(SuperMario.BRICK_BIT);
}
#Override
public void onHeadHit(Mario mario) {
if(mario.isBig()){
SuperMario.manager.get("audio/breakblock.wav", Sound.class).play();
setCategoryFilter(SuperMario.DESTROYED_BIT);
getCell().setTile(null);
}
else {
SuperMario.manager.get("audio/bump.wav", Sound.class).play();
// DOES THE EXACT SAME AS LATER 3 LINES
// getCell().getTile().setOffsetY(2);
getCell().setTile(tileSet.getTile(28)); //this can change texture of individual tile.
TiledMapTile tile = getCell().getTile();
tile.setOffsetY(2);
getCell().setTile(tile);
}
}
}
InteractiveTile:
public abstract class InteractiveTile {
private World world;
private TiledMap map;
private TiledMapTile tile;
private Rectangle bounds;
protected Body body;
protected final Fixture fixture;
protected PlayScreen screen;
protected MapObject object;
public InteractiveTile(PlayScreen screen, MapObject object){
this.screen = screen;
this.world = screen.getWorld();
this.map = screen.getMap();
this.object = object;
this.bounds = ((RectangleMapObject)object).getRectangle();
BodyDef bdef = new BodyDef();
FixtureDef fdef = new FixtureDef();
PolygonShape shape = new PolygonShape();
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set(
(bounds.getX()+ bounds.getWidth()/2)/ SuperMario.PPM,
(bounds.getY() + bounds.getHeight()/2)/SuperMario.PPM);
body = world.createBody(bdef);
shape.setAsBox(
(bounds.getWidth()/2)/SuperMario.PPM,
(bounds.getHeight()/2)/SuperMario.PPM); fdef.shape = shape;
fixture = body.createFixture(fdef);
}
public abstract void onHeadHit(Mario mario);
public TiledMapTileLayer.Cell getCell(){
TiledMapTileLayer layer = (TiledMapTileLayer) map.getLayers().get(1);
return layer.getCell(
//REVERT SCALING (PPM) AND by tile size
(int)(body.getPosition().x * SuperMario.PPM / 16),
(int)(body.getPosition().y * SuperMario.PPM / 16));
}
public void setCategoryFilter(short filterBit){
Filter filter = new Filter();
filter.categoryBits = filterBit;
fixture.setFilterData(filter);
}
}
is there an error in this code, or it is a limitation of the engine?
PS - the original (unmodified)files can be found on Brent Aurelis github site:
https://github.com/BrentAureli/SuperMario

libGDX - How do I add a (mouse)joint to an Actor in scene2d

If I have a GameStage with the following:
...
public GameStage() {
world = WorldUtils.createWorld();
setUpWorld();
setupCamera();
debugRenderer = new Box2DDebugRenderer();
}
private void setUpWorld() {
world = WorldUtils.createWorld();
world.setContactListener(this);
setupGround();
setupBall();
setupJoint();
}
private void setupBall() {
ball = new Ball(WorldUtils.createBall(world));
addActor(ball);
}
private void setupGround() {
ground = new Ground(WorldUtils.createGround(world));
addActor(ground);
}
private void setupJoint() {
jointDef = new MouseJointDef();
jointDef.bodyA = ???
jointDef.collideConnected = true;
jointDef.maxForce = 50f;
}
...
How do I reference the bodies within each actor so that I can add a joint between two bodies. Specifically I am trying to add a mousejoint to the ball body so that I can add a directional impulse (mousejoint is destroyed in touchup or if max impulse is reached). I set the ground as bodyA during the setupJoint method. In the touchdown method I set the bodyB as the ball. I then find the x and y values (unprojecting them first to move from World to local coordinates) from the touch and set the position of the mouse using jointDef.target.set. My problem is I cannot figure out to get the body from the actor. Here is an example of my createBall method in the WorldUtils class.
...
public static Body createBall(World world) {
// BALL
// Body Definition
BodyDef ballDef = new BodyDef();
ballDef.type = BodyDef.BodyType.DynamicBody;
ballDef.position.set(0, 10); // 1 Meter up not 1 pixel
// Ball shape
CircleShape ballShape = new CircleShape();
ballShape.setRadius(.5f);
// Fixture Definition
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = ballShape;
fixtureDef.density = 2.0f;
fixtureDef.friction = .5f; // 0 to 1
fixtureDef.restitution = .5f; // 0 to 1
Body body = world.createBody(ballDef);
body.createFixture(fixtureDef);
body.resetMassData();
body.setUserData(new BallUserData());
ballShape.dispose();
return body;
}
...
My Ball and Ground are defined like this
...
public class Ground extends GameActor {
public Ground(Body body) {
super(body);
}
#Override
public GroundUserData getUserData() {
return (GroundUserData) userData;
}
}
I am sure I am doing something stupid or I am misunstanding how the connection between scene2d and box2d works.
Thanks

libgdx - implementing moving Kinematic body

project: I am making a simple project in which i want to be able to make a kinematic body and move it from point x to y. There doesn't seem to be much directly on "Creating kinematic bodies". i've been following a few different tutorials on implementing kinematic bodies because i couldnt find one that specified how to do it correctly.
Problem: It seems to be a simple fix but i just can't figure out what the problem is because i don't fully understand how to implement a kinematic body. i believe the problem lies in this code kinematicBody.setLinearVelocity(0.0f, 1.0f); because i get an error in "setLinearVelocity"stating "The method setLinearVelocity(float, float) is undefined for the type BodyDef" i feel that i am doing something wrong here
Outcome i want: i want to be able to create a kinematic body that moves from point x to point y.
here is my relevant code:
package com.mohamed.JungleFighter;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.sun.xml.internal.ws.wsdl.writer.document.soap.Body;
public class JungleFighter extends Game {
World world = new World(new Vector2(0, -100), true);
Box2DDebugRenderer debugRenderer;
OrthographicCamera camera;
static final float STEP=1/60f;
static final int VELOCITYITERATIONS=6;
static final int POSITIONITERATIONS=2;
static final float WORLD_TO_BOX=0.01f;
static final float BOX_WORLD_TO=100f;
#Override
public void create() {
camera = new OrthographicCamera();
camera.viewportHeight = 320;
camera.viewportWidth = 480;
camera.position.set(camera.viewportWidth * .5f, camera.viewportHeight * .5f, 0f);
camera.update();
//test platform 3
BodyDef kinematicBody =new BodyDef();
kinematicBody.type = BodyType.KinematicBody;
kinematicBody.position.set(100, 250);
PolygonShape shape = new PolygonShape();
shape.setAsBox(50f, 25f);
fixtureDef.shape = shape;
fixtureDef.density = 0;
fixtureDef.friction = 0;
fixtureDef.restitution = 0;
kinematicBody.setLinearVelocity(0.0f, 1.0f);
// Create our body in the world using our body definition
world.createBody(kinematicBody).createFixture(shape, 50.0f);
shape.dispose();
debugRenderer = new Box2DDebugRenderer();
}
#Override
public void dispose() {
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
debugRenderer.render(world, camera.combined);
world.step(STEP, VELOCITYITERATIONS, POSITIONITERATIONS);
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
It appears as if you aren't using the fixtureDef object anywhere. You are supposed to set it to the body once it is created.
The way you create a Kinematic Body isn't much different from a Static Body. The only difference would be how you define the type of the BodyDef.
Create a Kinematic Body
It could be a StaticBody or DynamicBody too. Depends on what you want to accomplish.
BodyDef tempBodyDef = new BodyDef();
tempBodyDef.type = BodyType.KinematicBody;
Create the FixtureDefinition (The one that describes the properties of the fixture)
Also create a shape and assign it to the fixture.
You can modify the firction, isSensor, etc, properties of the tempFD to get the results you want.
FixtureDef tempFD = new FixtureDef();
PolygonShape tempShape = new PolygonShape();
tempFD.shape = tempShape;
The center of the shape for the body will be at 0,0
Vector2 tempVector = new Vector2();
tempVector.x = 0;
tempVector.y = 0;
Setting the size and position of the body's shape.
Notice I'm using half the width and height, as that is what the setAsBox function requires.
tempShape.setAsBox(myWidth/2f, myHeight/2f, tempVector, myAngle);
tempBodyDef.position.set(myXPosition, myYPosition);
Create the body and assign the fixture to it
Body testBody = world.createBody(tempBodyDef);
testBody.createFixture(tempFD);
Don't forget to dispose of the Shape once you are done with it.
tempShape.dispose();
And you are done.

Exception in thread "LWJGL Application" java.lang.NullPointerException

I am following a tutorial on creating a game with LibGdx from some ebook. the tutorial has steps for creating a game called "Canyon Bunny". Its a simple 2D game. but i keep getting this annoying error! (i also used to get the error on a different tutorial of the same genre)
i am in the early stages of the development for this game. and i am doing some test (of which i follow to the letter from the tutorial). I use a MAC and a i have tried many solutions with no luck at all.
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.Adel.CanyonBunny.game.WorldUpdater.updateTestObjects(WorldUpdater.java:83)
at com.Adel.CanyonBunny.game.WorldUpdater.update(WorldUpdater.java:76)
at com.Adel.CanyonBunny.CanyonBunnyMain.render(CanyonBunnyMain.java:39)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:207)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)
It is truly one of the most frustrating things a striving programmer can face.
ill get the code of all the classes in case that's related somehow...
This is CanyonBunnyMain in the general program:
package com.Adel.CanyonBunny;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.Adel.CanyonBunny.game.*;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.Application;
public class CanyonBunnyMain implements ApplicationListener {
private static final String TAG = CanyonBunnyMain.class.getName();
private WorldUpdater worldUpdater;
private WorldRenderer worldRenderer ;
private boolean paused ;
public void create() {
//I'll set the log to debug for the developing process
Gdx.app.setLogLevel(Application.LOG_DEBUG) ;
worldUpdater = new WorldUpdater();
worldRenderer = new WorldRenderer() ;
// since, upon creation, the game is not paused, then:
paused = false ;
}
public void render() {
if (paused = true) {
//update the game by the time passed since the last update
worldUpdater.update(Gdx.graphics.getDeltaTime()) ;
}
//sets the screen color to: CornFlower Blue
Gdx.gl.glClearColor(0x64 / 255.0f, 0x95 / 255.0f, 0xed / 255.0f, 0xff / 255.0f);
//clears the screen to prevent flickering
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT) ;
//Render the game to the screen
worldRenderer.render();
}
public void resize (int w, int h) {
worldRenderer.resize(w, h) ;
}
public void pause () {
paused = true ;
}
public void resume() {
paused = false ;
}
public void dispose() {
worldRenderer.dispose() ;
} }
this is the WorldRenderer (general program too) :
package com.Adel.CanyonBunny.game;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
public class WorldRenderer {
private OrthographicCamera cam;
private SpriteBatch batch ;
private WorldUpdater updater;
public void WorldRenderer(WorldUpdater worldUpdater) { }
public void init() { }
public void render() { }
public void resize(int w, int h) { }
public void dispose() { }
}
this is the main class (from the desktop project: the one that i run on my MAC) :
package com.Adel.CanyonBunny;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "CanyonBunny";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
new LwjglApplication(new CanyonBunnyMain(), cfg);
}
}
Any help will be wonderful.
tell me should you need extra data
this is the WorldUpdater class for those who asked:
package com.Adel.CanyonBunny.game;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.math.MathUtils;
public class WorldUpdater {
private final String TAG = WorldUpdater.class.getName();
public Sprite[] testSprites;
public int selectedSprite;
public WorldRenderer worldRenderer;
public void worldUpdater() {
init() ;
}
public void init() {
initTestObjects() ;
}
private void initTestObjects() {
// create new array of 5 sprites
testSprites = new Sprite[5] ;
// Create empty POT-sized Pixmap with 8 bit RGBA pixel data
int w = 32;
int h = 32;
Pixmap pixmap = createProceduralPixmap(w, h) ;
//create a new texture from Pixmap data
Texture texture = new Texture(pixmap) ;
//create sprites using the just created texture
for (int i = 0; i < testSprites.length; i++) {
Sprite spr = new Sprite(texture) ;
spr.setSize(1,1) ;
//set origin to sprite's center
spr.setOrigin(spr.getWidth() / 2.0f, spr.getHeight() / 2.0f) ;
float randomX = MathUtils.random(-2.0f, 2.0f) ;
float randomY = MathUtils.random(-2.0f, 2.0f) ;
spr.setPosition(randomX, randomY) ;
//put new sprite into array
testSprites[i] = spr ;
}
//set first sprite as the selected one
selectedSprite = 0 ;
}
private Pixmap createProceduralPixmap(int width, int height) {
Pixmap pixmap = new Pixmap(width, height , Format.RGBA8888) ;
//fill the square with red color at 50% opacity
pixmap.setColor(1, 0, 0, 0.5f) ;
pixmap.fill() ;
//draw a yellow X in the pixmap
pixmap.setColor(1, 1, 0 , 1) ;
pixmap.drawLine(0, 0, width, height) ;
pixmap.drawLine(width, 0, 0, height);
//draw a cyan-colored border around the square
pixmap.setColor(0, 1, 1, 1) ;
pixmap.drawRectangle(0, 0, width, height) ;
return pixmap;
}
public void update(float deltaTime) {
updateTestObjects(deltaTime);
}
private void updateTestObjects(float deltaTime) {
//get current rotation from the selected sprite
float rotation = testSprites[selectedSprite].getRotation();
//rotate sprite by 90 degrees per second
rotation += 90 * deltaTime;
//wrap around at 360 degrees
rotation %= 360 ;
testSprites[selectedSprite].setRotation(rotation);
}
}
Also, when i check this line out in Debugging mode:
testSprites = new Sprite[5] ;
"testSprites" keeps showing null.
i hope this clears up some details!
thanks again.
The problem is with your "constructors", mainly in the updater (as the renderer does nothing):
public void worldUpdater() { ... }
Constructors should not specify return types - that's part of how the compiler recognizes them as constructors. As it is in your code, it's just a method you could call on an existing object instance. Change it like so:
public WorldUpdater() { ... }
Note the lack of a return type and the uppercase W.
You can change the renderer the same way. (But then you will have to pass the updater to its constructor in the main class.)
Also, Nine Magics is right that the way you store renderer and updater references in each other doesn't make much sense, even if it's not related to this problem. I see no reason why an updater class would need to know about its renderer, I'd remove that field.
In your WorldRenderer you specify this:
public void WorldRenderer(WorldUpdater worldUpdater) { }
And WorldRendere also carries an instance of an worldUpdater?
private WorldUpdater updater;
But on your main file you create an instance of both renderer and updater?
worldUpdater = new WorldUpdater();
worldRenderer = new WorldRenderer() ;
I don't know, I might have tired eyes or something but this seems too complex. Can it be that you are refering to a wrong instance of WorldUpdater? Might edit this if I can wrap my head around it better.

Categories