Question

I am currently working on a little 2D Game based on Super Mario Bros. I'm using a Model-View-Controller-Pattern and i have a flickering issue in my Panel (extending JPanel). My blocks and everything but Mario are constantly flashing and i don't know why. I tried to do a BufferedReader to fix the problem but it did not change anyhting, neither a smaller resolution background did. I noticed that when i remove the background (and so we see traces left behind Mario), nothing flickers anymore but I can't let it like that... Do you have any ideas of where the problems come ?

Thank you very much for your attention, I join the code of my GUI here.

PS: I'm new in java so please forgive my beginner code and problems :). Also, forgive my english. I can add any other part of my code if needed.

Note : level is my main model loop and there is different bonuses with differents effects on Mario as differents status like OnAir, etc.

Window

package GUI;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JFrame;
import model.Level;
import observable.Observator;

public class Window extends JFrame implements Observator{

public Panel pan;
Level level;

public Window(Level level){
    setVisible(true);
    setTitle("Mario");
    setExtendedState(6);
    setDefaultCloseOperation(3);
    setLocationRelativeTo(null);
    setSize(level.cam.getHitboxx(),level.cam.getHitboxy());
    setResizable(false);
    this.level = level;
    this.pan = new Panel(level);
    setContentPane(this.pan);
    }

public void update(Level level){
this.level = level;
this.pan.setLevel(this.level);
this.pan.render();
this.pan.paintComponent(getGraphics());
}

public Level getLevel() {
return level;
 }

public void setLevel(Level level) {
this.level = level;
}

}

Panel

package GUI;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import model.Edge;
import model.Level;
import model.Mario;
import model.StaticEntity;

public class Panel extends JPanel{

protected Level level;
private Image marioNormalLeftImg;
private Image marioNormalRightImg;
private Image marioJumpingRightImg;
private Image marioJumpingLeftImg;
private Image marioCrouchRightImg;
private Image marioCrouchLeftImg;
private Image marioDeadImg;
private Image backgroundImg;
private Image rightGoombaImg;
private Image leftGoombaImg;
private Image brickImg;
private Image CoinImg;
private Image gameOverImg;
private Image winImg;
private Image WeedGIF;
private Image WeedBonusImg;
private Image metalShroomImg;
private Image lifeShroomImg;
private Image shroomImg;
private Image marioGIF;
private Image bonusBrickImg;
private Image groundImg;

public Panel(Level level){
    try
    {

      this.marioNormalLeftImg = ImageIO.read(new File("Mario_NormalLeft.png"));
      this.marioNormalRightImg = ImageIO.read(new File("Mario_NormalRight.png"));
      this.marioJumpingRightImg = ImageIO.read(new File("Mario_JumpRight.png"));
      this.marioJumpingLeftImg = ImageIO.read(new File("Mario_JumpLeft.png"));
      this.marioCrouchRightImg = ImageIO.read(new File("Mario_CrouchRight.png"));
      this.marioCrouchLeftImg = ImageIO.read(new File("Mario_CrouchLeft.png"));
      this.marioDeadImg = ImageIO.read(new File("Mario_Dead.png"));
      this.backgroundImg = ImageIO.read(new File("Background2.png"));
      this.rightGoombaImg = ImageIO.read(new File("goomba1.png"));
      this.leftGoombaImg = ImageIO.read(new File("goomba2.png"));
      this.brickImg = ImageIO.read(new File("Brick_Block.png"));
      this.bonusBrickImg = ImageIO.read(new File("Bonus_Block.png"));
      this.CoinImg = ImageIO.read(new File("Coin1.png"));
      this.gameOverImg = ImageIO.read(new File("GameOver.png"));
      this.winImg = ImageIO.read(new File("youwin.png"));
      this.WeedGIF = this.getToolkit().createImage("Weed_Background.gif");
      this.marioGIF = this.getToolkit().createImage("walkinggif.gif");
      this.WeedBonusImg = ImageIO.read(new File("Weed.png"));
      this.metalShroomImg = ImageIO.read(new File("metalShroom.png"));
      this.lifeShroomImg = ImageIO.read(new File("Green_Mushroom.png"));
      this.shroomImg = ImageIO.read(new File("Red_Mushroom.png"));
      this.groundImg = ImageIO.read(new File("ground_large.png"));
    }
    catch (IOException e)
    {
      e.printStackTrace();
    }

    this.level = level;

}


public void setLevel(Level level){
this.level = level;}


public void paintComponent(Graphics g){
    if(this.level.getTHCratio()>0){g.drawImage(this.WeedGIF, 0, 0, this.level.cam.getHitboxx(),  this.level.cam.getHitboxy(), this);
    }
    else{g.drawImage(this.backgroundImg, 0, 0,  this.level.cam.getHitboxx(),  this.level.cam.getHitboxy(), this);}
    this.paintMario(g);

    for(int i = 0;i<this.level.goombas.size();i++){
    if(this.level.goombas.get(i)!=null){this.paintGoomba(g, i);}}

    for(int i = 0;i<this.level.edges.size();i++){
        if(this.level.edges.get(i)!=null&&this.level.edges.get(i).visible){
            if(this.level.edges.get(i).type == "Normal"){
                drawComponent(this.level.edges.get(i),this.brickImg,0,g);
            }
            else if(this.level.edges.get(i).type == "Ground"){drawComponent(this.level.edges.get(i),this.groundImg,0,g);}
            else{drawComponent(this.level.edges.get(i),this.bonusBrickImg,0,g);}
        }       
    }
 for(int i = 0;i<this.level.bonus.size();i++){
        if(this.level.bonus.get(i)!=null){
            if(this.level.bonus.get(i).getClass().getName() == "model.Coin"){
            drawComponent(this.level.bonus.get(i),this.CoinImg,0,g);}
            else if (this.level.bonus.get(i).getClass().getName() == "model.WeedBonus"){
                drawComponent(this.level.bonus.get(i),this.WeedBonusImg,0,g);
            }
            else if (this.level.bonus.get(i).getClass().getName() == "model.MetalShroom"){
                drawComponent(this.level.bonus.get(i),this.metalShroomImg,0,g);
            }
            else if (this.level.bonus.get(i).getClass().getName() == "model.LifeShroom"){
                drawComponent(this.level.bonus.get(i),this.lifeShroomImg,0,g);
            }
            else if (this.level.bonus.get(i).getClass().getName() == "model.Shroom"){
                drawComponent(this.level.bonus.get(i),this.shroomImg,0,g);
            }
 }
 }

 Font police = (new Font("Mario Kart DS", Font.PLAIN, 30));
 if (police == null) {police = (new Font("Times New Roman", Font.PLAIN, 30));}
 g.setFont(police);
 g.setColor(Color.white);
 g.drawString("coins  " + String.valueOf(this.level.player.getCoins()), 1000, 50);
 g.drawString("score  " + String.valueOf(this.level.player.getScore()), 1000, 100);
 g.drawString("lives  " + String.valueOf(this.level.player.getLives()), 1000, 150);

 if(level.player.getLives() == 0){
     this.backgroundImg = this.gameOverImg;}
 if(this.level.player.getScore() == 200*level.goombas.size() + 100*level.bonus.size()){this.backgroundImg = this.winImg;this.leftGoombaImg = null;this.rightGoombaImg = null;this.brickImg = null;this.level.mario.setPosx(3000);this.level.mario.setPosy(3000);this.CoinImg = null;}           

}


public void paintMario(Graphics g){
    String statusName = this.level.mario.getStatus().getName();
    boolean goingRight = this.level.mario.getSpeedx()>=0;
    if(statusName == "OnAir"){
        if(goingRight){drawComponent(this.level.mario,this.marioJumpingRightImg,0,g);               
        }else{drawComponent(this.level.mario,this.marioJumpingLeftImg,0,g);}
    }
    else if(statusName == "DEAD"){
        drawComponent(this.level.mario,this.marioDeadImg,0,g);              
    }
    else if(statusName == "Crouch"){if(goingRight){drawComponent(this.level.mario,this.marioCrouchRightImg,0,g);            
    }else{drawComponent(this.level.mario,this.marioCrouchLeftImg,0,g);}}
    else{
        if(goingRight){drawComponent(this.level.mario,this.marioNormalRightImg,0,g);}
        else{drawComponent(this.level.mario,this.marioNormalLeftImg,0,g);}
    }
}

public void paintGoomba(Graphics g, int i){
    boolean goingRight = this.level.goombas.get(i).getSpeedx()>=0;
    if(goingRight){drawComponent(this.level.goombas.get(i),this.rightGoombaImg,10,g);}
    else{drawComponent(this.level.goombas.get(i),this.leftGoombaImg,10,g);}
}

private Image bufferImage = null;
private void gameRender()
{
    if(bufferImage == null)
    {
        bufferImage = createImage(1200, 800);
    }

    Graphics dbg = bufferImage.getGraphics();
    this.paintComponent(dbg);

}

private void gamePainting()
{
    Graphics g = this.getGraphics();
    if((g != null) && (bufferImage != null))
    {
        g.translate(0,0);
        g.drawImage(bufferImage, 0,  0,  null);
        g.dispose();
    }
}

public void render() {
    // TODO Auto-generated method stub
    this.gameRender();
    this.gamePainting();

}
public void drawComponent(StaticEntity obj, Image img,int shapeCorrector,Graphics g){
    if(this.level.cam.isOnHitbox(obj.getPosx(),obj.getPosy(),obj.getHitboxx(),obj.getHitboxy())){
        g.drawImage(img, obj.getPosx()-shapeCorrector-this.level.cam.getPosx(), obj.getPosy()-shapeCorrector-this.level.cam.getPosy(),  obj.getHitboxx()+shapeCorrector,  obj.getHitboxy()+shapeCorrector, null);
    }

}

}

Was it helpful?

Solution

  • Do call super.painComponent
  • Don't use getGraphics, it can be null and can be overridden by the paint sub system
  • There's no need for the gameRender method, Swing components are already double buffered.

You seem to think you can control the paint process in a Swing. Swing uses a passive painting process, which means that a paint update may occur at anytime for any reason, many times, without your involvement.

You can request an update using repaint, but it's up to the paint sub system to schedule and the actually perform the update when it takes it should be done

Take a look at

for more details

Get rid of your gameRender and gamePaint methods and simply call repaint on the panel when you want to update its output

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top