Im making a survival-mining processing game that has an objective to get all the ores within the time, and without being killed. Each new random level has more enemies and the enemies will get faster. I need a menu system that functions for when the player dies, and selecting level, and pausing. Please implement it I will provide my main class, but you can make another class if you need to, please implement it in an expandable way for me to implement looks to the UI

here is the main class:
// Game constants
final int TILE_SIZE = 32;
final int GRID_WIDTH = 40;
final int GRID_HEIGHT = 30;
final int SCREEN_WIDTH = GRID_WIDTH * TILE_SIZE;
final int SCREEN_HEIGHT = GRID_HEIGHT * TILE_SIZE;
final int MINING_RANGE = 1;
final int ENEMY_DETECTION_RANGE = 30 * TILE_SIZE;

// Game objects
Player player;
ArrayList<Enemy> enemies;
Tile[][] map;
ArrayList<Bullet> bullets;

// UI elements
int health = 4;
int ammo = 100;

// Sprites and animations
PImage playerSprite;
PImage enemySprite;
PImage[] oreSprites;
PImage pickaxeSprite;
PImage gunSprite;
PImage bulletSprite;
// Game state
boolean mining = false;
boolean isRunning = false;
boolean isMousePressed = false;
Tile currentHoveredTile = null;

float screenShakeAmount = 0;
float screenShakeDecay = 0.9;
float redFlashAlpha = 0;

// Resource tracking
HashMap<String, Integer> inventory;

void setup() {
    size(1280, 960);

    //Load sprites
    //playerSprite = loadImage("player.png");
    PImage playerSheet = loadImage("YellowMiner.png");
    player = new Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, playerSheet);

    enemySprite = loadImage("enemy.png");

    oreSprites = new PImage[4];
    for (int i = 0; i < 4; i++) {
        oreSprites[i] = loadImage("ore" + i + ".png");
    }
    playerSprite = loadImage("player.png");
    pickaxeSprite = loadImage("pickaxe.png");
    gunSprite = loadImage("gun.png");
    bulletSprite = loadImage("bullet.png");

    //Initialize game objects
    //player = new Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2);
    enemies = new ArrayList<Enemy>();
    enemies.add(new Enemy(100, 100)); // Add first enemy
    bullets = new ArrayList<Bullet>();
    
    //Initialize inventory
    inventory = new HashMap<String, Integer>();
    inventory.put("Rock", 0);
    inventory.put("Ore0", 0);
    inventory.put("Ore1", 0);
    inventory.put("Ore2", 0);
    
    //Generate or load the map
    generateMap();
}

void draw() {
    background(0);
    
    if (screenShakeAmount > 0) {
        translate(random( - screenShakeAmount, screenShakeAmount), random( - screenShakeAmount, screenShakeAmount));
        screenShakeAmount *= screenShakeDecay;
        if (screenShakeAmount < 0.1) screenShakeAmount = 0;
    }
    
    //Updateand draw map
    drawMap();
    
    //Updateand draw player
    player.update();
    player.display();
    
    //Update and draw enemies
    for (int i = enemies.size() - 1; i >= 0; i--) {  // traditional loop to allow concurrent removal when dead
        Enemy enemy = enemies.get(i);
        if (!enemy.isAlive()) {
            enemies.remove(i);
            continue;
        }
        enemy.update(enemies,map);
        enemy.display();

        if (dist(player.x, player.y, enemy.x, enemy.y) < TILE_SIZE && player.canTakeDamage()) {
            player.takeDamage();
            screenShakeAmount = 10;
            redFlashAlpha = 255;
        }
    }
    
    //Update anddraw bullets
   for (int i = bullets.size() - 1; i >= 0; i--) {
        Bullet bullet = bullets.get(i);
        bullet.update();
        bullet.display();

        if (bullet.isOffscreen()) {
            bullets.remove(i);
            continue;
        }

        for (int j = enemies.size() - 1; j >= 0; j--) {
            Enemy enemy = enemies.get(j);
            if (dist(bullet.x, bullet.y, enemy.x, enemy.y) < TILE_SIZE / 2) {
                enemy.takeDamage(10); // Assume each bullet deals 10 damage
                bullets.remove(i);
                break;
            }
        }
    }
    
    if (mining) {
        int tileX = floor(mouseX / TILE_SIZE);
        int tileY = floor(mouseY / TILE_SIZE);
        currentHoveredTile = map[tileX][tileY];
        
        if (isMousePressed) {}
        if (isWithinMiningRange(tileX, tileY)) {
            TileType minedType = map[tileX][tileY].mine();
            if (minedType != null) {
                addToInventory(minedType);
            }
        }
        drawMiningProgressBar();
        
    }
    
    if (redFlashAlpha > 0) {
        fill(102, 0, 0, redFlashAlpha);
        rect(0, 0, width, height);
        redFlashAlpha *= 0.7;
    }
    
    drawUI();
}

void drawMiningProgressBar() {
    if (currentHoveredTile != null && currentHoveredTile.type != TileType.EMPTY) {
        float barWidth = 200;
        float barHeight = 20;
        float x = (width - barWidth) / 2;
        float y = height - barHeight - 10;
        
        fill(100);
        rect(x, y, barWidth, barHeight);
        
        // Draw progress
        float progress = map(currentHoveredTile.health, 0, currentHoveredTile.getMaxHealth(), 0, barWidth);
        fill(96, 60, 31);
        rect(x, y, progress, barHeight);
        
        // Draw text
        fill(255);
        textAlign(CENTER, CENTER);
        text(currentHoveredTile.health + " / " + currentHoveredTile.getMaxHealth(), x + barWidth / 2, y + barHeight / 2);
        textAlign(LEFT);
    }
}

void addToInventory(TileType type) {
    switch(type) {
        case ROCK:
            inventory.put("Rock", inventory.get("Rock") + 1);
            break;
        case ORE0:
            inventory.put("Ore0", inventory.get("Ore0") + 1);
            break;
        case ORE1:
            inventory.put("Ore1", inventory.get("Ore1") + 1);
            break;
        case ORE2:
            inventory.put("Ore2", inventory.get("Ore2") + 1);
            break;
    }
}

boolean isWithinMiningRange(int tileX, int tileY) {
    int playerTileX = floor(player.x / TILE_SIZE);
    int playerTileY = floor(player.y / TILE_SIZE);
    return abs(tileX - playerTileX) <= MINING_RANGE && abs(tileY - playerTileY) <= MINING_RANGE;
}


void generateMap() {
    map = new Tile[GRID_WIDTH][GRID_HEIGHT];
    
    // Initialize all tiles as empty
    for (int x = 0; x < GRID_WIDTH; x++) {
        for (int y = 0; y < GRID_HEIGHT; y++) {
            map[x][y] = new Tile(TileType.EMPTY);
        }
    }
    
    // Place initial random rocks
    for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT * 0.4; i++) {
        int x = int(random(GRID_WIDTH));
        int y = int(random(GRID_HEIGHT));
        map[x][y].type = TileType.ROCK;
    }
    
    // Apply cellular automata to create clusters
    for (int step = 0; step < 5; step++) {
        Tile[][] newMap = new Tile[GRID_WIDTH][GRID_HEIGHT];
        for (int x = 0; x < GRID_WIDTH; x++) {
            for (int y = 0; y < GRID_HEIGHT; y++) {
                int neighbors = countRockNeighbors(x, y);
                
                if (map[x][y].type == TileType.ROCK) {
                    // Rock survives with 4 or more rock neighbors
                    newMap[x][y] = new Tile(neighbors >= 4 ? TileType.ROCK : TileType.EMPTY);
                } else {
                    // Empty becomes rock with 5 or more rock neighbors
                    newMap[x][y] = new Tile(neighbors >= 5 ? TileType.ROCK : TileType.EMPTY);
                }
            }
        }
        map = newMap;
    }
    
    // Generate ore clusters coherently
    int numClusters = 10;
    for (int i = 0; i < numClusters; i++) {
        int clusterX = int(random(GRID_WIDTH));
        int clusterY = int(random(GRID_HEIGHT));
        int clusterSize = int(random(5, 15));
        int oreType = int(random(0,4)); // 0, 1, or 2 for different ore types
        
        generateCluster(clusterX, clusterY, clusterSize, oreType);
    }
}


int countRockNeighbors(int x, int y) {
    int count = 0;
    for (int dx = -1; dx <= 1; dx++) {
        for (int dy = -1; dy <= 1; dy++) {
            if (dx == 0 && dy == 0) continue;
            
            int nx = x + dx;
            int ny = y + dy;
            
            if (nx >= 0 && nx < GRID_WIDTH && ny >= 0 && ny < GRID_HEIGHT && map[nx][ny].type == TileType.ROCK) {
                count++;
            }
        }
    }
    return count;
}

void generateCluster(int startX, int startY, int size, int oreType) {
    for (int i = 0; i < size; i++) {
        int x = startX + int(random( -3, 4));
        int y = startY + int(random( -3, 4));
        
        if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT) {
            TileType type = (oreType == 0) ? TileType.ORE0 : (oreType == 1) ? TileType.ORE1 : TileType.ORE2;
            map[x][y] = new Tile(type);
        }
    }
}

void drawMap() {
    for (int x = 0; x < GRID_WIDTH; x++) {
        for (int y = 0; y < GRID_HEIGHT; y++) {
            map[x][y].display(x * TILE_SIZE, y * TILE_SIZE);
        }
    }
}

void drawUI() {
    // Reset any transformations to ensure UI is drawn in the correct position
    resetMatrix();
    
    fill(255);
    textSize(20);
    text("Health: " + player.health, 10, 30);
    text("Ammo: " + ammo, 10, 60);
    text("Mining: " + (mining ? "ON" : "OFF"), 10, 90);
    
    // Display inventory
    text("Inventory:", 10, 120);
    int yOffset = 150;
    for (String resource : inventory.keySet()) {
        text(resource + ": " + inventory.get(resource), 10, yOffset);
        yOffset += 30;
    }
    
    drawMiningProgressBar();
}

void keyPressed() {
    // if(key == ' ') {
    //     bullets.add(new Bullet(player.x, player.y, player.facingDirection));
    //     ammo--;
// }
    if (key == 'm' || key == 'M') {
        mining = !mining;
    }

    if (keyCode == SHIFT) isRunning = !isRunning;
    player.setMove(keyCode, true);
}

void keyReleased() {
    player.setMove(keyCode, false);
}

void mousePressed() {
    isMousePressed = true;
    if (mouseButton == LEFT) {
        player.shoot();
        ammo--;
    }
}

void mouseReleased() {
    isMousePressed = false;
}

enum TileType {
    EMPTY, ROCK, ORE0, ORE1, ORE2
}


class Vector2D {
    float x, y;
    
    Vector2D(float x, float y) {
        this.x = x;
        this.y = y;
    }
    
    void add(Vector2D v) {
        x += v.x;
        y += v.y;
    }
    
    
    void mult(float n) {
        x *= n;
        y *= n;
    }
    
    void div(float n) {
        x /= n;
        y /= n;
    }
    
    float mag() {
        return sqrt(x*x + y*y);
    }
    
    void normalize() {
        float m = mag();
        if (m != 0) {
            div(m);
        }
    }
    
    void limit(float max) {
        if (mag() > max) {
            normalize();
            mult(max);
        }
    }
    
    Vector2D sub(Vector2D v) {
        return new Vector2D(x - v.x, y - v.y);
    }
}