The package “processing.core.PSurfaceAWT” does not exist

i get this

Libraries must be installed in a folder named ‘libraries’ inside the sketchbook folder (see the Preferences window).
The package “processing.core.PSurfaceAWT” does not exist. You might be missing a library.

when trying to add this

import processing.core.*;
import processing.core.PSurfaceAWT;
import processing.core.PSurfaceNone;
import java.awt.Frame;

i already tried placing a folder named code with the code.jar file in it in the mainsketch folder then import it with

import processing.core.*;

But it didn’t work, this is how my libraries folder looks like

iv’e tried manually extracting the data from core.jar with winrar into the libaries like that too

nothing works and i sat for so much time trying to solve this and i’m really clueless this is by far the most hardest thing iv’e faced and i can’t find any solotion anywhere online

Screenshot by Lightshot i think i don’t have it, do i? please help *(:slight_smile:

Hi @winterchan,

The reason is, that there is no
processing.core.PSurfaceAWT
but
processing.awt.PSurfaceAWT

Cheers
— mnse

PS: remove the things you made in code folder etc again…

2 Likes

thank you so much ! super fast reply and solved super quick ( I STILL HAVE A PROBLEM LOOK AT MY NEXT COMMENT]

altho now i don’t crash i still get this in console
when i try ti import processing.awt.PSurfaceAWT

No library found for processing.awt.PSurfaceAWT

do you know why?

Hi @winterchan,

Show your code, especially what is in your setup…

Cheers
— mnse

1 Like
import processing.awt.PSurfaceAWT;
import processing.awt.PSurfaceAWT.SmoothCanvas;
import javax.swing.JFrame;

BlackHole blackHole;
ArrayList<Star> objects;
MovableResizableWindow consoleWindow;
MovableResizableHUDWindow hudWindow;
PFont gameFont; // Font for the game HUD
PFont consoleFont; // Font for the console window
int points = 0;
int blackHoleMass = 1;
int gravityPull = 1; // Renamed from gravityBoost
int starSpeedDisplay = 1; // Initial display value for star speed
int starMultiplier = 1; // Initial value for star multiplier
int rainbowMultiplier = 1; // Initial value for rainbow star multiplier
int pointsMultiplier = 1; // Initial points multiplier value
color backgroundColor;
color textColor;
static float starSpeed = 0.25; // Initial slow speed of stars
static float spawnMultiplier = 1.0; // Global spawn multiplier
float starSpawnInterval = 60; // Base spawn interval for regular stars
float rainbowStarSpawnInterval; // Interval for spawning rainbow stars
final int INITIAL_BLACK_HOLE_SIZE = 50; // Initial size for the black hole
boolean pullAreaVisible = false; // Variable to track pull area visibility
boolean delayVisible = false; // Variable to track the visibility of spawn rate info

// Base values and scaling factors for the growth curve
int baseBlackHoleMass = 1;
int baseGravityPull = 1;
int baseStarSpeedDisplay = 1;
int baseStarMultiplier = 1;

// Maximum values
final int MAX_STAR_MULTIPLIER = 73500;
final int MAX_STAR_SPEED = 73500;
final int MAX_GRAVITY_PULL = 5400000;
final int MAX_BLACK_HOLE_MASS = 2850;
final int MAX_POINTS = 9999999;
final int MAX_RAINBOW_MULTIPLIER = MAX_STAR_MULTIPLIER; // Same max value for consistency

float kGrowth = 0.15; // Unified constant for balanced growth
float kGravityPull = 0.20; // Slightly higher growth rate for gravity pull
float kStarSpeed = 0.20; // Slightly higher growth rate for star speed
float kStarMultiplier = 0.20; // Slightly higher growth rate for star multiplier

int lastRainbowStarFrame = 0; // Frame count of the last rainbow star spawn

// New variables for screen management
String screenMode = "windowed";
boolean toggleFullscreen = false;
int targetWidth = 1920;
int targetHeight = 1080;

void settings() {
  fullScreen();
}

void setup() {
  backgroundColor = color(214, 255, 235); // #d6ffeb color
  textColor = color(101, 228, 167); // #65e4a7 color
  gameFont = createFont("PaladinsStraight.otf", 32); // Font size for the game HUD
  consoleFont = createFont("CascadiaMonoPL-Regular.otf", 16); // Font size for the console window
  textFont(gameFont);
  blackHole = new BlackHole(width / 2, height / 2, INITIAL_BLACK_HOLE_SIZE); // Initial size set
  objects = new ArrayList<Star>();
  consoleWindow = new MovableResizableWindow(100, 100, 800, 300, consoleFont, this); // Pass the console font and the current instance to the window
  hudWindow = new MovableResizableHUDWindow(100, 450, 400, 300, consoleFont, this); // HUD window for displaying game information

  // Set the initial rainbow star spawn interval
  rainbowStarSpawnInterval = starSpawnInterval * 50; // 50 times less frequent than regular stars
}

void draw() {
  if (toggleFullscreen) {
    toggleFullscreen = false;
    if (screenMode.equals("fullscreen")) {
      surface.setResizable(true);
      surface.setSize(displayWidth, displayHeight);
      surface.setLocation(0, 0);
      surface.setAlwaysOnTop(true);
      surface.setAlwaysOnTop(false);
      surface.setVisible(false);
      surface.setVisible(true);
    } else if (screenMode.equals("windowedfullscreen")) {
      surface.setResizable(true);
      surface.setSize(displayWidth, displayHeight);
      surface.setLocation(0, 0);
      surface.setAlwaysOnTop(true);
      surface.setAlwaysOnTop(false);
      surface.setVisible(false);
      surface.setVisible(true);
    } else if (screenMode.equals("windowed")) {
      surface.setResizable(true);
      surface.setSize(targetWidth, targetHeight);
      surface.setLocation((displayWidth - targetWidth) / 2, (displayHeight - targetHeight) / 2);
      surface.setAlwaysOnTop(false);
      surface.setVisible(false);
      surface.setVisible(true);
      restoreWindowedMode(); // Restore window decorations
    }
  }

  background(backgroundColor);

  // Game logic for normal stars
  if (frameCount % int(starSpawnInterval / spawnMultiplier) == 0) {
    objects.add(new StarMeteor(width, random(height), 15)); // Fixed star size
  }

  // Rainbow star spawning logic
  if (frameCount - lastRainbowStarFrame >= rainbowStarSpawnInterval) {
    objects.add(new RainbowStar(width, random(height), 15)); // Fixed rainbow star size
    lastRainbowStarFrame = frameCount; // Update the last spawn frame
  }

  blackHole.update();
  blackHole.display();

  if (pullAreaVisible) {
    drawPullArea();
    drawSpiralPath(); // Add the spiral path visualization
  }

  // Process all stars, including removal of marked ones
  for (int i = objects.size() - 1; i >= 0; i--) {
    Star obj = objects.get(i);
    if (obj.markForRemoval) {
      println("Removing star at frame: " + frameCount);
      objects.remove(i); // Remove the star if marked for removal
      continue; // Skip the rest of the loop for this object
    }
    obj.move();
    obj.display();
    blackHole.applyGravity(obj); // Apply gravity pull effect
    if (blackHole.absorb(obj)) {
      if (obj instanceof RainbowStar) {
        points = min(points + 100, MAX_POINTS); // Each rainbow star gives 100 points
      } else {
        points = min(points + 1, MAX_POINTS); // Each star gives exactly 1 point
      }
      objects.remove(i); // Remove absorbed stars
    }
  }

  if (delayVisible) {
    displaySpawnRates(); // Display spawn rate information
  }

  // Display the movable resizable HUD window
  hudWindow.display();

  // Display the movable resizable window
  consoleWindow.display();
}

void restoreWindowedMode() {
  PSurfaceAWT awtSurface = (PSurfaceAWT) surface;
  SmoothCanvas smoothCanvas = (SmoothCanvas) awtSurface.getNative();
  JFrame frame = (JFrame) smoothCanvas.getFrame();

  frame.dispose();
  frame.setUndecorated(false);
  frame.setResizable(true);
  frame.setSize(targetWidth, targetHeight);
  frame.setLocation((displayWidth - targetWidth) / 2, (displayHeight - targetHeight) / 2);
  frame.setVisible(true);
}

void drawPullArea() {
  int numDivisions = 10; // Number of divisions for the pull strength
  float maxPullStrength = 5.0; // Maximum pull strength at the center
  float minPullStrength = 0.1; // Minimum pull strength at the edge

  // Set the font to the console font for consistency
  textFont(consoleFont);
  textSize(10); // Smaller text size for the numbers

  for (int i = 0; i <= numDivisions; i++) {
    float strength = map(i, 0, numDivisions, maxPullStrength, minPullStrength);
    float radius = map(i, 0, numDivisions, 0, blackHole.gravityPullRadius);

    noFill();
    stroke(50, 50, 50, 150); // Dark grey with low opacity for the circles
    ellipse(blackHole.x, blackHole.y, radius * 2, radius * 2);

    // Calculate position for the text in a spiral
    float angle = PI / 4 * i; // Adjust the angle increment as needed for spiral effect
    float textX = blackHole.x + cos(angle) * radius;
    float textY = blackHole.y + sin(angle) * radius;

    fill(0); // Black color for text
    textAlign(CENTER, CENTER);
    text(nf(strength, 1, 1), textX, textY); // Display the strength value in the spiral path
  }
}

void drawSpiralPath() {
  stroke(255, 0, 0, 150); // Red color with low opacity for the spiral
  noFill();
  beginShape();
  float angle = 0;
  float radius = 0;
  while (radius < blackHole.gravityPullRadius) {
    float x = blackHole.x + cos(angle) * radius;
    float y = blackHole.y + sin(angle) * radius;
    vertex(x, y);
    angle += 0.1;
    radius += 0.5;
  }
  endShape();
}

void displaySpawnRates() {
  fill(textColor);
  textFont(consoleFont);
  textSize(20);
  textAlign(LEFT, TOP);
  text("Normal Stars Spawn Rate: " + (starSpawnInterval / spawnMultiplier), 20, 20);
  text("Rainbow Stars Spawn Rate: " + rainbowStarSpawnInterval, 20, 50);
}

void mousePressed() {
  println("Mouse Pressed at: " + mouseX + ", " + mouseY);

  // Handle click on "+"" icon for speed
  if (hudWindow.mouseOverSpeedIconPlus()) {
    println("Speed Icon Plus Clicked");
    if (points > 0 && starSpeedDisplay < MAX_STAR_SPEED) {
      points -= pointsMultiplier;
      hudWindow.updateStarSpeed(starSpeedDisplay + pointsMultiplier);
    } else {
      println("Star speed is at maximum value.");
    }
  }

  // Handle click on "+"" icon for gravity
  if (hudWindow.mouseOverGravityIconPlus()) {
    println("Gravity Icon Plus Clicked");
    if (points > 0 && gravityPull < MAX_GRAVITY_PULL) {
      points -= pointsMultiplier;
      hudWindow.updateGravityPull(gravityPull + pointsMultiplier);
    } else {
      println("Gravity pull is at maximum value.");
    }
  }

  // Handle click on "+"" icon for black hole mass
  if (hudWindow.mouseOverBlackHoleMassIconPlus()) {
    println("Black Hole Mass Icon Plus Clicked");
    if (points > 0 && blackHoleMass < MAX_BLACK_HOLE_MASS) {
      points -= pointsMultiplier;
      hudWindow.updateBlackHoleMass(blackHoleMass + pointsMultiplier);
    } else {
      println("Black hole mass is at maximum value.");
    }
  }

  // Handle click on "+"" icon for stars multiplier
  if (hudWindow.mouseOverStarMultiplierIconPlus()) {
    println("Star Multiplier Icon Plus Clicked");
    if (points > 0 && starMultiplier < MAX_STAR_MULTIPLIER) {
      points -= pointsMultiplier;
      hudWindow.updateStarMultiplier(starMultiplier + pointsMultiplier);
    } else {
      println("Star multiplier is at maximum value.");
    }
  }

  // Handle click on "+"" icon for rainbow multiplier
  if (hudWindow.mouseOverRainbowMultiplierIconPlus()) {
    println("Rainbow Multiplier Icon Plus Clicked");
    if (points > 0 && rainbowMultiplier < MAX_RAINBOW_MULTIPLIER) {
      points -= pointsMultiplier;
      hudWindow.updateRainbowMultiplier(rainbowMultiplier + pointsMultiplier);
    } else {
      println("Rainbow multiplier is at maximum value.");
    }
  }

  // Handle click on the points multiplier text
  if (hudWindow.mouseOverPointsMultiplier()) {
    println("Points Multiplier Text Clicked");
    togglePointsMultiplier();
  }

  // Handle click on the minimize button
  if (hudWindow.overMinimizeButton(mouseX, mouseY)) {
    hudWindow.toggleMinimize();
  }

  if (consoleWindow.visible) {
    if (consoleWindow.overTitleBar(mouseX, mouseY)) {
      consoleWindow.startDragging(mouseX, mouseY);
    } else if (consoleWindow.overResizeArea(mouseX, mouseY)) {
      consoleWindow.startResizing(mouseX, mouseY);
    } else {
      // Handle console window specific mousePressed events
      consoleWindow.handleMousePressed();
    }
  } else if (hudWindow.overWindow(mouseX, mouseY)) {
    hudWindow.startDragging(mouseX, mouseY);
  } else {
    checkHUDClicks();
  }
}

void mouseDragged() {
  if (consoleWindow.dragging || consoleWindow.resizing) {
    consoleWindow.update(mouseX, mouseY);
  } else if (consoleWindow.visible) {
    // Handle console window specific mouseDragged events
    consoleWindow.handleMouseDragged();
  } else if (hudWindow.dragging || hudWindow.resizing) {
    hudWindow.update(mouseX, mouseY);
  }
}

void mouseReleased() {
  if (consoleWindow.dragging || consoleWindow.resizing) {
    consoleWindow.stopDragging();
    consoleWindow.stopResizing();
  }
  if (hudWindow.dragging || hudWindow.resizing) {
    hudWindow.stopDragging();
    hudWindow.stopResizing();
  }
  if (consoleWindow.visible) {
    // Handle console window specific mouseReleased events
    consoleWindow.handleMouseReleased();
  }
}

void mouseWheel(MouseEvent event) {
  if (consoleWindow.visible && consoleWindow.overWindow(mouseX, mouseY)) {
    consoleWindow.mouseWheel(event);
  }
}

void keyPressed() {
  if (key == CODED && keyCode == 155) { // Key code for the "Insert" key
    consoleWindow.toggleVisibility(); // Toggle console window visibility
  } else if (consoleWindow.visible) {
    consoleWindow.handleKeyPressed();
  }
}

void checkHUDClicks() {
  float plusSize = textWidth("+");
  int baseY = height - 250;
  
  // Check if click is on the + for Black Hole Mass
  if (mouseY > baseY + 40 - gameFont.getSize() && mouseY < baseY + 40) {
    if (mouseX > width / 2 - textWidth("Black Hole Mass: " + blackHoleMass) / 2 - plusSize && mouseX < width / 2 - textWidth("Black Hole Mass: " + blackHoleMass) / 2) {
      if (points > 0 && blackHoleMass < MAX_BLACK_HOLE_MASS) {
        points -= pointsMultiplier;
        updateBlackHoleMass(blackHoleMass + pointsMultiplier);
      } else {
        println("Black hole mass is at maximum value.");
      }
    }
  }
  
  // Check if click is on the + for Gravity Pull
  if (mouseY > baseY + 80 - gameFont.getSize() && mouseY < baseY + 80) {
    if (mouseX > width / 2 - textWidth("Gravity Pull: " + gravityPull) / 2 - plusSize && mouseX < width / 2 - textWidth("Gravity Pull: " + gravityPull) / 2) {
      if (points > 0 && gravityPull < MAX_GRAVITY_PULL) {
        points -= pointsMultiplier;
        updateGravityPull(gravityPull + pointsMultiplier);
      } else {
        println("Gravity pull is at maximum value.");
      }
    }
  }

  // Check if click is on the + for Stars Speed
  if (mouseY > baseY + 120 - gameFont.getSize() && mouseY < baseY + 120) {
    if (mouseX > width / 2 - textWidth("Stars Speed: " + starSpeedDisplay) / 2 - plusSize && mouseX < width / 2 - textWidth("Stars Speed: " + starSpeedDisplay) / 2) {
      if (points > 0 && starSpeedDisplay < MAX_STAR_SPEED) {
        points -= pointsMultiplier;
        updateStarSpeed(starSpeedDisplay + pointsMultiplier);
      } else {
        println("Star speed is at maximum value.");
      }
    }
  }
  
  // Check if click is on the + for Stars Multiplier
  if (mouseY > baseY + 160 - gameFont.getSize() && mouseY < baseY + 160) {
    if (mouseX > width / 2 - textWidth("Stars Multiplier: " + starMultiplier) / 2 - plusSize && mouseX < width / 2 - textWidth("Stars Multiplier: " + starMultiplier) / 2) {
      if (points > 0 && starMultiplier < MAX_STAR_MULTIPLIER) {
        points -= pointsMultiplier;
        updateStarMultiplier(starMultiplier + pointsMultiplier);
      } else {
        println("Star multiplier is at maximum value.");
      }
    }
  }
}

void setPoints(int newPoints) {
  if (newPoints > MAX_POINTS) {
    newPoints = MAX_POINTS;
    consoleWindow.consoleText.add("The MAX Value Can Only Be: " + MAX_POINTS);
  }
  points = min(newPoints, MAX_POINTS);
}

void setGravityPull(int newGravityPull) {
  updateGravityPull(newGravityPull);
  consoleWindow.consoleText.add("Gravity pull set to: " + gravityPull);
}

void setBlackHoleMass(int mass) {
  updateBlackHoleMass(mass);
}

void setStarMultiplier(int multiplier) {
  updateStarMultiplier(multiplier);
  consoleWindow.consoleText.add("Stars multiplier set to: " + starMultiplier);
}

void setRainbowMultiplier(int multiplier) {
  updateRainbowMultiplier(multiplier);
  consoleWindow.consoleText.add("Rainbow multiplier set to: " + rainbowMultiplier);
}

void setDelayVisible(boolean visibility) {
  delayVisible = visibility;
  consoleWindow.consoleText.add("Delay visibility set to: " + (visibility ? "on" : "off"));
}

float calculateBalancedGrowth(int baseValue, float k, int pointsSpent) {
  return baseValue * pow(1 + k, log(pointsSpent + 1) * 2);
}

void updateBlackHoleMass(int mass) {
  if (mass > MAX_BLACK_HOLE_MASS) {
    mass = MAX_BLACK_HOLE_MASS;
    consoleWindow.consoleText.add("The MAX Value Can Only Be: " + MAX_BLACK_HOLE_MASS);
  }
  blackHoleMass = min(max(1, mass), MAX_BLACK_HOLE_MASS);
  float newSize = max(INITIAL_BLACK_HOLE_SIZE, calculateBalancedGrowth(INITIAL_BLACK_HOLE_SIZE, kGrowth, blackHoleMass));
  blackHole.setSize(newSize);
  println("Black hole mass updated: " + blackHoleMass + ", New size: " + newSize);
}

void updateGravityPull(int pull) {
  if (pull > MAX_GRAVITY_PULL) {
    pull = MAX_GRAVITY_PULL;
    consoleWindow.consoleText.add("The MAX Value Can Only Be: " + MAX_GRAVITY_PULL);
  }
  gravityPull = min(max(1, pull), MAX_GRAVITY_PULL); // Assuming the minimum pull value is 1
  blackHole.setGravityPullRadius(calculateBalancedGrowth(baseGravityPull, kGravityPull, gravityPull));
  println("Gravity pull radius updated: " + gravityPull);
}

void updateStarSpeed(int speed) {
  if (speed > MAX_STAR_SPEED) {
    speed = MAX_STAR_SPEED;
    consoleWindow.consoleText.add("The MAX Value Can Only Be: " + MAX_STAR_SPEED);
  }
  starSpeedDisplay = min(max(1, speed), MAX_STAR_SPEED); // Ensure the speed display doesn’t go below 1
  BlackHoleFrenzy.starSpeed = calculateBalancedGrowth(baseStarSpeedDisplay, kStarSpeed, starSpeedDisplay) * 0.1;
  println("Star speed updated: " + starSpeedDisplay);
}

void updateStarMultiplier(int multiplier) {
  if (multiplier > MAX_STAR_MULTIPLIER) {
    multiplier = MAX_STAR_MULTIPLIER;
    consoleWindow.consoleText.add("The MAX Value Can Only Be: " + MAX_STAR_MULTIPLIER);
  }
  starMultiplier = min(max(1, multiplier), MAX_STAR_MULTIPLIER); // Ensure the multiplier doesn’t go below 1
  BlackHoleFrenzy.spawnMultiplier = calculateBalancedGrowth(baseStarMultiplier, kStarMultiplier, starMultiplier);
  println("Star multiplier updated: " + starMultiplier);
}

void updateRainbowMultiplier(int multiplier) {
  if (multiplier > MAX_RAINBOW_MULTIPLIER) {
    multiplier = MAX_RAINBOW_MULTIPLIER;
    consoleWindow.consoleText.add("The MAX Value Can Only Be: " + MAX_RAINBOW_MULTIPLIER);
  }
  rainbowMultiplier = min(max(1, multiplier), MAX_RAINBOW_MULTIPLIER); // Ensure the multiplier doesn’t go below 1
  rainbowStarSpawnInterval = starSpawnInterval * (50 / (1 + log(rainbowMultiplier) * 0.1)); // Adjust spawn interval based on multiplier
  println("Rainbow multiplier updated: " + rainbowMultiplier);
}

void togglePointsMultiplier() {
  switch (pointsMultiplier) {
    case 1:
      pointsMultiplier = 10;
      break;
    case 10:
      pointsMultiplier = 100;
      break;
    case 100:
      pointsMultiplier = 1000;
      break;
    case 1000:
      pointsMultiplier = 10000;
      break;
    case 10000:
      pointsMultiplier = MAX_POINTS;
      break;
    default:
      pointsMultiplier = 1;
  }
}

String getPointsMultiplierText() {
  if (pointsMultiplier == MAX_POINTS) {
    return "MAX";
  }
  return pointsMultiplier + "X";
}

// New console commands

void setResolution(String resolution) {
  String[] dims = split(resolution, 'x');
  if (dims.length == 2) {
    int w = int(trim(dims[0]));
    int h = int(trim(dims[1]));
    if (w > 0 && h > 0) {
      targetWidth = w;
      targetHeight = h;
      size(targetWidth, targetHeight);
      consoleWindow.consoleText.add("Resolution set to: " + w + "x" + h);
    } else {
      consoleWindow.consoleText.add("Invalid resolution dimensions.");
    }
  } else {
    consoleWindow.consoleText.add("Invalid resolution format. Use WIDTHxHEIGHT (e.g., 1920x1080).");
  }
}

void setScreenMode(String mode) {
  screenMode = mode.toLowerCase();
  toggleFullscreen = true;
  if (screenMode.equals("fullscreen")) {
    surface.setVisible(false);
    fullScreen();
    surface.setVisible(true);
  } else if (screenMode.equals("windowedfullscreen")) {
    surface.setVisible(false);
    size(displayWidth, displayHeight, P2D);
    surface.setLocation(0, 0);
    surface.setVisible(true);
  } else if (screenMode.equals("windowed")) {
    surface.setVisible(false);
    size(targetWidth, targetHeight);
    surface.setLocation((displayWidth - targetWidth) / 2, (displayHeight - targetHeight) / 2);
    surface.setVisible(true);
    restoreWindowedMode(); // Restore window decorations
  } else {
    consoleWindow.consoleText.add("Invalid screen mode. Use fullscreen, windowedfullscreen, or windowed.");
  }
}

That’s my code, for this spesific pde file, i am trying to be able to switch from full screen to windowed without losing the window decorations (the top bar with the X - Minimize icons)
the current problem is that when i use console to switch to from default fullscreen to windowed
the window becomes smaller without the top bar and all that so it’s not really windowed

this is the code related to my console

next comment

code related to console

import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Clipboard;
import java.awt.Toolkit;

class MovableResizableWindow {
  float x, y, w, h;
  boolean dragging = false;
  boolean resizing = false;
  boolean visible = false;
  PVector dragOffset;
  PVector resizeOffset;
  PFont font;
  PFont consoleFont;
  ArrayList<String> consoleText = new ArrayList<String>();
  int scrollPos = 0;
  int lineHeight = 20;
  int visibleLines;
  boolean isSelecting = false;
  int selectionStartLine = -1;
  int selectionEndLine = -1;
  int selectionStartChar = -1;
  int selectionEndChar = -1;
  String userInput = "";
  boolean inputActive = false;
  BlackHoleFrenzy gameInstance;

  // Minimum dimensions for the console window
  final float minWidth;
  final float minHeight;

  // CMD colors
  color cmdBackgroundColor = color(12, 13, 13, 165);  // #0c0d0d Black background with 65% opacity
  color cmdTextColor = color(192, 192, 192, 165);     // #C0C0C0 Light gray text with 65% opacity
  color cmdSelectionColor = color(192, 192, 192, 150);  // Light gray with 150 alpha for selection
  color strokeColor = color(50); // Dark grey stroke color

  MovableResizableWindow(float x, float y, float w, float h, PFont consoleFont, BlackHoleFrenzy gameInstance) {
    this.x = x;
    this.y = y;
    this.w = w;
    this.h = h;
    this.consoleFont = consoleFont;
    this.gameInstance = gameInstance;
    dragOffset = new PVector();
    resizeOffset = new PVector();
    font = createFont("Arial", 16, true);
    visibleLines = int((h - 110) / lineHeight);
    this.minWidth = w;
    this.minHeight = h;
  }

  void display() {
    if (visible) {
      fill(cmdBackgroundColor);
      stroke(strokeColor); // Dark grey stroke color
      rect(x, y, w, h);
      fill(cmdTextColor);
      textFont(consoleFont); // Use console font for title
      textAlign(CENTER, CENTER);
      text("Console Window", x + w / 2, y + 20);
      
      fill(cmdBackgroundColor);
      stroke(strokeColor); // Add stroke to inner area
      rect(x + 10, y + 40, w - 20, h - 110);
      
      noStroke();
      if (selectionStartLine != -1 && selectionEndLine != -1) {
        fill(cmdSelectionColor);
        for (int i = min(selectionStartLine, selectionEndLine); i <= max(selectionStartLine, selectionEndLine); i++) {
          int lineY = int(y + 50 + lineHeight * (i - max(0, consoleText.size() - visibleLines - scrollPos)));
          if (i == selectionStartLine && i == selectionEndLine) {
            float startX = x + 20 + textWidth("> ") + textWidth(getSubstring(consoleText.get(i), 0, min(selectionStartChar, selectionEndChar)));
            float endX = (selectionEndChar > consoleText.get(i).length()) ? x + w - 20 : x + 20 + textWidth("> ") + textWidth(getSubstring(consoleText.get(i), 0, max(selectionStartChar, selectionEndChar)));
            rect(startX, lineY, endX - startX, lineHeight);
          } else if (i == selectionStartLine) {
            float startX = x + 20 + textWidth("> ") + textWidth(getSubstring(consoleText.get(i), 0, min(selectionStartChar, selectionEndChar)));
            rect(startX, lineY, x + w - startX - 20, lineHeight);
          } else if (i == selectionEndLine) {
            float endX = (selectionEndChar > consoleText.get(i).length()) ? x + w - 20 : x + 20 + textWidth("> ") + textWidth(getSubstring(consoleText.get(i), 0, max(selectionStartChar, selectionEndChar)));
            rect(x + 20 + textWidth("> "), lineY, endX - (x + 20 + textWidth("> ")), lineHeight);
          } else {
            rect(x + 20 + textWidth("> "), lineY, w - 40 - textWidth("> "), lineHeight);
          }
        }
      }
      
      fill(cmdTextColor);
      textFont(consoleFont);
      textAlign(LEFT, TOP);
      int start = max(0, consoleText.size() - visibleLines - scrollPos);
      int end = min(consoleText.size(), consoleText.size() - scrollPos);
      for (int i = start; i < end; i++) {
        String line = consoleText.get(i);
        int lineY = int(y + 50 + lineHeight * (i - start));
        text("> " + line, x + 20, lineY);
      }
      
      fill(cmdBackgroundColor);
      stroke(strokeColor); // Add stroke to input area
      rect(x + 10, y + h - 40, w - 20, 30);
      fill(cmdTextColor);
      textAlign(LEFT, CENTER);
      text("> " + userInput, x + 20, y + h - 25);
    }
  }

  void toggleVisibility() {
    visible = !visible;
  }

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

  void startResizing(float mx, float my) {
    if (overResizeArea(mx, my)) {
      resizing = true;
      resizeOffset.set(mx - (x + w), my - (y + h));
    }
  }

  void stopDragging() {
    dragging = false;
  }

  void stopResizing() {
    resizing = false;
  }

  void update(float mx, float my) {
    if (dragging) {
      x = mx - dragOffset.x;
      y = my - dragOffset.y;
    } else if (resizing) {
      w = max(minWidth, mx - x - resizeOffset.x);
      h = max(minHeight, my - y - resizeOffset.y);
      visibleLines = int((h - 110) / lineHeight);
    }
  }

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

  boolean overResizeArea(float mx, float my) {
    return visible && mx > x + w - 20 && mx < x + w && my > y + h - 20 && my < y + h;
  }

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

  void handleMousePressed() {
    int start = max(0, consoleText.size() - visibleLines - scrollPos);
    int end = min(consoleText.size(), consoleText.size() - scrollPos);
    int lineIndex = constrain((mouseY - int(y) - 50) / lineHeight + start, 0, consoleText.size() - 1);

    if (consoleText.size() > 0) {
      int charIndex = getCharIndex(consoleText.get(lineIndex), mouseX - x - 20 - textWidth("> "));

      if (mouseX >= x + 20 && mouseX < x + w - 20 && mouseY >= y + 50 && mouseY < y + h - 110) {
        isSelecting = true;
        selectionStartLine = lineIndex;
        selectionEndLine = lineIndex;
        selectionStartChar = charIndex;
        selectionEndChar = charIndex;
      }
    }

    if (mouseX >= x + 20 && mouseX < x + w - 20 && mouseY >= y + h - 40 && mouseY < y + h - 10) {
      inputActive = true;
    } else {
      inputActive = false;
    }
  }

  void handleMouseDragged() {
    int start = max(0, consoleText.size() - visibleLines - scrollPos);
    int end = min(consoleText.size(), consoleText.size() - scrollPos);
    int lineIndex = constrain((mouseY - int(y) - 50) / lineHeight + start, 0, consoleText.size() - 1);

    if (consoleText.size() > 0) {
      int charIndex = getCharIndex(consoleText.get(lineIndex), mouseX - x - 20 - textWidth("> "));

      if (isSelecting) {
        selectionEndLine = lineIndex;
        selectionEndChar = charIndex;
      }
    }
  }

  void handleMouseReleased() {
    if (isSelecting) {
      isSelecting = false;
      copySelectionToClipboard();
    }
  }

  int getCharIndex(String line, float x) {
    if (line.length() == 0) return 0;
    float width = 0;
    for (int i = 0; i <= line.length(); i++) {
      float charWidth = (i == line.length()) ? textWidth(" ") : textWidth(line.charAt(i));
      if (width + charWidth >= x) {
        return i;
      }
      width += charWidth;
    }
    return line.length() + (int)((x - width) / textWidth(" "));
  }

  String getSubstring(String line, int start, int end) {
    return line.substring(start, min(end, line.length())) + " ".repeat(max(0, end - line.length()));
  }

  void copySelectionToClipboard() {
    if (selectionStartLine >= 0 && selectionEndLine >= 0) {
      int startLine = min(selectionStartLine, selectionEndLine);
      int endLine = max(selectionStartLine, selectionEndLine);
      StringBuilder selectedText = new StringBuilder();

      for (int i = startLine; i <= endLine; i++) {
        int startChar = (i == selectionStartLine) ? min(selectionStartChar, selectionEndChar) : 0;
        int endChar = (i == selectionEndLine) ? max(selectionStartChar, selectionEndChar) : consoleText.get(i).length();

        startChar = constrain(startChar, 0, consoleText.get(i).length());
        if (endChar > consoleText.get(i).length()) {
          selectedText.append(consoleText.get(i).substring(startChar) + " ".repeat(endChar - consoleText.get(i).length())).append("\n");
        } else {
          selectedText.append(consoleText.get(i).substring(startChar, endChar)).append("\n");
        }
      }

      StringSelection stringSelection = new StringSelection(selectedText.toString());
      Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
      clipboard.setContents(stringSelection, null);
    }
  }

  void handleKeyPressed() {
    if (inputActive) {
      char c = key;

      if (key == ENTER || key == RETURN) {
        processCommand(userInput);
        userInput = "";
      } else if (key == BACKSPACE) {
        if (userInput.length() > 0) {
          userInput = userInput.substring(0, userInput.length() - 1);
        }
      } else if (key == TAB) {
        // Ignore tab key
      } else if (isAllowedCharacter(c)) {
        userInput += c;
      }
    } else if (isAllowedCharacter(key)) {
      inputActive = true;
      userInput += key;
    }
  }

  boolean isAllowedCharacter(char c) {
    return (Character.isLetterOrDigit(c) || c == ' ' || c == '-') && 
           (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.BASIC_LATIN);
  }

  void processCommand(String command) {
    command = command.trim().toLowerCase();
    String[] parts = command.split(" ");
    if (parts.length == 0) return;

    switch (parts[0]) {
      case "set":
        if (parts.length > 2) {
          try {
            int value = Integer.parseInt(parts[2]);
            switch (parts[1]) {
              case "speed":
                gameInstance.updateStarSpeed(value);
                break;
              case "multiplier":
                gameInstance.updateStarMultiplier(value);
                break;
              case "points":
                gameInstance.setPoints(value);
                break;
              case "mass":
                gameInstance.updateBlackHoleMass(value);
                break;
              case "pull":
                gameInstance.updateGravityPull(value);
                break;
              case "rainbowmultiplier":
                gameInstance.updateRainbowMultiplier(value);
                break;
              default:
                consoleText.add("UNKNOWN SET COMMAND: " + parts[1]);
            }
          } catch (NumberFormatException e) {
            consoleText.add("INVALID NUMBER: " + parts[2]);
          }
        } else {
          consoleText.add("INVALID SET COMMAND FORMAT");
        }
        break;
      case "pull":
        if (parts.length > 1) {
          if (parts[1].equals("visible")) {
            if (parts.length > 2) {
              if (parts[2].equals("on")) {
                gameInstance.pullAreaVisible = true;
                consoleText.add("Pull area visibility turned on.");
              } else if (parts[2].equals("off")) {
                gameInstance.pullAreaVisible = false;
                consoleText.add("Pull area visibility turned off.");
              } else {
                consoleText.add("Invalid option for pull visibility: " + parts[2]);
              }
            } else {
              consoleText.add("Missing parameter for pull visibility. Use 'on' or 'off'.");
            }
          } else {
            consoleText.add("Unknown pull command: " + parts[1]);
          }
        } else {
          consoleText.add("Invalid pull command format.");
        }
        break;
      case "delay":
        if (parts.length > 1) {
          if (parts[1].equals("visible")) {
            if (parts.length > 2) {
              if (parts[2].equals("on")) {
                gameInstance.setDelayVisible(true);
                consoleText.add("Delay visibility turned on.");
              } else if (parts[2].equals("off")) {
                gameInstance.setDelayVisible(false);
                consoleText.add("Delay visibility turned off.");
              } else {
                consoleText.add("Invalid option for delay visibility: " + parts[2]);
              }
            } else {
              consoleText.add("Missing parameter for delay visibility. Use 'on' or 'off'.");
            }
          } else {
            consoleText.add("Unknown delay command: " + parts[1]);
          }
        } else {
          consoleText.add("Invalid delay command format.");
        }
        break;
      case "help":
        displayHelp();
        break;
      case "setreso":
        if (parts.length == 2) {
          String[] resolution = parts[1].split("x");
          if (resolution.length == 2) {
            try {
              int width = Integer.parseInt(resolution[0]);
              int height = Integer.parseInt(resolution[1]);
              surface.setSize(width, height);
              consoleText.add("Resolution set to: " + width + "x" + height);
            } catch (NumberFormatException e) {
              consoleText.add("Invalid resolution format. Use WIDTHxHEIGHT.");
            }
          } else {
            consoleText.add("Invalid resolution format. Use WIDTHxHEIGHT.");
          }
        } else {
          consoleText.add("Invalid setreso command format.");
        }
        break;
      case "screenmode":
        if (parts.length == 2) {
          if (parts[1].equals("fullscreen")) {
            surface.setVisible(false);
            gameInstance.fullScreen();
            surface.setVisible(true);
            consoleText.add("Screen mode set to fullscreen.");
          } else if (parts[1].equals("windowedfullscreen")) {
            surface.setVisible(false);
            surface.setSize(displayWidth, displayHeight);
            surface.setLocation(0, 0);
            surface.setVisible(true);
            consoleText.add("Screen mode set to windowed fullscreen.");
          } else if (parts[1].equals("windowed")) {
            surface.setVisible(false);
            surface.setSize(1920, 1080); // Set default windowed size
            surface.setLocation((displayWidth - 1920) / 2, (displayHeight - 1080) / 2);
            surface.setResizable(true);
            surface.setVisible(true);
            consoleText.add("Screen mode set to windowed.");
          } else {
            consoleText.add("Invalid screen mode. Use fullscreen, windowedfullscreen, or windowed.");
          }
        } else {
          consoleText.add("Invalid screenmode command format.");
        }
        break;
      default:
        consoleText.add("UNKNOWN COMMAND: " + command);
    }
    scrollToBottom();
  }

  void displayHelp() {
    consoleText.add("List Of All Commands:");
    consoleText.add("set speed [value] - Set the star speed.");
    consoleText.add("set multiplier [value] - Set the spawn multiplier.");
    consoleText.add("set points [value] - Set the points.");
    consoleText.add("set mass [value] - Set the black hole mass.");
    consoleText.add("set pull [value] - Set the gravity pull.");
    consoleText.add("set rainbowmultiplier [value] - Set the rainbow star spawn multiplier.");
    consoleText.add("pull visible on/off - Toggle pull area visibility.");
    consoleText.add("delay visible on/off - Toggle delay information visibility.");
    consoleText.add("setreso WIDTHxHEIGHT - Set the resolution.");
    consoleText.add("screenmode MODE - Set the screen mode (fullscreen, windowedfullscreen, windowed).");
    consoleText.add("help - Display this help message.");
  }

  void scrollToBottom() {
    scrollPos = 0;
  }

  void mouseWheel(MouseEvent event) {
    if (visible && overWindow(mouseX, mouseY)) {
      float scrollAmount = event.getCount();
      scrollPos = max(0, min(scrollPos - int(scrollAmount), consoleText.size() - visibleLines));
    }
  }
}

Hi @winterchan,

To much code to track now in my head, as I’m not at my box… :slight_smile:

Regarding:
No library found for processing.awt.PSurfaceAWT

Try
import processing.awt.*;
instead and get the JFrame like this…

JFrame frame=(JFrame) ((PSurfaceAWT.SmoothCanvas)getSurface().getNative()).getFrame();

Should work …

Cheers
— mnse

PS: Hope you’ve not messed up the processing environment, by your tries with core.jar :crossed_fingers:

2 Likes

Thanks, what you offered let me load the game without error but it doesn’t solve my problem

someone told me in reddit “In my experience you can change window size at runtime but you can’t change whether you have a decorated window - either you start in fullScreen() or you get the window handle, no way around it afaik.”

do you think theres really no way to do that?

Hi @winterchan,

here’s something to tinker with. hope that helps …

Cheers
— mnse

import processing.awt.*;
import javax.swing.*;
import java.awt.*;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsDevice;

GraphicsDevice device;
JFrame frame;
Dimension prevDimension;
Rectangle bounds;
int mode = 0;

void setup() {
	size(500,500);
  frame=(JFrame) ((PSurfaceAWT.SmoothCanvas)getSurface().getNative()).getFrame();
  prevDimension = ((PSurfaceAWT.SmoothCanvas)getSurface().getNative()).getPreferredSize();
  bounds = frame.getBounds();
  GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  device = ge.getDefaultScreenDevice();  
}

void keyReleased() {
  if (key == ' ') { // press space
    switch(++mode % 2) {
      case 0:
        frame.setVisible(false);
        frame.dispose();
        frame.setUndecorated(false);
        frame.setBounds(bounds);
        surface.setSize((int)prevDimension.getWidth(),(int)prevDimension.getHeight());          
        device.setFullScreenWindow(null);
        frame.setVisible(true);
        break;
      case 1:
        frame.setVisible(false);
        frame.dispose();
        frame.setUndecorated(true);
        surface.setSize(displayWidth,displayHeight);
        device.setFullScreenWindow(frame);
        frame.setVisible(true);
        break;
    }  
    ((PSurfaceAWT.SmoothCanvas)getSurface().getNative()).requestFocus();
  }
}

void draw() {
  background(0);
  fill(255,0,255);
  noStroke();
  ellipse(width/2,height/2,height/2,height/2);
}
1 Like

Hi, thanks a lot for taking the time and finding this, so first of all that worked, does require a little bit of de-bugging but that’s something related to my console so ill figure that out, but ill do appreciate if you could elaborate on how did you make that work and what made that specific code work. Thanks a lot and have a great day!

1 Like

Hi @winterchan,

Hmmm! There is no magic voodoo behind.
Basically, it stores the settings (window size) on the beginning and then by pressing space it switches to fullscreen an back to window mode with the stored settings. In best case this values should be stored before switching to fullscreen to get back to those settings when switching back to window mode…

Generally it does.

  • Release the window frame to be able to apply new settings
  • Apply the wanted settings
  • Show the window again by set visible

Cheers
— mnse

3 Likes