Search code examples
memoryprocessing

Issue with memory in Processing, program slowly climbs in memory and then crashes


I am making a short game in Processing, although I'm having an issue with the program crashing if I leave it running too long. When I open the program, the memory slowly rises to 800 MB, then as it nears 900 MB, it dies down and slowly goes back down. Whenever it hits around 500 MB, the program crashes. I am fairly new to using Processing, so I am probably just forgetting something and a counter is getting out of hand, but I don't seem to be able to find the issue. Thanks for reading.

I haven't been able to figure out much regarding the issue, I have already researched "System.gc();" but I'm not sure if this is part of the issue and how to implement this, as I have already attempted.

//Imports
import processing.sound.*;

//Global variables
int gameState = 0; //Using an integer value just in case I want to add more maps in future updates
int backX = 1800; //Current background x value
float theta = 0.0; //Used to control sin wave for oscillation
int menuCounter = 0; //Main menu space bar counter
int menuSpaceSize = 25; //Space text size
int menuSpaceX = 90; //Space text menu
float menuSpaceModifier = 1.0; //Allows for space text movement
int mainMenuX = 50; //Main menu x position
color spaceColor = color(255); //Color the space text is (used for color changes on space press)
boolean[] keys = new boolean[4]; //WASD keys
PImage backImage; //Images
SoundFile select, bg, menubg; //Sound files
boolean bgPlay, menuPlay = false; //Music Playing boolean

//Setup function (Runs once)
void setup() {
  //Set frame name
  surface.setTitle("Game");

  //Size
  size(600, 600, P3D);

  //Load images
  backImage = loadImage("https://github.com/Attaxika/stuff/blob/master/BackgroundImage.png?raw=true");

  //Load sound files
  select = new SoundFile(this, "https://raw.githubusercontent.com/Attaxika/stuff/master/select.wav?raw=true");
  bg = new SoundFile(this, "https://raw.githubusercontent.com/Attaxika/stuff/master/bg.mp3?raw=true");
  menubg = new SoundFile(this, "https://raw.githubusercontent.com/Attaxika/stuff/master/menu.wav?raw=true");
}

//Draw function (Runs 60 times a second)
void draw() {
  //Reset opacity
  tint(255, 255);

  //Reset color
  fill(0);

  //Make smooth
  smooth();

  //Background
  background(0, 0, 0);

  //Framerate set
  frameRate(60);

  //If the game isn't running
  if(gameState == 0) {
    //Stop background music
    bg.stop();
    bgPlay = false;

    //Start menu music
    if(!menuPlay) {
      menuPlay = true;
      menubg.amp(1);
      menubg.loop();
    }

    //Main menu
    textSize(50);

    //y value for main menu text oscillation
    float y = (sin(theta) + 1 ) * 20;

    //Increment theta
    theta += 0.05;

    //Primary game menu
    fill(255, 0, 0);
    text("Game Menu", width/2 - 150, y + 75);

    //4th fill value represents alpha
    fill(255, 255, 255, 25);
    //Shadow Text
    text("Game Menu", width/2 - 155, y + 74);

    //Space to start text
    fill(spaceColor);
    textSize(menuSpaceSize);
    text("Space to Start", (width/2 - menuSpaceX) + menuSpaceModifier, 200);

    //Check for space pressed
    if(menuCounter > 0 && menuCounter < 30) {
      menuCounter += 1;
      menuSpaceSize = 30;
      menuSpaceX = 140;
      menuSpaceModifier += 20;
    }

    //Check for space timer
    if(menuCounter == 29) {
      gameState = 1;
    }
  }
  //If the game is running
  else if(gameState == 1) {
    //Music start
    if(!bgPlay) {
      //Stop menu music
      menuPlay = false;
      menubg.stop();

      bgPlay = true;
      bg.amp(.40);
      bg.loop();
    }

    //Background image
    imageMode(CENTER);
    image(backImage, backX, backImage.height / 2, backImage.width, backImage.height);
    backX -= 1;

    //Reset background x if it gets to the end
    if(backX <= 0) {
      backX = 1800;
    }
  }

  //Unknown gameState
  else {
    exit();
  }
}

//Key pressing (Keyboard input)
void keyPressed() {
  //Pressed space & is on menu
  if(key == ' ' && gameState == 0 && menuCounter == 0) {
    spaceColor = color(0, 255, 0);
    menuCounter += 1;
    select.play();
    bgPlay = true;
  }
}

The expected result would be for it to run over a long period of time without taking up memory to the point where it crashes.

EDIT: Someone responded but deleted their response, but I followed some instructions, but to no avail. I added the following code to my program, the menu screen now runs indefinitely with low memory usage, but entering the actual game (gameState = 1) causes it to crash, stating that it had a NullPointerException at "image(backImage, backX, backImage.height / 2, backImage.width, backImage.height);"

Here's what I added directly after my "void draw() {"

  clear();

  if(backImage!=null) {
    image(backImage, backX, backImage.height / 2, backImage.width, backImage.height);
  }

  if(millis() > 20000 && backImage!=null) {
    g.removeCache(backImage);
    backImage = null;
  }
  System.gc();

Solution

  • After looking through my code and looking through some peoples' suggestions and finding out that it wasn't something to do with an image being rendered multiple times and never being cleared or my sound files, I found out that my issues were coming from me using the P3D renderer. I removed the "P3D" from my size(); and then my memory usage for the program stabilized below 200 MB and never spiked. (As far as I know, using a shape and then applying a texture on top of that 3D shape is a potential solution if you don't want to use the default 2D renderer)