Help with simple java game.

Hi.
This is my first post. I have studied maths & CS at uni for a year. Had done no CS before this. I find it really tough but really wanna get better.
One of our assignments was to write a simple game in java. this was back in march. i did ok but never got the game to properly work. thought id try over summer but am having some trouble. its a simple ball and some yellow moving blocks.
i just can’t get the red ball to jump and have no idea where to go from here. i have 3 classes: Play, BackFrame and Jump. Play adds components to the frame and handles animation. BackFrame draws the background and adds components. And Jump handles the jump button. i’ve copied all the code down below. sorry if thats not what you’re supposed to do.
it’d mean SO much if anyone could have a look and point me in the write direction!
thanks!
james


import javax.swing.*;
import java.awt.*;
import java.net.*;
import javax.imageio.ImageIO;
import java.io.*;

class Play implements Runnable
{

  private BackFrame back = new BackFrame();
  private Jump jump = new Jump();
  public static void main (String [] args)
  {
    Play program = new Play ();
    SwingUtilities.invokeLater(program);
    program.brickstart();
  }
  
  public void run ()
  {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
    frame.add(back);
    frame.pack ();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
  }

  void brickstart()
  {
    for (int i=0; i<100; i++)
    {
      try 
      {
        Thread.sleep(1000);
      }
      catch (InterruptedException interruption)
      {
      }

     back.move();
    }
  }
}


import javax.swing.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;


public class BackFrame extends JPanel
{
  private int brickspeed = 3;
  private int brickpos = 640;
  private int brickpos2 = 890;
  private Image background;
  private JLabel gameover = new JLabel();
  private JButton button = new JButton ("JUMP");
  private Jump jump = new Jump();
  private int yball = jump.newballpos();

  BackFrame()
  {
    setPreferredSize(new Dimension(640, 480));
    add(button);
    button.addActionListener(jump);
    //URL goveraddress = Play.class.getResource("GAMEOVERBACK.jpg");
    //ImageIcon goverimage = new ImageIcon(goveraddress);
    //gameover = new JLabel(goverimage);
  }

  public void move ()
  {
    while (true) 
    {
      brickpos = brickpos - brickspeed;
      brickpos2 = brickpos2 - brickspeed;

        if (brickpos < -60)
        {
          brickpos = 640;
        }
        if (brickpos2 < -60)
        {
          brickpos2 = 640;
          brickspeed = brickspeed + 1;
        }
        /*if (yball>310)
        {
          if ((brickpos<=104) || (brickpos2<=104))
          {
            System.exit(1);
          }
        }*/
        try 
        {
          Thread.sleep(1000 / 30);
        } 
        catch (InterruptedException ex)
        {
        }
       
      repaint();
    }
  }

  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    URL backaddress = Play.class.getResource("GAMEBACK.jpg");
    ImageIcon backimage = new ImageIcon(backaddress);
    background = backimage.getImage();
    g2.drawImage(background,0,0,this);
    g2.setColor(Color.RED);
    g2.fillOval(20, yball, 80, 80);
    g2.setColor(Color.YELLOW);
    g2.fillRect(brickpos, 365, 60, 60);
    g2.fillRect(brickpos2 , 365, 60, 60);
            
  }
}


import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

class Jump implements ActionListener
{
  private int yball = 350;

  public Jump ()
  {
  }

  public void actionPerformed(ActionEvent e) 
  {
     {
       yball = yball - 10;
     }
  }

  public int newballpos()
  {
    return yball;
  }

}

Integers are primitives, so by assigning yball in BackFrame on initialization, it will be given the initial value of jump.newballpos() but will not continue to change along with the return value of newballpos(). This is because any primitive is just a copy of another primitive. Therefore once you call jump.newballpos(), you never have any connection to that function again, you have only its return value at that moment in time.

You have two options to fix this:

  1. Continually update the value of yball every frame.

public void move ()
  {
    while (true) 
    {
      yball = jump.newballpos();
      brickpos = brickpos - brickspeed;
      brickpos2 = brickpos2 - brickspeed;
 
        if (brickpos < -60)
        {
          brickpos = 640;
        }
        if (brickpos2 < -60)
        {
          brickpos2 = 640;
          brickspeed = brickspeed + 1;
        }
        /*if (yball>310)
        {
          if ((brickpos<=104) || (brickpos2<=104))
          {
            System.exit(1);
          }
        }*/
        try
        {
          Thread.sleep(1000 / 30);
        } 
        catch (InterruptedException ex)
        {
        }
        
      repaint();
    }
  }

  1. Do things the “proper” object-oriented way and just get the value from an accessor.

public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    URL backaddress = Play.class.getResource("GAMEBACK.jpg");
    ImageIcon backimage = new ImageIcon(backaddress);
    background = backimage.getImage();
    g2.drawImage(background,0,0,this);
    g2.setColor(Color.RED);
    g2.fillOval(20, jump.newballpos(), 80, 80);
    g2.setColor(Color.YELLOW);
    g2.fillRect(brickpos, 365, 60, 60);
    g2.fillRect(brickpos2 , 365, 60, 60);
  }

Objects are passed by reference, primitives are not. Let me know if this doesn’t make sense to you.

In the future, you can debug this sort of thing by setting breakpoints or using System.out.println() to discover that yball never actually gets changed. That would end up leading you to figure out what I’ve told you.

ah great!
thanks so much for the reply!

A small but important thing - you’ll want to move your code for loading your background image to somewhere like your “BackFrame” constructor. That way it’s only loaded once. As you have it now, the image will be loaded from disk each frame, which obviously isn’t necessary.

Yeah very good point, I should have noticed that as well. :slight_smile:

Also jamesovine, I would maybe spend some time reading tutorials or a programming book just to learn a bit more about Object-Oriented design principles. Your code is a bit all over the place in that regard, and a strong understanding of that will really help you.

Hi again.
Yeah i thought it was… Do you have any books or tutorials you could recommend?
Thanks
James

At the top of the page there is a link to JGOs Java Gaming Resources. You can also click here to get to it.