Spritesheet problem

(1/2) > >>

Porlus:
Hello, I've got a problem with a spritesheet I'm trying to make using Java 2D. I first load an external PNG into a BufferedImage using the ImageIO class and using a Sprite class I pass in the buffered spritesheet, where I want it in the frame (x, y), the top left hand point of the tile from the spritesheet that I want to extract (xOffset, yOffset) and the width and height of the tile.

The external PNG is just a spritesheet containing the characters a-z, 0-9 that I made in photoshop, with each tile being 20x20 pixels. I'll post the code so you can see exactly what I mean, but what the problem is, is that when a new character is drawn using the Component classes paint method, the previously rendered characters disappear.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class Main
{
   public static final int WIDTH = 300;
   public static final int HEIGHT = 300;
   
   private Screen screen;
   
   public Main()
   {
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setLayout(new BorderLayout());
      frame.setSize(WIDTH, HEIGHT);
      frame.setLocationRelativeTo(null);
      frame.setResizable(false);
      frame.setVisible(true);
     
      BufferedImage ss = null;
      try
      {
         ss = ImageIO.read(new File("charSprite.png"));
      }
      catch(IOException e)
      {
         e.printStackTrace();
      }
     
      screen = new Screen(WIDTH, HEIGHT);
      screen.loadImage(new Sprite(ss, 0, 0, 20, 20).getSprite(), 20, 20);
      screen.loadImage(new Sprite(ss, 0, 0, 20, 20).getSprite(), 40, 40);
     
      frame.add(screen);
   }
   
   public static void main(String[] args)
   {
      new Main();
   }
}


Here's the Sprite class, for dissecting the tile from the spritesheet:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
import java.awt.image.BufferedImage;

public class Sprite
{
   private BufferedImage sprite;
   
   public Sprite(BufferedImage ss, int xOffset, int yOffset, int width, int height)
   {
      sprite = ss.getSubimage(xOffset, yOffset, width, height);
   }
   
   public BufferedImage getSprite()
   {
      return sprite;
   }
}


Here's the screen class which holds the bufferedimage containing each element within the screen:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class Screen extends Component
{
   private BufferedImage display = null;
   private int[] pixels;
   
   public Screen(int w, int h)
   {
      display = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
      pixels = new int[w * h];
   }
   
   public void loadImage(BufferedImage im, int x, int y)
   {
      int[] p = im.getRGB(0, 0, im.getWidth(), im.getHeight(), null, 0, im.getWidth());
      for(int y1 = 0; y1 < im.getHeight(); y1++)
      {
         for(int x1 = 0; x1 < im.getWidth(); x1++)
         {
            pixels[(y1 + y) * display.getWidth() + (x1 + x)] = p[y1 * im.getWidth() + x1];
         }
      }
      display.setRGB(0, 0, display.getWidth(), display.getHeight(), pixels, 0, display.getWidth());
         
      repaint();
   }
   
   public void paint(Graphics g)
   {
      g.drawImage(display, 0, 0, display.getWidth(), display.getHeight(), null);
   }
}


I'm quite new to this and just trying to understand how swing works so any help would be appreciated. Thanks!

Paul

ra4king:
JFrame's ContentPane's default layout is BorderLayout, which uses 1 component for the center, and 1 component for each of the 4 sides. Calling JFrame.add(Component) adds it to the center component. Any further calls will replace the previous one. What you need is 1 component that you draw everything to.

Porlus:
Thanks for the reply. Yeah, I've just thought to add a screen class to keep a pixels by pixels reference of everything on the screen, then I can just pass in bufferedimages, extract their pixel arrays and then overlay the new image within a nested loop in the correct position.

I've updated my original post now to what I currently have and it seems to work perfectly, except the images only seem to appear roughly 50% of the time once the program is ran. If I minimize the program and maximize it again the images appear, though. Any idea what could be causing that?

GabrielBailey74:
Could be because you're only adding the Screen there once, you'd need to add a loop of somekind, than handle your paint method in there so it's constantly repainting.

Porlus:
I think it stays as it is until you clear the pixel array and update the screen buffer. I'll have to create a clear buffer method or something to clear that out. I think the problem lies around here in the main class:

1  
ss = ImageIO.read(new File("charSprite.png"));


As when the pictures don't render, they both don't and likewise when they do. So that would suggest that it was a problem with the spritesheet I'm feeding into the sprite classes. Not really sure about a solution though.

Navigation

[0] Message Index

[#] Next page