platformR = new ShapeRenderer();
platformR.setProjectionMatrix(camera.combined);
platformR.begin(ShapeType.Filled);
platformR.identity();
platformR.setColor(new Color(0, 1, 0, 1));
platformR.rotate(0, 0, 1, 90);*/
platformR.rect(getxPos(), getyPos(), getSprite().getWidth() + getxPos(),
getSprite().getHeight() + getxPos());
platformR.end();
This is the code I have for displaying a rectangle, but the rectangle doesn't display. Is there anything I'm missing?
Make sure you place your .begin() / .end() method calls in the render() method.
public class ShapeRendererExample extends ApplicationAdapter {
ShapeRenderer shapeRenderer;
#Override
public void create () {
shapeRenderer = new ShapeRenderer();
}
#Override
public void render () {
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.setColor(new Color(1, 0, 0, 1));
shapeRenderer.rect(100f, 100f, 100f, 100f);
shapeRenderer.end();
}
private void clearScreen()
{
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
}
Related
I have an issue in LibGDX where when i call upon Gdx.input.getY(), it selects a pixel that's on the other side of the application relative to the center of the screen.
public class Main extends ApplicationAdapter {
private SpriteBatch batch;
private Texture img;
private OrthographicCamera camera;
int xPos;
int yPos;
private Vector3 tp = new Vector3();
BitmapFont font;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("crosshair.png");
camera = new OrthographicCamera();
camera.setToOrtho(false, 1280, 720);
font = new BitmapFont();
}
#Override
public void render () {
yPos = Gdx.input.getY();
xPos = Gdx.input.getX();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.unproject(tp.set(xPos, yPos, 0));
batch.begin();
font.draw(batch,xPos + " , " + yPos, Gdx.input.getX() - 25, Gdx.input.getY() - 5);
batch.draw(img, xPos, yPos);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
img.dispose();
}
Subtracting the viewport height with the touch location won't work, because that would be subtracting world coordinates with touch coordinates. (and even for a pixel perfect projection it would be height - 1 - y). Instead use the unproject method to convert touch coordinates to world coordinates.
There are two problems with your code:
You are never setting the batch projection matrix.
Even though you are using the unproject method, you are never using its result.
So instead use the following:
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
camera.unproject(tp.set(Gdx.input.getX(), Gdx.input.getY(), 0));
font.draw(batch,tp.x+ " , " + tp.y, tp.x - 25, tp.y - 5);
batch.draw(img, tp.x, tp.y);
batch.end();
}
I would suggest to read the following pages, which describe this and the reasoning behind it in detail:
https://github.com/libgdx/libgdx/wiki/Coordinate-systems
https://xoppa.github.io/blog/pixels/
https://github.com/libgdx/libgdx/wiki/Viewports
It's better to try this
yPos = camera.viewportHeight - Gdx.input.getY();
I am trying to draw different textures of balloons and I want them to appear in different times about half second between each one, and move in the world. first balloons are rendered but after about half second the other balloons are rendered next to the previous ones, not in the initial place:
this is code:
private Ballons ballons;
private Ballons ballons2;
private Ballons ballons3;
private Ballons ballons4;
private Texture background;
public Celebration(Fruits game, float level)
{
this.game=game;
this.level=level;
gamecam=new OrthographicCamera();
gameport=new StretchViewport(820/Fruits.PPM,580/Fruits.PPM,gamecam);
stage=new Stage(gameport,((Fruits) game).batch);
background=new Texture("Wining.jpg");
gamecam.position.set(gameport.getWorldWidth()/2f,gameport.getWorldHeight()/2f,0);
temp=0;
counter=400;
world=new World(new Vector2(0,0.5f),true);
b2dr=new Box2DDebugRenderer();
ballons=new Ballons(world,this,1,140);
ballons4=new Ballons(world,this,2,290);
ballons3=new Ballons(world,this,3,480);
ballons2=new Ballons(world,this,4,650);
}
#Override
public void show() {
}
public void handleinput(float dt)
{
if(Gdx.input.isTouched())
game.setScreen(new GlobalWorld(game, 1));
}
public void update(float dt)
{
handleinput(dt);
world.step(1 /60f, 6, 2);
//player.update(dt);
gamecam.update();
// renderer.setView(gamecam);
ballons.update(dt);
ballons2.update(dt);
ballons3.update(dt);
ballons4.update(dt);
}
#Override
public void render(float delta) {
float level;
update(delta);
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
counter--;
b2dr.render(world, gamecam.combined);
game.batch.setProjectionMatrix(gamecam.combined);
game.batch.begin();
game.batch.draw(background, 0, 0, gameport.getWorldWidth(), gameport.getWorldHeight());
if (counter < 200) {
ballons.draw(game.batch);
ballons2.draw(game.batch);
}
if (counter < 100) {
ballons3.draw(game.batch);
ballons4.draw(game.batch);
}
game.batch.end();
}
#Override
public void resize(int width, int height) {
gameport.update(width, height);
}
}
Ballons class:
public class Ballons extends Sprite {
public World world;
public Body b2body;
private TextureRegion collectorStand;
public Ballons(World world,Celebration screen,float image, float x)
{
// super(screen.getAtlas().findRegion("boy1"));
this.world=world;
defineCollector(x);
if(image==1) {
collectorStand = new TextureRegion(new Texture("Balloon1.png"));
setBounds(0, 0, 200 / Fruits.PPM, 200 / Fruits.PPM);
}
else if(image==2) {
collectorStand = new TextureRegion(new Texture("Balloon2.png"));
setBounds(0, 0, 170 / Fruits.PPM, 185 / Fruits.PPM);
}
else if(image==3) {
collectorStand = new TextureRegion(new Texture("Balloon3.png"));
setBounds(0, 0, 150 / Fruits.PPM, 175 / Fruits.PPM);
}
else if(image==4) {
collectorStand = new TextureRegion(new Texture("Balloon4.png"));
setBounds(0, 0, 150 / Fruits.PPM, 175 / Fruits.PPM);
}
else if(image==5) {
collectorStand = new TextureRegion(new Texture("Balloon5.png"));
setBounds(0, 0, 150 / Fruits.PPM, 175 / Fruits.PPM);
}
setRegion(collectorStand);
}
public void update(float dt)
{
setPosition(b2body.getPosition().x-getWidth()/2,b2body.getPosition().y-getHeight()/2.8f);
}
public void defineCollector(float x)
{
BodyDef bdef=new BodyDef();
bdef.position.set(x/Fruits.PPM,-20/Fruits.PPM);
bdef.type=BodyDef.BodyType.DynamicBody;
b2body=world.createBody(bdef);
FixtureDef fdef=new FixtureDef();
CircleShape shape=new CircleShape();
shape.setRadius(15/Fruits.PPM);
fdef.shape=shape;
b2body.createFixture(fdef);
}
}
No matter what actual counter value is you are calling update(delta); inside your render method. I see there
ballons.update(dt);
ballons2.update(dt);
ballons3.update(dt);
ballons4.update(dt);
Unfortunately you have not attached Ballons class implementation but I'm pretty sure that update method is modifying balloons'es positions.
You should call then ballon's update method inside your if-else statements rather not inside the update method. It could look like
public void update(float dt)
{
handleinput(dt);
world.step(1 /60f, 6, 2);
//player.update(dt);
gamecam.update();
//renderer.setView(gamecam);
}
#Override
public void render(float delta) {
...
if (counter < 200) {
ballons.update(dt);
ballons2.update(dt);
ballons.draw(game.batch);
ballons2.draw(game.batch);
}
if (counter < 100) {
ballons3.update(dt);
ballons4.update(dt);
ballons3.draw(game.batch);
ballons4.draw(game.batch);
}
The problem is that your update function is only fixing the position of the balloons to the Box2D body. Since the Box2D body is created and added to the world on creation, the body will still be moving even though it is not drawn.
You can disable the balloon's bodies until they are ready to be drawn, like so:
Balloons.java
public void defineCollector(float x) {
BodyDef bdef=new BodyDef();
bdef.position.set(x/Fruits.PPM,-20/Fruits.PPM);
bdef.type=BodyDef.BodyType.DynamicBody;
b2body=world.createBody(bdef);
FixtureDef fdef=new FixtureDef();
CircleShape shape=new CircleShape();
shape.setRadius(15/Fruits.PPM);
fdef.shape=shape;
b2body.createFixture(fdef);
b2body.setActive(false);
}
Celebration.java
public Celebration(Fruits game, float level) {
...
stage.addAction(
Actions.sequence(
Actions.delay(0.5f),
Actions.run(
new Runnable() {
ballons.b2body.setActive(true);
ballons2.b2body.setActive(true);
}
),
Actions.delay(0.5f),
Actions.run(
new Runnable() {
ballons3.b2body.setActive(true);
ballons4.b2body.setActive(true);
}
)
)
);
}
public void update(float dt) {
stage.act(dt);
...
}
#Override
public void render(float delta) {
...
if (ballons.b2body.isActive()) {
ballons.draw(game.batch);
}
if (ballons2.b2body.isActive()) {
ballons2.draw(game.batch);
}
if (ballons3.b2body.isActive()) {
ballons3.draw(game.batch);
}
if (ballons4.b2body.isActive()) {
ballons4.draw(game.batch);
}
}
I would recommend using Scene2D to handle your logic by changing your balloons to extend Image and adding your balloons to the stage like so: stage.addActor(balloon). You can then handle your logic inside of the act method, and override draw to position the texture over the Box2D body.
I have an image that I want to move to the right. To do this I increase its x position by 200f*Gdx.graphics.getDeltaTime(); every time render is called. I've read other posts where people had similar problems but were they were not multiplying by delta or Gdx.graphics.getDeltaTime(). Because I obviously do this why is my image flickering/vibrating when its moving???
My code:
public class gm extends Game{
OrthographicCamera cam;
SpriteBatch batch;
Texture img;
float x = 0;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
cam = new OrthographicCamera();
cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
#Override
public void render () {
super.render();
//x += 200f*Gdx.graphics.getDeltaTime();
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(img, x += 100f*Gdx.graphics.getDeltaTime(), 0);
batch.end();
}
}
So I have this world called pokemon world and this is how I atempt to render my stage which contains a custom actor called MenuActor
public PokemonWorld(ChromeGame game) {
this.game = game;
createMenu();
}
protected void createMenu() {
stage = new Stage();
stage.setViewport(150, 720, true);
menu = new MenuActor();
stage.addActor(menu);
Gdx.app.log(ChromeGame.LOG, "Menu Created");
}
#Override
public void render(float delta) {
super.render(delta);
if (menuVisible) {
stage.act(delta);
stage.draw();
}
}
And this is my custom Actor
public class MenuActor extends Actor {
Texture region;
public MenuActor() {
super();
region = new Texture(Gdx.files.internal("imgs/OptionBox.png"));
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
batch.draw(region, getX(), getY(), 150, 720, 0, 0,
region.getWidth(), getHeight());
}
}
As you can see, the actor is given a texture and in its draw method, it draws it. In the PokemonWorld class it adds the MenuActor to the stageand the asks the stage to draw by stage.draw();
What am I missing? I feel like I'm doing all the right steps but I might be missing a step/line of code.
I suppose the last parameter should be some height (instead of getWidth()).
batch.draw(region, getX(), getY(), 150, 720, 0, 0,
region.getWidth(), getWidth());
I'm working on a 2D game in LWJGL. I have successfully rendered QUADS with textures using glBegin but moving to VBOs turned out to be a big undertaking. At the moment I can switch between the vbo and non-vbo rendering with a boolean, both using the same vertex- and texture coordinates. The VBO-implementation won't draw anything onto the screen. Can anyone point me in the right direction?
This is my initialization:
public void init() {
VBOID = VBOHandler.createVBOID();
TBOID = VBOHandler.createVBOID();
float[] vdata = {0, 0,
width, 0,
width, height,
0, height};
float[] tdata = {sx, sy,
ex, sy,
ex, ey,
sx, ey};
//Texture coordinates: (0,0)(1,0)(1,1) and (0,1)
FloatBuffer fb = BufferUtils.createFloatBuffer(8);
fb.put(vdata);
VBOHandler.bufferData(VBOID, fb);
fb = BufferUtils.createFloatBuffer(8);
fb.put(tdata);
VBOHandler.bufferData(TBOID, fb);
}
And here is my rendering code:
private void render() {
texture.bind();
if(vbo) {
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
VBOHandler.bindBuffer(VBOID);
GL11.glVertexPointer(2, GL11.GL_FLOAT, 0, 0);
VBOHandler.bindBuffer(TBOID);
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
VBOHandler.bindElementBuffer(VBOHandler.getDefaultIBOID());
// I figured why not use a standard IBO for all my sprite drawing
// The default IBO ID is initialized earlier in the program, not shown in this code
GL12.glDrawRangeElements(GL11.GL_TRIANGLE_FAN, 0, 3, 4, GL11.GL_UNSIGNED_SHORT, 0);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
} else {
GL11.glBegin(GL11.GL_TRIANGLE_FAN);
GL11.glTexCoord2f(sx, sy);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(ex, sy);
GL11.glVertex2f(width,0);
GL11.glTexCoord2f(ex, ey);
GL11.glVertex2f(width, height);
GL11.glTexCoord2f(sx, ey);
GL11.glVertex2f(0, height);
GL11.glEnd();
}
}
And the VBOHandler class, for those interested
public class VBOHandler {
private static int IBOID;
public static void initDefaultIBO() {
IBOID = createVBOID();
short[] indexdata = {0, 1, 2, 3};
ShortBuffer shortBuffer = BufferUtils.createShortBuffer(4);
shortBuffer.put(indexdata);
VBOHandler.bufferElementData(IBOID, shortBuffer);
}
public static int getDefaultIBOID() {
return IBOID;
}
public static int createVBOID() {
if(GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
return ARBVertexBufferObject.glGenBuffersARB();
}
return 0;
}
public static void bufferData(int id, FloatBuffer buffer) {
if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
}
}
public static void bufferElementData(int id, ShortBuffer buffer) {
if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
}
}
public static void bindBuffer(int id) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
}
public static void bindElementBuffer(int id) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id);
}
}
The above render-function lies within my Sprite class. It is called by my GameView every frame as so:
public void renderGame() {
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
sprite.render();
}
The GameView is initialized with the following code:
Display.setDisplayMode(new DisplayMode(1024, 768));
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glEnable(GL11.GL_BLEND); // enable alpha blending
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(x - width/2, x + width/2, y + height / 2, y - height / 2, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
You did not call 'flip' on the FloatBuffers before passing them to OpenGL. You need to call 'flip()' on FloatBuffers before you pass them to OpenGL, or it will not be able to read them. It is worth noting that you cannot read the FloatBuffers after you call 'flip()' yourself.