Image moving side to side - java

My question is I'm creating a game where I have to get an image moving from one side of the screen to the other, and then coming back from the same side of the screen. For example I have an image of a jellyfish, it starts moving from the right side of the screen, to the left side, and then I want it to come back from the right side. I'm stuck and don't know what to do. I'm using LIBGDX and JAVA.
My code so far is :
package gdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
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;
import java.awt.Graphics;
public class Main extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
Sprite sprite;
float fGrav, fVelo, fX, fY;
#Override
public void create() {
batch = new SpriteBatch();
img = new Texture("JellyFish.png");
sprite = new Sprite(img);
sprite.setScale(0.3f);
fX=0;
fY=0;
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
sprite.draw(batch);
batch.end();
}
#Override
public void dispose() {
batch.dispose();
img.dispose();
}
}

If you want to continuously bounce an image from left to right, create an infinite loop that increases x until it is >= your display width, and then decrease it until it is <= 0, and then repeat.
I've never worked with LIBGDX, but if you wanted to use the Graphics class it would be as follows:
Example:
boolean f = true;
int x = 0;
while (f) {
while (x <= SCREEN_WIDTH) {
x++;
}
while (x >= 0) {
x--;
}
}
This should loop indefinitely.

Related

LibGDX multiple cameras

So, I am working with LiBGDX and Box2D, using the PixelsPerMeter conversion, and I have a camera that follows the player around, but when I turn debug mode on I need to be able to draw a font with the fps on screen, so I always can see it in the corner. The problem is that when I try to scale the BitmapFont down, so it looks normal, cause everything else is scaled down, because of the Box2D. I found something that said something about using multiple cameras, so I don't have to scale the font down, but it didn't have any documentation. I tried to figure how to do it, but with no luck. How should I draw the font to the screen?
Here is my game state in which I tried the multiple cameras:
package com.platformer.gamestates;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.platformer.Entities.Player;
import com.platformer.game.Game;
import com.platformer.generation.MenuTiles;
import com.platformer.generation.TiledMaps;
import com.platformer.managers.GameContacts;
import com.platformer.managers.GameStateManager;
import static com.platformer.managers.B2DVars.PPM;
public class MenuState extends GameState {
World world;
Box2DDebugRenderer debugRenderer;
Texture close, far, house;
BitmapFont font;
OrthographicCamera fontCam;
public static Player player;
MenuTiles menuTiles;
SpriteBatch batch;
float camx,camy;
float lerp=0.1f,lerpy=0.2f;
GameContacts gameContacts;
public MenuState(GameStateManager gsm){
super(gsm);
}
public void init(){
close=new Texture(Gdx.files.internal("menu_backgrounds/background_close.png"));
far=new Texture(Gdx.files.internal("menu_backgrounds/background_far.png"));
house=new Texture(Gdx.files.internal("menu_backgrounds/house_selected.png"));
batch=new SpriteBatch();
font=new BitmapFont();
fontCam=new OrthographicCamera();
fontCam.setToOrtho(false,Game.WIDTH,Game.HEIGHT);
fontCam.position.set(Game.WIDTH/2/PPM,Game.HEIGHT/2/PPM,0);
world=new World(new Vector2(0,-9.81f),true);
world.setVelocityThreshold(0);
gameContacts=new GameContacts();
world.setContactListener(gameContacts);
debugRenderer=new Box2DDebugRenderer();
player=new Player(world,960/2,49+20);
menuTiles=new MenuTiles(world);
}
public void update(float dt){
world.step(1/60f,6,2);
player.update(dt,gameContacts);
if(player.shouldPlay){gsm.setState(GameStateManager.PLAY);dispose();}
camx+=(player.x-camx)*lerp;
camy+=(player.y-camy)*lerpy;
}
public void draw(OrthographicCamera camera){
camera.position.x=Math.min(Math.max(camx,Game.WIDTH/2/PPM),(MenuTiles.levelWidth/PPM)-(Game.WIDTH/2/PPM));
camera.position.y=Math.min(Math.max(camy,Game.HEIGHT/2/PPM),(MenuTiles.levelHeight/PPM)-(Game.HEIGHT/2/PPM));
batch.begin();
batch.draw(far, 0, 0, 960 / PPM, 720 / PPM);
batch.draw(close,0,0,960/PPM,720/PPM);
batch.end();
//draw map
menuTiles.draw(camera);
batch.begin();
if(gameContacts.isOnHouse())batch.draw(house,192/PPM,48/PPM,2*MenuTiles.tileSize/PPM,2*MenuTiles.tileSize/PPM);
batch.end();
//draw player
player.draw(batch);
if(player.DebugOn){
debugRenderer.render(world, camera.combined);
batch.setProjectionMatrix(fontCam.combined);
batch.begin();
font.draw(batch,"fps",0,0);
batch.end();
System.out.println(Gdx.graphics.getFramesPerSecond()+" fps");
}
camera.update();
batch.setProjectionMatrix(camera.combined);
}
public void handleInput(){}
public void dispose(){
menuTiles.dispose();
close.dispose();
far.dispose();
house.dispose();
}
}
I don't think you want to divide by PPM in this line...
fontCam.position.set(Game.WIDTH/2/PPM,Game.HEIGHT/2/PPM,0);
I'm assuming the Game.WIDHT and HEIGHT are in pixels (this is not clear from your code snippet). If that's not teh case, then you should include the divide by PPM into this line...
fontCam.setToOrtho(false,Game.WIDTH,Game.HEIGHT);
At present it's not being consistently applied.
Also, you need to call fontcam.update() after setting its position.
Additionally: This is not to do with your question per se, but I'm not sure why you have the following lines at the end of teh render. I would place them right after I've changed the position of the standard camera.
camera.update();
batch.setProjectionMatrix(camera.combined);

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.

Move a ball on mouse click in Java

I'm trying to create the classic Breakout game as part of my programming assignment. I have to start moving the ball on a mouse click from the user. So I'm using a mouselistener to achieve that. The code below is just a smaller, simpler version of what I'm trying to do. But it does not move the ball in gradual steps. It just displays the ball at it's final position after the while loop is done executing.
import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class BallMoveTest extends GraphicsProgram {
public void run() {
ball = new GOval(20,20);
ball.setFilled(true);
add(ball, 100, 100);
addMouseListeners();
}
public void mouseClicked(MouseEvent e) {
while (counter < 100) {
moveBall();
counter++;
pause(20);
}
}
public void moveBall(){
ball.move(2, 2);
}
// Private instance variables
private GOval ball;
private int counter = 1;
}
However this alternate code works wonderfully well, but does not allow the user to click to start the movement of the ball.
import acm.program.*;
import acm.graphics.*;
public class TestGOval extends GraphicsProgram {
public void run() {
int counter = 1;
GOval ball = new GOval(20,20);
ball.setFilled(true);
add(ball,100,100);
while (counter < 100) {
ball.move(2, 2);
counter++;
pause(20);
}
}
}
Could someone point out what I'm doing wrong here and more importantly, why the first code block not work as intended?
PS: This is my first question, and I'm a novice at programming. Go easy on me if you can. :)
It may just be that you aren't showing all of your code, but you should have a class that implements MouseListener. Just having the mouse clicked method isn't enough for java to recognise that this is your intention; there's a tutorial here that has more detail: http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
One conceptual solution could be to add a thread class which can access all the objects positions (at least the ball in your case). This thread must be able to refresh the canvas of your GraphicsProgram class. You can give to this thread a refresh frequency of 30Hz, making it sleep for 33ms after each refresh.
If you need more details about how to refresh your canvas you should provide us more details.
With such solution you also need to put a sleep of 33 ms into your while loop.
use this code:
import acm.graphics.*;
import acm.program.*;
import acm.util.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class BallMoveTest extends GraphicsProgram {
public void run() {
ball = new GOval(20,20);
ball.setFilled(true);
add(ball, 100, 100);
addMouseListeners();
waitForClick();
animation();
}
public void animation() {
while(counter<100){
moveBall();
pause(DELAY);
}
}
public void moveBall(){
ball.move(2, 2);
}
// Private instance variables
private GOval ball;
private int counter = 1;
private int DELAY=20;
}

LibGDX font not appearing on screen

I've tried to get my text to appear, but I cannot get it on screen. I've played with the numbers a few times and found out that LibGDX drew the font to abnormally large sizes, but I don't exactly know if I still need to scale the font size smaller, or if I'm drawing them offscreen. I've copied the entire code and pasted it below.
I used Hiero to make a 256x256 bitmapfont of ariel black on white background.
package com.me.manners;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.me.input.Input;
public class Choice implements Screen
{
private PerspectiveCamera camera;
private SpriteBatch batch;
private Texture arrowT;
private Sprite arrowS;
private BitmapFont font;
private String str1 = "Hello World!";
private Input input = new Input();
private Manners game;
public Choice(Manners game)
{
this.game = game;
camera = new PerspectiveCamera();
batch = new SpriteBatch();
font = new BitmapFont(Gdx.files.internal("data/choice/ariel.fnt"), Gdx.files.internal("data/choice/ariel.png"),false);
Gdx.input.setInputProcessor(input);
arrowT = new Texture(Gdx.files.internal("data/choice/arrow.png"));
arrowT.setFilter(TextureFilter.Linear, TextureFilter.Linear);
arrowS = new Sprite(new TextureRegion(arrowT, 0, 0, 64, 64));
arrowS.setSize(0.125f, 0.25f);
arrowS.setPosition(-0.75f, 0);
}
#Override
public void dispose() {
batch.dispose();
arrowT.dispose();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
arrowS.draw(batch);
font.setColor(1.0f,1.0f,0.0f,1.0f);
font.setScale(0.5f,0.5f);
font.draw(batch, str1, Gdx.graphics.getWidth()*0.5f, Gdx.graphics.getHeight()*0.5f);
batch.end();
}
}
I think your game is 2D game, so using camera = new OrthographicCamera(viewportWidth, viewportHeight) can fix your problem.
phucvin makes a very good observation. It seems your game is 2d ,so you should use an OrtographicCamera. I would recommend you to use big numbers, because the BitmapFont will render using its correct pixel size (thus thats the reason you saw very big letters).
camera = new OrthographicCamera(480, 320); //for example.
Of course you will need to change the Sprite size to something bigger
arrowS.setSize(100, 20); //for example
Or using a second camera with low viewport values for the sprites.

LWJGL - How to create a button to close the application

I have made it open a full screen window but now how can i create a button to have it exit the application?
Also, do you know any good tutorials to learn. I can't seem to find many?
Lastly can i use the opengl code that i learn to work with java in c++ or is that opengl completely different?
This is the code i have:
package game;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.opengl.*;
import org.lwjgl.*;
public class Main {
public Main() {
try {
Display.setDisplayMode(Display.getDesktopDisplayMode());
Display.setFullscreen(true);
Display.create();
} catch(LWJGLException e) {
e.printStackTrace();
}
}
}
lwjgl does not provide any high level widgets such as buttons. You'll need to draw the button using gl calls (use the button image as texture for a quad. Start with a colored rectangle before trying textures). Then you'll need to check for mouse click events in the button area. You may want to consider using a higher level library on top of lwjgl to simplify this.
Here is some code that I made that draws and handles buttons.
You can specify the X, Y and Texture of each button and when the button is clicked the variable isClicked becomes true. As for closing the application , use
if(EXITBUTTON.isClicked)
{
System.exit(0);
}
Button Class:
You need LWJGL and Slick Util.
import java.awt.Rectangle;
import java.io.IOException;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;
public class Button {
public int X;
public int Y;
public Texture buttonTexture;
public boolean isClicked=false;
Rectangle bounds = new Rectangle();
public void addButton(int x, int y , String TEXPATH){
X=x;
Y=y;
try {
buttonTexture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream(TEXPATH));
System.out.println(buttonTexture.getTextureID());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bounds.x=X;
bounds.y=Y;
bounds.height=buttonTexture.getImageHeight();
bounds.width=buttonTexture.getImageWidth();
System.out.println(""+bounds.x+" "+bounds.y+" "+bounds.width+" "+bounds.height);
}
public void Draw(){
if(bounds.contains(Mouse.getX(),(600 - Mouse.getY()))&&Mouse.isButtonDown(0)){
isClicked=true;
}else{
isClicked=false;
}
Color.white.bind();
buttonTexture.bind(); // or GL11.glBind(texture.getTextureID());
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(X,Y);
GL11.glTexCoord2f(1,0);
GL11.glVertex2f(X+buttonTexture.getTextureWidth(),Y);
GL11.glTexCoord2f(1,1);
GL11.glVertex2f(X+buttonTexture.getTextureWidth(),Y+buttonTexture.getTextureHeight());
GL11.glTexCoord2f(0,1);
GL11.glVertex2f(X,Y+buttonTexture.getTextureHeight());
GL11.glEnd();
}
}

Categories