Implementing a Processing app inside another one

Hi guys, iv’e been trying to do this for hours but every time i try i fail.

i made a slotmachine.pde with a fully working slot machine

ArrayList<Coin> coins = new ArrayList<Coin>();  // List to store the coins
float gravity = 0.5;  // Gravity effect on the coins
float coinSize = 40;  // Size of each coin (increased)
float coinTankX = -900;  // Move the coin tank further to the left
float coinTankY = -100;   // Position the coin tank higher up
float coinTankWidth = 100; // Adjusted width of the coin tank (thinner)
float coinTankHeight = 400; // Height of the coin tank

PFont font1;
boolean bool_spin; // the lever has been pulled
boolean bool_spinning; // the machine is spinning
int spinframe;
int time;

boolean bool_reels; // to display the reels after it has spun
int reel1 = -1; // Slot 1
int reel2 = -1; // Slot 2
int reel3 = -1; // Slot 3

float float_spinframe; // to calculate how fast to switch the shapes
int[] currentShapes = {0, 0, 0}; // Track current shape index for each slot
float spinSpeed = 0.5; // Initial speed for spinning
int spinDuration = 360; // Total duration of spinning (6 seconds at 60 fps)
int spinTimer = 0; // Timer to track spinning time

// Variables for custom shapes
PImage meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic;
PImage[] slotShapesImages;
float[] shapeChances = {
  30.0,  // meteor.png (30% chance)
  25.0,  // rainbowstar.png (25% chance)
  18.0,  // datagemstar.png (18% chance)
  12.0,  // dwarvengold.png (12% chance)
  8.0,   // alienruby.png (8% chance)
  5.0,   // polyhedron.png (5% chance)
  2.0    // geodesic.png (2% chance)
};

String[] shapeNames = {
  "Meteor", "RainbowStar", "DataGemStar", "DwarvenGold", "AlienRuby", "Polyhedron", "Geodesic"
};

float handleRotation = 0; // Add this variable to control handle rotation

boolean handleActive = true;  // Track if handle can be used
boolean hasWon = false;  // Track winning status

boolean canAddCoin = true;  // Track if a new coin can be added
int maxCoins = 9;  // Maximum number of coins allowed in the tank

void setup() {
  size(1000, 1000, P3D);  // Larger window size
  stroke(0);  // Set stroke color to black
  strokeWeight(2);  // Set stroke thickness for everything else
  
  // Initialize the font
  font1 = createFont("Times New Roman", 30); 
  textFont(font1);
  textAlign(CENTER, CENTER); 
  
  // Load images
  meteor = loadImage("meteor.png");
  rainbowstar = loadImage("rainbowstar.png");
  datagemstar = loadImage("datagemstar.png");
  dwarvengold = loadImage("dwarvengold.png");
  alienruby = loadImage("alienruby.png");
  polyhedron = loadImage("polyhedron.png");
  geodesic = loadImage("geodesic.png");
  
  // Add the images to the array
  slotShapesImages = new PImage[]{meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic};
  
  // Note: No call to shuffleSlotShapes() here to keep the slots empty until the lever is pulled
}

void draw() {
  background(200);
  
  // Set the camera to be in front of the slot machine, and closer
  camera(width / 2.0, height / 2.0, (height / 2.0) / tan(PI * 30.0 / 180.0) + 300,  // Adjusted for larger view
         width / 2.0, height / 2.0, 0,
         0, 1, 0);
  
  translate(width/2, height/2, 0);
  
  // Draw the cable first so it appears behind everything else
  drawCable();
  
  // Draw the main body of the slot machine (scaled up)
  pushMatrix();
  fill(150);
  stroke(0);  // Ensure stroke color is black
  strokeWeight(2);  // Ensure the stroke for everything else is set to the original thickness
  box(400, 900, 300);  // Main body scaled up vertically
  popMatrix();
  
  // Draw the slots as 3D cubes recessed into the machine
  for (int i = 0; i < 3; i++) {
    pushMatrix();
    translate((i - 1) * 130, -100, 110);  // Position each slot (pushed back into the machine)
    fill(255);
    box(100, 300, 100);  // Draw a 3D cube representing the slot

    pushMatrix();
    translate(0, 0, 51);  // Move shapes slightly forward to be visible on the front face

    // Draw the current or final shape
    if (bool_spinning) {
      // Display a different shape for each slot during spinning
      int shapeIndex = int((float_spinframe + i * 0.33) % slotShapesImages.length);
      drawShape(shapeIndex, 0, i);
    } else {
      // Draw the final shape after spinning
      int shapeIndex;
      if (i == 0) shapeIndex = reel1;
      else if (i == 1) shapeIndex = reel2;
      else shapeIndex = reel3;

      drawShape(shapeIndex, 0, i);
    }

    popMatrix();
    popMatrix();
  }

// Handle spinning logic
if (bool_spinning) {
  // Increase the spin timer and adjust the speed
  spinTimer++;
  if (spinTimer < spinDuration) {
    float_spinframe += spinSpeed;

    // Adjust the slowdown factor to make the curve less steep
    // Reduce the rate of deceleration by using a smaller factor
    spinSpeed *= 0.99; // Instead of 0.98, using 0.99 for a less steep slowdown

    // Ensure spinSpeed doesn't get too slow
    if (spinSpeed < 0.1) {
      spinSpeed = 0.1;  // Minimum speed threshold to keep the spin relatively fast
    }
  } else {
    bool_spinning = false; // Stop spinning after the duration
    bool_reels = true; // Show final reels
    spinTimer = 0;
    spinSpeed = 0.5; // Reset the spin speed for next time
    handleActive = true; // Enable handle use again

    // Debugging: Print reel contents right after stopping
    println("Final reel1: " + reel1);
    println("Final reel2: " + reel2);
    println("Final reel3: " + reel3);

    checkWinningCondition(); // Check if the player has won
  }

  // Loop the frame counter
  if (float_spinframe >= slotShapesImages.length) {
    float_spinframe = 0;
  }
}

  // Draw and animate the handle
  pushMatrix();
  translate(225, -100, 100);  // Move handle along Z-axis behind the main body and slightly down
  
  if (bool_spin) {
    handleRotation += 0.05;  // Increase the rotation to simulate pulling down
    if (handleRotation > HALF_PI) {  // Stop at 90 degrees (HALF_PI radians)
      handleRotation = HALF_PI;
      bool_spinning = true;  // Start spinning when handle is fully down
      bool_spin = false; // Disable further clicks during spinning
      startCoinFall(); // Start coin fall when handle is pulled
    }
  } else if (!bool_spinning) {
    handleRotation -= 0.05;  // Reset the handle back to the original position
    if (handleRotation < 0) {
      handleRotation = 0;
    }
  }
  
  rotateZ(PI/4 + handleRotation);  // Rotate the handle based on the current animation state
  fill(100);
  box(30, 200, 30);  // Handle rod, scaled up
  translate(0, -100, -5);  // Position the knob
  fill(255, 0, 0);
  sphere(50);  // Handle knob, scaled up
  popMatrix();

  // Draw the display area (where "JACKPOT" is displayed, scaled up)
  pushMatrix();
  translate(0, -350, 160);
  fill(50);
  box(300, 75, 20);  // Display area, scaled up
  popMatrix();
  
  // Adjust this section to move the text lower
  pushMatrix();
  translate(0, -365, 170);  // Adjusted Y position to move the text lower
  fill(255);  // Set text color to white
  textSize(32);  // Set text size
  text("SLOT MACHINE", 0, 0);  // Display text
  popMatrix();

  // Draw the base (scaled up)
  pushMatrix();
  translate(0, 450, 0);
  fill(100);
  box(500, 75, 350);  // Base of the machine, scaled up
  popMatrix();

  // Draw the result window at the bottom
  drawResultWindow();
  
  // Draw the coin tank beside the slot machine
  drawCoinTank();
  
  // Update and display coins
  boolean allCoinsStopped = true;
  for (Coin coin : coins) {
    coin.update();
    coin.display();
    if (!coin.isStopped()) {
      allCoinsStopped = false;
    }
  }
  if (allCoinsStopped) {
    canAddCoin = true;
  }

  // Draw the button to generate coins
  drawCoinButton();
}


// Function to select a unique random shape for each slot
int selectUniqueRandomShape(int slotIndex) {
    ArrayList<Integer> availableShapes = new ArrayList<Integer>();

     // Fill the list with available shapes excluding the ones already used in other slots
    for (int i = 0; i < slotShapesImages.length; i++) {
        boolean used = false;
        for (int j = 0; j < slotIndex; j++) {
            if (currentShapes[j] == i) {
                used = true;
                break;
            }
        }
        if (!used) {
            availableShapes.add(i);
        }
    }

    // Select a random shape from the available shapes
    int selectedShape = availableShapes.get(int(random(availableShapes.size())));
    currentShapes[slotIndex] = selectedShape;  // Store the selected shape for this slot

    return selectedShape;
}

void drawShape(int shapeType, float yOffset, int slotIndex) {
  if (shapeType >= 0 && shapeType < slotShapesImages.length) {
    PImage shapeImage = slotShapesImages[shapeType];  // Get the corresponding image
    pushMatrix();
    translate(0, yOffset, 0);  // Offset position vertically
    imageMode(CENTER);
    image(shapeImage, 0, 0, 60, 60);  // Draw the shape image with consistent size
    popMatrix();
  } else {
    println("Error: Invalid shapeType value: " + shapeType);
  }
}


void drawResultWindow() {
    // Draw the result window background with the same gray as the background behind "SLOT MACHINE"
    pushMatrix();
    translate(0, 200, 200);  // Position the background box further up
    fill(70);  // Set fill color to a darker gray to match the "SLOT MACHINE" background
    stroke(0);  // Set stroke color to black
    strokeWeight(2);  // Set stroke thickness
    box(330, 180, 20);  // Result window box, slightly smaller height
    popMatrix();
  
    // Display the result text
    pushMatrix();
    translate(0, 200, 210);  // Align the text with the result window
    fill(255);  // Set text color to white
    textSize(18);  // Set text size here
    textAlign(CENTER, CENTER);
  
    if (bool_reels && !bool_spinning) {  // Ensure the text only displays after the spinning stops
        if (hasWon) {
            text("YOU WIN!", 0, -30);
        } else {
            text("YOU LOSE!", 0, -30);
        }

        // Map reel values to shape names
        String shape1 = shapeNames[reel1];
        String shape2 = shapeNames[reel2];
        String shape3 = shapeNames[reel3];
    
        // Display the shape names
        text(shape1 + " " + shape2 + " " + shape3, 0, 20);
    } else {
        text("", 0, 0);  // Clear text when not spinning
    }
  
    popMatrix();
}

void drawCoinTank() {
    pushMatrix();
    translate(coinTankX + width / 2, coinTankY + height / 2, -25);  // Position the tank
  
    // Draw the tank with the same color as the machine
    fill(150);  // Use the same gray color as the machine
    stroke(0);  // Black outline for the tank
    strokeWeight(4);  // Thicker outlines to make it look 3D
    box(coinTankWidth, coinTankHeight, 50);  // Main body of the tank
    
    // Draw the inner rectangle with darker grey color
    pushMatrix();
    translate(0, 0, 25);  // Adjust Z to ensure it's inside the tank
    fill(100);  // Darker grey color
    noStroke();  // No outline for this area
    rectMode(CENTER);
    rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Dark grey rectangle inside the tank
    popMatrix();
  
    // Draw coins with stroke effect on top of the darker grey area
    for (Coin coin : coins) {
        // Draw the actual coin with a stroke
        pushMatrix();
        translate(0, 0, 30);  // Move coins slightly forward
        coin.display();  // Draw each coin
        popMatrix();
    }

    // Create a transparent window to see the coins
    translate(0, 0, 26);  // Move the window slightly forward to appear as a transparent part of the tank
    noFill();  // Make the window transparent
    stroke(0);  // Outline for the window
    strokeWeight(2);  // Outline for the window, thinner than the tank outline
  
    // Draw the outline for the window
    rectMode(CENTER);
    rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Draw the window slightly smaller than the tank height
  
    // Add a cover to hide the unwanted parts
    fill(150);  // Use the same color as the tank
    noStroke();  // Remove strokes for a seamless look
  
    // Cover the top part
    rectMode(CORNER);
    rect(-coinTankWidth / 4, -coinTankHeight / 2.5 - coinSize, coinTankWidth / 2, coinSize * 0.5);
  
    // Cover the bottom part
    rect(-coinTankWidth / 4, coinTankHeight / 2 - coinSize * 0.5, coinTankWidth / 2, coinSize * 0.5);

    popMatrix();
}

void drawCoinButton() {
  pushMatrix();
  translate(width / 2 - 895, height / 2 - 410, 50);  // Keep the button's Z position behind the slot machine
  
  // Increase the size of the button
  float buttonWidth = 150;  // Increase width
  float buttonHeight = 75;  // Increase height
  float buttonDepth = 30;   // Increase depth

  // Increase the stroke thickness
  float buttonStrokeWeight = 4;  // Increase stroke weight

  // Draw the 3D box for the button with increased size and stroke
  fill(150);  // Gray color for the box
  stroke(0);  // Black stroke for the box
  strokeWeight(buttonStrokeWeight);  // Apply thicker stroke weight
  box(buttonWidth, buttonHeight, buttonDepth);  // Apply increased dimensions for the 3D box
  
  // Draw the "Add Coin" text on the box
  translate(0, 0, 15);  // Move the text slightly forward to appear on the front face of the box
  fill(255);  // White color for the text
  textSize(24);  // Increase text size to match larger button
  textAlign(CENTER, CENTER);
  text("Add Coin", 0, 0);  // Draw the text at the center of the box
  popMatrix();
}

class Coin {
  float x, y;
  float speedY;
  boolean stopped;

  Coin(float x, float y) {
    this.x = x;  // The initial x position of the coin
    this.y = y;  // The initial y position of the coin
    this.speedY = 5;  // Initial speed to simulate throwing
    this.stopped = false;
  }

  void update() {
    if (!stopped) {
      // Apply gravity
      speedY += gravity;
      y += speedY;

      // Adjust the resting position to be slightly lower
      if (y > height / 2 + coinTankY + coinTankHeight / 2 - coinSize * 0.75) {
        y = height / 2 + coinTankY + coinTankHeight / 2 - coinSize * 0.75;
        speedY = 0;
        stopped = true;
      }
      
      // Check for collision with the previous coin
      if (coins.size() > 1 && this != coins.get(0)) {
        Coin previousCoin = coins.get(coins.indexOf(this) - 1);
        if (y > previousCoin.y - coinSize) {
          y = previousCoin.y - coinSize;
          speedY = 0;
          stopped = true;
        }
      }
    }
  }

  void display() {
    // 1. Calculate the horizontal offset to center the coins more accurately
    float offsetX = (coinTankWidth - coinSize) / 128.0;  // Adjust this value to control how far the coins move

    // 2. Draw the black stroke (slightly larger circle)
    fill(0);  // Black color for the stroke
    ellipse(x + offsetX, y, coinSize + 4, coinSize + 4);  // Apply offset to the stroke

    // 3. Draw the yellow coin
    fill(255, 255, 0);  // Yellow color for the coin
    ellipse(x + offsetX, y, coinSize, coinSize);  // Apply the same offset to the coin
  }

  boolean isStopped() {
    return stopped;
  }
}

void mousePressed() {
    // Adjust the button click region based on the desired coordinates
    float adjustedX1 = 118;  // Move the left boundary further left
    float adjustedX2 = 255;  // Move the right boundary further right
    float adjustedY1 = 540;  // Move the top boundary further up
    float adjustedY2 = 610;  // Move the bottom boundary further down

    println("MouseX: " + mouseX + ", MouseY: " + mouseY);  // Print coordinates for debugging
    if (mouseX > adjustedX1 && mouseX < adjustedX2 && mouseY > adjustedY1 && mouseY < adjustedY2 && canAddCoin && coins.size() < maxCoins) {  
        println("Add Coin button clicked!");  // Debugging message
        // Generate a new coin at the correct position
        Coin newCoin = new Coin(width / 2 + coinTankX, height / 2 + coinTankY - coinTankHeight / 2 + coinSize / 2);
        coins.add(newCoin);
        canAddCoin = false;  // Prevent adding another coin until the current one stops
    }

    // Handle logic for lever pull
    if (dist(mouseX, mouseY, width / 2 + 225, height / 2 - 100) < 50) { 
        if (handleActive && !bool_spinning && coins.size() > 0) {  // Check if there is at least one coin
            bool_spin = true; 
            handleActive = false; // Disable handle during spinning
            shuffleSlotShapes(); // Shuffle and populate the shapes each time before spinning
            bool_reels = false; // Ensure the result text is hidden during the spin
        }
    }
}

void checkWinningCondition() {
    // Check if all three shapes match
    if (reel1 == reel2 && reel2 == reel3) {
        hasWon = true;
    } else {
        hasWon = false;
    }
}

void shuffleSlotShapes() {
    // Select a shape based on the chances
    int selectedShape = selectShapeBasedOnChance();

    // Determine if the player wins or loses (50% chance)
    boolean win = random(100) < 50;

    if (win) {
        // If the player wins, set all reels to the selected shape
        reel1 = selectedShape;
        reel2 = selectedShape;
        reel3 = selectedShape;
    } else {
        // If the player loses, select different shapes for each reel
        reel1 = selectedShape;
        reel2 = selectDifferentShape(selectedShape);
        reel3 = selectDifferentShape(reel2);
    }
}

int selectShapeBasedOnChance() {
    float rand = random(100);
    float cumulativeChance = 0;
    
    for (int i = 0; i < shapeChances.length; i++) {
        cumulativeChance += shapeChances[i];
        if (rand < cumulativeChance) {
            return i;
        }
    }
    return shapeChances.length - 1;  // Fallback in case of rounding errors
}

int selectDifferentShape(int previousShape) {
    int newShape;
    do {
        newShape = selectShapeBasedOnChance();
    } while (newShape == previousShape);
    return newShape;
}

void drawCable() {
  pushMatrix();
  pushStyle();  // Save the current stroke and fill settings

  stroke(0);  // Set base cable color to black
  strokeWeight(8);  // Base thickness of the cable
  
  // Base cable line
  float startX = coinTankX + width / 2.6 + coinTankWidth / 2;  // Right edge of the coin tank
  float startY = coinTankY + height / 2;  // Middle of the coin tank's height
  float startZ = -100;  // Move the cable farther back in 3D space
  
  float endX = -200;  // Position on the left side of the slot machine
  float endY = 100;  // Position near the base of the slot machine
  float endZ = 50;  // Make sure this is also behind the slot machine
  
  // Draw the base cable line
  line(startX, startY, startZ, endX, endY, endZ);

  // Add electricity effect
  drawElectricityEffect(startX, startY, startZ, endX, endY, endZ);

  popStyle();  // Restore the previous stroke and fill settings
  popMatrix();
}

void drawElectricityEffect(float startX, float startY, float startZ, float endX, float endY, float endZ) {
    int segments = 40;  // Increase number of segments for smoother waves
    float waveAmplitude = 15;  // Amplitude of the wave
    float waveFrequency = 0.05;  // Frequency of the wave
    float speed = millis() * 0.005;  // Speed of the wave motion over time
    stroke(173, 216, 230);  // Light blue color for the electricity (R:173, G:216, B:230)
    strokeWeight(4);  // Thinner stroke for the electricity effect
    
    float prevX = startX;
    float prevY = startY;
    float prevZ = startZ;

    for (int i = 1; i <= segments; i++) {
        float t = (float) i / segments;
        
        // Interpolate positions along the cable
        float x = lerp(startX, endX, t);
        float y = lerp(startY, endY, t);
        float z = lerp(startZ, endZ, t);
        
        // Apply sine wave to create electricity effect
        x += sin(TWO_PI * waveFrequency * i + speed) * waveAmplitude;
        y += cos(TWO_PI * waveFrequency * i + speed) * waveAmplitude;
        
        // Draw electricity wave segment
        line(prevX, prevY, prevZ, x, y, z);
        
        // Update previous position for the next segment
        prevX = x;
        prevY = y;
        prevZ = z;
    }
}

void startCoinFall() {
    if (!coins.isEmpty()) {
        // Start the falling animation from the bottom coin
        Coin bottomCoin = coins.get(0);  // Get the bottom-most coin
        bottomCoin.speedY = 5;  // Reset the speed for the bottom coin to fall
        bottomCoin.stopped = false;
        
        // Remove the bottom coin after the animation is done (i.e., it reaches the bottom of the tank)
        coins.remove(0);
        
        // Update the position of the remaining coins to make them fall in place
        for (Coin coin : coins) {
            if (coin.isStopped()) {
                coin.speedY = 5;  // Trigger the fall of the remaining coins
                coin.stopped = false;
            }
        }
    }
}

I am trying to integrate it into my main game, i created a Space Casino File which is basically just a moveable window with 3 buttons that you can open by pressing c, one of them is saying “Slot Machine” When clicked i want it to open a overlay with the slot machine on it with it’s original size and lookalike instead of the red circle (See images)

class MovableResizableSpaceCasinoWindow {
    float x, y, w, h;
    boolean dragging = false;
    boolean resizing = false;
    boolean minimized = false;
    boolean animating = false;
    boolean visible = false; // Set the visible flag to false by default
    boolean slotMachineLayerActive = false; // To track if the slot machine layer is active
    float animationProgress = 1.0;
    int animDirection = 1;
    PVector dragOffset;
    PVector resizeOffset;
    PFont font;
    BlackHoleFrenzy gameInstance;

    final float minWidth;
    final float minHeight;

    color backgroundColor = color(12, 13, 13, 130);
    color textColor = color(255, 255, 255);
    color titleBarColor = color(255, 255, 255);
    color iconColor = color(0, 0, 0); // Color for the three lines icon
    color buttonColor = color(255, 255, 255); // White color for buttons
    color buttonTextColor = color(0, 0, 0); // Black color for button text

    float iconSize = 20;
    int fadeAlpha = 0;
    int fadeInDelay = 10;
    int currentFadeDelay = 0;

    final float titleBarHeight = 30;

    MovableResizableSpaceCasinoWindow(float x, float y, float w, float h, PFont font, BlackHoleFrenzy gameInstance) {
        this.x = x;
        this.y = y;
        this.w = w + 800; // Increase the width by 800 units
        this.h = h * 3.7f; // Increase the height by 3.7 times the original height
        this.font = font;
        this.gameInstance = gameInstance;
        dragOffset = new PVector();
        resizeOffset = new PVector();
        this.minWidth = this.w; // Update the minimum width accordingly
        this.minHeight = this.h; // Update the minimum height accordingly
    }

void display() {
    if (!visible) return; // Skip drawing if not visible

    if (animating) {
        animationProgress += 0.1 * animDirection;
        animationProgress = constrain(animationProgress, 0.0, 1.0);

        if (animationProgress == 0.0) {
            animating = false;
            minimized = true;
            fadeAlpha = 0;
        } else if (animationProgress == 1.0) {
            animating = false;
            minimized = false;
            currentFadeDelay = fadeInDelay;
        }

        if (animDirection == -1) {
            fadeAlpha = 0;
        }
    }

    if (!minimized || animating) {
        float animScale = animating ? animationProgress : 1.0;
        float currentH = h * animScale;

        fill(backgroundColor);
        stroke(textColor);
        strokeWeight(2);
        rect(x, y, w, currentH);

        fill(titleBarColor);
        rect(x, y, w, titleBarHeight);

        if (currentFadeDelay == 0 && animDirection == 1 && animationProgress == 1.0) {
            fadeAlpha = min(fadeAlpha + 50, 255);
        }

        // Draw the three lines icon with black color
        fill(iconColor, fadeAlpha);
        noStroke();
        float iconOffsetY = titleBarHeight / 2 - 7;
        for (int i = 0; i < 3; i++) {
            rect(x + 10, y + iconOffsetY + i * 7, 20, 3);
        }

        textFont(font);
        textAlign(CENTER, CENTER);
        textSize(42);
        float headerX = x + w / 2; // Center horizontally
        float headerY = y + titleBarHeight + 80; // Move header further down
        fill(textColor);
        text("Space Casino", headerX, headerY);

        if (!slotMachineLayerActive) {
            // Display the buttons in the center of the window if slot machine layer is not active
            displayButtons();
        } else {
            // If the slot machine layer is active, fill the screen with a new layer
            fill(0, 100); // Semi-transparent black background
            rect(x, y, w, currentH);

            // You can add more UI elements for the slot machine here
            textSize(32);
            fill(255);
            text("Slot Machine Layer Active", headerX, headerY + 100);

            // Draw the red circle
            fill(255, 0, 0); // Red color
            noStroke();
            ellipse(x + w / 2, y + currentH / 2, 50, 50); // Draw the circle at the center of the slot machine layer
        }
    } else {
        fill(titleBarColor);
        stroke(textColor);
        strokeWeight(2);
        rect(x, y, 40, titleBarHeight);

        // Draw the three lines icon with black color
        fill(iconColor);
        noStroke();
        float iconOffsetY = titleBarHeight / 2 - 7;
        for (int i = 0; i < 3; i++) {
            rect(x + 10, y + iconOffsetY + i * 7, 20, 3);
        }
    }

    if (currentFadeDelay > 0) {
        currentFadeDelay--;
    }
}

    void displayButtons() {
        float buttonWidth = 300;
        float buttonHeight = 60;
        float spacing = 40;
        float centerX = x + w / 2;
        float startY = y + h / 2 - (buttonHeight * 3 + spacing * 2) / 2;

        // Draw each button and check for hover
        drawButton("Wheel Of Fortune", centerX, startY, buttonWidth, buttonHeight);
        drawButton("Slot Machine", centerX, startY + buttonHeight + spacing, buttonWidth, buttonHeight);
        drawButton("Mind Games", centerX, startY + 2 * (buttonHeight + spacing), buttonWidth, buttonHeight);
    }

    void drawButton(String label, float cx, float cy, float bw, float bh) {
        float x1 = cx - bw / 2;
        float y1 = cy - bh / 2;

        boolean isHovering = overRect(x1, y1, bw, bh);
        fill(buttonColor);
        stroke(textColor);
        strokeWeight(2);
        rect(x1, y1, bw, bh, 10); // Rounded corners

        fill(buttonTextColor);
        textFont(font);
        textAlign(CENTER, CENTER);
        textSize(28); // Adjust text size to fit the button
        text(label, cx, cy);

        // Check if the button is clicked
        if (isHovering && mousePressed && label.equals("Slot Machine")) {
            slotMachineLayerActive = true;
        }
    }

    boolean overRect(float x, float y, float w, float h) {
        return mouseX > x && mouseX < x + w && mouseY > y && mouseY < y + h;
    }

    void startDragging(float mx, float my) {
        if (overTitleBar(mx, my)) {
            dragging = true;
            dragOffset.set(mx - x, my - y);
        }
    }

    void stopDragging() {
        dragging = false;
    }

    void update(float mx, float my) {
        if (dragging) {
            x = mx - dragOffset.x;
            y = my - dragOffset.y;
            x = constrain(x, 0, width - w);
            y = constrain(y, 0, height - h);
        }
    }

    boolean overTitleBar(float mx, float my) {
        return mx > x && mx < x + w && my > y && my < y + titleBarHeight;
    }

    boolean overWindow(float mx, float my) {
        return mx > x && mx < x + w && my > y && my < y + h;
    }

    void toggleVisibility() {
        visible = !visible;
    }

    void handleKeyPressed() {
        if (key == 'C' || key == 'c') {
            toggleVisibility();
        }
    }
}

The main problem is i don’t know how to embed the slot machine into the overlay instead of the red circle, every time i tried it completely messed up the sizing and it looked really visually glitched, instead of just “copy pasting” it into the window as it is now without having any visual difference or a change in functionality

1 Like

The following is one technique that could be used to open your slot machine sketch inside of another sketch. This demo requires that you have ‘processing-java’ installed, which is a command line app: https://github.com/processing/processing/wiki/Command-Line. You can then use Processing’s exec() to run your sketch by supplying the sketch’s folder location. I used macos to design and run this demo.

import java.io.*;

int _wndW = 400;
int _wndH = 300;

Process proc = null;

void setup() {
  size(_wndW, _wndH);
  surface.setTitle("Space Casino");
  background(0);
  stroke(0);
  strokeWeight(3.0);
}

void draw() {
  fill(0, 255, 0);
  rect(100, 100, 150, 30, 15);
  fill(0);
  textSize(18.0);
  textAlign(CENTER, CENTER);
  text("Run sketch", 100, 98, 150, 30);
}

void mousePressed() {
  if ((mouseX >= 100) && (mouseX <= 100 + 150) && (mouseY >= 100) && (mouseY <= 100 + 30)) {
    try {
      proc = exec("/usr/local/bin/processing-java", "--sketch=/Users/yourName/Documents/Processing/SpaceCasinoSlotMachine", "--run");

      BufferedReader out = new BufferedReader(new InputStreamReader(proc.getInputStream()));
      BufferedReader err = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
      String s = null;
      while ((s = out.readLine()) != null) {
        println(s);
      }
      while ((s = err.readLine()) != null) {
        println(s);
      }
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

1 Like

Am I missing something, can’t you just create a PGraphics that has your slot machine in… and then show/hide that slotmachine based on whether the button is clicked?

3 Likes

One solution is a program with states.

The program can be in different states. Like water can be ice, water or steam.

The state variable can indicate the state, it’s an integer variable.

It indicates whether you want to show screen a or screen b or screen c.

So essentially merge the two Sketches using an if-clause in draw() to distinguish the two states:

// eval "state"
if(state==0){
    .... Sketch 1
} else if(state==1){
    .... Sketch 2
}

(you can also use switch(state){ of course)

(When you merge the two Sketches you can only have one setup() and one draw() etc.)

When you want to change the state, say state = 0; or state = 1;.

Warm regards,

Chrisir

3 Likes

There’s quite a bit of animation of the slot machine when the handle is hit or a coin is dropped. Is that a problem to reproduce with a PGraphic?

1 Like

Thanks but when i try to do that i get some stange defects i don’t know how to handle, i don’t know why is it so complicated for me to just take one application and embed it into another probably something i’m missing


r

same as the comment above

and @Chrisir thanks ill dig in to that and update

1 Like

You came a lot closer than I thought you would. Could be a matter of where you locate the image, ie, image(graphic,x,y). Try relocating by changing the x,y coordinates. Also you may not have created the initial graphic large enough eg, createGraphics(width, height) where width and height are too small. What about the animation? Does that work? I’d love to see the code that you used to get the PGraphic; any way to post?

1 Like

Thanks so much for the fast response!
i tried and i get this

SlotMachine.pde

class SlotMachine {

    // Global variables specific to the slot machine
    ArrayList<Coin> coins = new ArrayList<Coin>();  // List to store the coins
    float gravity = 0.5;  // Gravity effect on the coins
    float coinSize = 40;  // Size of each coin (increased)
    float coinTankX = -900;  // Move the coin tank further to the left
    float coinTankY = -100;   // Position the coin tank higher up
    float coinTankWidth = 100; // Adjusted width of the coin tank (thinner)
    float coinTankHeight = 400; // Height of the coin tank

    PFont font1;
    boolean bool_spin; // the lever has been pulled
    boolean bool_spinning; // the machine is spinning
    int spinframe;
    int time;

    boolean bool_reels; // to display the reels after it has spun
    int reel1 = -1; // Slot 1
    int reel2 = -1; // Slot 2
    int reel3 = -1; // Slot 3

    float float_spinframe; // to calculate how fast to switch the shapes
    int[] currentShapes = {0, 0, 0}; // Track current shape index for each slot
    float spinSpeed = 0.5; // Initial speed for spinning
    int spinDuration = 360; // Total duration of spinning (6 seconds at 60 fps)
    int spinTimer = 0; // Timer to track spinning time

    // Variables for custom shapes
    PImage meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic;
    PImage[] slotShapesImages;
    float[] shapeChances = {
        30.0,  // meteor.png (30% chance)
        25.0,  // rainbowstar.png (25% chance)
        18.0,  // datagemstar.png (18% chance)
        12.0,  // dwarvengold.png (12% chance)
        8.0,   // alienruby.png (8% chance)
        5.0,   // polyhedron.png (5% chance)
        2.0    // geodesic.png (2% chance)
    };

    String[] shapeNames = {
        "Meteor", "RainbowStar", "DataGemStar", "DwarvenGold", "AlienRuby", "Polyhedron", "Geodesic"
    };

    float handleRotation = 0; // Add this variable to control handle rotation

    boolean handleActive = true;  // Track if handle can be used
    boolean hasWon = false;  // Track winning status

    boolean canAddCoin = true;  // Track if a new coin can be added
    int maxCoins = 9;  // Maximum number of coins allowed in the tank

    // Constructor
    SlotMachine() {
        setupSlotMachine();
    }

    // Setup method for slot machine
    void setupSlotMachine() {
        stroke(0);  // Set stroke color to black
        strokeWeight(2);  // Set stroke thickness for everything else

        // Initialize the font
        font1 = createFont("Times New Roman", 30); 
        textFont(font1);
        textAlign(CENTER, CENTER); 

        // Load images
        meteor = loadImage("meteor.png");
        rainbowstar = loadImage("rainbowstar.png");
        datagemstar = loadImage("datagemstar.png");
        dwarvengold = loadImage("dwarvengold.png");
        alienruby = loadImage("alienruby.png");
        polyhedron = loadImage("polyhedron.png");
        geodesic = loadImage("geodesic.png");

        // Add the images to the array
        slotShapesImages = new PImage[]{meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic};
    }

    // Draw method for slot machine with PGraphics parameter
    void drawSlotMachine(PGraphics pg) {
        pg.beginDraw();
        pg.background(200);

        // Set the camera to be in front of the slot machine, and closer
        pg.camera(pg.width / 2.0, pg.height / 2.0, (pg.height / 2.0) / tan(PI * 30.0 / 180.0) + 300,
            pg.width / 2.0, pg.height / 2.0, 0,
            0, 1, 0);

        pg.translate(pg.width / 2, pg.height / 2, 0);

        // Draw the cable first so it appears behind everything else
        drawCable(pg);

        // Draw the main body of the slot machine (scaled up)
        pg.pushMatrix();
        pg.fill(150);
        pg.stroke(0);  // Ensure stroke color is black
        pg.strokeWeight(2);  // Ensure the stroke for everything else is set to the original thickness
        pg.box(400, 900, 300);  // Main body scaled up vertically
        pg.popMatrix();

        // Draw the slots as 3D cubes recessed into the machine
        for (int i = 0; i < 3; i++) {
            pg.pushMatrix();
            pg.translate((i - 1) * 130, -100, 110);  // Position each slot (pushed back into the machine)
            pg.fill(255);
            pg.box(100, 300, 100);  // Draw a 3D cube representing the slot

            pg.pushMatrix();
            pg.translate(0, 0, 51);  // Move shapes slightly forward to be visible on the front face

            // Draw the current or final shape
            if (bool_spinning) {
                // Display a different shape for each slot during spinning
                int shapeIndex = int((float_spinframe + i * 0.33) % slotShapesImages.length);
                drawShape(pg, shapeIndex, 0, i);
            } else {
                // Draw the final shape after spinning
                int shapeIndex;
                if (i == 0) shapeIndex = reel1;
                else if (i == 1) shapeIndex = reel2;
                else shapeIndex = reel3;

                drawShape(pg, shapeIndex, 0, i);
            }

            pg.popMatrix();
            pg.popMatrix();
        }

        // Handle spinning logic
        if (bool_spinning) {
            // Increase the spin timer and adjust the speed
            spinTimer++;
            if (spinTimer < spinDuration) {
                float_spinframe += spinSpeed;

                // Adjust the slowdown factor to make the curve less steep
                // Reduce the rate of deceleration by using a smaller factor
                spinSpeed *= 0.99; // Instead of 0.98, using 0.99 for a less steep slowdown

                // Ensure spinSpeed doesn't get too slow
                if (spinSpeed < 0.1) {
                    spinSpeed = 0.1;  // Minimum speed threshold to keep the spin relatively fast
                }
            } else {
                bool_spinning = false; // Stop spinning after the duration
                bool_reels = true; // Show final reels
                spinTimer = 0;
                spinSpeed = 0.5; // Reset the spin speed for next time
                handleActive = true; // Enable handle use again

                // Debugging: Print reel contents right after stopping
                println("Final reel1: " + reel1);
                println("Final reel2: " + reel2);
                println("Final reel3: " + reel3);

                checkWinningCondition(); // Check if the player has won
            }

            // Loop the frame counter
            if (float_spinframe >= slotShapesImages.length) {
                float_spinframe = 0;
            }
        }

        // Draw and animate the handle
        pg.pushMatrix();
        pg.translate(225, -100, 100);  // Move handle along Z-axis behind the main body and slightly down

        if (bool_spin) {
            handleRotation += 0.05;  // Increase the rotation to simulate pulling down
            if (handleRotation > HALF_PI) {  // Stop at 90 degrees (HALF_PI radians)
                handleRotation = HALF_PI;
                bool_spinning = true;  // Start spinning when handle is fully down
                bool_spin = false; // Disable further clicks during spinning
                startCoinFall(); // Start coin fall when handle is pulled
            }
        } else if (!bool_spinning) {
            handleRotation -= 0.05;  // Reset the handle back to the original position
            if (handleRotation < 0) {
                handleRotation = 0;
            }
        }

        pg.rotateZ(PI / 4 + handleRotation);  // Rotate the handle based on the current animation state
        pg.fill(100);
        pg.box(30, 200, 30);  // Handle rod, scaled up
        pg.translate(0, -100, -5);  // Position the knob
        pg.fill(255, 0, 0);
        pg.sphere(50);  // Handle knob, scaled up
        pg.popMatrix();

        // Draw the display area (where "JACKPOT" is displayed, scaled up)
        pg.pushMatrix();
        pg.translate(0, -350, 160);
        pg.fill(50);
        pg.box(300, 75, 20);  // Display area, scaled up
        pg.popMatrix();

        // Adjust this section to move the text lower
        pg.pushMatrix();
        pg.translate(0, -365, 170);  // Adjusted Y position to move the text lower
        pg.fill(255);  // Set text color to white
        pg.textSize(32);  // Set text size
        pg.text("SLOT MACHINE", 0, 0);  // Display text
        pg.popMatrix();

        // Draw the base (scaled up)
        pg.pushMatrix();
        pg.translate(0, 450, 0);
        pg.fill(100);
        pg.box(500, 75, 350);  // Base of the machine, scaled up
        pg.popMatrix();

        // Draw the result window at the bottom
        drawResultWindow(pg);

        // Draw the coin tank beside the slot machine
        drawCoinTank(pg);

        // Update and display coins
        boolean allCoinsStopped = true;
        for (Coin coin : coins) {
            coin.update();
            coin.display(pg);
            if (!coin.isStopped()) {
                allCoinsStopped = false;
            }
        }
        if (allCoinsStopped) {
            canAddCoin = true;
        }

        // Draw the button to generate coins
        drawCoinButton(pg);
        pg.endDraw();
    }

    // Function to select a unique random shape for each slot
    int selectUniqueRandomShape(int slotIndex) {
        ArrayList<Integer> availableShapes = new ArrayList<Integer>();

        // Fill the list with available shapes excluding the ones already used in other slots
        for (int i = 0; i < slotShapesImages.length; i++) {
            boolean used = false;
            for (int j = 0; j < slotIndex; j++) {
                if (currentShapes[j] == i) {
                    used = true;
                    break;
                }
            }
            if (!used) {
                availableShapes.add(i);
            }
        }

        // Select a random shape from the available shapes
        int selectedShape = availableShapes.get(int(random(availableShapes.size())));
        currentShapes[slotIndex] = selectedShape;  // Store the selected shape for this slot

        return selectedShape;
    }

    void drawShape(PGraphics pg, int shapeType, float yOffset, int slotIndex) {
        if (shapeType >= 0 && shapeType < slotShapesImages.length) {
            PImage shapeImage = slotShapesImages[shapeType];  // Get the corresponding image
            pg.pushMatrix();
            pg.translate(0, yOffset, 0);  // Offset position vertically
            pg.imageMode(CENTER);
            pg.image(shapeImage, 0, 0, 60, 60);  // Draw the shape image with consistent size
            pg.popMatrix();
        } else {
            println("Error: Invalid shapeType value: " + shapeType);
        }
    }

    void drawResultWindow(PGraphics pg) {
        // Draw the result window background with the same gray as the background behind "SLOT MACHINE"
        pg.pushMatrix();
        pg.translate(0, 200, 200);  // Position the background box further up
        pg.fill(70);  // Set fill color to a darker gray to match the "SLOT MACHINE" background
        pg.stroke(0);  // Set stroke color to black
        pg.strokeWeight(2);  // Set stroke thickness
        pg.box(330, 180, 20);  // Result window box, slightly smaller height
        pg.popMatrix();

        // Display the result text
        pg.pushMatrix();
        pg.translate(0, 200, 210);  // Align the text with the result window
        pg.fill(255);  // Set text color to white
        pg.textSize(18);  // Set text size here
        pg.textAlign(CENTER, CENTER);

        if (bool_reels && !bool_spinning) {  // Ensure the text only displays after the spinning stops
            if (hasWon) {
                pg.text("YOU WIN!", 0, -30);
            } else {
                pg.text("YOU LOSE!", 0, -30);
            }

            // Map reel values to shape names
            String shape1 = shapeNames[reel1];
            String shape2 = shapeNames[reel2];
            String shape3 = shapeNames[reel3];

            // Display the shape names
            pg.text(shape1 + " " + shape2 + " " + shape3, 0, 20);
        } else {
            pg.text("", 0, 0);  // Clear text when not spinning
        }

        pg.popMatrix();
    }

    void drawCoinTank(PGraphics pg) {
        pg.pushMatrix();
        pg.translate(coinTankX + pg.width / 2, coinTankY + pg.height / 2, -25);  // Position the tank

        // Draw the tank with the same color as the machine
        pg.fill(150);  // Use the same gray color as the machine
        pg.stroke(0);  // Black outline for the tank
        pg.strokeWeight(4);  // Thicker outlines to make it look 3D
        pg.box(coinTankWidth, coinTankHeight, 50);  // Main body of the tank

        // Draw the inner rectangle with darker grey color
        pg.pushMatrix();
        pg.translate(0, 0, 25);  // Adjust Z to ensure it's inside the tank
        pg.fill(100);  // Darker grey color
        pg.noStroke();  // No outline for this area
        pg.rectMode(CENTER);
        pg.rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Dark grey rectangle inside the tank
        pg.popMatrix();

        // Draw coins with stroke effect on top of the darker grey area
        for (Coin coin : coins) {
            // Draw the actual coin with a stroke
            pg.pushMatrix();
            pg.translate(0, 0, 30);  // Move coins slightly forward
            coin.display(pg);  // Draw each coin
            pg.popMatrix();
        }

        // Create a transparent window to see the coins
        pg.translate(0, 0, 26);  // Move the window slightly forward to appear as a transparent part of the tank
        pg.noFill();  // Make the window transparent
        pg.stroke(0);  // Outline for the window
        pg.strokeWeight(2);  // Outline for the window, thinner than the tank outline

        // Draw the outline for the window
        pg.rectMode(CENTER);
        pg.rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Draw the window slightly smaller than the tank height

        // Add a cover to hide the unwanted parts
        pg.fill(150);  // Use the same color as the tank
        pg.noStroke();  // Remove strokes for a seamless look

        // Cover the top part
        pg.rectMode(CORNER);
        pg.rect(-coinTankWidth / 4, -coinTankHeight / 2.5 - coinSize, coinTankWidth / 2, coinSize * 0.5);

        // Cover the bottom part
        pg.rect(-coinTankWidth / 4, coinTankHeight / 2 - coinSize * 0.5, coinTankWidth / 2, coinSize * 0.5);

        pg.popMatrix();
    }

    void drawCoinButton(PGraphics pg) {
        pg.pushMatrix();
        pg.translate(pg.width / 2 - 895, pg.height / 2 - 410, 50);  // Keep the button's Z position behind the slot machine

        // Increase the size of the button
        float buttonWidth = 150;  // Increase width
        float buttonHeight = 75;  // Increase height
        float buttonDepth = 30;   // Increase depth

        // Increase the stroke thickness
        float buttonStrokeWeight = 4;  // Increase stroke weight

        // Draw the 3D box for the button with increased size and stroke
        pg.fill(150);  // Gray color for the box
        pg.stroke(0);  // Black stroke for the box
        pg.strokeWeight(buttonStrokeWeight);  // Apply thicker stroke weight
        pg.box(buttonWidth, buttonHeight, buttonDepth);  // Apply increased dimensions for the 3D box

        // Draw the "Add Coin" text on the box
        pg.translate(0, 0, 15);  // Move the text slightly forward to appear on the front face of the box
        pg.fill(255);  // White color for the text
        pg.textSize(24);  // Increase text size to match larger button
        pg.textAlign(CENTER, CENTER);
        pg.text("Add Coin", 0, 0);  // Draw the text at the center of the box
        pg.popMatrix();
    }

    class Coin {
        float x, y;
        float speedY;
        boolean stopped;

        Coin(float x, float y) {
            this.x = x;  // The initial x position of the coin
            this.y = y;  // The initial y position of the coin
            this.speedY = 5;  // Initial speed to simulate throwing
            this.stopped = false;
        }

        void update() {
            if (!stopped) {
                // Apply gravity
                speedY += gravity;
                y += speedY;

                // Adjust the resting position to be slightly lower
                if (y > height / 2 + coinTankY + coinTankHeight / 2 - coinSize * 0.75) {
                    y = height / 2 + coinTankY + coinTankHeight / 2 - coinSize * 0.75;
                    speedY = 0;
                    stopped = true;
                }

                // Check for collision with the previous coin
                if (coins.size() > 1 && this != coins.get(0)) {
                    Coin previousCoin = coins.get(coins.indexOf(this) - 1);
                    if (y > previousCoin.y - coinSize) {
                        y = previousCoin.y - coinSize;
                        speedY = 0;
                        stopped = true;
                    }
                }
            }
        }

        void display(PGraphics pg) {
            // 1. Calculate the horizontal offset to center the coins more accurately
            float offsetX = (coinTankWidth - coinSize) / 128.0;  // Adjust this value to control how far the coins move

            // 2. Draw the black stroke (slightly larger circle)
            pg.fill(0);  // Black color for the stroke
            pg.ellipse(x + offsetX, y, coinSize + 4, coinSize + 4);  // Apply offset to the stroke

            // 3. Draw the yellow coin
            pg.fill(255, 255, 0);  // Yellow color for the coin
            pg.ellipse(x + offsetX, y, coinSize, coinSize);  // Apply the same offset to the coin
        }

        boolean isStopped() {
            return stopped;
        }
    }

    // Handle mouse press events for slot machine
    void mousePressedSlotMachine() {
        // Adjust the button click region based on the desired coordinates
        float adjustedX1 = 118;  // Move the left boundary further left
        float adjustedX2 = 255;  // Move the right boundary further right
        float adjustedY1 = 540;  // Move the top boundary further up
        float adjustedY2 = 610;  // Move the bottom boundary further down

        println("MouseX: " + mouseX + ", MouseY: " + mouseY);  // Print coordinates for debugging
        if (mouseX > adjustedX1 && mouseX < adjustedX2 && mouseY > adjustedY1 && mouseY < adjustedY2 && canAddCoin && coins.size() < maxCoins) {  
            println("Add Coin button clicked!");  // Debugging message
            // Generate a new coin at the correct position
            Coin newCoin = new Coin(width / 2 + coinTankX, height / 2 + coinTankY - coinTankHeight / 2 + coinSize / 2);
            coins.add(newCoin);
            canAddCoin = false;  // Prevent adding another coin until the current one stops
        }

        // Handle logic for lever pull
        if (dist(mouseX, mouseY, width / 2 + 225, height / 2 - 100) < 50) { 
            if (handleActive && !bool_spinning && coins.size() > 0) {  // Check if there is at least one coin
                bool_spin = true; 
                handleActive = false; // Disable handle during spinning
                shuffleSlotShapes(); // Shuffle and populate the shapes each time before spinning
                bool_reels = false; // Ensure the result text is hidden during the spin
            }
        }
    }

    void checkWinningCondition() {
        // Check if all three shapes match
        if (reel1 == reel2 && reel2 == reel3) {
            hasWon = true;
        } else {
            hasWon = false;
        }
    }

    void shuffleSlotShapes() {
        // Select a shape based on the chances
        int selectedShape = selectShapeBasedOnChance();

        // Determine if the player wins or loses (50% chance)
        boolean win = random(100) < 50;

        if (win) {
            // If the player wins, set all reels to the selected shape
            reel1 = selectedShape;
            reel2 = selectedShape;
            reel3 = selectedShape;
        } else {
            // If the player loses, select different shapes for each reel
            reel1 = selectedShape;
            reel2 = selectDifferentShape(selectedShape);
            reel3 = selectDifferentShape(reel2);
        }
    }

    int selectShapeBasedOnChance() {
        float rand = random(100);
        float cumulativeChance = 0;

        for (int i = 0; i < shapeChances.length; i++) {
            cumulativeChance += shapeChances[i];
            if (rand < cumulativeChance) {
                return i;
            }
        }
        return shapeChances.length - 1;  // Fallback in case of rounding errors
    }

    int selectDifferentShape(int previousShape) {
        int newShape;
        do {
            newShape = selectShapeBasedOnChance();
        } while (newShape == previousShape);
        return newShape;
    }

    void drawCable(PGraphics pg) {
        pg.pushMatrix();
        pg.pushStyle();  // Save the current stroke and fill settings

        pg.stroke(0);  // Set base cable color to black
        pg.strokeWeight(8);  // Base thickness of the cable

        // Base cable line
        float startX = coinTankX + pg.width / 2.6 + coinTankWidth / 2;  // Right edge of the coin tank
        float startY = coinTankY + pg.height / 2;  // Middle of the coin tank's height
        float startZ = -100;  // Move the cable farther back in 3D space

        float endX = -200;  // Position on the left side of the slot machine
        float endY = 100;  // Position near the base of the slot machine
        float endZ = 50;  // Make sure this is also behind the slot machine

        // Draw the base cable line
        pg.line(startX, startY, startZ, endX, endY, endZ);

        // Add electricity effect
        drawElectricityEffect(pg, startX, startY, startZ, endX, endY, endZ);

        pg.popStyle();  // Restore the previous stroke and fill settings
        pg.popMatrix();
    }

    void drawElectricityEffect(PGraphics pg, float startX, float startY, float startZ, float endX, float endY, float endZ) {
        int segments = 40;  // Increase number of segments for smoother waves
        float waveAmplitude = 15;  // Amplitude of the wave
        float waveFrequency = 0.05;  // Frequency of the wave
        float speed = millis() * 0.005;  // Speed of the wave motion over time
        pg.stroke(173, 216, 230);  // Light blue color for the electricity (R:173, G:216, B:230)
        pg.strokeWeight(4);  // Thinner stroke for the electricity effect

        float prevX = startX;
        float prevY = startY;
        float prevZ = startZ;

        for (int i = 1; i <= segments; i++) {
            float t = (float) i / segments;

            // Interpolate positions along the cable
            float x = lerp(startX, endX, t);
            float y = lerp(startY, endY, t);
            float z = lerp(startZ, endZ, t);

            // Apply sine wave to create electricity effect
            x += sin(TWO_PI * waveFrequency * i + speed) * waveAmplitude;
            y += cos(TWO_PI * waveFrequency * i + speed) * waveAmplitude;

            // Draw electricity wave segment
            pg.line(prevX, prevY, prevZ, x, y, z);

            // Update previous position for the next segment
            prevX = x;
            prevY = y;
            prevZ = z;
        }
    }

    void startCoinFall() {
        if (!coins.isEmpty()) {
            // Start the falling animation from the bottom coin
            Coin bottomCoin = coins.get(0);  // Get the bottom-most coin
            bottomCoin.speedY = 5;  // Reset the speed for the bottom coin to fall
            bottomCoin.stopped = false;

            // Remove the bottom coin after the animation is done (i.e., it reaches the bottom of the tank)
            coins.remove(0);

            // Update the position of the remaining coins to make them fall in place
            for (Coin coin : coins) {
                if (coin.isStopped()) {
                    coin.speedY = 5;  // Trigger the fall of the remaining coins
                    coin.stopped = false;
                }
            }
        }
    }
}
class MovableResizableSpaceCasinoWindow {
    float x, y, w, h;
    boolean dragging = false;
    boolean resizing = false;
    boolean minimized = false;
    boolean animating = false;
    boolean visible = false; // Set the visible flag to false by default
    boolean slotMachineLayerActive = false; // To track if the slot machine layer is active
    float animationProgress = 1.0;
    int animDirection = 1;
    PVector dragOffset;
    PVector resizeOffset;
    PFont font;
    BlackHoleFrenzy gameInstance;

    final float minWidth;
    final float minHeight;

    color backgroundColor = color(12, 13, 13, 130);
    color textColor = color(255, 255, 255);
    color titleBarColor = color(255, 255, 255);
    color iconColor = color(0, 0, 0); // Color for the three lines icon
    color buttonColor = color(255, 255, 255); // White color for buttons
    color buttonTextColor = color(0, 0, 0); // Black color for button text

    float iconSize = 20;
    int fadeAlpha = 0;
    int fadeInDelay = 10;
    int currentFadeDelay = 0;

    final float titleBarHeight = 30;

    // Slot Machine rendering
    PGraphics slotMachineGraphics;
    boolean slotMachineVisible = false;

    // Constructor
    MovableResizableSpaceCasinoWindow(float x, float y, float w, float h, PFont font, BlackHoleFrenzy gameInstance, PGraphics slotMachineGraphics) {
        this.x = x;
        this.y = y;
        this.w = w + 800; // Increase the width by 800 units
        this.h = h * 3.7f; // Increase the height by 3.7 times the original height
        this.font = font;
        this.gameInstance = gameInstance;
        this.slotMachineGraphics = slotMachineGraphics; // Use the provided PGraphics for slot machine rendering
        dragOffset = new PVector();
        resizeOffset = new PVector();
        this.minWidth = this.w; // Update the minimum width accordingly
        this.minHeight = this.h; // Update the minimum height accordingly
    }

    void display() {
        if (!visible) return; // Skip drawing if not visible

        if (animating) {
            animationProgress += 0.1 * animDirection;
            animationProgress = constrain(animationProgress, 0.0, 1.0);

            if (animationProgress == 0.0) {
                animating = false;
                minimized = true;
                fadeAlpha = 0;
            } else if (animationProgress == 1.0) {
                animating = false;
                minimized = false;
                currentFadeDelay = fadeInDelay;
            }

            if (animDirection == -1) {
                fadeAlpha = 0;
            }
        }

        if (!minimized || animating) {
            float animScale = animating ? animationProgress : 1.0;
            float currentH = h * animScale;

            fill(backgroundColor);
            stroke(textColor);
            strokeWeight(2);
            rect(x, y, w, currentH);

            fill(titleBarColor);
            rect(x, y, w, titleBarHeight);

            if (currentFadeDelay == 0 && animDirection == 1 && animationProgress == 1.0) {
                fadeAlpha = min(fadeAlpha + 50, 255);
            }

            // Draw the three lines icon with black color
            fill(iconColor, fadeAlpha);
            noStroke();
            float iconOffsetY = titleBarHeight / 2 - 7;
            for (int i = 0; i < 3; i++) {
                rect(x + 10, y + iconOffsetY + i * 7, 20, 3);
            }

            textFont(font);
            textAlign(CENTER, CENTER);
            textSize(42);
            float headerX = x + w / 2; // Center horizontally
            float headerY = y + titleBarHeight + 80; // Move header further down
            fill(textColor);
            text("Space Casino", headerX, headerY);

            if (slotMachineLayerActive) {
                // Render the slot machine graphics
                renderSlotMachineGraphics();

                // Display the slot machine graphics
                image(slotMachineGraphics, x, y, w, h);
            } else {
                // Display the buttons in the center of the window if slot machine layer is not active
                displayButtons();
            }
        } else {
            fill(titleBarColor);
            stroke(textColor);
            strokeWeight(2);
            rect(x, y, 40, titleBarHeight);

            // Draw the three lines icon with black color
            fill(iconColor);
            noStroke();
            float iconOffsetY = titleBarHeight / 2 - 7;
            for (int i = 0; i < 3; i++) {
                rect(x + 10, y + iconOffsetY + i * 7, 20, 3);
            }
        }

        if (currentFadeDelay > 0) {
            currentFadeDelay--;
        }
    }

    void displayButtons() {
        float buttonWidth = 300;
        float buttonHeight = 60;
        float spacing = 40;
        float centerX = x + w / 2;
        float startY = y + h / 2 - (buttonHeight * 3 + spacing * 2) / 2;

        // Draw each button and check for hover
        drawButton("Wheel Of Fortune", centerX, startY, buttonWidth, buttonHeight);
        drawButton("Slot Machine", centerX, startY + buttonHeight + spacing, buttonWidth, buttonHeight);
        drawButton("Mind Games", centerX, startY + 2 * (buttonHeight + spacing), buttonWidth, buttonHeight);
    }

    void drawButton(String label, float cx, float cy, float bw, float bh) {
        float x1 = cx - bw / 2;
        float y1 = cy - bh / 2;

        boolean isHovering = overRect(x1, y1, bw, bh);
        fill(buttonColor);
        stroke(textColor);
        strokeWeight(2);
        rect(x1, y1, bw, bh, 10); // Rounded corners

        fill(buttonTextColor);
        textFont(font);
        textAlign(CENTER, CENTER);
        textSize(28); // Adjust text size to fit the button
        text(label, cx, cy);

        // Check if the button is clicked
        if (isHovering && mousePressed && label.equals("Slot Machine")) {
            slotMachineLayerActive = true;
            slotMachineVisible = true;
        }
    }

    void renderSlotMachineGraphics() {
        slotMachineGraphics.beginDraw();
        slotMachineGraphics.background(0, 100); // Semi-transparent black background

        // Render the slot machine on the PGraphics
        gameInstance.slotMachine.drawSlotMachine(slotMachineGraphics);

        slotMachineGraphics.endDraw();
    }

    boolean overRect(float x, float y, float w, float h) {
        return mouseX > x && mouseX < x + w && mouseY > y && mouseY < y + h;
    }

    void startDragging(float mx, float my) {
        if (overTitleBar(mx, my)) {
            dragging = true;
            dragOffset.set(mx - x, my - y);
        }
    }

    void stopDragging() {
        dragging = false;
    }

    void update(float mx, float my) {
        if (dragging) {
            x = mx - dragOffset.x;
            y = my - dragOffset.y;
            x = constrain(x, 0, width - w);
            y = constrain(y, 0, height - h);
        }
    }

    boolean overTitleBar(float mx, float my) {
        return mx > x && mx < x + w && my > y && my < y + titleBarHeight;
    }

    boolean overWindow(float mx, float my) {
        return mx > x && mx < x + w && my > y && my < y + h;
    }

    void toggleVisibility() {
        visible = !visible;
    }

    void handleKeyPressed() {
        if (key == 'C' || key == 'c') {
            toggleVisibility();
        }
    }
}

and i had to send some of my message here because it was too long

https://justpaste.it/fla02

@svan

another quick update

even if i use this size

slotMachineGraphics = createGraphics(4200, 4200, P3D); // Increase the height of the slot machine graphics context

compared to the original 1000, 1000

it doesn’t change the size of the window and i don’t know why…

stuck like that

Boy that is a lot of code. I was looking for just the code where you created the PGraphic. I successfully scaled down your original SlotMachine code but it was still in the P3D renderer window (two separate apps). Unfortunately there is not a lot that can be done with a GLWindow as far as changing the canvas size (at least as far as I have discovered). One of my ideas was to reduce the canvas size and put buttons at the top to change from one scene to the other, but not being able to add buttons to a GLWindow negated that idea. How badly do you need 3 dimensions? It would be a lot easier with the default renderer and a JFrame. I think @Chrisir’s approach could work if you could get everything in one window, but there are a lot of code lines to stuff into one window; you’d probably have to use multiple tabs in the editor. I can show you how I rescaled your original slot machine if you think you could use it; it’s not too difficult. Just add scale(0.75) in the right place and change the translation a little; I got it into a 600x600 window. Also had to change the mousePressed() coordinates to accommodate the smaller size after first mapping the coin box and slot machine handle.

SlotMachine_rev1:

ArrayList<Coin> coins = new ArrayList<Coin>();  // List to store the coins

float gravity = 0.5;  // Gravity effect on the coins
float coinSize = 40;  // Size of each coin (increased)
float coinTankX = -900;  // Move the coin tank further to the left
float coinTankY = -100;   // Position the coin tank higher up
float coinTankWidth = 100; // Adjusted width of the coin tank (thinner)
float coinTankHeight = 400; // Height of the coin tank

PFont font1;
boolean bool_spin; // the lever has been pulled
boolean bool_spinning; // the machine is spinning
int spinframe;
int time;

boolean bool_reels; // to display the reels after it has spun
int reel1 = -1; // Slot 1
int reel2 = -1; // Slot 2
int reel3 = -1; // Slot 3

float float_spinframe; // to calculate how fast to switch the shapes
int[] currentShapes = {0, 0, 0}; // Track current shape index for each slot
float spinSpeed = 0.5; // Initial speed for spinning
int spinDuration = 360; // Total duration of spinning (6 seconds at 60 fps)
int spinTimer = 0; // Timer to track spinning time

// Variables for custom shapes
PImage meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic;
PImage[] slotShapesImages;
float[] shapeChances = {
  30.0,  // meteor.png (30% chance)
  25.0,  // rainbowstar.png (25% chance)
  18.0,  // datagemstar.png (18% chance)
  12.0,  // dwarvengold.png (12% chance)
  8.0,   // alienruby.png (8% chance)
  5.0,   // polyhedron.png (5% chance)
  2.0    // geodesic.png (2% chance)
};

String[] shapeNames = {
  "Meteor", "RainbowStar", "DataGemStar", "DwarvenGold", "AlienRuby", "Polyhedron", "Geodesic"
};

float handleRotation = 0; // Add this variable to control handle rotation

boolean handleActive = true;  // Track if handle can be used
boolean hasWon = false;  // Track winning status

boolean canAddCoin = true;  // Track if a new coin can be added
int maxCoins = 9;  // Maximum number of coins allowed in the tank

int _wndW = 600;
int _wndH = 600;

void setup() {
  size(_wndW, _wndH, P3D);  // Larger window size
  stroke(0);  // Set stroke color to black
  strokeWeight(2);  // Set stroke thickness for everything else
  
  // Initialize the font
  font1 = createFont("Times New Roman", 30); 
  textFont(font1);
  textAlign(CENTER, CENTER); 
  
  // Load images
  meteor = loadImage("meteor.png");
  rainbowstar = loadImage("rainbowstar.png");
  datagemstar = loadImage("datagemstar.png");
  dwarvengold = loadImage("dwarvengold.png");
  alienruby = loadImage("alienruby.png");
  polyhedron = loadImage("polyhedron.png");
  geodesic = loadImage("geodesic.png");
  
  // Add the images to the array
  slotShapesImages = new PImage[]{meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic};
  
  // Note: No call to shuffleSlotShapes() here to keep the slots empty until the lever is pulled
}

void draw() {
  background(200);
  
  // Set the camera to be in front of the slot machine, and closer
  // Adjusted for larger view
  camera(width / 2.0, height / 2.0, (height / 2.0) / tan(PI * 30.0 / 180.0) + 300, width / 2.0, height / 2.0, 0, 0, 1, 0); 
  translate(width/2 + 100, height/2, 0);
  scale(0.75);
  // Draw the cable first so it appears behind everything else
  drawCable();  
  // Draw the main body of the slot machine (scaled up)
  pushMatrix();
  fill(150);
  stroke(0);  // Ensure stroke color is black
  strokeWeight(2);  // Ensure the stroke for everything else is set to the original thickness
  box(400, 900, 300);  // Main body scaled up vertically
  popMatrix();
  
  // Draw the slots as 3D cubes recessed into the machine
  for (int i = 0; i < 3; i++) {
    pushMatrix();
    translate((i - 1) * 130, -100, 110);  // Position each slot (pushed back into the machine)
    fill(255);
    box(100, 300, 100);  // Draw a 3D cube representing the slot

    pushMatrix();
    translate(0, 0, 51);  // Move shapes slightly forward to be visible on the front face

    // Draw the current or final shape
    if (bool_spinning) {
      // Display a different shape for each slot during spinning
      int shapeIndex = int((float_spinframe + i * 0.33) % slotShapesImages.length);
      drawShape(shapeIndex, 0);
    } else {
      // Draw the final shape after spinning
      int shapeIndex;
      if (i == 0) shapeIndex = reel1;
      else if (i == 1) shapeIndex = reel2;
      else shapeIndex = reel3;

      drawShape(shapeIndex, 0);
    }

    popMatrix();
    popMatrix();
  }

// Handle spinning logic
if (bool_spinning) {
  // Increase the spin timer and adjust the speed
  spinTimer++;
  if (spinTimer < spinDuration) {
    float_spinframe += spinSpeed;

    // Adjust the slowdown factor to make the curve less steep
    // Reduce the rate of deceleration by using a smaller factor
    spinSpeed *= 0.99; // Instead of 0.98, using 0.99 for a less steep slowdown

    // Ensure spinSpeed doesn't get too slow
    if (spinSpeed < 0.1) {
      spinSpeed = 0.1;  // Minimum speed threshold to keep the spin relatively fast
    }
  } else {
    bool_spinning = false; // Stop spinning after the duration
    bool_reels = true; // Show final reels
    spinTimer = 0;
    spinSpeed = 0.5; // Reset the spin speed for next time
    handleActive = true; // Enable handle use again

    // Debugging: Print reel contents right after stopping
    println("Final reel1: " + reel1);
    println("Final reel2: " + reel2);
    println("Final reel3: " + reel3);

    checkWinningCondition(); // Check if the player has won
  }

  // Loop the frame counter
  if (float_spinframe >= slotShapesImages.length) {
    float_spinframe = 0;
  }
}

  // Draw and animate the handle
  pushMatrix();
  translate(225, -100, 100);  // Move handle along Z-axis behind the main body and slightly down
  
  if (bool_spin) {
    handleRotation += 0.05;  // Increase the rotation to simulate pulling down
    if (handleRotation > HALF_PI) {  // Stop at 90 degrees (HALF_PI radians)
      handleRotation = HALF_PI;
      bool_spinning = true;  // Start spinning when handle is fully down
      bool_spin = false; // Disable further clicks during spinning
      startCoinFall(); // Start coin fall when handle is pulled
    }
  } else if (!bool_spinning) {
    handleRotation -= 0.05;  // Reset the handle back to the original position
    if (handleRotation < 0) {
      handleRotation = 0;
    }
  }
  
  rotateZ(PI/4 + handleRotation);  // Rotate the handle based on the current animation state
  fill(100);
  box(30, 200, 30);  // Handle rod, scaled up
  translate(0, -100, -5);  // Position the knob
  fill(255, 0, 0);
  sphere(50);  // Handle knob, scaled up
  popMatrix();

  // Draw the display area (where "JACKPOT" is displayed, scaled up)
  pushMatrix();
  translate(0, -350, 160);
  fill(50);
  box(300, 75, 20);  // Display area, scaled up
  popMatrix();
  
  // Adjust this section to move the text lower
  pushMatrix();
  translate(0, -365, 170);  // Adjusted Y position to move the text lower
  fill(255);  // Set text color to white
  textSize(32);  // Set text size
  text("SLOT MACHINE", 0, 0);  // Display text
  popMatrix();

  // Draw the base (scaled up)
  pushMatrix();
  translate(0, 450, 0);
  fill(100);
  box(500, 75, 350);  // Base of the machine, scaled up
  popMatrix();

  // Draw the result window at the bottom
  drawResultWindow();  
  // Draw the coin tank beside the slot machine
  drawCoinTank();  
  // Update and display coins
  boolean allCoinsStopped = true;
  for (Coin coin : coins) {
    coin.update();
    coin.display();
    if (!coin.isStopped()) {
      allCoinsStopped = false;
    }
  }
  if (allCoinsStopped) {
    canAddCoin = true;
  }

  // Draw the button to generate coins
  drawCoinButton();
}

// Function to select a unique random shape for each slot
int selectUniqueRandomShape(int slotIndex) {
    ArrayList<Integer> availableShapes = new ArrayList<Integer>();
     // Fill the list with available shapes excluding the ones already used in other slots
    for (int i = 0; i < slotShapesImages.length; i++) {
        boolean used = false;
        for (int j = 0; j < slotIndex; j++) {
            if (currentShapes[j] == i) {
                used = true;
                break;
            }
        }
        if (!used) {
            availableShapes.add(i);
        }
    }

    // Select a random shape from the available shapes
    int selectedShape = availableShapes.get(int(random(availableShapes.size())));
    currentShapes[slotIndex] = selectedShape;  // Store the selected shape for this slot

    return selectedShape;
}
//, int slotIndex
void drawShape(int shapeType, float yOffset) {  
  if (shapeType >= 0 && shapeType < slotShapesImages.length) {
    PImage shapeImage = slotShapesImages[shapeType];  // Get the corresponding image
    pushMatrix();
    translate(0, yOffset, 0);  // Offset position vertically
    imageMode(CENTER);
    image(shapeImage, 0, 0, 60, 60);  // Draw the shape image with consistent size
    popMatrix();
  } else {
    println("Error: Invalid shapeType value: " + shapeType);
  }
}

void drawResultWindow() {
    // Draw the result window background with the same gray as the background behind "SLOT MACHINE"
    pushMatrix();
    translate(0, 200, 200);  // Position the background box further up
    fill(70);  // Set fill color to a darker gray to match the "SLOT MACHINE" background
    stroke(0);  // Set stroke color to black
    strokeWeight(2);  // Set stroke thickness
    box(330, 180, 20);  // Result window box, slightly smaller height
    popMatrix();
  
    // Display the result text
    pushMatrix();
    translate(0, 200, 210);  // Align the text with the result window
    fill(255);  // Set text color to white
    textSize(22);  // Set text size here
    textAlign(CENTER, CENTER);
  
    if (bool_reels && !bool_spinning) {  // Ensure the text only displays after the spinning stops
        if (hasWon) {
            text("YOU WIN!", 0, -30);
        } else {
            text("YOU LOSE!", 0, -30);
        }

        // Map reel values to shape names
        String shape1 = shapeNames[reel1];
        String shape2 = shapeNames[reel2];
        String shape3 = shapeNames[reel3];
    
        // Display the shape names
        textSize(18);
        text(shape1 + " " + shape2 + " " + shape3, 0, 20);
    } else {
        text("", 0, 0);  // Clear text when not spinning
    }
  
    popMatrix();
}

void drawCoinTank() {
    pushMatrix();
    translate(coinTankX + width / 2, coinTankY + height / 2, -25);  // Position the tank
  
    // Draw the tank with the same color as the machine
    fill(150);  // Use the same gray color as the machine
    stroke(0);  // Black outline for the tank
    strokeWeight(4);  // Thicker outlines to make it look 3D
    box(coinTankWidth, coinTankHeight, 50);  // Main body of the tank
    
    // Draw the inner rectangle with darker grey color
    pushMatrix();
    translate(0, 0, 25);  // Adjust Z to ensure it's inside the tank
    fill(100);  // Darker grey color
    noStroke();  // No outline for this area
    rectMode(CENTER);
    rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Dark grey rectangle inside the tank
    popMatrix();
  
    // Draw coins with stroke effect on top of the darker grey area
    for (Coin coin : coins) {
        // Draw the actual coin with a stroke
        pushMatrix();
        translate(0, 0, 30);  // Move coins slightly forward
        coin.display();  // Draw each coin
        popMatrix();
    }

    // Create a transparent window to see the coins
    translate(0, 0, 26);  // Move the window slightly forward to appear as a transparent part of the tank
    noFill();  // Make the window transparent
    stroke(0);  // Outline for the window
    strokeWeight(2);  // Outline for the window, thinner than the tank outline
  
    // Draw the outline for the window
    rectMode(CENTER);
    rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Draw the window slightly smaller than the tank height
  
    // Add a cover to hide the unwanted parts
    fill(150);  // Use the same color as the tank
    noStroke();  // Remove strokes for a seamless look
  
    // Cover the top part
    rectMode(CORNER);
    rect(-coinTankWidth / 4, -coinTankHeight / 2.5 - coinSize, coinTankWidth / 2, coinSize * 0.5);
  
    // Cover the bottom part
    rect(-coinTankWidth / 4, coinTankHeight / 2 - coinSize * 0.5, coinTankWidth / 2, coinSize * 0.5);

    popMatrix();
}

void drawCoinButton() {
  pushMatrix();
  translate(width / 2 - 895, height / 2 - 410, 50);  // Keep the button's Z position behind the slot machine
  
  // Increase the size of the button
  float buttonWidth = 150;  // Increase width
  float buttonHeight = 75;  // Increase height
  float buttonDepth = 30;   // Increase depth

  // Increase the stroke thickness
  float buttonStrokeWeight = 4;  // Increase stroke weight

  // Draw the 3D box for the button with increased size and stroke
  fill(150);  // Gray color for the box
  stroke(0);  // Black stroke for the box
  strokeWeight(buttonStrokeWeight);  // Apply thicker stroke weight
  box(buttonWidth, buttonHeight, buttonDepth);  // Apply increased dimensions for the 3D box
  
  // Draw the "Add Coin" text on the box
  translate(0, 0, 15);  // Move the text slightly forward to appear on the front face of the box
  fill(255);  // White color for the text
  textSize(24);  // Increase text size to match larger button
  textAlign(CENTER, CENTER);
  text("Add Coin", 0, 0);  // Draw the text at the center of the box
  popMatrix();
}


void mousePressed() {
    // Adjust the button click region based on the desired coordinates
   // float adjustedX1 = 118;  // Move the left boundary further left
    float adjustedX1 = 30;
    float adjustedX2 = 255;  // Move the right boundary further right
//    float adjustedY1 = 540;  // Move the top boundary further up
    float adjustedY1 = 228;
    float adjustedY2 = 610;  // Move the bottom boundary further down

    println("MouseX: " + mouseX + ", MouseY: " + mouseY);  // Print coordinates for debugging
    if (mouseX > adjustedX1 && mouseX < adjustedX2 && mouseY > adjustedY1 && mouseY < adjustedY2 && canAddCoin && coins.size() < maxCoins) {  
        println("Add Coin button clicked!");  // Debugging message
        // Generate a new coin at the correct position
        Coin newCoin = new Coin(width / 2 + coinTankX, height / 2 + coinTankY - coinTankHeight / 2 + coinSize / 2);
        coins.add(newCoin);
        canAddCoin = false;  // Prevent adding another coin until the current one stops
    }

    // Handle logic for lever pull
    if (dist(mouseX, mouseY, width / 2 + 225, height / 2 - 100) < 50) { 
        if (handleActive && !bool_spinning && coins.size() > 0) {  // Check if there is at least one coin
            bool_spin = true; 
            handleActive = false; // Disable handle during spinning
            shuffleSlotShapes(); // Shuffle and populate the shapes each time before spinning
            bool_reels = false; // Ensure the result text is hidden during the spin
        }
    }
}

void checkWinningCondition() {
    // Check if all three shapes match
    if (reel1 == reel2 && reel2 == reel3) {
        hasWon = true;
    } else {
        hasWon = false;
    }
}

void shuffleSlotShapes() {
    // Select a shape based on the chances
    int selectedShape = selectShapeBasedOnChance();

    // Determine if the player wins or loses (50% chance)
    boolean win = random(100) < 50;

    if (win) {
        // If the player wins, set all reels to the selected shape
        reel1 = selectedShape;
        reel2 = selectedShape;
        reel3 = selectedShape;
    } else {
        // If the player loses, select different shapes for each reel
        reel1 = selectedShape;
        reel2 = selectDifferentShape(selectedShape);
        reel3 = selectDifferentShape(reel2);
    }
}

int selectShapeBasedOnChance() {
    float rand = random(100);
    float cumulativeChance = 0;
    
    for (int i = 0; i < shapeChances.length; i++) {
        cumulativeChance += shapeChances[i];
        if (rand < cumulativeChance) {
            return i;
        }
    }
    return shapeChances.length - 1;  // Fallback in case of rounding errors
}

int selectDifferentShape(int previousShape) {
    int newShape;
    do {
        newShape = selectShapeBasedOnChance();
    } while (newShape == previousShape);
    return newShape;
}

void drawCable() {
  pushMatrix();
  pushStyle();  // Save the current stroke and fill settings

  stroke(0);  // Set base cable color to black
  strokeWeight(8);  // Base thickness of the cable
  
  // Base cable line
  float startX = coinTankX + width / 2.6 + coinTankWidth / 2;  // Right edge of the coin tank
  float startY = coinTankY + height / 2;  // Middle of the coin tank's height
  float startZ = -100;  // Move the cable farther back in 3D space
  
  float endX = -200;  // Position on the left side of the slot machine
  float endY = 100;  // Position near the base of the slot machine
  float endZ = 50;  // Make sure this is also behind the slot machine
  
  // Draw the base cable line
  line(startX, startY, startZ, endX, endY, endZ);

  // Add electricity effect
  drawElectricityEffect(startX, startY, startZ, endX, endY, endZ);

  popStyle();  // Restore the previous stroke and fill settings
  popMatrix();
}

void drawElectricityEffect(float startX, float startY, float startZ, float endX, float endY, float endZ) {
    int segments = 40;  // Increase number of segments for smoother waves
    float waveAmplitude = 15;  // Amplitude of the wave
    float waveFrequency = 0.05;  // Frequency of the wave
    float speed = millis() * 0.005;  // Speed of the wave motion over time
    stroke(173, 216, 230);  // Light blue color for the electricity (R:173, G:216, B:230)
    strokeWeight(4);  // Thinner stroke for the electricity effect
    
    float prevX = startX;
    float prevY = startY;
    float prevZ = startZ;

    for (int i = 1; i <= segments; i++) {
        float t = (float) i / segments;
        
        // Interpolate positions along the cable
        float x = lerp(startX, endX, t);
        float y = lerp(startY, endY, t);
        float z = lerp(startZ, endZ, t);
        
        // Apply sine wave to create electricity effect
        x += sin(TWO_PI * waveFrequency * i + speed) * waveAmplitude;
        y += cos(TWO_PI * waveFrequency * i + speed) * waveAmplitude;
        
        // Draw electricity wave segment
        line(prevX, prevY, prevZ, x, y, z);
        
        // Update previous position for the next segment
        prevX = x;
        prevY = y;
        prevZ = z;
    }
}

void startCoinFall() {
    if (!coins.isEmpty()) {
        // Start the falling animation from the bottom coin
        Coin bottomCoin = coins.get(0);  // Get the bottom-most coin
        bottomCoin.speedY = 5;  // Reset the speed for the bottom coin to fall
        bottomCoin.stopped = false;
        
        // Remove the bottom coin after the animation is done (i.e., it reaches the bottom of the tank)
        coins.remove(0);
        
        // Update the position of the remaining coins to make them fall in place
        for (Coin coin : coins) {
            if (coin.isStopped()) {
                coin.speedY = 5;  // Trigger the fall of the remaining coins
                coin.stopped = false;
            }
        }
    }
}

Coin class is in a separate tab. Font size increased a little in this code (not in image below)

1 Like

Can you try scaling it down first; scale(0.75) should allow it to fit into a 600x600 window and still look decent. See other post.

Addendum:
I found the PGraphics code.

1 Like

I managed to make it appear now i just need to make the add coin + coin tank sit in their correct position im not sure what made them not be…
but im checking it now and ill update, if you have any ideas go ahead…

Try running this code. I scaled it down to create the PGraphic. It’s displayed in a 600x600 window:


PGraphics slotMachineGraphics;

class SlotMachine {

    // Global variables specific to the slot machine
    ArrayList<Coin> coins = new ArrayList<Coin>();  // List to store the coins
    float gravity = 0.5;  // Gravity effect on the coins
    float coinSize = 40;  // Size of each coin (increased)
    float coinTankX = -900;  // Move the coin tank further to the left
    float coinTankY = -100;   // Position the coin tank higher up
    float coinTankWidth = 100; // Adjusted width of the coin tank (thinner)
    float coinTankHeight = 400; // Height of the coin tank

    PFont font1;
    boolean bool_spin; // the lever has been pulled
    boolean bool_spinning; // the machine is spinning
    int spinframe;
    int time;

    boolean bool_reels; // to display the reels after it has spun
    int reel1 = -1; // Slot 1
    int reel2 = -1; // Slot 2
    int reel3 = -1; // Slot 3

    float float_spinframe; // to calculate how fast to switch the shapes
    int[] currentShapes = {0, 0, 0}; // Track current shape index for each slot
    float spinSpeed = 0.5; // Initial speed for spinning
    int spinDuration = 360; // Total duration of spinning (6 seconds at 60 fps)
    int spinTimer = 0; // Timer to track spinning time

    // Variables for custom shapes
    PImage meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic;
    PImage[] slotShapesImages;
    float[] shapeChances = {
        30.0,  // meteor.png (30% chance)
        25.0,  // rainbowstar.png (25% chance)
        18.0,  // datagemstar.png (18% chance)
        12.0,  // dwarvengold.png (12% chance)
        8.0,   // alienruby.png (8% chance)
        5.0,   // polyhedron.png (5% chance)
        2.0    // geodesic.png (2% chance)
    };

    String[] shapeNames = {
        "Meteor", "RainbowStar", "DataGemStar", "DwarvenGold", "AlienRuby", "Polyhedron", "Geodesic"
    };

    float handleRotation = 0; // Add this variable to control handle rotation

    boolean handleActive = true;  // Track if handle can be used
    boolean hasWon = false;  // Track winning status

    boolean canAddCoin = true;  // Track if a new coin can be added
    int maxCoins = 9;  // Maximum number of coins allowed in the tank

    // Constructor
    SlotMachine() {
        setupSlotMachine();
    }

    // Setup method for slot machine
    void setupSlotMachine() {
        stroke(0);  // Set stroke color to black
        strokeWeight(2);  // Set stroke thickness for everything else

        // Initialize the font
        font1 = createFont("Times New Roman", 30); 
        textFont(font1);
        textAlign(CENTER, CENTER); 

        // Load images
        meteor = loadImage("meteor.png");
        rainbowstar = loadImage("rainbowstar.png");
        datagemstar = loadImage("datagemstar.png");
        dwarvengold = loadImage("dwarvengold.png");
        alienruby = loadImage("alienruby.png");
        polyhedron = loadImage("polyhedron.png");
        geodesic = loadImage("geodesic.png");

        // Add the images to the array
        slotShapesImages = new PImage[]{meteor, rainbowstar, datagemstar, dwarvengold, alienruby, polyhedron, geodesic};
    }

    // Draw method for slot machine with PGraphics parameter
    void drawSlotMachine(PGraphics pg) {
        pg.beginDraw();
        pg.background(200);

        // Set the camera to be in front of the slot machine, and closer
        pg.camera(pg.width / 2.0, pg.height / 2.0, (pg.height / 2.0) / tan(PI * 30.0 / 180.0) + 300,
            pg.width / 2.0, pg.height / 2.0, 0,
            0, 1, 0);
       // **** changed svan **** //
        pg.translate(pg.width / 2 + 100, pg.height / 2, 0);
        pg.scale(0.75); // **** Added svan **** //

        // Draw the cable first so it appears behind everything else
        drawCable(pg);

        // Draw the main body of the slot machine (scaled up)
        pg.pushMatrix();
        pg.fill(150);
        pg.stroke(0);  // Ensure stroke color is black
        pg.strokeWeight(2);  // Ensure the stroke for everything else is set to the original thickness
        pg.box(400, 900, 300);  // Main body scaled up vertically
        pg.popMatrix();

        // Draw the slots as 3D cubes recessed into the machine
        for (int i = 0; i < 3; i++) {
            pg.pushMatrix();
            pg.translate((i - 1) * 130, -100, 110);  // Position each slot (pushed back into the machine)
            pg.fill(255);
            pg.box(100, 300, 100);  // Draw a 3D cube representing the slot

            pg.pushMatrix();
            pg.translate(0, 0, 51);  // Move shapes slightly forward to be visible on the front face

            // Draw the current or final shape
            if (bool_spinning) {
                // Display a different shape for each slot during spinning
                int shapeIndex = int((float_spinframe + i * 0.33) % slotShapesImages.length);
                drawShape(pg, shapeIndex, 0, i);
            } else {
                // Draw the final shape after spinning
                int shapeIndex;
                if (i == 0) shapeIndex = reel1;
                else if (i == 1) shapeIndex = reel2;
                else shapeIndex = reel3;

                drawShape(pg, shapeIndex, 0, i);
            }

            pg.popMatrix();
            pg.popMatrix();
        }

        // Handle spinning logic
        if (bool_spinning) {
            // Increase the spin timer and adjust the speed
            spinTimer++;
            if (spinTimer < spinDuration) {
                float_spinframe += spinSpeed;

                // Adjust the slowdown factor to make the curve less steep
                // Reduce the rate of deceleration by using a smaller factor
                spinSpeed *= 0.99; // Instead of 0.98, using 0.99 for a less steep slowdown

                // Ensure spinSpeed doesn't get too slow
                if (spinSpeed < 0.1) {
                    spinSpeed = 0.1;  // Minimum speed threshold to keep the spin relatively fast
                }
            } else {
                bool_spinning = false; // Stop spinning after the duration
                bool_reels = true; // Show final reels
                spinTimer = 0;
                spinSpeed = 0.5; // Reset the spin speed for next time
                handleActive = true; // Enable handle use again

                // Debugging: Print reel contents right after stopping
                println("Final reel1: " + reel1);
                println("Final reel2: " + reel2);
                println("Final reel3: " + reel3);

                checkWinningCondition(); // Check if the player has won
            }

            // Loop the frame counter
            if (float_spinframe >= slotShapesImages.length) {
                float_spinframe = 0;
            }
        }

        // Draw and animate the handle
        pg.pushMatrix();
        pg.translate(225, -100, 100);  // Move handle along Z-axis behind the main body and slightly down

        if (bool_spin) {
            handleRotation += 0.05;  // Increase the rotation to simulate pulling down
            if (handleRotation > HALF_PI) {  // Stop at 90 degrees (HALF_PI radians)
                handleRotation = HALF_PI;
                bool_spinning = true;  // Start spinning when handle is fully down
                bool_spin = false; // Disable further clicks during spinning
                startCoinFall(); // Start coin fall when handle is pulled
            }
        } else if (!bool_spinning) {
            handleRotation -= 0.05;  // Reset the handle back to the original position
            if (handleRotation < 0) {
                handleRotation = 0;
            }
        }

        pg.rotateZ(PI / 4 + handleRotation);  // Rotate the handle based on the current animation state
        pg.fill(100);
        pg.box(30, 200, 30);  // Handle rod, scaled up
        pg.translate(0, -100, -5);  // Position the knob
        pg.fill(255, 0, 0);
        pg.sphere(50);  // Handle knob, scaled up
        pg.popMatrix();

        // Draw the display area (where "JACKPOT" is displayed, scaled up)
        pg.pushMatrix();
        pg.translate(0, -350, 160);
        pg.fill(50);
        pg.box(300, 75, 20);  // Display area, scaled up
        pg.popMatrix();

        // Adjust this section to move the text lower
        pg.pushMatrix();
        // *** Changed this svan *** //
       // pg.translate(0, -365, 170);  // Adjusted Y position to move the text lower
        pg.translate(-100, -350, 170);  // Adjusted Y position to move the text lower
        pg.fill(255);  // Set text color to white
        pg.textSize(32);  // Set text size
        pg.text("SLOT MACHINE", 0, 0);  // Display text
        pg.popMatrix();

        // Draw the base (scaled up)
        pg.pushMatrix();
        pg.translate(0, 450, 0);
        pg.fill(100);
        pg.box(500, 75, 350);  // Base of the machine, scaled up
        pg.popMatrix();

        // Draw the result window at the bottom
        drawResultWindow(pg);

        // Draw the coin tank beside the slot machine
        drawCoinTank(pg);

        // Update and display coins
        boolean allCoinsStopped = true;
        for (Coin coin : coins) {
            coin.update();
            coin.display(pg);
            if (!coin.isStopped()) {
                allCoinsStopped = false;
            }
        }
        if (allCoinsStopped) {
            canAddCoin = true;
        }

        // Draw the button to generate coins
        drawCoinButton(pg);
        pg.endDraw();
    }

    // Function to select a unique random shape for each slot
    int selectUniqueRandomShape(int slotIndex) {
        ArrayList<Integer> availableShapes = new ArrayList<Integer>();

        // Fill the list with available shapes excluding the ones already used in other slots
        for (int i = 0; i < slotShapesImages.length; i++) {
            boolean used = false;
            for (int j = 0; j < slotIndex; j++) {
                if (currentShapes[j] == i) {
                    used = true;
                    break;
                }
            }
            if (!used) {
                availableShapes.add(i);
            }
        }

        // Select a random shape from the available shapes
        int selectedShape = availableShapes.get(int(random(availableShapes.size())));
        currentShapes[slotIndex] = selectedShape;  // Store the selected shape for this slot

        return selectedShape;
    }

    void drawShape(PGraphics pg, int shapeType, float yOffset, int slotIndex) {
        if (shapeType >= 0 && shapeType < slotShapesImages.length) {
            PImage shapeImage = slotShapesImages[shapeType];  // Get the corresponding image
            pg.pushMatrix();
            pg.translate(0, yOffset, 0);  // Offset position vertically
            pg.imageMode(CENTER);
            pg.image(shapeImage, 0, 0, 60, 60);  // Draw the shape image with consistent size
            pg.popMatrix();
        } else {
            println("Error: Invalid shapeType value: " + shapeType);
        }
    }

    void drawResultWindow(PGraphics pg) {
        // Draw the result window background with the same gray as the background behind "SLOT MACHINE"
        pg.pushMatrix();
        pg.translate(0, 200, 200);  // Position the background box further up
        pg.fill(70);  // Set fill color to a darker gray to match the "SLOT MACHINE" background
        pg.stroke(0);  // Set stroke color to black
        pg.strokeWeight(2);  // Set stroke thickness
        pg.box(330, 180, 20);  // Result window box, slightly smaller height
        pg.popMatrix();

        // Display the result text
        pg.pushMatrix();
        pg.translate(0, 200, 210);  // Align the text with the result window
        pg.fill(255);  // Set text color to white
        pg.textSize(18);  // Set text size here
        pg.textAlign(CENTER, CENTER);

        if (bool_reels && !bool_spinning) {  // Ensure the text only displays after the spinning stops
            if (hasWon) {
                pg.text("YOU WIN!", 0, -30);
            } else {
                pg.text("YOU LOSE!", 0, -30);
            }

            // Map reel values to shape names
            String shape1 = shapeNames[reel1];
            String shape2 = shapeNames[reel2];
            String shape3 = shapeNames[reel3];

            // Display the shape names
            pg.text(shape1 + " " + shape2 + " " + shape3, 0, 20);
        } else {
            pg.text("", 0, 0);  // Clear text when not spinning
        }

        pg.popMatrix();
    }

    void drawCoinTank(PGraphics pg) {
        pg.pushMatrix();
        pg.translate(coinTankX + pg.width / 2, coinTankY + pg.height / 2, -25);  // Position the tank

        // Draw the tank with the same color as the machine
        pg.fill(150);  // Use the same gray color as the machine
        pg.stroke(0);  // Black outline for the tank
        pg.strokeWeight(4);  // Thicker outlines to make it look 3D
        pg.box(coinTankWidth, coinTankHeight, 50);  // Main body of the tank

        // Draw the inner rectangle with darker grey color
        pg.pushMatrix();
        pg.translate(0, 0, 25);  // Adjust Z to ensure it's inside the tank
        pg.fill(100);  // Darker grey color
        pg.noStroke();  // No outline for this area
        pg.rectMode(CENTER);
        pg.rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Dark grey rectangle inside the tank
        pg.popMatrix();

        // Draw coins with stroke effect on top of the darker grey area
        for (Coin coin : coins) {
            // Draw the actual coin with a stroke
            pg.pushMatrix();
            pg.translate(0, 0, 30);  // Move coins slightly forward
            coin.display(pg);  // Draw each coin
            pg.popMatrix();
        }

        // Create a transparent window to see the coins
        pg.translate(0, 0, 26);  // Move the window slightly forward to appear as a transparent part of the tank
        pg.noFill();  // Make the window transparent
        pg.stroke(0);  // Outline for the window
        pg.strokeWeight(2);  // Outline for the window, thinner than the tank outline

        // Draw the outline for the window
        pg.rectMode(CENTER);
        pg.rect(0, 0, coinTankWidth / 2, coinTankHeight * 0.9);  // Draw the window slightly smaller than the tank height

        // Add a cover to hide the unwanted parts
        pg.fill(150);  // Use the same color as the tank
        pg.noStroke();  // Remove strokes for a seamless look

        // Cover the top part
        pg.rectMode(CORNER);
        pg.rect(-coinTankWidth / 4, -coinTankHeight / 2.5 - coinSize, coinTankWidth / 2, coinSize * 0.5);

        // Cover the bottom part
        pg.rect(-coinTankWidth / 4, coinTankHeight / 2 - coinSize * 0.5, coinTankWidth / 2, coinSize * 0.5);

        pg.popMatrix();
    }

    void drawCoinButton(PGraphics pg) {
        pg.pushMatrix();
        pg.translate(pg.width / 2 - 895, pg.height / 2 - 410, 50);  // Keep the button's Z position behind the slot machine

        // Increase the size of the button
        float buttonWidth = 150;  // Increase width
        float buttonHeight = 75;  // Increase height
        float buttonDepth = 30;   // Increase depth

        // Increase the stroke thickness
        float buttonStrokeWeight = 4;  // Increase stroke weight

        // Draw the 3D box for the button with increased size and stroke
        pg.fill(150);  // Gray color for the box
        pg.stroke(0);  // Black stroke for the box
        pg.strokeWeight(buttonStrokeWeight);  // Apply thicker stroke weight
        pg.box(buttonWidth, buttonHeight, buttonDepth);  // Apply increased dimensions for the 3D box

        // Draw the "Add Coin" text on the box
        pg.translate(0, 0, 15);  // Move the text slightly forward to appear on the front face of the box
        pg.fill(255);  // White color for the text
        pg.textSize(24);  // Increase text size to match larger button
        pg.textAlign(CENTER, CENTER);
        pg.text("Add Coin", 0, 0);  // Draw the text at the center of the box
        pg.popMatrix();
    }

    class Coin {
        float x, y;
        float speedY;
        boolean stopped;

        Coin(float x, float y) {
            this.x = x;  // The initial x position of the coin
            this.y = y;  // The initial y position of the coin
            this.speedY = 5;  // Initial speed to simulate throwing
            this.stopped = false;
        }

        void update() {
            if (!stopped) {
                // Apply gravity
                speedY += gravity;
                y += speedY;

                // Adjust the resting position to be slightly lower
                if (y > height / 2 + coinTankY + coinTankHeight / 2 - coinSize * 0.75) {
                    y = height / 2 + coinTankY + coinTankHeight / 2 - coinSize * 0.75;
                    speedY = 0;
                    stopped = true;
                }

                // Check for collision with the previous coin
                if (coins.size() > 1 && this != coins.get(0)) {
                    Coin previousCoin = coins.get(coins.indexOf(this) - 1);
                    if (y > previousCoin.y - coinSize) {
                        y = previousCoin.y - coinSize;
                        speedY = 0;
                        stopped = true;
                    }
                }
            }
        }

        void display(PGraphics pg) {
            // 1. Calculate the horizontal offset to center the coins more accurately
            float offsetX = (coinTankWidth - coinSize) / 128.0;  // Adjust this value to control how far the coins move

            // 2. Draw the black stroke (slightly larger circle)
            pg.fill(0);  // Black color for the stroke
            pg.ellipse(x + offsetX, y, coinSize + 4, coinSize + 4);  // Apply offset to the stroke

            // 3. Draw the yellow coin
            pg.fill(255, 255, 0);  // Yellow color for the coin
            pg.ellipse(x + offsetX, y, coinSize, coinSize);  // Apply the same offset to the coin
        }

        boolean isStopped() {
            return stopped;
        }
    }

    // Handle mouse press events for slot machine
    void mousePressedSlotMachine() {
        // Adjust the button click region based on the desired coordinates
        float adjustedX1 = 118;  // Move the left boundary further left
        float adjustedX2 = 255;  // Move the right boundary further right
        float adjustedY1 = 540;  // Move the top boundary further up
        float adjustedY2 = 610;  // Move the bottom boundary further down

        println("MouseX: " + mouseX + ", MouseY: " + mouseY);  // Print coordinates for debugging
        if (mouseX > adjustedX1 && mouseX < adjustedX2 && mouseY > adjustedY1 && mouseY < adjustedY2 && canAddCoin && coins.size() < maxCoins) {  
            println("Add Coin button clicked!");  // Debugging message
            // Generate a new coin at the correct position
            Coin newCoin = new Coin(width / 2 + coinTankX, height / 2 + coinTankY - coinTankHeight / 2 + coinSize / 2);
            coins.add(newCoin);
            canAddCoin = false;  // Prevent adding another coin until the current one stops
        }

        // Handle logic for lever pull
        if (dist(mouseX, mouseY, width / 2 + 225, height / 2 - 100) < 50) { 
            if (handleActive && !bool_spinning && coins.size() > 0) {  // Check if there is at least one coin
                bool_spin = true; 
                handleActive = false; // Disable handle during spinning
                shuffleSlotShapes(); // Shuffle and populate the shapes each time before spinning
                bool_reels = false; // Ensure the result text is hidden during the spin
            }
        }
    }

    void checkWinningCondition() {
        // Check if all three shapes match
        if (reel1 == reel2 && reel2 == reel3) {
            hasWon = true;
        } else {
            hasWon = false;
        }
    }

    void shuffleSlotShapes() {
        // Select a shape based on the chances
        int selectedShape = selectShapeBasedOnChance();

        // Determine if the player wins or loses (50% chance)
        boolean win = random(100) < 50;

        if (win) {
            // If the player wins, set all reels to the selected shape
            reel1 = selectedShape;
            reel2 = selectedShape;
            reel3 = selectedShape;
        } else {
            // If the player loses, select different shapes for each reel
            reel1 = selectedShape;
            reel2 = selectDifferentShape(selectedShape);
            reel3 = selectDifferentShape(reel2);
        }
    }

    int selectShapeBasedOnChance() {
        float rand = random(100);
        float cumulativeChance = 0;

        for (int i = 0; i < shapeChances.length; i++) {
            cumulativeChance += shapeChances[i];
            if (rand < cumulativeChance) {
                return i;
            }
        }
        return shapeChances.length - 1;  // Fallback in case of rounding errors
    }

    int selectDifferentShape(int previousShape) {
        int newShape;
        do {
            newShape = selectShapeBasedOnChance();
        } while (newShape == previousShape);
        return newShape;
    }

    void drawCable(PGraphics pg) {
        pg.pushMatrix();
        pg.pushStyle();  // Save the current stroke and fill settings

        pg.stroke(0);  // Set base cable color to black
        pg.strokeWeight(8);  // Base thickness of the cable

        // Base cable line
        float startX = coinTankX + pg.width / 2.6 + coinTankWidth / 2;  // Right edge of the coin tank
        float startY = coinTankY + pg.height / 2;  // Middle of the coin tank's height
        float startZ = -100;  // Move the cable farther back in 3D space

        float endX = -200;  // Position on the left side of the slot machine
        float endY = 100;  // Position near the base of the slot machine
        float endZ = 50;  // Make sure this is also behind the slot machine

        // Draw the base cable line
        pg.line(startX, startY, startZ, endX, endY, endZ);

        // Add electricity effect
        drawElectricityEffect(pg, startX, startY, startZ, endX, endY, endZ);

        pg.popStyle();  // Restore the previous stroke and fill settings
        pg.popMatrix();
    }

    void drawElectricityEffect(PGraphics pg, float startX, float startY, float startZ, float endX, float endY, float endZ) {
        int segments = 40;  // Increase number of segments for smoother waves
        float waveAmplitude = 15;  // Amplitude of the wave
        float waveFrequency = 0.05;  // Frequency of the wave
        float speed = millis() * 0.005;  // Speed of the wave motion over time
        pg.stroke(173, 216, 230);  // Light blue color for the electricity (R:173, G:216, B:230)
        pg.strokeWeight(4);  // Thinner stroke for the electricity effect

        float prevX = startX;
        float prevY = startY;
        float prevZ = startZ;

        for (int i = 1; i <= segments; i++) {
            float t = (float) i / segments;

            // Interpolate positions along the cable
            float x = lerp(startX, endX, t);
            float y = lerp(startY, endY, t);
            float z = lerp(startZ, endZ, t);

            // Apply sine wave to create electricity effect
            x += sin(TWO_PI * waveFrequency * i + speed) * waveAmplitude;
            y += cos(TWO_PI * waveFrequency * i + speed) * waveAmplitude;

            // Draw electricity wave segment
            pg.line(prevX, prevY, prevZ, x, y, z);

            // Update previous position for the next segment
            prevX = x;
            prevY = y;
            prevZ = z;
        }
    }

    void startCoinFall() {
        if (!coins.isEmpty()) {
            // Start the falling animation from the bottom coin
            Coin bottomCoin = coins.get(0);  // Get the bottom-most coin
            bottomCoin.speedY = 5;  // Reset the speed for the bottom coin to fall
            bottomCoin.stopped = false;

            // Remove the bottom coin after the animation is done (i.e., it reaches the bottom of the tank)
            coins.remove(0);

            // Update the position of the remaining coins to make them fall in place
            for (Coin coin : coins) {
                if (coin.isStopped()) {
                    coin.speedY = 5;  // Trigger the fall of the remaining coins
                    coin.stopped = false;
                }
            }
        }
    }
}

void setup(){
  size(600,600,P3D);
  slotMachineGraphics = createGraphics(600, 600, P3D);
  SlotMachine slotMachine = new SlotMachine();
  slotMachine.drawSlotMachine(slotMachineGraphics);
}

void draw(){
  image(slotMachineGraphics,0,0);
}

Ty so much for all the help ill dig more into that soon and update you on the result!

What’s that little spiral thing to the left? Is that obscuring part of it?

You could do that using a JFrame with an embedded JInternalFrame, but I know of no way to do it with a GLWindow (which is what P3D uses):

Sound like you’re almost there…

I remembered the UI library G4P (add it to Processing) then look at Window on Demand in the Examples section… as another way to do it.

1 Like

It is complicated because you assumed there is a simple answer :grin: when in fact there just isn’t one.

Processing was designed to support just one display window per sketch and that sketch has its own event handling and rendering threads. Trying to run a second sketch inside an existing one will result in thread conflict and concurrent access issues.

In your scenario (“Space Casino”) where you have multiple mini-games to switch between e.g. “Wheel of Fortune”, “Slot Machine” and “Mind Games” I can see two possible solutions.

  1. Multiple Windows. You have the main casino window with the game selection buttons and when you click on one the selected mini-game starts in a new window. Both G4P and controlP5 support multiple windows and if you didn’t want to use a library there are window creation examples to be found on the forum.

  2. Single Window. The sketch effective has a number of modes and each mode represents a mini-game. This discussion might give you some ideas how it might be implemented.

4 Likes

Anything big should be done in a “real” IDE with “real” Java.

You can convert your Processing code to Java by clicking Export Project and copying the .java files in the source folder of the exported appplication.

If you copy the .java files into a Java project created with your IDE and follow this guide to get the Processing library .jar file and add the Library in your IDE, you can run you Processing code as Java code.

Java is a much more powerful language than Processing and has WAY more guides and wikis.

Java IDEs like Intellij IDEA and Eclipse are also MUCH better than the Processing IDE.

1 Like