JAVA POO - Estourando limite de array e etc

Bom dia,

Pessoal estou desenvolvendo um programa na qual irei gerar veiculos (caminhao,carro e moto)Cada um terá um numero , eles serão gerados quando passar na fabrica que será os numeros 2 na minha matriz.

A matrix é [30][60] , preenchidas com zeros,com numeros 1 nas bordas e as fabricas com blocos de 2
Os veiculos sofrem colisão então por exemplo se caminhao (numero 5) bate no carro (numero 3) o carro some e etc.Por enquanto estou testando só com carro.
Aqui esta um link do programa funcionando:

Estou com os seguintes problemas ::
1-Quando executo dependendo da execução , ele da erro de vetor estourado:
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: -1
at Carro.moverCarro(Carro.java:69)
at Main.main(Main.java:95)

2-Estou com duvidas em como fazer as condições de colisões e para quando por exemplo o carro chegar em uma posição de numero 1 ela voltar para o começo da linha ou coluna , ou seja , sair da Matriz
Exemplo: m[29][60] ai na proximair para m[1][60] levando em conta que a posição 0 tem 1.

Segue meus códigos:

//Carro =3 , Moto=4  ,Caminhao=5


    import java.util.ArrayList;
    import java.util.Random;


    public class Main {
      
      //Declaração Global dos ArrayLists para poder armazenar a quantidade
      // de cada veiculo
      public static  ArrayList<Carro> c = new ArrayList<>();

    public static void main(String[] args) 
    	{
	  
		int [][] matrix = new int[30][60];
		
		//Criação da Matriz
		for(int x = 0; x < matrix.length; x++)
		{
			for (int i = 0; i < matrix[x].length; i++) 
			{
				if((x==0)||(x==(matrix.length)-1))
					matrix[x][i]=1;
				else
					if((i==0)||(i==(matrix[x].length)-1))
						matrix[x][i]=1;
					else
						matrix[x][i]=0;
			}
		}
			
		for(int x = 0; x < matrix.length; x++)
		{
			for (int i = 0; i < matrix[x].length; i++) 
			{
			if(matrix[x][i] == 0){
			  for(int n = 5; n < 12 ;n++){
			    for(int m = 3; m <= 5 ;m++){
          matrix[m][n] = 2;
			      
			    }
			  }
			  for(int n = 5; n < 12 ;n++){
			    for(int m = 24; m <= 26 ;m++){
          matrix[m][n] = 2;
			      
			    }
			  }
			  for(int n = 48; n < 55 ;n++){
			    for(int m = 3; m <= 5 ;m++){
          matrix[m][n] = 2;
			      
			    }
			  }
			  for(int n = 48; n < 55 ;n++){
			    for(int m = 24; m <= 26 ;m++){
          matrix[m][n] = 2;
			      
			    }
			  }
			  for(int n =23 ; n <33  ;n++){
			    for(int m =13 ; m <= 15 ;m++){
          matrix[m][n] = 2;
			      
			    }
			  }
			  
	
      }
				System.out.print(matrix[x][i]);
			}
System.out.println();
		}
		
		//Instanciando Objeto
		Carro carros = new Carro();
		
		//Gerando carro e adicionando na ArrayList
		carros.gerarCarro(matrix);
		c.add(new Carro());
		
		int velcar = 2;
	
		
			for(int x = 0; x < matrix.length; x++)
		{
			for (int i = 0; i < matrix[x].length; i++) 
			{
			  
				System.out.print(matrix[x][i]);
			}
System.out.println();
		}
		
		
		//While para o carro ficar se movendo 
		while(true){
		carros.moverCarro(matrix);
		//print da matriz após cada movimento
		for(int x = 0; x < matrix.length; x++)
		{
			for (int i = 0; i < matrix[x].length; i++) 
			{
			  
				System.out.print(matrix[x][i]);
			}
    System.out.println();
		}
		}
	}
		
	
}

E aqui esta a classe Carro:

import java.util.Random;
import java.util.ArrayList;

public class Carro{

   //Método para gerar um Carro em um lugar aleatório da matriz
  	public void gerarCarro(int matrix[][]){

		  Random r= new Random();
		  int a =r.nextInt(29);
    int b =r.nextInt(59);
		  if(matrix[a][b] == 0){
		    matrix[a][b]=3;
		    
		  
	}
	
	}
	public void moverCarro(int matrix[][]) {
	  
    for (int l = 0; l < matrix.length; l++) {
        for (int c = 0; c < matrix[l].length; c++) {
            int numero = matrix[l][c];

            if (numero == 3) {
                Random random = new Random();
                int direcao = random.nextInt(4);
                matrix[l][c] = 0;

                switch (direcao) {
                    // move para cima
                    case 0:
                        if ((l - 2) < matrix[l].length) {
                            l = l - 2;
                        }

                        break;
                    //move para baixo
                    case 1:
                        if ((l + 2) < matrix[l].length) {
                            l = l + 2;
                        
                        }

                        break;
                    //move para direita
                    case 2:
                        if ((c - 2) < matrix[c].length) {
                            c = c - 2;
                       
                          
                        }
                          
                        

                        break;
                    //move para esquerda
                    case 3:
                        if ((c + 2) < matrix[c].length){
                            c = c + 2;
                        }
                        

                        break;
                    
                }
                
                matrix[l][c]=numero;

                
        
                  
                }
            }
        }
	}
    }

Esse erro se da por causa de ter estourado o limite da matriz, pois se você tiver tentando acessar a posição da linha maior ou igual 30 e da coluna maior ou igual a 60 ele retorna esse erro. Para voltar para o primeiro você pode usar a função mod que é representada por % no java. Ai você poderia colocar algo parecido com isso no case 1: l=(l+2)%60; garantindo que o número seja de 0 a 59, retirando o if e ficando só igual coloquei em negrito. no case 2 você teria que usar modulo para garantir que o número nunca fosse negativo ou então se ele tiver que voltar ao inicio você teria que usar um if verificando se o numero for menor igual a 0, ou menor igual a 1 como você anda de 2 em 2, para ele voltar para a posição 59.