Another dumb question..

Hey guys. I can’t express my appreciation for your help enough. I’m working on my first ever Java game. I’m using libgdx. I’ve got the paddle and ball set up and moving around. I know i’m doing some of this stuff incorrectly (ie: using rect.collide to check on collision of ball and paddle) but I plan on redoing all of it. Just getting my foot in the door and seeing something working right now.

I want to encapsulate the ball and the paddle classes with different java class files. I’m a little confused on how to do this with libgdx. I’ve found some tutorials, but haven’t been able to discern this.

What do I need to do to set the class up? i’m not sure which classes I need to import or where to do the actual drawing of the paddle and ball. Do I need a create(), render(), etc. in the Ball class? I’m confused basically, on how to separate the code from the main Game class. I’ve attached my code so far, below. It’s a bit messy, I apologize for that. That is the reason for me asking this question, so I can clean it up a bit.


package com.psillicoder.brickbreaker;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
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.badlogic.gdx.math.Rectangle;


public class Game implements ApplicationListener {
	private OrthographicCamera camera;
	private SpriteBatch batch;
	private Texture ballImage;
	private Texture paddleImage;
	
	private int ballSpeedX;
	private int ballSpeedY;
	
	private int paddleSpeed;
	
	//private TextureRegion region;
	
	//rectangles
	Rectangle ballRect;
	private Rectangle paddleRect;
	
	@Override
	public void create() {		
		float w = Gdx.graphics.getWidth();
		float h = Gdx.graphics.getHeight();
	
		
		ballSpeedX = 1;
		ballSpeedY = 1;
		
		paddleSpeed = 2;
		
		paddleImage = new Texture(Gdx.files.internal("data/paddle.PNG"));
		ballImage = new Texture(Gdx.files.internal("data/ball.png"));
		//region = new TextureRegion(paddleImage,0,0,64,16);
		
		camera = new OrthographicCamera(1, h/w);
		batch = new SpriteBatch();
		
		//paddle 
		paddleRect = new Rectangle();
		paddleRect.x = 400/2 - 64/2;
		paddleRect.y = 20;
		paddleRect.width = 64;
		paddleRect.height = 16;
		
		
		ballRect = new Rectangle();
		ballRect.x = 400/2;
		ballRect.y = 600/2;
		ballRect.width = 16;
		ballRect.height = 16;
		
		
		
		}
		

	@Override
	public void dispose() {
		batch.dispose();
		//ballImage.dispose();
		paddleImage.dispose();
	}

	@Override
	public void render() {		
		Gdx.gl.glClearColor(1, 1, 1, 1);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		//camera.update();

		CheckKeys();
		moveBall();
		
		//batch.setProjectionMatrix(camera.combined);
		batch.begin();
		batch.draw(ballImage,ballRect.x,ballRect.y);
		batch.draw(paddleImage, paddleRect.x, paddleRect.y);
		batch.end();
	}

	@Override
	public void resize(int width, int height) {
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

	public void moveBall() {
		ballRect.x= ballRect.x + ballSpeedX;
		ballRect.y= ballRect.y + ballSpeedY;
		
		if (ballRect.x >= 400-16){ballSpeedX=-ballSpeedX;}
		if (ballRect.x <= 0){ballSpeedX=-ballSpeedX;}
		
		if (ballRect.y >= 600-16){ballSpeedY=-ballSpeedY;}
		if (ballRect.y <= 0){ballSpeedY=-ballSpeedY;}
		
		if (ballRect.overlaps(paddleRect)){ballSpeedY = -ballSpeedY;}
		
		
		ballRect.x= ballRect.x + ballSpeedX;
		ballRect.y= ballRect.y + ballSpeedY;
		
		
		
	}
	
	public void CheckKeys(){
		boolean isLeftPressed;
		boolean isRightPressed;
				
			if(Gdx.input.isKeyPressed(Keys.DPAD_LEFT))
			{
				isLeftPressed=true;
			}else{isLeftPressed=false;}
			
		if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT))
		{
			isRightPressed=true;
		}else{isRightPressed=false;}
		
		if (isLeftPressed==true && paddleRect.x >=0){paddleRect.x=paddleRect.x-paddleSpeed;}
		if (isRightPressed==true && paddleRect.x <= 400 - 64){paddleRect.x=paddleRect.x+paddleSpeed;}
		
		System.out.println(isLeftPressed);
		System.out.println("Paddle X: " + paddleRect.x + " Paddle Y: " + paddleRect.y );
	}
	
	
	}



Thanks! You guys are awesome!

Hopefully I won’t have such elementary problems in the future.

In your separate ball class nothing is truly required From it.so just create a new class file, and maybe create one method called draw that takes a sprite batch as a parameter and then maybe another method called move ball which is what you had in your code above. Then in your main class create a new object for this class and call the two or more methods defined.

I’ve tried this, but the issue i’m having is, Spritebatch cannot be resolved to a type…I know this is being called because spritebatch isn’t setup in the ball class. There is something I am forgetting. Here is the ball.java


package com.psillicoder.brickbreaker;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;

public class Ball {
	private Texture ballImage;
	private int ballSpeedX;
	private int ballSpeedY;
	private Rectangle ballRect;
	
	
	public Ball(){
	//Load Ball Texture
	ballImage = new Texture(Gdx.files.internal("data/ball.png"));
	
	//Set Ball Speed
	ballSpeedX = 1;
	ballSpeedY = 1;
	
	//Setup initial Rectangle
	ballRect = new Rectangle();
	ballRect.x = 400/2;
	ballRect.y = 600/2;
	ballRect.width = 16;
	ballRect.height = 16;
	
	
	
	}
	
	public void Draw(SpriteBatch spritebatch) {
		spritebatch.draw(ballImage,ballRect.x,ballRect.y);
		return spritebatch;
	}
	
	
	
	
	
	public void moveBall() {
		ballRect.x= ballRect.x + ballSpeedX;
		ballRect.y= ballRect.y + ballSpeedY;
		
		if (ballRect.x >= 400-16){ballSpeedX=-ballSpeedX;}
		if (ballRect.x <= 0){ballSpeedX=-ballSpeedX;}
		
		if (ballRect.y >= 600-16){ballSpeedY=-ballSpeedY;}
		if (ballRect.y <= 0){ballSpeedY=-ballSpeedY;}
		
		if (ballRect.overlaps(paddleRect)){ballSpeedY = -ballSpeedY;}
		
		
		ballRect.x= ballRect.x + ballSpeedX;
		ballRect.y= ballRect.y + ballSpeedY;
		
		
		
	}
	
}

you dont need


return spritebatch;

in your draw method.

You cant return a variable when its a void.
void methods do not return anything, you can have


return;

to break out of the method, but it is useless in your case.

Also as a standard java technique, method names / variables usually start in a lower case letter while class names are capitol. So change Draw to draw

Nice!! Thanks. I think I got it figured out. I’m going to toy around with it a bit and encapsulate it better now using getters and setters. Appreciate it to both of you!

Call all the rendering in your main class…


public class Game implements ApplicationListener {
   private OrthographicCamera camera;
   private SpriteBatch batch;
   //private Texture ballImage;
   //private Texture paddleImage;

   Paddle paddle; 
   Ball ball; 

   @Override
   public void create() {    
       float w = Gdx.graphics.getWidth();
       float h = Gdx.graphics.getHeight();
       
       camera = new OrthographicCamera(1, h/w);
       batch = new SpriteBatch();       

       //Initialize your custom classes
       Ball ball = new Ball();
       Paddle paddle = new paddle(); 

   }  

   @Override
   public void dispose() {
      batch.dispose();
      ball.dispose();
      paddle.dispose();
   }

   public void render(){
       Gdx.gl.glClearColor(1, 1, 1, 1);
       Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

       CheckKeys();
       ball.overlaps(paddle);

       batch.begin()
       //Send the SpriteBatch to the ball and paddle render method
       ball.render(batch); 
       paddle.render(batch);
       batch.end();
   }

    public void CheckKeys(){
            
         if(Gdx.input.isKeyPressed(Keys.DPAD_LEFT))
         {
            paddle.isLeftPressed=true;
         }else{paddle.isLeftPressed=false;}
         
      if (Gdx.input.isKeyPressed(Keys.DPAD_RIGHT))
      {
         paddle.isRightPressed=true;
      }else{paddle.isRightPressed=false;}
   }


public class Paddle
{
     Texture texture;
     Rectangle paddleRect;
     
     int paddleSpeed;
      
     public boolean isRightPressed = false;
     public boolean isLeftPressed = false;
     
    //You could also create other constructors that allow you to assign a texture, paddle size etc.
     public Paddle(){
        texture = new Texture(...);
        paddleRect.x = 400/2 - 64/2;
        paddleRect.y = 20;
        paddleRect.width = 64;
        paddleRect.height = 16;
    }

    public void render(SpriteBatch batch){

         if (isLeftPressed==true && paddleRect.x >=0){paddleRect.x=paddleRect.x-paddleSpeed;}
         if (isRightPressed==true && paddleRect.x <= 400 - 64){paddleRect.x=paddleRect.x+paddleSpeed;}

        batch.draw(texture, paddleRect.x, paddleRect.y);
    }
    //dispose etc...
}



//import your Paddle class
public class Ball
{
       Texture texture;
       Vector2 ballSpeed;

       Rectangle ballRect;
       
       //Once again you can add different contstructors to set different variables
       public Ball(){
           texture = new Texture(...);
           ballSpeed = new Vector2(1, 1);
           ballRect = new Rectangle();
           ballRect.x = 400/2;
           ballRect.y = 600/2;
           ballRect.width = 16;
           ballRect.height = 16;
       }
       
       public void render(SpriteBatch batch){
            ballRect.x= ballRect.x + ballSpeed.x;
            ballRect.y= ballRect.y + ballSpeed.y;
      
            if (ballRect.x >= 400-16){ballSpeedX=-ballSpeed.x;}
            if (ballRect.x <= 0){ballSpeedX=-ballSpeed.x;}
      
            if (ballRect.y >= 600-16){ballSpeedY=-ballSpeed.y;}
            if (ballRect.y <= 0){ballSpeedY=-ballSpeed.y;}
      
      
            ballRect.x= ballRect.x + ballSpeed.x;
            ballRect.y= ballRect.y + ballSpeed.y;

            batch.draw(texture,ballRect.x,ballRect.y);
       }

       //I made this a boolean but you can make it void if you don't want it to return anything
       public boolean overlaps(Paddle paddle){
            if (ballRect.overlaps(paddle.paddleRect)){ballSpeed.y = -ballSpeed.y; return true; }
            return false;
       }
       //dispose etc...
}

That’s roughly what I would do.

Note: I changed a few variable types but forgot to change it in the original code I got from you but you get the idea.

     
  public boolean overlaps(Paddle paddle){
            if (ballRect.overlaps(paddle.paddleRect)){ballSpeed.y = -ballSpeed.y; return true; }
            return false;
       }

I originally did this, but paddleRect was private in the paddle class so it wasn’t visible. I tried to make a getter for the ballRect in the paddle class, but quickly found out I couldn’t do it…or I wasn’t doing it right. This is my ball class now, its working pretty great.


package com.psillicoder.brickbreaker;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class Ball {
	private Texture ballImage;
	private int ballSpeedX;
	private int ballSpeedY;
	private Rectangle ballRect;
	
	
	public Ball(){
	//Load Ball Texture
	ballImage = new Texture(Gdx.files.internal("data/ball.png"));
	
	//Set Ball Speed
	ballSpeedX = 1;
	ballSpeedY = 1;
	
	//Setup initial Rectangle
	ballRect = new Rectangle();
	ballRect.x = 400/2;
	ballRect.y = 600/2;
	ballRect.width = 16;
	ballRect.height = 16;
	
	
	
	}
	
	public void draw(SpriteBatch spritebatch) {
		spritebatch.draw(ballImage,ballRect.x,ballRect.y);
	
	}

	public void checkPaddleCollision(Paddle paddle)
	{
		if (ballRect.overlaps(paddle.paddleRect)) 
		{
			ballSpeedY = -ballSpeedY;
		}
	
	}
	
	
	
	
	public void moveBall() {
		ballRect.x= ballRect.x + ballSpeedX;
		ballRect.y= ballRect.y + ballSpeedY;
		
		if (ballRect.x >= 400-16){ballSpeedX=-ballSpeedX;}
		if (ballRect.x <= 0){ballSpeedX=-ballSpeedX;}
		
		if (ballRect.y >= 600-16){ballSpeedY=-ballSpeedY;}
		if (ballRect.y <= 0){ballSpeedY=-ballSpeedY;}
		
		//if (ballRect.overlaps(paddleRect)){ballSpeedY = -ballSpeedY;}
		
		
		ballRect.x= ballRect.x + ballSpeedX;
		ballRect.y= ballRect.y + ballSpeedY;
		
		
		
	}
	
}

I can’t seem to get my brick class working now either…It’s throwing a null pointer exception. I’ve set it to load 10 bricks…very basic.


package com.psillicoder.brickbreaker;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
public class Brick {
	
	private Texture brickImage;
	
	private Rectangle brickRect;
	
	//private Vector2 brickLoc; 
	
	//private int brickType;
	
	public Brick(int type, float x, float y) {
		brickImage = new Texture(Gdx.files.internal("data/bluebrick.PNG"));
		//brickType = type;
		brickRect.x = x;
		brickRect.y = y;
		brickRect.width = 32;
		brickRect.height = 16;
		
	}

public void draw(SpriteBatch spritebatch)
{
	spritebatch.draw(brickImage,brickRect.x,brickRect.y);
}

}

and also in my Game.java:


public void loadBricks() {
		for(int i= 0; i < 10;i++) {
			bricks[i] = new Brick(0,i*32,i*16);
			bricks[i].draw(batch);
		}
		
	}

is called from create()

Do you ever initialize the Brick array?

bricks = new Brick[10];

I figured it out. I wasn’t sure because I won’t always know how many bricks need to be added. I’m going to make different levels for it. I’m thinking I may have to go with an arraylist. Gotta read up on them a bit.

Just a FYI: There are no dumb questions but there are dumb topic/subject titles. Ask the question, that way people who can/want to help will read your post. Things like “help please” “I have a question” are really bad since most people will not read the thread to see what you asked. Many forums will delete such topics.

But we are nicer around here. :persecutioncomplex: