Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (472)
Games in Android Showcase (105)
games submitted by our members
Games in WIP (524)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Spritesheet problem  (Read 1950 times)
0 Members and 1 Guest are viewing this topic.
Offline Porlus

Junior Member





« Posted 2012-02-07 17:57:54 »

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
Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #1 - Posted 2012-02-08 01:14:17 »

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.

Offline Porlus

Junior Member





« Reply #2 - Posted 2012-02-08 01:53:26 »

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?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline GabrielBailey74
« Reply #3 - Posted 2012-02-08 01:56:24 »

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.

Offline Porlus

Junior Member





« Reply #4 - Posted 2012-02-08 02:05:25 »

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.
Offline GabrielBailey74
« Reply #5 - Posted 2012-02-08 02:08:12 »

What I would do, and what I do do is:
Take the spritesheet, chop it down into proper frames, give it a pinkish background color (if you want it to be transparent), load it through transparency and ignore those pink pixels.
Thought i've never tried grabbing a subImage of a image..

You could make your Screen class extend a JPanel, than add the JPanel to the frame, make your Main class "extends Screen".
You could do your Screen class like this:

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  
import java.awt.Component;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

public class Screen extends JPanel // Updated
{
   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 cycle() { // Updated
     repaint();
   }

   public void paint(Graphics g) // Updated
  {
      super.paint(g);
      final Graphics2D g2d = (Graphics2D) g;
      g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
      g2d.drawImage(display, 0, 0, display.getWidth(), display.getHeight(), null);
   }
}


And your Main class like this:
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  
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 extends Screen implements Runnable { //Updated
  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);
      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(new Screen());
      frame.setVisible(true); // Just realized you were setting your screen to visible, THAN you were adding everything.
  }
   
   public static void main(String[] args) {
      new Main();
   }

   @Override
   public void run() { //Updated
     super.cycle();
   }
}


So your Main class is automaticly calling that "cycle" method from your Screen class which is than telling it to "repaint", which was changed to "super.paint(g)", which would paint your GUI/Main screen.

Hope it helps some mate (Would need proper imports/changes made).

Offline Porlus

Junior Member





« Reply #6 - Posted 2012-02-08 02:36:51 »

How foolish of me. :] Just moved the setvisible below the add call and now it's rendering in time. Cheers both of you for your help!
Offline GabrielBailey74
« Reply #7 - Posted 2012-02-08 02:38:17 »

Np mate, i'm fairly newish.
Need any help drop me a pm.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CopyableCougar4 (13 views)
2014-07-10 02:26:14

CopyableCougar4 (25 views)
2014-07-09 02:55:38

Code Mage (23 views)
2014-07-08 23:57:00

Code Mage (8 views)
2014-07-08 23:49:08

AppleSauce (19 views)
2014-07-08 19:25:32

CopyableCougar4 (21 views)
2014-07-06 01:51:26

ipe369 (26 views)
2014-07-05 14:18:25

vastrolorde (37 views)
2014-07-04 18:45:44

theagentd (53 views)
2014-07-02 22:19:37

theagentd (50 views)
2014-07-02 22:17:51
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!