Método paintComponent() apagando imagens no JFrame

Eu preciso gerar um mapa de acordo com um arquivo txt que recebo como entrada. Cada tipo de letra do meu arquivo txt corresponde a um tipo de terreno do mapa. Criei arrays de Image que vão armazenar as imagens que posso usar para cada tipo de terreno e desenho essas imagens no Jframe. Já verifiquei e o caminho das imagens estão corretos, mas como eu chamo o método onPaint várias vezes durante a execução do programa, o mapa acaba sendo apagado (acredito que esse seja esse o motivo). Preciso desenhar o mapa apenas uma vez e, feito isso, movimentar um avatar sobre ele. Como faço pra desenhar o mapa, deixá-lo montado e redesenhar apenas o avatar conforme ele se movimenta?

Segue o código:

public class MapaInterface extends JPanel implements ActionListener {

BuscaHeuristicaGameOfThrones busca = new BuscaHeuristicaGameOfThrones();
private Image fundo;
private Image explosao = new ImageIcon("src/res/exp1.png").getImage();
private Image agua = new ImageIcon("/src/res/agua.png").getImage();
public static ArrayList<Image> grama = new ArrayList<>();
public static ArrayList<Image> terra = new ArrayList<>();
public static Agente daenerys;
private Timer timer;
FileReader arquivo = null;
BufferedReader leitor;
String linha = "";

public MapaInterface() {
    try {
        arquivo = new FileReader("mapaInvertido.txt");
        leitor = new BufferedReader(arquivo);
    } catch (FileNotFoundException ex) {
        Logger.getLogger(MapaInterface.class.getName()).log(Level.SEVERE, null, ex);
    }
    ImageIcon referencia = new ImageIcon("src/res/mapaGot2.png");
    fundo = referencia.getImage();
    timer = new Timer(1, this);
    preencheArrayDeImagens();
    timer.start();
    daenerys = new Agente();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D graficos = (Graphics2D) g;
    Random random = new Random();
    int numAleatorio = random.nextInt(23);
    int x = 0, y = 0;
    String tipo = "";
    graficos.drawImage(new ImageIcon("src/res/terrinha.png").getImage(), x,y, this);
    try {
        linha = leitor.readLine();
        StringTokenizer tokenizer;
        while(linha != null){
            tokenizer = new StringTokenizer(linha, ",");
           while(!tipo.equals("|")){
                tipo = tokenizer.nextToken();
                if (tipo.equals("T")) {
                    graficos.drawImage(terra.get(numAleatorio), x, y, null);
                    g.dispose();
                }
                if (tipo.equals("G")) {
                    graficos.drawImage(grama.get(numAleatorio), x, y, null);
                }
                if (tipo.equals("A")) {
                    graficos.drawImage(agua, x, y, null);
                }
                x += 16;
            }
            y+=16;
            linha = leitor.readLine();
        }
    } catch (IOException ex) {
        Logger.getLogger(MapaInterface.class.getName()).log(Level.SEVERE, null, ex);
    }
    graficos.drawImage(daenerys.getImagem(), daenerys.getPosicaoMI().getX(), daenerys.getPosicaoMI().getY(), this);
    if (daenerys.chegouDestino == true) {
        graficos.drawImage(explosao, daenerys.getPosicaoMI().getX(), daenerys.getPosicaoMI().getY(), this);
        daenerys.chegouDestino = false;
    }
    g.dispose();
}

@Override
public void actionPerformed(ActionEvent e) {
    if (daenerys.destinoMuralha == true) {
        if (daenerys.chegouMuralha == false) {
            daenerys.movimentaAgenteMuralha();
            repaint();
        } else {
        }
    } else {
        daenerys.movimentaAgente();
    }
    repaint();
}

public static Agente getDaenerys() {
    return daenerys;
}

public static void setDaenerys(Agente daenerys) {
    MapaInterface.daenerys = daenerys;
}

public void preencheArrayDeImagens() {
    Image blocoTerra = new ImageIcon("src/res/cogumeloterra.png").getImage();
    terra.add(blocoTerra);
    blocoTerra = new ImageIcon("src/res/fogueira.png").getImage();
    terra.add(blocoTerra);
    blocoTerra = new ImageIcon("src/res/tronco.png").getImage();
    terra.add(blocoTerra);
    blocoTerra = new ImageIcon("src/res/tronco2.png").getImage();
    terra.add(blocoTerra);

    Image blocoGrama = new ImageIcon("src/res/florbranca.png").getImage();
    grama.add(blocoGrama);
    blocoGrama = new ImageIcon("src/res/florvermelha.png").getImage();
    grama.add(blocoGrama);
    blocoGrama = new ImageIcon("src/res/matinho.png").getImage();
    grama.add(blocoGrama);
    blocoGrama = new ImageIcon("/src/res/cogumelovermelho.png").getImage();
    grama.add(blocoGrama);

    for (int i = 0; i < 20; i++) {
        grama.add(new ImageIcon("src/res/graminha.png").getImage());
        terra.add(new ImageIcon("src/res/terrinha.png").getImage());
    }
}

Fiz alguns testes e dessa forma funciona normalmente:

    graficos.drawImage(terra.get(numAleatorio), 16, y, this);
    graficos.drawImage(terra.get(numAleatorio), 32, y, this);
    graficos.drawImage(terra.get(numAleatorio), 48, y, this);

Só que não posso fazer isso pois o tipo de terreno depende das letras no txt

Não vou responder em cima do seu código porque faltam mais partes para entender como ele está estruturado. Mas aqui vão alguns comentários:

  • você está lendo o arquivo toda vez que o paintComponent é chamado. Não faça isso. Ler um arquivo é um processo lento demais para ser feito a cada chamada a paintComponent;
  • faça a leitura do arquivo1 vez só (ao iniciar o programa ou no construtor do JPanel), para uma outra estrutura (exemplo: ArrayList). No paintComponent, você desenha a partir dessa estrutura;
  • o paintComponent deve ser usado somente para os métodos de desenho. Toda a lógica que não for de desenho (ler arquivo, gerar coisas aleatórias, etc) deve ficar fora do paintComponent ;
  • o JFrame (que contém seu JPanel, suponho) precisa ser exibido usando a thread do Swing. Veja como em http://www.pontov.com.br/site/java/48-java2d/92-conhecendo-o-jframe , quase no final do artigo. Isso é importante para resolver diversos problemas de exibição do JFrame e do JPanel;

Recomendo a leitura dos artigos do Ponto V sobre java 2d ( http://www.pontov.com.br/site/index.php/java/48-java2d ). Lá fala sobre o loop de animação, algo que lhe será útil.

Abraço.