Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

  • Makeing a Timer Function Without Global Variables

    Thank you GoToLoop for the link. I'm still a little confused by the example on the GitHub page though.

    I'm not trying to create a stopwatch type of timer. I understand how that works. What I'm trying to create is something where every "x" amount of milliseconds a counter goes up from "n" to "n+1" and will stop at some predetermined number, say "n+100".

    I am using this as part of a larger function that will pull data from somewhere else. For example, when the function runs, rather than arrayofimages[n] being displayed on the screen you will see arrayofimages[n+1]. Then after so many milliseconds arrayofimages[n+2] will appear.

    My apologies if my question was not clear. I'm still getting my sea legs with regards to programming in general.

  • How to start a timer only on a certain scene??

    Hi I'm making a game where I need a timer but it only starts on a certain scene. I need the timer (timer.start()) to start only on level 1. Thanks for the help!

    import lord_of_galaxy.timing_utils.*;
    PImage pic;
    PImage pic2;
    PImage pic3;
    PImage pic4;
    PImage pic5;
    PImage pic6;
    PImage pic7;
    PImage pic8;
    PImage pic9;
    PImage pic10;
    PImage pic11;
    PImage pic12;
    PImage pic13;
    PImage loseImage;
    PFont menuFont;
    PFont animFont;
    PFont loseFont;
    PFont menuFont2;
    PFont menuFont3;
    float imgX = 100;
    float imgY = 750;
    float eggX = 500;
    float eggY = 700;
    float opacity = 0;
    float opacity2 = 255;
    float opacity3 = 0;
    float cloud1 = 100;
    float cloud2 = 300;
    float cloud3 = 500;
    float cloud4 = 700;
    float cloud5 = 900;
    float anim = 5;
    float animTimer = 0;
    float animTimer2 = 0;
    float loseTimer = 0;
    float menuTimer = 0;
    int food = 0;
    float menuX = 500;
    float cloudContinue = 1200;
    String[] lost = new String [2];
    String lose; 
    boolean backgroundIsWhite = false;
    Stopwatch timer;
    Bass[] b = new Bass[2];
    AquaticBug[] a = new AquaticBug[3];
    Mayfly[] m = new Mayfly[3];
    Plankton[] p = new Plankton[4];
    Heron[] h = new Heron[1];
    Pike[] pi = new Pike[2];
    
    String scene = "animation"; 
    
    
    void setup() {
      noStroke();
      size(1000, 1000);
      rectMode(CENTER);
      imageMode(CENTER);
      textAlign(CENTER);
      pic = loadImage("chinook-salmon-alevin.png");
      pic2 = loadImage("491375864 (1).png");
      pic4 = loadImage("Moomans hellgrammite.gif");
      pic5 = loadImage("LargemouthBass.gif");
      pic6 = loadImage("2017-hafele-spinner-3-1110.gif");
      pic7 = loadImage("2921797_orig.gif");
      pic8 = loadImage("plankton-md.gif");
      pic9 = loadImage("532606-ocean-water-wallpaper-1920x1200-xiaomi.gif");
      pic11 = loadImage("heron-clipart-96.gif");
      pic12 = loadImage("northern-pike-800px-Custom.gif");
      pic13 = loadImage("273px-SalmonoidsBergeau.gif");
      loseImage = loadImage("2921797_orig.gif");
      menuFont = loadFont("TwCenMT-CondensedBold-100.vlw");
      animFont = loadFont("TwCenMT-CondensedBold-48.vlw");
      loseFont = loadFont("TwCenMT-CondensedBold-70.vlw");
      menuFont2 = loadFont("TwCenMT-CondensedBold-65.vlw");
      menuFont3 = loadFont("TwCenMT-CondensedBold-40.vlw");
      timer = new Stopwatch(this);   
      for (int i = 0; i < b.length; i++) {
        b[i] = new Bass();
      }
      for (int i = 0; i < a.length; i++) {
        a[i] = new AquaticBug();
      }
      for (int i = 0; i < m.length; i++) {
        m[i] = new Mayfly();
      }
      for (int i = 0; i < p.length; i++) {
        p[i] = new Plankton();
      }
      for (int i = 0; i < h.length; i++) {
        h[i] = new Heron();
      }
      for (int i = 0; i < pi.length; i++) {
        pi[i] = new Pike();
      }
    }
    
    void checkForTimer() {
      if (scene == "level1") {
        timer.start();
      }
    }
    void useCloud() {
      drawCloud(cloud1, 100);
      drawCloud(cloud2, 300);
      drawCloud(cloud3, 100);
      drawCloud(cloud4, 300);
      if (cloud1 < -200) {
        cloud1 = cloudContinue;
      }
      if (cloud2 < -200) {
        cloud2 = cloudContinue;
      }
      if (cloud3 < -200) {
        cloud3 = cloudContinue;
      }
      if (cloud4 < -200) {
        cloud4 = cloudContinue;
      }
      if (cloud5 < -200) {
        cloud5 = cloudContinue;
      }
    }  
    void drawCloud(float a, float b) {
      float one = a; // 100
      float two = a + 50;
      float four = a + 100;
      float six = 100;
      float seven = b; // 100
      float nine = b - 25;
      float eleven = b + 10;
    
      fill(255, 255, 255);
      ellipse(one, seven, six, six);
      ellipse(two, nine, six, six);
      ellipse(four, seven, six, six);
      ellipse(two, eleven, six, six);
    }
    void drawSea() {
      fill(0, 100, 255);
      rect(500, 800, 1300, 550);
      fill(78, 79, 75);
      rect(500, 950, 1500, 100);
    }
    void draw() {
      switch(scene) {
      case "menu" : 
        {
          image(pic9, 500, 500);
          textFont(menuFont);
          fill(0, 0, 0);
          text("A Salmon's Life", 500, 250);
          image(pic2, menuX, 400, 306, 190);
          fill(0, 102, 204);
          rect(500, 500, 200, 100, 200);
          rect(500, 650, 200, 100, 200);
          rect(500, 800, 200, 100, 200);
          fill(255, 255, 255);
          textFont(menuFont2);
          text("PLAY", 500, 517);
          text("INFO", 500, 817);
          text("HOW TO", 500, 670);
          menuTimer += 1;
          if (menuTimer >= 50) {
            menuX -= 4;
          }
          if (menuX <= -350) {
            menuX = 1350;
          }
          if (mouseX > 400 && mouseX < 600 && mouseY > 450 && mouseY < 550) {
            fill(255, 255, 255);
            rect(500, 500, 200, 100, 200);
            textFont(menuFont2);
            fill(0, 102, 204);
            text("PLAY", 500, 517);
          }
          if (mouseX > 400 && mouseX < 600 && mouseY > 450 && mouseY < 550 && mousePressed == true) {
            scene = "level1";
          }
    
          if (mouseX > 400 && mouseX < 600 && mouseY > 750 && mouseY < 850) {
            fill(255, 255, 255);
            rect(500, 800, 200, 100, 200);
            textFont(menuFont2);
            fill(0, 102, 204);
            text("INFO", 500, 817);
          }
          if (mouseX > 400 && mouseX < 600 && mouseY > 750 && mouseY < 850 && mousePressed == true) {
            scene = "info";
          }
    
          if (mouseX > 400 && mouseX < 600 && mouseY > 600 && mouseY < 700) {
            fill(255, 255, 255);
            rect(500, 650, 200, 100, 200);
            textFont(menuFont2);
            fill(0, 102, 204);
            text("HOW TO", 500, 670);
          }
          if (mouseX > 400 && mouseX < 600 && mouseY > 600 && mouseY < 700 && mousePressed == true) {
            scene = "how to";
          }
    
          break;
        }
      case "how to" : 
        {
        }
      case "info" : 
        {
        }
      case "animation" : 
        {
          background(255, 255, 255, opacity2);
          opacity2 -= 5;
          animTimer2 += 1;
          fill(0, 100, 255);
          rect(500, 500, 10000, 10000); // sea background
          fill(78, 79, 75);
          rect(500, 900, 1000, 500); // gravel
          fill(255, 153, 153);
          ellipse(eggX, eggY, 100, 100); // egg
          textFont(menuFont);
          fill(0, 0, 0);
          text("A salmon is hatching!", 500, 200);
          textFont(menuFont3);
          text("Click anywhere to start!", 500, 950); 
          eggX += 0.5;
          eggY += 0.5;
          animTimer += 5;
          if (eggX >= 501) {
            eggX -= 4;
          }
          if (eggY >= 701) {
            eggY -= 3;
          }
          if (animTimer >= 500) {
            backgroundIsWhite = true;
          }
          if (backgroundIsWhite == true) {
            fill(255, 255, 255, opacity);
            rect(0, 0, 10000, 10000);
            opacity += 5;
          }
          if (animTimer >= 1000) {
            backgroundIsWhite = false;
            fill(0, 100, 255);
            rect(500, 0, 10000, 10000);
            fill(78, 79, 75);
            rect(500, 900, 1000, 300);
            fill(255, 153, 153);
            textSize(20);
            textFont(animFont);
            fill(0, 0, 0);
            text("A salmon has hatched! A baby salmon is called an alevin!", 500, 200);
            textFont(menuFont3);
            text("Use the arrow keys to move and avoid the bass and water bugs!", 500, 800);
            text("Click anywhere to start!", 500, 950); 
            image(pic, 500, 550, 250, 125);
          }
          if (mousePressed == true) {
            scene = "menu";
          } 
          break;
        }
    
      case "level1" : 
        {
          background(135, 206, 235);
          drawSea();
          if (keyCode == DOWN && keyPressed == true) {
            imgY += anim;
          }
          if (keyCode == UP && keyPressed == true) {
            imgY -= anim;
          }
          if (keyCode == RIGHT && keyPressed == true) {
            imgX += anim;
          }
          if (keyCode == LEFT && keyPressed == true) {
            imgX -= anim;
          }
          useCloud();
          image(pic, constrain(imgX, 0, width - 100), constrain(imgY, 550, height - 100));
          cloud1 -= 2;
          cloud2 -= 2;
          cloud3 -= 2;
          cloud4 -= 2;
          cloud5 -= 2;
          fill(0, 0, 0);
          textFont(menuFont3);
          text("Survive for 30 seconds!", 830, 50); 
          text(str(timer.time()/1000), 900, 100);
          if (timer.time()/1000 == 30) {
            scene = "transition1";
          }
          for (int i = 0; i < b.length; i++) {
            b[i].bass();
            b[i].move();
          }
          for (int i = 0; i < a.length; i++) {
            a[i].aquaticBug();
            a[i].move();
          }
          for (int i = 0; i < b.length; i++) {
            if (dist(imgX, imgY, b[i].x - 125, b[i].y) < 35) {
              scene = "lose";
              lose = "bass!";
              loseImage = pic5;
            }
          }
          for (int i = 0; i < a.length; i++) {
            if (dist(imgX, imgY, a[i].x - 70, a[i].y) < 40) {
              scene = "lose";
              lose = "water bug!";
              loseImage = pic4;
            }
          }
          break;
        }
      case "transition1" : 
        {
          fill(0, 102, 204, opacity3);
          rect(500, 500, 1500, 1500);
          fill(0, 0, 0);
          textFont(menuFont2);
          text("Nice Job! You beat the first stage!", 500, 300);
          textFont(menuFont3);
          text("You are now a Fry! Click anywhere to continue on!", 500, 700);
          text("Eat:", 100, 800);
          text("Avoid:", 100, 900);
          image(pic6, 170, 790);
          image(pic7, 500, 500);
          image(pic8, 220, 790);
          image(pic5, 350, 890);
          image(pic11, 700, 890);
          if (mousePressed == true) {
            scene = "level2";
          }
          opacity3 += .2;
          break;
        }
      case "level2" : 
        {
          background(135, 206, 235);
          drawSea();
          if (keyCode == DOWN && keyPressed == true) {
            imgY += anim;
          }
          if (keyCode == UP && keyPressed == true) {
            imgY -= anim;
          }
          if (keyCode == RIGHT && keyPressed == true) {
            imgX += anim;
          }
          if (keyCode == LEFT && keyPressed == true) {
            imgX -= anim;
          }
          useCloud();
          image(pic7, constrain(imgX, 100, width - 100), constrain(imgY, 550, height - 100), 150, 50);
          cloud1 -= 2;
          cloud2 -= 2;
          cloud3 -= 2;
          cloud4 -= 2;
          cloud5 -= 2;
          fill(0, 0, 0);
          textFont(menuFont3);
          text("Score: " + food, 900, 90);
          text("Get a food score of 50!", 800, 50);
          if (food == 50) {
            scene = "transition2";
          }
          for (int i = 0; i < m.length; i++) {
            m[i].mayfly();
            m[i].move();
          }
          for (int i = 0; i < p.length; i++) {
            p[i].plankton();
            p[i].move();
          }
          for (int i = 0; i < b.length; i++) {
            b[i].bass();
            b[i].move();
          }
          for (int i = 0; i < h.length; i++) {
            h[i].heron();
            h[i].move();
          }
          for (int i = 0; i < m.length; i++) {
            if (dist(imgX, imgY, m[i].x - 37.5, m[i].y) < 35) {
              food += 5;
              m[i].x = random(1000, 3000);
              m[i].y = random(550, 950);
            }
          }
          for (int i = 0; i < p.length; i++) {
            if (dist(imgX, imgY, p[i].x - 17.25, p[i].y) < 35) {
              food += 5;
              p[i].x = random(1000, 3000);
              p[i].y = random(550, 950);
            }
          }
          for (int i = 0; i < b.length; i++) {
            if (dist(imgX, imgY, b[i].x - 125, b[i].y) < 30) {
              scene = "lose";
              lose = "bass!";
              loseImage = pic5;
            }
          }
          for (int i = 0; i < h.length; i++) {
            if (dist(imgX, imgY, h[i].x + 129, h[i].y + 101) < 30) {
              scene = "lose";
              lose = "heron!";
              loseImage = pic11;
            }
          }
          break;
        }
      case "transition2" : 
        {    
          fill(0, 102, 204, opacity3);
          rect(500, 500, 1500, 1500);
          fill(0, 0, 0);
          textFont(menuFont2);
          text("AMAZING!! You beat the second stage!", 500, 300);
          textFont(menuFont3);
          text("You are now a Parr! Click anywhere to continue on!", 500, 700);
          text("Eat:", 100, 800);
          text("Avoid:", 100, 900);
          image(pic6, 170, 790);
          image(pic13, 500, 500, 400, 143);
          image(pic8, 220, 790);
          image(pic12, 350, 890);
          image(pic11, 700, 890);
          if (mousePressed == true) {
            scene = "level3";
          }
          opacity3 += .2;
          break;
        }
      case "level3" : 
        {
          background(135, 206, 235);
          drawSea();
          if (keyCode == DOWN && keyPressed == true) {
            imgY += anim;
          }
          if (keyCode == UP && keyPressed == true) {
            imgY -= anim;
          }
          if (keyCode == RIGHT && keyPressed == true) {
            imgX += anim;
          }
          if (keyCode == LEFT && keyPressed == true) {
            imgX -= anim;
          }
          useCloud();
          image(pic13, constrain(imgX, 100, width - 100), constrain(imgY, 550, height - 100), 150, 50);
          cloud1 -= 2;
          cloud2 -= 2;
          cloud3 -= 2;
          cloud4 -= 2;
          cloud5 -= 2;
          fill(0, 0, 0);
          textFont(menuFont3);
          text("Survive for 45 seconds!", 830, 50); 
          text(str(timer.time()/1000) + " seconds", 920, 150);
          if (timer.time()/1000 == 45) {
            scene = "transition2";
          }
          text("Get a food score of 150!", 830, 100);
          text("Score: " + food, 930, 200);
          for (int i = 0; i < m.length; i++) {
            m[i].mayfly();
            m[i].move();
          }
          for (int i = 0; i < p.length; i++) {
            p[i].plankton();
            p[i].move();
          }
          for (int i = 0; i < h.length; i++) {
            h[i].heron();
            h[i].move();
          }
          for (int i = 0; i < pi.length; i++) {
            pi[i].pike();
            pi[i].move();
          }
          for (int i = 0; i < m.length; i++) {
            if (dist(imgX, imgY, m[i].x - 37.5, m[i].y) < 35) {
              food += 5;
              m[i].x = random(1000, 3000);
              m[i].y = random(550, 950);
            }
          }
          for (int i = 0; i < p.length; i++) {
            if (dist(imgX, imgY, p[i].x - 17.25, p[i].y) < 35) {
              food += 5;
              p[i].x = random(1000, 3000);
              p[i].y = random(550, 950);
            }
          }
          for (int i = 0; i < h.length; i++) {
            if (dist(imgX, imgY, h[i].x + 129, h[i].y + 101) < 30) {
              scene = "lose";
              lose = "heron!";
              loseImage = pic11;
            }
          }
          for (int i = 0; i < pi.length; i++) {
            if (dist(imgX, imgY, pi[i].x - 200, pi[i].y) < 30) {
              scene = "lose";
              lose = "pike!";
              loseImage = pic12;
            }
          }
          break;
        }
      case "lose" : 
        {
          fill(255, 0, 0, loseTimer);
          rect(500, 500, 1500, 1500);
          fill(0, 0, 0);
          textFont(loseFont);
          text("You became a snack for a " + lose, 500, 400);
          text("Better luck next time...", 500, 800);
          textFont(menuFont);
          text("YOU LOST!!", 500, 300);
          fill(0, 102, 204);
          rect(500, 900, 200, 100, 200);
          textFont(animFont);
          fill(255, 255, 255);
          text("TRY AGAIN", 500, 913);
          image(loseImage, 500, 600);
          if (mouseX > 400 && mouseY > 850 && mouseX < 600 && mouseY < 950) {
            fill(255, 255, 255);
            rect(500, 900, 200, 100, 200);
            textFont(animFont);
            fill(0, 102, 204);
            text("TRY AGAIN", 500, 913);
          } 
          if (mouseX > 400 && mouseY > 850 && mouseX < 600 && mouseY < 950 && mousePressed) {
            scene = "menu";
          }
          loseTimer += 0.2;
          break;
        }
      case "win" : 
        {
        }
      }
    }
    

    Tell me if you need the extra tabs. :-h

  • How to make a timer in processing??

    From the github example:

    import lord_of_galaxy.timing_utils.*;
    
    Stopwatch s;//Declare
    
    void setup(){
      size(640, 360);
    
      //Creating a stopwatch to keep time
      s = new Stopwatch(this);
    
      //Start the stopwatch
      s.start();
    } 
    
    void draw(){
      background(0);
      fill(255);
    
      textSize(50);
    
      //Use s.time() to get current time in milliseconds
      text(str(s.time()), 50, 100);
    }
    

    To get the time in seconds for the last line:

    text("Time in secs: "+str(s.time()/1000.0), 50, 100);

    To format the number, look at round(), floor(), nf() in the reference.

    Kf

  • Using Sprite Library

    Some things you need to know about the Sprites library.

    It was designed to update and display a large number of sprites with minimal programming by the user. To do this the library remembers / registers every sprite created so that they can be updated and drawn as a block with single instructions.

    To do that we need a timing device. In Sprites this is done with the StopWatch class. See line 8.

    In the draw we need to get the elapsed time since the last frame (line 20) and use this to update the sprites animation (line 21). All the sprites are rendered with a the statement S4P.drawSprites(); (see line 27)

    The Sprites uses seconds rather than milliseconds so I have changed the sprite frame sequence statement to

    player.setFrameSequence(0, 3, 0.2);

    The interval time between sprite frames is 0.2 seconds. Also you had the frame sequence 0-40 when in fact there are only 16 frames in the image.

    So here is the corrected code

    import sprites.*;
    import sprites.maths.*;
    import sprites.utils.*;
    Sprite player;
    int i=0;
    float pos_x, pos_y;
    
    StopWatch sw = new StopWatch();
    
    void setup()
    {
      size(600, 600, P2D);
      player=new Sprite(this, "https:// opengameart.org/sites/default/files/daxbotsheet.png", 4, 4, 0);
      player.setFrameSequence(0, 3, 0.2);
    }
    
    void draw()
    {
      // Get the elapsed time and updatre the sprites accordingly
      float elapsedTime = (float) sw.getElapsedTime();
      S4P.updateSprites(elapsedTime);
      // Start of frame rendering
      background(255);
      translate(width/2, height/2);
      translate(pos_x, pos_y);
      // Draw all 'registered' sprites
      S4P.drawSprites();
      if (key==CODED)
      {
        if (keyCode==LEFT)
        {
          pos_x-=3;
        } else if (keyCode==RIGHT)
        {
          pos_x+=3;
        } else if (keyCode==UP)
        {
          pos_y-=3;
        } else if (keyCode==DOWN)
        {
          pos_y+=3;
        }
      }
    }
    

    Note the 'space' after the // in the link this would need to be removed.

  • Strange overlapping of sprites with Sprite library, what's wrong?

    Hello and good day.
    I work with the Sprite library by Peter Lager.
    My current project is a 2D platformer and I got a rly strange problem but I cant't find the exact source.
    I restricted the problem of the overlapping Sprites to the WorldManager class in the void registerWorld(int index) function.
    I use S4P.updateSprites(sw.getElapsedTime()); S4P.drawSprites();
    to display the sprites.
    It seems that all 3 worlds get registered by S4P at the same time.
    The content of the 3 worldfiles I got here is like that,

    OOOOOOOOOO
    
    O________O
    
    OZZZZZZZZO
    

    //GameProject_Disconnect
    import sprites.*;
    import sprites.maths.*;
    import sprites.utils.*;
    import java.util.*;
    import java.lang.*;
    
    StopWatch sw;
    WorldManager wm;
    
    void setup() {
      size(500, 500);
      sw = new StopWatch();
      wm = new WorldManager(this);
    }
    
    
    void draw() {
      background(0);
      S4P.updateSprites(sw.getElapsedTime());
      S4P.drawSprites();
    }
    
    //WorldManager 
    
    class WorldManager {
      FileManager fm;
      WorldTranslater wt;
      ArrayList<World> worlds;
    
      WorldManager(PApplet _pa) {
        fm = new FileManager();
        wt = new WorldTranslater(_pa);
        initWorlds();
        registerWorld(0);
      }
    
    
      void registerWorld(int index) {
        Sprite[][] tempW = worlds.get(index).getWorldMap();
        for (int i=0; i < 5; i++) {
          for (int j=0; j < 10; j++) {
            S4P.registerSprite(tempW[i][j]);
          }
        }
      }
    
    
      private void initWorlds() {
        worlds = new ArrayList<World>();
        for (int i=0; i < fm.getNumberOfWorlds(); i++) {
          World tempWorld = new World(
            fm.getFileContent(i), 
            wt.translateWorld(fm.getFileContent(i)), 
            fm.getTrimmedFilename(i), 
            fm.getWorldPath(i));
          worlds.add(new World());
          worlds.set(i, tempWorld);
        }
        println("Worlds successful loaded!");
      }
    }
    
    //FileManager
    
    class FileManager {
      private String worldPath; // Path of the world files. 
      private String[] rawFilenames; // Filenames with prefix and suffix.
      private String[] trimmedFilenames; // Filenames without prefix and suffix.
      private ArrayList<String[]> fileContent; // Save the file content here. 
      private int numberOfFiles; // Number of worlds found.
    
      FileManager() {
        worldPath = new String(sketchPath() + "/Worlds/");
        readFileDirectory();
        numberOfFiles = rawFilenames.length;
        trimFilenames();
        fileContent  = new ArrayList<String[]>();
        initFileContent();
      }
      // Give me the content of one file chosen by index.
      String[] getFileContent(int index) {
        return fileContent.get(index);
      }
    
      int getNumberOfWorlds() {
        return numberOfFiles;
      }
    
      String getWorldPath(int index) {
        return new String(worldPath + rawFilenames[index]);
      }
    
      String getRawFilename(int index) {
        return rawFilenames[index];
      }
    
      String getTrimmedFilename(int index) {
        return trimmedFilenames[index];
      }
    
      private void initFileContent() {
        for (int i=0; i < numberOfFiles; i++) {
          fileContent.add(new String[0]);
          fileContent.set(i, parseFile(rawFilenames[i]));
        }
      }
    
      // Get all filenames from the world directory.
      private void readFileDirectory() {
        rawFilenames = getFilenames(worldPath);
      }
      // Cut the prefix and suffix off.
      private void trimFilenames() {
        trimmedFilenames = cutFilenames(getFilenames(worldPath));
      }
    
      // Reade the content of the file.
      private String[] parseFile(String filename) {
        BufferedReader reader = createReader(worldPath + filename);
        String line = null;
        String[] tempWorld = new String[5];
        int counter = 0;
        try {
          while ((line = reader.readLine()) != null) {
            tempWorld[counter] = line;
            counter++;
          }
          reader.close();
        } 
        catch (IOException e) {
          e.printStackTrace();
        }
        return tempWorld;
      }
    
      // Return all the raw filenames in a directory as an array of Strings.
      private String[] getFilenames(String dir) { 
        File file = new File(dir);
        if (file.isDirectory()) { 
          String[] names = file.list();
          return names;
        } else {
          // If it's not a directory.
          println("ERROR: There is no worlds directory!");
          return null;
        }
      }
    
      // Delete the prefix and the suffix of the filename.
      private String[] cutFilenames(String[] filenames) {
        String[] names = filenames;
        for (int i=0; i < names.length; i++) { 
          names[i] = names[i].substring(2, names[i].length()-4); // -4 for the ".txt" suffix.
        }
        return names;
      }
    }
    
    //WorldTranslater
    
    class WorldTranslater {
      PApplet pa;
      // Agreements for the height and width of a world.
      final int mapWidth = 10;
      final int mapHeight = 5;
    
      private String[] crypticWorld;
      private Sprite[][] translatedWorld;
    
      final String wall = "Sprites/Wall.png";
      final String background = "Sprites/Background.png";
      final String ground = "Sprites/Ground.png";
      final String platform = "Sprites/Platform2.png";
      final String nothing = "Sprites/Nothing.png";
    
      final int viewDistance = 1; // The higher the number, the closer is the picture in the foreground.
    
      WorldTranslater(PApplet _pa) {
        pa = _pa;
        crypticWorld    = null;
        translatedWorld = new Sprite[mapHeight][mapWidth];
      }
      // Give me the fancy sprite array from this cryptical String array plz.
      public Sprite[][] translateWorld(String[] cw) {
        crypticWorld = cw;
        translateCWorld();
        return translatedWorld;
      }
    
      // Translate the crypticWorld to a world with fancy sprites.
      private void translateCWorld() {
        Sprite sp; 
        for (int i=0; i < mapHeight; i++) {
          for (int j=0; j < mapWidth; j++) {
            sp = distinguishSprite(crypticWorld[i].charAt(j));
            sp.setPos(new Vector2D(sp.getWidth()*j, sp.getHeight()*i));
            translatedWorld[i][j] = sp;
          }
        }
      }
    
      // Check which token is which sprite.
      private Sprite distinguishSprite(char c) {
        if (c == 'O') {
          return new Sprite(pa, wall, viewDistance);
        } else if (c == 'X') {
          return new Sprite(pa, background, viewDistance);
        } else if (c == 'Z') {
          return new Sprite(pa, ground, viewDistance);
        } else if (c == '_') {
          return new Sprite(pa, platform, viewDistance);
        } else if (c == ' ') {
          return new Sprite(pa, nothing, viewDistance);
        }
        println("ERROR: Invalid token");
        return null;
      }
    };
    
    //WorldObjekt
    
    class World {
      private String[] rawWorldMap;
      private Sprite[][] worldMap;
      private String name;
      private String path;
    
      World() {
        rawWorldMap = null;
        worldMap = null;
        name = null;
        path = null;
      }
    
      World(String[] _rawWorldMap, Sprite[][] _worldMap, String _name, String _path) {
        rawWorldMap = _rawWorldMap;
        worldMap = _worldMap;
        name = _name;
        path = _path;
      }
    
      public Sprite[][] getWorldMap() {
        return worldMap;
      }
    
      String[] getRawWorldMap() {
        return rawWorldMap;
      }
    
      String getName() {
        return name;
      }
    
      String getPath() {
        return path;
      }
    };
    
  • Time delay in python mode?

    There are a couple of different versions implemented by different users. Here for example: https://github.com/Lord-of-the-Galaxy/Timing-Utilities/blob/master/timing_utils/src/lord_of_galaxy/timing_utils/Stopwatch.java is a version done by Lord_of_the_Galaxy. The code is in Java and it should be easy to use this code to write the python version. Give it a try if you want.

    Kf

  • The constructor is undefinded .. how can I solve it?

    Hey!

    I'm trying to make a game for my programming class and I want to use the AI for 2D Games library. I'm working at the guide at the moment and copied some code from the page, but unfortunately i get this error message: "The constructor BitmapPic(AnimRenderer_01, String, int, int, int) is undefinded"

    That's the code I'm using: (the problem is in line 33)

    import game2dai.*;
    import game2dai.entities.*;
    import game2dai.entityshapes.*;
    import game2dai.entityshapes.ps.*;
    import game2dai.fsm.*;
    import game2dai.graph.*;
    import game2dai.maths.*;
    import game2dai.steering.*;
    import game2dai.utils.*;
    
    // AnimRenderer_01
    World world;
    StopWatch sw;
    Vehicle tank;
    Vector2D target = new Vector2D();
    BitmapPic view;
    
    public void setup() {
      size(600, 320);
      world = new World(width, height);
      sw = new StopWatch();
      // Create the mover
      tank = new Vehicle(new Vector2D(width/2, height/2), // position
        40,                 // collision radius
        new Vector2D(0, 0), // velocity
        40,                 // maximum speed
        new Vector2D(1, 0), // heading
        15,                 // mass
        1.5f,               // turning rate
        1000                // max force
      ); 
      // What does this mover look like
      view = new BitmapPic(this, "tanks.png", 8, 1, 0);    
      view.showHints(Hints.HINT_COLLISION | Hints.HINT_HEADING | Hints.HINT_VELOCITY);
      tank.renderer(view);
      // Finally we want to add this to our game domain
      world.add(tank);
      sw.reset();
    }
    
    public void draw() {
      double elapsedTime = sw.getElapsedTime();
      target.set(mouseX, mouseY);
      tank.AP().arriveOn(target);
      float speed = (float) tank.speed();
      float maxSpeed = (float) tank.maxSpeed();    
      if (speed > 1) {
        float newInterval = map(speed, 0, maxSpeed, 0.6, 0.04);
        view.setAnimation(newInterval, 1);
      }
      else {
        view.pauseAnimation();
      }
      world.update(elapsedTime);
      background(218, 140, 54);
      world.draw(elapsedTime);
    }
    

    I'm using Processing 3.3.4 and AI for 2D Games 1.1,

    I really hope someone can help me!

    Best Regards from Germany!

  • Drawing over Sprites library jigsaw example

    I've been using the Sprites library S4P_Jigsaw_Player example to build an interactive project. I want to draw other things on top of the jigsaw puzzle, but I can't figure out where in the code I can superimpose something in the void draw section. I've been testing it out by trying to place a random image on top of the puzzle, but the closest I've gotten to making something appear is by placing it in the keyPressed command section and then the image will flash for a second. Does anyone know how to do this?

         import java.io.File;
    
            import sprites.utils.*;
            import sprites.maths.*;
            import sprites.*;
    
            final int SPLASH = 0;
            final int TRANSITION_FROM_SPLASH = 1;
            final int SOLVE_PUZZLE = 2;
            final int VIEW_PIC = 4;
    
            int mode = SPLASH;
            int colBoard, colEdge;
    
            ArrayList<Jigsaw> jigs;
            int jSelect = 0;
            int nextZ;
            Jigsaw jigsaw;
    
            PFont font;
            String splashText = "[S] solve this one";
            String inPlayText = "[N] New jigsaw puzzle : [V] View solution";
            String viewSolutionText = "[B] Back to solving the puzzle";
            int splashTextX, inPlayTextX, viewSolutionTextX;
    
            float timeToSpread = 2.5f;
            StopWatch sw = new StopWatch();
    
            PImage horse;
    
            void setup() {
            size(800, 800);
              //cursor(CROSS);
              rectMode(CORNER);  
              colBoard = color(255);
              colEdge = color(0, 0, 48);
              font = createFont("Arial Black", 24);
              textFont(font, 24);
              splashTextX = (width - (int) textWidth(splashText))/2;
              inPlayTextX = (width - (int) textWidth(inPlayText))/2;
              viewSolutionTextX = (width - (int) textWidth(viewSolutionText))/2;
                // Get a list of jigsaws
                File data = new File(dataPath(""));
                File[] jjigs = data.listFiles();
                jigs = new ArrayList<Jigsaw>();
                for(File f : jjigs){
                  if(f.isDirectory()){
                    String folder = f.getName();
                    if(folder.startsWith("JSP_"))
                      jigs.add(new Jigsaw(folder, width, height)); 
                  }
                }
              jSelect = 0;
              jigsaw = jigs.get(jSelect);
              sw.reset();
    
              horse = loadImage("horse.jpg");
            }
    
            void draw() {
    
              float elapsedTime = (float) sw.getElapsedTime();
              background(255);
              switch(mode) {
              case SPLASH:
                drawSplash();
                break;
              case TRANSITION_FROM_SPLASH:
                drawSolutionTable();
                S4P.updateSprites(elapsedTime);
                S4P.drawSprites();
                if (sw.getRunTime() >= timeToSpread) {
                  for (int p = 0; p < jigsaw.nbrPieces; p++) {
                    jigsaw.pieces[p].setVelXY(0, 0);
                    jigsaw.solved[p] = false;
                  }
                  mode = SOLVE_PUZZLE;
    
                }
                break;
              case SOLVE_PUZZLE:
                drawSolutionTable();
                float inPlace = jigsaw.progress();
                if (inPlace > 0) {
                  fill(128, 0, 0);
                  rect(0, 0, width * inPlace, 36);
                  fill(255);
                  text(nf(100 * inPlace, 2, 1) + "% solved", 5, 26);
                }
                fill(0);
                text(inPlayText, inPlayTextX, height - 30);
                S4P.drawSprites();  
                break;
              case VIEW_PIC:
                drawSolutionTable();
                fill(0);
                text(viewSolutionText, viewSolutionTextX, height - 30);
                imageMode(CORNER);
                image(jigsaw.picture, jigsaw.offX, jigsaw.offY);
                break;
    
              }
            }
    
            void drawSolutionTable() {
              background(colBoard);
              noStroke();
              fill(colEdge);
              rect(jigsaw.offX-10, jigsaw.offY-10, jigsaw.jWidth+20, jigsaw.jHeight+20);
              fill(128);
              rect(jigsaw.offX, jigsaw.offY, jigsaw.jWidth, jigsaw.jHeight);
    
            }
    
            void drawSplash() {
              imageMode(CORNER);
              int fx = (width - (int) textWidth(jigsaw.title))/2;
              fill(255);
              text(jigsaw.title, fx, 100);
              image(jigsaw.picture, jigsaw.offX, jigsaw.offY);
              fill(0);
              text(splashText, splashTextX, height -40);
            }
    
            void keyPressed() {
              if (mode == SPLASH) {
    
                 if (key == 's' || key == 'S') {
                  jigsaw.loadPieces(this);
                  nextZ = 3000;
                  mode = TRANSITION_FROM_SPLASH;
                  prepareToSplitJigsaw();
                  sw.reset();
                }
    
              }
              else if (mode == SOLVE_PUZZLE) {
                if (key == 'n' || key == 'N') {
                  jigsaw.unloadPieces();
                  mode = SPLASH;
                }
                else if (key == 'v' || key == 'V') {
                  mode = VIEW_PIC;
                }
              }
    
        //HERE'S WHERE I'VE PLACED THE HORSE CURRENTLY
    
              else if (mode == VIEW_PIC) {
                if (key == 'b' || key == 'B') {
                  mode = SOLVE_PUZZLE;
                         image(horse,0, 0);
    
                }
              }
            }
    
            void prepareToSplitJigsaw() {
              drawSolutionTable();
              int ex, ey;
              for (int p = 0; p < jigsaw.nbrPieces; p++) {
                do {
                  ex = (int) random(12, width - 24);
                  ey = (int) random(12, height - 24);
                } 
                while (get (ex, ey) != colBoard);
                float velX = ((float)(ex - jigsaw.px[p])) / timeToSpread;
                float velY = ((float)(ey - jigsaw.py[p])) / timeToSpread;
                jigsaw.pieces[p].setVelXY(velX, velY);
                jigsaw.solved[p] = false;
              }
            }
    
            void handleSpriteEvents(Sprite sprite) { 
              if (sprite.eventType == Sprite.PRESS) {
                sprite.setZorder(nextZ++); // bring to front
              }
              else if (sprite.eventType == Sprite.RELEASE) {
                int pn = sprite.tagNo; // get piece number
                int deltaX = abs(jigsaw.px[pn] - round((float) sprite.getX()));
                int deltaY = abs(jigsaw.py[pn] - round((float) sprite.getY()));
                if (deltaX < 3 && deltaY < 3) {
                  sprite.setXY(jigsaw.px[pn], jigsaw.py[pn]);
                  jigsaw.solved[pn] = true;
                }
                else {
                  jigsaw.solved[pn] = false;
                }
              }
            }
    
            class Jigsaw {
              String folder;
              String title;
              PImage picture;
              int cols, rows, nbrPieces;
              int pWidth, pHeight;
    
              int jWidth, jHeight;
              int offX, offY;
    
              Sprite[] pieces = null;
              int[] px = null;
              int[] py = null;
              boolean[] solved; // 0 = no, 1 = yes
    
              Jigsaw(String folder, int w, int h) {
                this.folder = folder;
                picture = loadImage(this.folder + "/picture.jpg");
                String[] info = loadStrings(this.folder + "/info.txt");
                title = info[0];
                cols = Integer.parseInt(info[1]);
                rows = Integer.parseInt(info[2]);
                pWidth = Integer.parseInt(info[3]);
                pHeight = Integer.parseInt(info[4]);
                nbrPieces = rows * cols;
                jWidth = cols * pWidth;
                jHeight = rows * pHeight;
                offX = (w - jWidth)/2;
                offY = (h - jHeight)/2;
              }
    
              void loadPieces(PApplet app) {
                if (pieces == null) {
                  String fname;
                  pieces = new Sprite[nbrPieces];
                  px = new int[nbrPieces];
                  py = new int[nbrPieces];
                  solved = new boolean[nbrPieces];
                  int p = 0, x, y;
                  y = offY + pHeight/2;
                  for (int r = 0; r < rows; r++) {
                    x = offX + pWidth/2;
                    for (int c = 0; c < cols; c++) {
                      fname = folder + "/piece_" + nf(p, 3) + ".png";
                      int z = (int) random(1000, 2999);
                      px[p] = x;
                      py[p] = y;
                      pieces[p] = new Sprite(app, fname, z);
                      pieces[p].tagNo = p;
                      pieces[p].setXY(px[p], py[p]);
                      solved[p] = true;
                      pieces[p].respondToMouse(true);
                      pieces[p].setDraggable(true);
                      x += pWidth;
                      p++;
                    }
                    y += pHeight;
                  }
                }
                else {
                  resetPieces();
                }
              }
    
              void resetPieces() {
                for (int p = 0; p < nbrPieces; p++) {
                  int z = (int) random(1000, 2999);
                  pieces[p].setZorder(z, false);
                  pieces[p].setXY(px[p], py[p]);
                  solved[p] = true;
                  pieces[p].respondToMouse(true);
                  pieces[p].setDraggable(true);  
                  S4P.registerSprite(pieces[p]);
                }
                S4P.sortZorder();
              }
    
              void unloadPieces() {
                for (int p = 0; p < nbrPieces; p++) {
                  pieces[p].respondToMouse(false);
                  pieces[p].setDraggable(false);
                  S4P.deregisterSprite(pieces[p]);
                }
              }
    
              // Returns true if all pieces in place
              boolean isSolved() {
                for (boolean b : solved)
                  if (!b) return false;
                return true;
              }
    
    
              float progress() {
                float count = 0;
                for (boolean b : solved)
                  if (b) count++;
                return count / nbrPieces;
              }
            }
    
  • Can p5 js run in the background?

    All modern browsers throttle performance for inactive/outta-focus tabs: :-&
    http://StackOverflow.com/questions/15871942/how-do-browsers-pause-change-javascript-when-tab-or-window-is-not-active

    My advice is for you to stick w/ Processing's Java Mode for stopwatch/alarm programs! :-\"

  • Can p5 js run in the background?

    Hey all,

    I have made a stopwatch/alarm and use the draw() function to decrement to calculate the time remaining. The problem is, the program will pause when you alt-tab to a different window. I understand that this normally is what most people want, but is there a way that you can tell p5 to keep running in the background?

    If I can't, then my stopwatch/alarm isn't much use unless you want to keep that page open constantly :D.

    Thanks, Steve

  • How to stop timer at the certain time automaticlly?

    @Lord_of_the_Galaxy -- it is true that stopwatch timers are a common question -- looking forward to seeing what you come up with!

    While I haven't used them, the two timing-related libraries that I'm aware of in Processing Contributions (Utilities) are CountdownTimer by Dong Hyun Choi and TimedEvents by Jason Gessner -- it might be interesting to look at them for reference / comparison.

  • How to stop timer at the certain time automaticlly?

    Sorry, but this is more of a stopwatch to measure a time elapsed and not a timer

    But I can have a look later

  • timer

    Not sure if this is what you want, but you might want to look at the java.util.Timer class.
    There also are many existing Stopwatch classes in Java, as can be seen in this post on stackoverflow.com.

  • How to use sprites

    I am not going to try and incorporate the library into your code instead I am going to give you an example of how to effectively use the Sprite library. Then you can adapt your code to suit.

    The first thing is that the base class should be the Sprite class. This gives your classes all the power of Sprite including easy updating and displaying. It also allows you to add extra functionality.

    I have made your Entity class non-abstract because it now inherits from Sprite.

    The update method in the child classes overrides the one in Sprite so we have to call the overridden method in Sprite first to make sure the sprite moves and is animated.

    Hopefully you will manage to work out what the code is doing but if not ask here. :)

    BTW the images used are below except explosion which is above. I leave you to open the Tardis doors ;)

    import sprites.*;
    import sprites.maths.*;
    import sprites.utils.*;
    
    StopWatch sw = new StopWatch();
    
    Entity dalek;
    Tardis tardis;
    Bullet bullet;
    VisualEffect explosion;
    MuzzleFlash flash;
    
    public void settings() {
      size(800, 600, P2D);
    }
    
    public void setup() {
      frameRate(120);
      tardis = new Tardis(this, "tardis.png", 5, 2, 10);
      tardis.setDomain(200, -150, width + 60, height + 150, Sprite.REBOUND);
      tardis.setXY(width/2, height/2);
      tardis.setVelXY(400*sin(radians(37)), 400*sin(radians(37)));
      explosion = new VisualEffect(this, "explosion.png", 5, 5, 20);
      dalek = new Entity(this, "dalek.png", 1, 1, 10);
      dalek.setDomain(0, 40, 60, height - 40, Sprite.HALT);
      dalek.setXY(30, height/2);
      dalek.setVelXY(0, 0);
      flash = new MuzzleFlash(this, "flash.png", 1, 4, 50);
      flash.setDead(true);
      bullet = new Bullet(this, "bullet.png", 2, 1, 10);
      bullet.setDead(true);
    }
    
    public void draw() {
      dalek.setVelY(1.5 * (mouseY - dalek.getY()));
      background(0);
      double et = sw.getElapsedTime();
      S4P.updateSprites(et);
      S4P.drawSprites();
    
      // Test for hit
      if (!bullet.isDead()) {
        if (tardis.pp_collision(bullet)) {
          tardis.hit(explosion);
          bullet.setDead(true);
        }
      }
    }
    
    public void mouseClicked() {
      flash.fire(dalek);
      bullet.fire(dalek);
    }
    
    // General purpose base class for your own game objects. 
    class Entity extends Sprite {
    
      public Entity(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    }
    
    class VisualEffect extends Entity {
    
      public VisualEffect(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    }
    
    class Tardis extends Entity {
    
      VisualEffect effect = null;
      double hx, hy;
      public Tardis(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    
      public void hit(VisualEffect effect) {
        this.effect = effect;
        effect.setFrameSequence(0, 24, 0.05, 1);
        effect.setDead(false);
        // Save pixel collosion position
        hx = getHitX();
        hy = getHitY();
      }
    
      public void update(double deltaTime) {
        // Make sure we do the library Sprite class update method
        super.update(deltaTime);
        // Now do any extra stuff
        // If the explosion is animating then keep it with the tardis otherwise
        // mark it as dead
        if (effect != null) {
          if (effect.isImageAnimating())
            effect.setXY(getX() - getWidth()/2 + hx, getY() - getHeight()/2 + hy);
          else 
          effect.setDead(true);
        }
      }
    }
    
    class Bullet extends Entity {
    
      public Bullet(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    
      public void fire(Entity dalek) {
        setFrameSequence(0, 1, 0.05);
        setXY(dalek.getX() + 88, dalek.getY());
        setVelXY(1000, 0);
        setDead(false);
      }
    
      public void update(double deltaTime) {
        // Make sure we do the library Sprite class update method
        super.update(deltaTime);
        // Now do any extra stuff
        // If the bullet has moved of screen ten it is dead
        if (!isOnScreem())
          setDead(true);
      }
    }
    
    class MuzzleFlash extends Entity {
    
      Entity dalek = null;
    
      public MuzzleFlash(PApplet theApplet, String imageFname, int cols, int rows, int zOrder) {
        super(theApplet, imageFname, cols, rows, zOrder);
      }
    
      public void update(double deltaTime) {
        // Make sure we do the library Sprite class update method
        super.update(deltaTime);
        // Now do any extra stuff
        // Track the dalek if we have one
        if (dalek != null && !dead)
          setXY(dalek.getX() + 78, dalek.getY());
        // If the animation is stopped then this is dead
        if (!isImageAnimating())
          setDead(true);
      }
    
      public void fire(Entity dalek) {
        this.dalek = dalek;
        setFrameSequence(0, 3, 0.02f, 10);
        setDead(false);
      }
    }
    

    bullet dalek flash tardis

  • How to use sprites

    First thing is that the image you are using is not suitable for sprites. It is common in games to use a sprites sheet, this is an image-file with multiple tiled images where ALL tiles are the same size. In your image the tiles are not the same size.

    Here is a sprite sheet I downloaded of the internet and I have used it in the sketch shown below. Notice it has 25 frames and they are numbered left-to-right top-to-bottom starting with 0 (zero). So the frame numbers are 0-24 inclusive.

    explosion

    The zOrder attribute determines the order that sprites are drawn. For instance if you have a spaceship and explosion sprite you would want the explosion to appear 'over' the spaceship. So the explosion sprite should have a higher number than the spaceship. The actual zOrder values are unimportant they simply decide on the order sprites are drawn on the screen.

    To animate the sprite we simply tell the sprite which frames to animate, the time interval between frames and how many times to repeat the animation.

    So in my sketch we have

    // Animate the sprite using frames 0 to 24 with a frame interval 
    // of 0.02 seconds and play the sequence just once 
    explosion.setFrameSequence(0, 24, 0.02, 1);
    

    In the sketch below we have created a StopWatch object (line 9) and this will be used to measure the elapsed time between frames. The real power of Sprites can be seen in the draw method.
    Line 18: we make a note of the elapsed time in seconds.
    Line 19: this single statement will update ALL sprites that have been created
    Line 20: this single statement will display ALL sprites that have been created

    Sprites is a powerful library which means that it takes a while getting used to but will do most of the hard work for you. You can use the sketch code below as a basis for trying out different parts of the library.

    import sprites.*;
    import sprites.maths.*;
    import sprites.utils.*;
    
    Sprite explosion;
    float px, py;
    
    // This will be used for timing
    StopWatch sw = new StopWatch();
    
    void setup() {
      size(400, 400);
      explosion = new Sprite(this, "explosion.png", 5, 5, 10);
    }
    
    void draw() {  
      // Get the elapsed time since the last frame
      float elapsedTime = (float) sw.getElapsedTime();
      S4P.updateSprites(elapsedTime);
      background(200, 200, 255);
      S4P.drawSprites();
    }
    
    void mouseClicked(){
      // Move the sprite so it in centerd over the mouse position
      explosion.setXY(mouseX, mouseY);
      // Animate the sprite using frames 0 to 24 with a frame interval 
      // of 0.02 seconds and play the sequence just once 
      explosion.setFrameSequence(0, 24, 0.02, 1);
    }
    
  • Show running time at the end of process

    I found those notes, so I'm going to go ahead and post them here in case they are useful to anyone in the future.

    If you just need a console log...

    Do as in kfrajer's post above -- done.

    void draw() {}
    void keyPressed() {
      println("Exiting at " + millis()/1000.0 + " seconds");
      exit();
    } 
    

    If you need to display to the screen...

    Save your time to a variable -- then reveal a special message in the draw loop.

    /**
     * Display a screen timing message
     * 2016-08-06  Processing 3.2.1
     */
    float doneTime = 0;
    void draw() {
      background(192);
      translate(width/2,height/2);
      textAlign(CENTER,CENTER);
      if(doneTime = 0){
        text("Timing...\n" + millis()/1000, 0, 0);
      } else {
        text("Done at\n" + doneTime + " seconds", 0, 0);
      }  
    }
    void keyPressed() {  
      doneTime = millis()/1000.0;
      println("Done at " + doneTime + " seconds");
    } 
    

    QUIRK: Processing may take it a long time (even multiple seconds) to render your very first text() drawn to the screen (I believe can be due to lazy loading). If your sketch is already drawing text to the screen (as this example does) then this won't affect you. If the timing message is your first text however then the long delay for it to appear may be confusing. You can work around this by briefly loading text to the screen when your sketch starts.

    If you want to display to the screen BEFORE EXIT....

    You'll either need a two-stage exit with two inputs (first stop, then confirm exit) or you will want to wait so that the user has time to read the exit message on the screen before the window disappears. It is tempting to use delay(), however, this will prevent drawing the message to the screen on the next draw loop. However since we already have our exit time, an easy solution is to test if exiting is true and then run exit() 5 seconds later.

    /**
     * Display a screen exit timing message
     * 2016-08-06
     */
    boolean exiting = false;
    float exitTime = 0;
    void draw() {
      background(192);
      translate(width/2,height/2);
      textAlign(CENTER,CENTER);
      if(exiting==false){
        text("Timing...\n" + millis()/1000, 0, 0);
      } else {
        text("Exiting at\n" + exitTime + " seconds",0,0);
        if(exitTime + 5 < millis()/1000.0){
          exit();
        }
      }
    }  
    void keyPressed() {
      exitTime = millis()/1000.0;
      println("Exiting at " + exitTime + " seconds");
      exiting = true;   //// reveal screen exit message in draw loop
    }
    

    If you have more complicated things to do on exit then instead of an if in the draw loop you could use a thread() -- which allows screen drawing to continue, even if it uses delay() as a stopwatch timer. For example, add a thread call to your input check:

    thread("doExit");
    

    ...and have it call a doExit function, which waits, then closes the sketch. Drawing will continue while this function runs:

    void doExit(){
      delay(5000);
      exit();
    }
    

    If you need to log your final message and time to a file

    Try using createWriter() -- be sure to write, flush, close, THEN exit (see the example). If you might close unexpectedly and/or can't trust the user to quit correctly then you can write to your log file at periodic intervals rather than just once at the end.

    If you want your exit code to run in more varied situations

    Supposing that the users press ESC, or click window-close -- your exit code timing won't run. Fullscreen might be one way to encourage them. Overriding the default Processing quit key (ESC) might be another.

    void setup() {
      fullScreen(true);
    }
    void keyPressed{
      if(key=ESC){ exiting==true; } // override default exit();
    }
    

    If you want something to run reliably as the very last thing your sketch does

    At the point where we want something (like writing to a log file) to be the very last thing that a sketch does, and to happen no matter what and no matter how the sketch is stopped, then we start to get into dark arts... running code on exit can be hard to guarantee in Processing / Java. I believe that the currently recommended best way is to add a DisposeHandler, although I haven't done it myself -- you can find some good technical discussion of that here:

  • I created a arduino game and would like to save scores in txt file somehow , How do i?!??

    Heyy guys ! New arduino and proccesing user and ive recently created this buzzwire game on arduino. It works pretty much the same as a stopwatch. I would like to know if it is possible to save the times using processing and how to do it !So when a player hits the stopwatch and his time appears on the arduino serial monitor i want that time to be saved Here is my current arduino code

    `````unsigned long start, finished, elapsed, bonus;

    void setup() // run once, when the sketch starts { Serial.begin(9600); // set up Serial library at 9600 bps pinMode(2, INPUT); // start button pinMode(3, INPUT); // stop button pinMode(4,INPUT); // Wire touch

    Serial.println("Press 1 for Start/reset, 2 for elapsed time"); }

    void displayResult() //Fucntion converts elapsed time from miliseconds to minutes & seconds { float h, m, s, ms; unsigned long over; elapsed = finished - start; h = int(elapsed / 3600000); over = elapsed % 3600000; m = int(over / 60000); over = over % 60000;

    ms = over % 1000; s = bonus + int(over / 1000); Serial.print("Raw elapsed time: "); Serial.println(elapsed); Serial.print("Elapsed time: "); Serial.print(h, 0); Serial.print("h "); Serial.print(m, 0); Serial.print("m "); Serial.print(s, 0); Serial.print("s "); Serial.print(ms, 0); Serial.println("ms"); Serial.println(); }

    void loop() { if (digitalRead(2) == HIGH) { start = millis(); delay(500); // for debounce Serial.println("Started..."); }

    if (digitalRead(4) == HIGH) { bonus += 1000; delay(500); // for debounce Serial.println("TOUCH"); }

    if (digitalRead(3) == HIGH) { finished = millis(); delay(500); // for debounce displayResult(); } }````