Setting a background image in a simple java game - java

I'm making my first simple game, that looks like Space Invaders.
I have used paint for drawing my hero on my JPanel. Now I guess if it's possible, in a simple way, to add a background image on my JPanel.
ImageIcon img = new ImageIcon(this.getClass().getResource("back.gif"));
Image image = img.getImage();
setDoubleBuffered(true);
hero = new Hero("hbarrel.gif",350,500);
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(hero.getImage(), hero.getX(), hero.getY(), this);
g2d.drawImage(image,0,0,this);
// Toolkit.getDefaultToolkit().sync();
g.dispose();
}
So, this is it: I tried to use my background img as hero img, and it works! but when I use the code above it only paints my hero img.... so it isn't a resource position issue.

Override paintComponent(Graphics) method and use Graphics.drawImage() to do that in your own custom component.

Well, try to paint the background image first and then the hero so that you have hero above background image

Related

Java (re)painting mechanism [duplicate]

In java awt or swing when you want to change painting of some component you usually have to override the method paint(Graphics g) (in awt) or paintComponent(Graphics g) (in swing).
This is usually (maybe allways - I'm not sure) done when you are creating the component for example:
JPanel jPanel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
//... my implementation of paint, some transfromations, rotation, etc
}
};
Imagine that you have container of components which could for example consists of some JLabels, some JTextFields, some image. Which will be all put on one component.
By container I mean you have some list or map with ids or some similar structure in which are all components you will put on one JFrame.
The question is if I can change the painting method after creating with all of the components which are in this list in the moment when all of them are already created. For example I want do the rotation action (rotate), which is defined in Graphisc2D, with all of them.
So basicaly what I want is that I throught the list of componets I have and say:
"All of you (components) which are in the list will be rotated by some angle". Is that possible? If yes how?
Edit:
This is my not correctly working solution:
graphicalDisplayPanel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.rotate(Math.PI, anchorx, anchory);
}
#Override
public void paintChildren(Graphics g) {
super.paintChildren(g);
Graphics2D g2d2 = (Graphics2D) g;
g2d2.rotate(Math.PI, anchorx, anchory);
}
};
JFrame jFrame = JFrame();
// ... setting dimension, position, visible etc for JFrame, it works correctly nonrotated
jFrame.setContentPane(graphicalDisplayPanel);
I have not tested this, but it seems like it would work. A JComponent's paint() method calls:
paintComponent(co);
paintBorder(co);
paintChildren(co);
where co is a Graphics object. In theory you create an image, retrieve the graphics object and then pass that into paintChildren(). you will have to call paintComponent() and paintBorder() yourself, if you do this. Then, just rotate the image and draw it into your component. You may have to crop the image or resize your component accordingly for this to work. It might look something like this:
BufferedImage myImage;
#Override
public void paint(Graphics g){
myImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TRANSLUCENT);
//using a transparent BufferedImage might not be efficient in your case
Graphics myGraphics = myImage.getGraphics();
super.paintComponent(g);
super.paintBorder(g);
super.paintChildren(myGraphics);
//rotation code here
// ...
//draw children onto your component
g.drawImage(myImage, 0, 0,getWidth(), getHeight(), null);
}
I hope I didn't make any mistakes, please let me know if this works.
So basicaly what I want is that I throught the list of componets I have and say: "All of you (components) which are in the list will be rotated by some angle".
If you want to rotate panel and therefore all the components on the panel as a single using then you need to do the custom painting in the paintComponent() method.
If you want to rotate, for example, individual images that each have a different angle of rotation then you can again do this in the paintComponent(...) method and change the angle for each component.
Or, in this second case you can use the Rotated Icon class. In this case the Icon is just added to a JLabel. Then you can change the degrees of rotation and repaint the label, so there is no custom painting (except in the Icon itself).

why drawing directly to the graphics object of jpanel cause significant lag to the game?

Below are two ways to draw graphics in a java game.
First approach:
We draw to a separate image canvas also called double buffering i think, and in the end of the frame, we draw that image to the graphics object of jpanel.
public class GamePanel extends JPanel implements Runnable{
private Graphics2D g;
private void init(){
running = true;
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
}
private void render(){
g.setColor(Color.black);
g.fillRect(0, 0, WIDTH, HEIGHT);
tileMap.draw(g);
player.draw(g);
}
private void draw(){
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, null);
g2.dispose();
}
}
}
Second approach:
We directly draw to the graphics object of the jpanel.
public class GamePanel extends JPanel implements Runnable{
private void init(){
running = true;
}
private void render(){
g.setColor(Color.black);
g.fillRect(0, 0, WIDTH, HEIGHT);
tileMap.draw((Graphics2D)getGraphics());
player.draw((Graphics2D)getGraphics());
}
}
}
After testing both ways in a simple mario like platform game, i noticed serious flickering with the second approach. My question is why exactly is this problem seen in the second approach? Is the flickering in the second approach because of the number of draw calls to the jpanel graphics object compared to just 1 call in the first approach? I want to know what exactly is going on underneath that is causing this problem. Thank you!
Double buffering is used to combat that exact reason, the flickering, tearing etc.
Without double buffering sometimes you will get to see the intermediate stage of the canvas being cleared and all the objects being redrawn. This is why you're getting flickering.
With double buffering you see no such flickering because the entire image is drawn in one single draw action.

How to create a new canvas on JPanel?

i'm making an MSPaint like application on java, but i'm stuck on create a new canvas (a white background JPanel)
My Code is this:
public void creaLienzo(){
BufferedImage canvas=new BufferedImage(lienzo.getWidth(),
lienzo.getHeight(),BufferedImage.TYPE_INT_RGB);
Graphics2D g2=canvas.createGraphics();
g2.setBackground(Color.WHITE);
lienzo.paint(g2);
}
But the JPanel doesn't draw the white background.
Setting the background would Not be the way to do this.
Since you would only want this once, use:
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, getWidth(), getHeight());
assuming that you have a separate panel for the canvas you could do this.
public void addNew(JPanel panel)
{
panel.removeAll();
panel.add(new Canvas());
}
you can set the background color for a jPanel by using
jPanelName.setBackground(Color.white);

Getting started with Drawing and the 2D API

I'm trying to integrate some drawing functionality into my program.
I have a JLabel that has an image set on it.
I want to write a method to return my image:
public Graphics getImage(){
Graphics g = currentImage;
return g
}
But I don't know how to convert it from a JLabel to a graphics object. Then as a simple test I want to draw a line on this image:
public void paint(Graphics g) {
g.drawLine(20, 500, 700, 600);
}
Some help with getting started on this would be great.
Override paintComponent(Graphics g) method of JLabel and place all the drawing code there.
I have a JLabel that has an image set on it.
Create a copy of the image (BufferedImage image2..) and put image2 in the label.
When you need to draw, call image2.getGraphics() for a Graphics object, or image2.createGraphics() for a Graphics2D object.
See this answer for examples of creating and using images.

JOptionPane background Image

How to set background Image of JOptionPane? I want to show a different image on background of an JOptionPane.
You could extend the JOptionPane class and override the paint method.
Edit:
Depending on the image resolution and quality you might be able to stretch it with an AffineTransform during the WindowResize events without to much distortion. This would let you handle the JOptionPane and image size discrepancies mentioned below.
class ImageBackgroundPane extends JOptionPane
{
private BufferedImage img;
public ImageBackgroundPane (BufferedImage image)
{
this.img = image;
}
#Override
public void paint(Graphics g)
{
//Pick one of the two painting methods below.
//Option 1:
//Define the bounding region to paint based on image size.
//Be careful, if the image is smaller than the JOptionPane size you
//will see a solid white background where the image does not reach.
g.drawImage(img, 0, 0, img.getWidth(), img.getHeight());
//Option 2:
//If the image can be guaranteed to be larger than the JOptionPane's size
Dimension curSize = this.getSize();
g.drawImage(img, 0, 0, curSize.width, curSize.height, null);
//Make sure to paint all the other properties of Swing components.
super.paint(g);
}
}

Categories