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.
Related
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!
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.
I have just started with LibGdx and I have figured out how to center text with it. Now I am having trouble with center justifying text. I was wondering if someone can help. I have attach my code for centering. Thank you in advance.
package com.tutorials.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class TextDemo extends ApplicationAdapter {
SpriteBatch batch;
BitmapFont font;
String myText;
GlyphLayout layout = new GlyphLayout();
#Override
public void create () {
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("myFont.fnt"));
myText = "I took one, one cause you left me\n"
+ "Two, two for my family\n"
+ "Three, three for my heartache";
layout.setText(font,myText);
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float x = Gdx.graphics.getWidth()/2 - layout.width/2;
float y = Gdx.graphics.getHeight()/2 + layout.height/2;
batch.begin();
font.draw(batch,layout,x,y);//Center Text
batch.end();
}
You can use following setText() method instead and set targetWidth to screen width, Aligh.center, and set wrap to true. Also, set x = 0 so the text is centered across the whole screen.
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
public void setText(BitmapFont font,
java.lang.CharSequence str,
Color color,
float targetWidth,
int halign,
boolean wrap)
Updated example:
#Override
public void create () {
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("myFont.fnt"));
myText = "I took one, one cause you left me\n"
+ "Two, two for my family\n"
+ "Three, three for my heartache";
layout.setText(font,myText,Color.BLACK,Gdx.graphics.getWidth(),Align.center,true);
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float x = 0;
float y = Gdx.graphics.getHeight()/2 + layout.height/2;
batch.begin();
font.draw(batch,layout,x,y);//Center Text
batch.end();
}
Instead of using the font.draw method, use the following one instead...
public TextBounds drawMultiLine (Batch batch, CharSequence str, float x, float y, float alignmentWidth, HAlignment alignment)
alignmentWidth is the max width you want your text to take up. Any more than that and it will wrap. Set it to something stupidly high if you don't want wrapping.
'alignment' is the key thing and takes an HAlignment enum and can be either LEFT, RIGHT or CENTER
The batch, str, x and y parameters are the same as you're already doing.
Ok, I need to crop an ImageView in a particular shape, and I can't do this by adding over a png, because the background can be variable (ex. a pattern). So, I need that the area outside the shape is transparent.
The shape must be this:
I thought to use Path() to draw this shape and use it to mask the ImageView, but I have absolutely no idea how to draw a complex shape like this with Path().
Many thanks.
So I was bored and this looked like fun, so I've thrown together a simple Drawable you can use to do this. You could get fancier and add strokes and whatnot to it, but this works for the basic case you've suggested, and allows you to set the arrow to be pointing to any of the corners, and will also scale your image to fit the bounds of the Drawable. Here's the result:
You can use it by:
BubbleDrawable bubbleDrawable = new BubbleDrawable(
this, R.drawable.your_image, BubbleDrawable.Corner.TOP_RIGHT);
myImageView.setImageDrawable(bubbleDrawable);
And here's the code for BubbleDrawable:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import static android.graphics.Matrix.ScaleToFit.FILL;
import static android.graphics.Paint.ANTI_ALIAS_FLAG;
import static android.graphics.Path.Direction.CW;
import static android.graphics.PixelFormat.TRANSPARENT;
import static android.graphics.Shader.TileMode.CLAMP;
import static test.com.testrotationanimation.BubbleDrawable.Corner.TOP_LEFT;
public final class BubbleDrawable extends Drawable {
private final Matrix mMatrix = new Matrix();
private final Paint mPaint = new Paint(ANTI_ALIAS_FLAG);
private final Path mPath = new Path();
private final RectF mSrcRect = new RectF();
private final RectF mDstRect = new RectF();
private final Shader mShader;
private Corner mArrowCorner = TOP_LEFT;
public BubbleDrawable(Bitmap bitmap, Corner arrowCorner) {
// Initialize a BitmapShader with the image you wish to draw
// (you can use other TileModes like REPEAT or MIRROR if you prefer)
mShader = new BitmapShader(bitmap, CLAMP, CLAMP);
mPaint.setShader(mShader);
// Save the bounds of the bitmap as the src rectangle -- will
// be used later to update the matrix when the bounds change
// so that the image fits within the bounds of this drawable
mSrcRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
// Set the corner in which the arrow will be drawn
mArrowCorner = arrowCorner;
}
public BubbleDrawable(Context ctx, int drawableResource, Corner arrowCorner) {
this(BitmapFactory.decodeResource(ctx.getResources(), drawableResource), arrowCorner);
}
public Corner getArrowCorner() {
return mArrowCorner;
}
public void setArrowCorner(Corner corner) {
mArrowCorner = corner;
updatePath();
invalidateSelf();
}
#Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
updateMatrix(bounds);
updatePath();
}
private void updateMatrix(Rect bounds) {
// Set the destination rectangle for the bitmap to be the
// new drawable bounds
mDstRect.set(bounds);
// Scale the bitmap's rectangle to the bounds of this drawable
mMatrix.setRectToRect(mSrcRect, mDstRect, FILL);
// Update the shader's matrix (to draw the bitmap at the right size)
mShader.setLocalMatrix(mMatrix);
}
private void updatePath() {
final Rect bounds = getBounds();
final float x = bounds.exactCenterX();
final float y = bounds.exactCenterY();
// Draw the initial circle (same for all corners)
mPath.reset();
mPath.addCircle(x, y, Math.min(x, y), CW);
// Add the rectangle which intersects with the center,
// based on the corner in which the arrow should draw
switch (mArrowCorner) {
case TOP_LEFT:
mPath.addRect(bounds.left, bounds.top, x, y, CW);
break;
case TOP_RIGHT:
mPath.addRect(x, bounds.top, bounds.right, y, CW);
break;
case BOTTOM_LEFT:
mPath.addRect(bounds.left, y, x, bounds.bottom, CW);
break;
case BOTTOM_RIGHT:
mPath.addRect(x, y, bounds.right, bounds.bottom, CW);
break;
}
}
#Override
public void draw(Canvas canvas) {
// Easy enough, just draw the path using the paint.
// It already has the BitmapShader applied which
// will do the work for you.
canvas.drawPath(mPath, mPaint);
}
#Override
public int getOpacity() {
// Indicate that this Drawable has fully-transparent pixel values
return TRANSPARENT;
}
#Override
public void setColorFilter(ColorFilter colorFilter) {
// Yay, you can even support color filters for your drawable
mPaint.setColorFilter(colorFilter);
}
#Override
public void setAlpha(int i) {
// You could do this by doing some canvas magic but I'm
// lazy and don't feel like it. Exercise for the reader. :)
throw new UnsupportedOperationException("Not implemented.");
}
public enum Corner {
TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT
}
}
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.