[gameprogrammer] Re: I wonder if I can go Remedial Applet on you all... :)

  • From: "Dave Slutzkin" <daveslutzkin@xxxxxxxxxxx>
  • To: gameprogrammer@xxxxxxxxxxxxx
  • Date: Thu, 31 Mar 2005 15:42:42 +1000

On Wed, 30 Mar 2005 22:32:56 -0500, "Mike Gillissie" <Niyoto@xxxxxxxxxx>
said:
> I like the fun stuff... ;)

That's why we do this...

All right, a few things:

> OK, latest revision does the following:
> 
> - creates the JPanels with the sizes I'd specified

Looks good.

> - loads an image I've got (grass) into a BufferedImage object

I don't think you want to read the image each time you paint.  That
should be done in the constructor so you just have to refer to the
already loaded BufferedImage object in the paint method.  (Not the paint
method, actually, as I'll get to.)

> - tiles the image on the screen (by drawing it x*y times) - this will
> change 
> soon to allow me to draw appropriate tile images based on which part of
> the 
> map I'm showing

The code to do this is correct.  But.  Before you do any custom painting
(which is what you're doing, rather than letting components draw
themselves) you need to read this stuff:
http://java.sun.com/docs/books/tutorial/uiswing/14painting/index.html. 
The long and the short of it is that you shouldn't override the paint()
method, you in fact need to override paintComponent().

Also, I wouldn't override the method in JFrame.  Just let the JFrame
paint itself however it sees fit (this is probably the heart of your
resize problems).

Instead, I'd try creating a (for instance) MapPanel class which extends
JPanel.  That's encapsulation, right?  The JFrame has nothing to do with
painting its children, the children should each paint themselves. 
Remember, Java loves having lots and lots of classes.

I'd imagine this could look something like this:

class MapPanel
  extends JPanel
{
  private BufferedImage mImage;
  public MapPanel(BufferedImage image)
  {
    super();
    mImage = image;
  }
  public void paintComponent(Graphics g)
  {
    Graphics2D graphics = (Graphics2D)g;
    for (int x = 0, width = getWidth(); x < width; x +=
    mImage.getWidth())
    {
      for (int y = 0, height = getHeight(); y < height; y +=
      mImage.getHeight())
      {
        graphics.drawImage(mImage, x, y, this);
      }
    }
  }
}

Same code, different place, basically.

> Two main questions so far:
> 
> 1) Is my method of using BufferedImage and Graphics2D.drawImage the most 
> efficient method? Although the overall map will be very large, the
> visible 
> portion will be quite managable - but am I making things more difficult
> for myself than need be?

At this point, do the simplest thing that could possibly work.  This
should work fine.  If you start to have performance problems later, then
worry about it, but at the moment you just want to get something on the
screen.

> 2) What's the deal with Paint and Update? Resizing the window is 
> automatically painting on me, which isn't bad, but sometimes resizing
> just 
> leaves me with an empty-looking window - should I be overriding some sort
> of 
> window resize events, painting only when the resize is done? Or would I
> do 
> better to (*gag*) lock the window size?

It may _eventually_ end up being useful to lock the window size.  For
the app as it currently exists, it shouldn't be necessary.  Get it
working with resizing, then decide if the cost is worth it.

All the stuff about paint (and probably update as well) is explained in
the section I pointed out.  The Swing painting model is a little
complicated, but you need to have some idea of what's going on behind
the scenes.

Dave.

> -- Code so far, probably worth a chuckle or 12... ----------------
> package map;
> 
> import java.awt.Container;
> import java.awt.Dimension;
> import java.awt.Graphics;
> import java.awt.Graphics2D;
> import java.awt.Image;
> import java.awt.Toolkit;
> import java.awt.image.BufferedImage;
> import java.io.File;
> 
> import javax.imageio.ImageIO;
> import javax.swing.JFrame;
> import javax.swing.JPanel;
> 
> public class ThisIsTheGame extends JFrame implements GameSettings
> {
>  public static ThisIsTheGame app;
>  private static final int APP_WIDTH = 800;
>  private static final int APP_HEIGHT = 600;
>  public Container   map;
>  public Container   navigator;
> 
>  public static void main(String[] args)
>  {
>   app = new ThisIsTheGame();
>   app.setVisible(true);
>   app.setTitle("Good... Bad... I'm the guy with the game.");
>  }
> 
>  public ThisIsTheGame()
>  {
>   super();
> 
>   setSize(new Dimension(APP_WIDTH, APP_HEIGHT));
>   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
> 
>   getContentPane().setLayout(new java.awt.BorderLayout());
>   buildInterface(getContentPane());
>  }
> 
>  public void buildInterface(java.awt.Container contentPane)
>  {
>   navigator = buildNavigatorPane();
>   map = buildGamePane();
> 
>   contentPane.add(navigator, java.awt.BorderLayout.WEST);
>   contentPane.add(map, java.awt.BorderLayout.CENTER);
>  }
> 
>  public javax.swing.JComponent buildNavigatorPane()
>  {
>   JPanel board = new JPanel();
>   board.setPreferredSize(new Dimension(200, 600));
>   board.setMinimumSize(new Dimension(200, 600));
>   return board;
>  }
> 
>  public javax.swing.JComponent buildGamePane()
>  {
>   JPanel board = new JPanel();
>   board.setPreferredSize(new Dimension(600, 600));
> 
>   return board;
>  }
> 
>  public void paint(Graphics gfx)
>  {
>   System.out.println("PAINT");
> 
>   //super.paint(gfx);
> 
>   Graphics2D workAreaGfx = (Graphics2D) map.getGraphics();
> 
>   String name = WORKING_DIRECTORY + "/grass.gif";
>   Image image = Toolkit.getDefaultToolkit().getImage(name);
> 
>   File f = new File(name);
>   BufferedImage bufi = null;
>   try
>   {
>    bufi = ImageIO.read(f);
>   } catch (Exception e)
>   {
>    e.printStackTrace();
>   }
> 
>   for (int x = 0; x < map.getWidth(); x += bufi.getWidth())
>    for (int y = 0; y < map.getWidth(); y += bufi.getHeight())
>     workAreaGfx.drawImage(bufi, x, y, this);
> 
>   workAreaGfx = (Graphics2D) navigator.getGraphics();
>  }
> 
>  public void update(Graphics arg0)
>  {
>   System.out.println("UPDATE");
>  }
> }
-- 
  Dave Slutzkin
  Melbourne, Australia
  daveslutzkin@xxxxxxxxxxx



---------------------
To unsubscribe go to http://gameprogrammer.com/mailinglist.html


Other related posts: