How to create an actual splash screen

So I'm almost finished with my app although it takes quite a while to initialize everything when I start it up, I've looked up how to create a splash screen but I've only seen people put a picture inside setup but that doesn't do it for me since when I open the app I see a grey screen after which I would see a splash screen from setup, but I want the splash screen to be visible from the beginning (before setup?) how would I go about this

Tagged:

Answers

  • edited May 2017

    AFAIK, that isn't possible. There are complex workarounds though (like what processing IDE uses), or slightly simpler but slower ones (multithreading). You need a bit of knowledge of things to do any of them. Ask if you need help.

  • edited May 2017

    You can achieve this with a state model in draw(). Afaik you can even display the image in draw() and do the loading of images and setting up everything afterwards (because you wrote "although it takes quite a while to initialize everything").

    Your setup() is nearly empty in this approach. Except for splash=loadImage("....");

    Basically say state=0; in setup

    In draw say switch (state) {

    In state 0 say display splash screen image(splash);

    say state=1;

    In state 1 load everything, then say state = 2;

  • Just like in this recent post (ignore any arduino code... jump to the PAGE0/1/2 example): https://forum.processing.org/two/discussion/comment/99022/#Comment_99022

    Notice you can flip pages based on an user event or using system's tools, a timer for example.

    Kf

  • edited June 2017

    I went ahead and loaded everything in draw like @kfrajer and @Chrisir mentioned and this is the result (I also added a timer since at certain parts I slowed the footage down)

    As you can see to make it obvious when it's loading I turned the load screen completely red for now and it works fine although it starts off with a gray screen and then switches to red I know I'm nitpicking here since the gray screen is only like 1/10 of a sec.

    I'm assuming that the extra time is because of initializing all the variables before setup I could move some of the initializations inside the code but not al can work local since I need most of them "across" the code

    Which is why I'm wondering is it possible to initialize all the variables inside the code without them becoming local? (except the ones I need for the load screen like the "state" value that @Chrisir mentioned)

  • Hard to tell without seeing your code

    You need a background() in setup too

  • edited June 2017

    @Chrisir my bad. This isn't the whole code but only the part that I think is essential to the problem.

    ArrayList <Bullet> bullets;
    int health_alpha;
    int death_aplha;
    PFont font;
    
    boolean game_pressed;
    boolean game_death;
    int game_highscore;
    boolean game_load;
    float game_speed;
    int frame_error;
    int game_error;
    int framerate;
    
    float background_y1;
    float background_y2;
    PImage background_1;
    PImage background_2;
    PImage player;
    PImage bullet;
    PImage enemy;
    
    int highscore_y;
    int special_y;
    int health_y;
    int bullet_y;
    int bullet_x;
    int player_x;
    int player_y;
    int mouse_y;
    int score_y;
    int enemy_x;
    int enemy_y;
    int boot_y;
    int text_y;
    
    int player_points;
    int player_health;
    
    boolean traveling_boolean;
    boolean highscore_boolean;
    boolean position_boolean;
    boolean visible_boolean;
    boolean respawn_boolean;
    boolean flicker_boolean;
    boolean appear_boolean;
    boolean bullet_boolean;
    boolean global_boolean;
    boolean second_boolean;
    boolean alpha_boolean;
    boolean shoot_boolean;
    boolean mouse_boolean;
    boolean alive_boolean;
    boolean score_boolean;
    boolean death_boolean;
    boolean enemy_boolean;
    boolean frame_boolean;
    boolean blink_boolean;
    boolean shot_boolean;
    boolean text_boolean;
    
    int reappear_timer;
    int bullet_timer;
    int global_timer;
    int second_timer;
    int shoot_timer;
    int mouse_timer;
    int score_timer;
    int enemy_timer;
    int frame_timer;
    int death_timer;
    int blink_timer;
    
    boolean stage1;
    boolean stage2;
    boolean stage3;
    boolean stage4;
    boolean stage5;
    boolean stage6;
    
    int textheight_1;
    int textheight_2;
    int textheight_5;
    int textheight_6;
    int textheight_7;
    int textsize_1;
    int textsize_2;
    int textsize_3;
    int textsize_4;
    int textsize_5;
    int textsize_6;
    int textsize_7;
    
    void setup() {
      size(480, 800, P2D);
      background(#ED0000);
    }
    
    void draw() {
      if (game_load == false) {
        resolution();
        textsize();
        setting();
        if (game_error == 0) {
          highscore();
          values();
        }
        game_load = true;
      } else {
        //game code
      }
    }
    
    void resolution() {
      background_1 = loadImage("background_1 " + width + "x" + height + ".png");
      background_2 = loadImage("background_2 " + width + "x" + height + ".png");
      player = loadImage("player_" + width + "x" + height + ".png");
      bullet = loadImage("bullet_" + width + "x" + height + ".png");
      enemy = loadImage("enemy_" + width + "x" + height + ".png");
      if (background_1 == null || background_2 == null || player == null || bullet == null || enemy == null) game_error = 2;
    }
    
    void textsize() {
      textFont(loadFont("font.vlw"));
      int text_size;
    
      textSize(1);
      text_size = 1;    
      while (textWidth("000") < width/3) {
        textSize(text_size);
        text_size ++;
        textheight_1 = int(textDescent());
        textsize_1 = text_size;
      }
      textSize(1);
      text_size = 1;
      while (textWidth("Your score is") < width/1.5) {
        textSize(text_size);
        text_size ++;
        textheight_2 = int(textDescent());
        textsize_2 = text_size;
      }
      textSize(1);
      text_size = 1;
      while (textWidth("Your phone appears to be too low specced") < width - width/6) {
        textsize_3 = text_size;
        textSize(text_size);
        text_size ++;
      }
      textSize(1);
      text_size = 1;
      while (textWidth("You're resolution is not supported") < width - width/6) {
        textsize_4 = text_size;
        textSize(text_size);
        text_size ++;
      }
      textSize(1);
      text_size = 1;
      while (textWidth("TO START") < width - width/10) {
        textheight_5 = int(textDescent());
        textsize_5 = text_size;
        textSize(text_size);
        text_size ++;
      }
      textSize(1);
      text_size = 1;
      while (textWidth("PRESS HERE") <   width/1.3) {
        textheight_6 = int(textDescent());
        textsize_6 = text_size;
        textSize(text_size);
        text_size ++;
      }
      textSize(1);
      text_size = 1;
      while (textWidth("SPECIAL THANKS TO SHIN AND WYVER9") < width - width/16) {
        textheight_7 = int(textDescent());
        textsize_7 = text_size;
        textSize(text_size);
        text_size ++;
      }
    }
    
    void setting() {
      textAlign(CENTER, CENTER);
      rectMode(CENTER);
      strokeWeight(2);
      frameRate(50);
      stroke(255);
    }
    
    void highscore() {
      String[] lines = loadStrings("list.txt");
      if (highscore_boolean == false) {
        if (lines == null) {
          lines = split(str(0), ' ');
          saveStrings("list.txt", lines);
        } else {
          game_highscore = int(lines[0]);
        }
        highscore_boolean = true;
      }
    
      if (int(lines[0]) < int(str(player_points).replaceAll("0", "1"))) { 
        lines = split(str(player_points).replaceAll("0", "1"), ' ');
        saveStrings("list.txt", lines);
        game_highscore = int(str(player_points).replaceAll("0", "1"));
      }
    }
    
    void values() {
      health_y = (width/32 + (width - width/32*2)/14 + (width - width/32*2)/28);
      special_y = height - width/32 + textheight_7 * 2;
      bullet_y = height + bullet.height/2;
      player_y = height + player.height/2;
      highscore_y = -textheight_2 * 8;
      text_y -= textheight_2 * 2;
      bullets = new ArrayList();
      boot_y = height/6*2;
      text_boolean = true;
      player_x = width/2;
      player_health = 5;
      death_aplha = 0;
      game_speed = 1;
    }
    
  • My approach is different see above

  • @Chrisir indeed although I fail to see how your approach would be faster? Since we both move the loading etc into draw() but before that we both draw something (in your example you load in an image and I just draw a background). But perhaps I'm missing something?

  • edited June 2017
    1. draw() doesn't update the screen until it returns.
    2. loadImage() can slow down draw returning
    3. text() dynamically loads the text library the first time it is called. this can slow down draw returning a lot.
    4. if you are calling loadImage() -- or text() for the first time -- there may be lag on that frame.
    5. so update ("splash") the screen with draw first, and then introduce the laggy operations on later frames

    So this sketch takes a big hit on its first draw frame -- the frame loads late:

    void setup(){
      frameRate(1);
      background(255,0,0);
      println(millis());
    }
    void draw(){
      background(0,0,128+frameCount*32);
      text(frameCount,width/2,height/2);
      println(millis());
    }
    

    ...and this sketch loads the first draw frame just fine -- the big hit happens on the second draw frame:

    void setup(){
      frameRate(1);
      background(255,0,0);
      println(millis());
    }
    void draw(){
      if(frameCount==1){
        background(0,255,0);
        println(millis());
        return;
      }
      background(0,0,128+frameCount*32);
      text(frameCount,width/2,height/2);
      println(millis());
    }
    
  • @jeremydouglass Thank you! So the mistake I made in my first code (the one in the video) until @Chrisir corrected me by putting background() into setup. Would be that I call background() and after that I load everything in but the frame only gets drawn after the draw is complete right? And it would only complete if everything is loaded in or you return.

      if (game_load == false) {
        background(#ED0000);
        resolution();
        textsize();
        setting();
        if (game_error == 0) {
          highscore();
          values();
        }
    
  • Just look at my original post and do this

  • That's right. Your code here:

    void setup() {
      size(480, 800, P2D);
      background(#ED0000);
    }     
    void draw() {
      if (game_load == false) {
        resolution();
        textsize();
        setting();
        if (game_error == 0) {
          highscore();
          values();
        }
        game_load = true;
      } else {
        //game code
      }
    }
    
    1. On setup() (frame 0):
      • calls background()
      • updates the screen for the 1st time
    2. On draw() the first time time it runs (frame 1):
      • it calls resolution() and loads a bunch of images (lag)
      • it calls textsize() and loads the full text library (big lag)
      • ... eventually, draw returns
      • ...THEN it updates the screen for the 2nd time
  • I think @chrisir wants you to implement the states he is reffering to in his original post.

    In state 0 say display splash screen image(splash);

    say state=1;

    In state 1 load everything, then say state = 2;

    By doing what Chrisir is suggesting, you are forcing 1 run through draw before you do anything else. Because you first draw the image (or background), then you load everything and then you continue to the code.

    If I were you, I would not do background or image in setup or draw, I would just do text("loading", width/2, height/2);. Because the default background is a neutral grey tone and the text will get the point across.

    I am not sure, but I guess you could also make use of the thread() function.

  • edited June 2017

    BTW, you can make variable global by specifying that when you initialize it:

    public int x = width/2; // this is accessible globally

  • Answer ✓

    Hello,

    here is a similar version to what I described:

    It uses a variable firstTime to note whether drawForStateSplashScreen() runs the first time or not.

    In the first time, the splash screen is displayed by drawForStateSplashScreen().

    Only the 2nd time your loading / heavy calculations take place in init1() while the splash screen is already visible.

    Note that drawForStateSplashScreen() uses the same background color (255) as setup().

    Best, Chrisir

    // demonstrates states 
    // consts 
    final int stateGame = 0;
    final int stateMenu = 1;
    final int stateSplashScreen = 2;
    final int stateHelp = 3;  // not in use
    // current state 
    int state = stateSplashScreen;
    
    // for splash screen !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    boolean firstTime = true; 
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
    PFont font1;
    
    // ------------------------------------------------
    
    void setup() {
      // runs once 
      size( 750, 700);
      background(255);
      println (""+"End of setup()."+"");
    } // func 
    
    void draw() 
    { 
      // runs on and on in a loop
    
      // states: 
      switch(state) {
    
      case stateSplashScreen:
        // show splash screen
        drawForStateSplashScreen();
        break; 
    
      case stateGame:
        drawForStateGame();
        break;
    
      case stateHelp:
        // help
        drawForStateHelp();
        break;  
    
      case stateMenu:
        // not in use
        drawForStateHelp();
        break; 
    
      default:
        // error 
        println ("Error 197");
        break;
      } // switch
      //
    } // func 
    
    // -----------------------------------------------------
    
    void drawForStateHelp() {
      background(111);
      textSize(22);
      textAlign(LEFT);
      int xpos=20;
      text(" Help for ..............", xpos, 90);
      text(" You can ........", xpos, 130);
      text(" ...................", xpos, 160);
      text(" ...........", xpos, 190);
      text(" ........", xpos, 220);
    }
    
    // --------------------------------------------------------------
    
    void drawForStateSplashScreen() {
      // 
      background(255);
      fill(0);
      stroke(0);
      textSize(22);
    
      // the big rect for the splashscreen
      noStroke();
      fill(111);  // gray 
      rect (100, 100, width-200, height-200);
      // the texts 
      fill(255, 0, 0); // red 
      textSize(32);
      text ("Game", width/2-100, height /2);
      fill(0);
      textSize(22);
      text ("Loading...", width/2, height /2+60); 
    
      int time = millis();
      if (!firstTime) {
        init1();
        // get rid of this while loop: 
        while ( millis () < time + 500000) {
          // wait
          // println ("wait");
        }// end of while 
        state = stateGame;
      }
      firstTime=false;
    }
    
    void init1 () {
      // loading all / heavy calculations 
      // make font 
      font1  = createFont("Arial", 32);
      textFont(font1);
    
      // some really heavy nasty calculation 
      float dummy=0.0;
      for (int i = 0; i<3600; i++) 
        dummy = sin(radians(i));
      println (""+"End of init1()."+"");
    }
    
    void drawForStateGame() {
    
      background(111);
    
      textSize(22);
    
      //
      rectMode(CENTER);
      stroke(39, 20, 1, 150);
      fill(255);
      rect (30, 30, 100, 100);
      text ("Game", 140, 140);
    }
    
    // ==============================================
    
  • @Chrisir thank you so much for your code although do your code and the code of @jeremydouglass not do the same in different ways? Since you go from drawing a splash screen to loading and after that initialize the game although your code also allows for instance, a game menu quite easy but with the code from @jeremydouglass it checks whether or not a frame has been drawn before if not it draws one (the splash screen) and finishes the draw with return (please correct me if I'm wrong) in the next cycle it "sees" that a frame has been drawn before and loads everything in if that finishes the code moves on to the rest of the code and next cycle into the draw it "sees" that everything has been loaded and directly moves on to the game.

    @Eeyorelife thanks, the reason I wanted to know is so I can initialize it after setup so I can display the splash screen and then initialize everything except the variables I needed to run the splash screen of course (since those have been initialized before setup). But after googling I can't seem to find a way to initialize it publicly inside a void without making it final (which makes it unchangeable to my understanding). I also don't know if initializing the variables actually takes time so perhaps moving this after setup so I can display the splash screen before doesn't make any difference?

  • Why isn't anyone doing multithreading? It has the added advantage that you can show the progress of the loading process.

  • edited June 2017

    similar as my last sketch

    instead of using variable firstTime now a state of its own named stateSplashScreenAndLoadingStuff

    Best, Chrisir ;-)

    // demonstrates states 
    // consts 
    final int stateGame = 0;
    final int stateMenu = 1;
    final int stateSplashScreen = 2;
    final int stateHelp = 3;  // not in use
    final int stateSplashScreenAndLoadingStuff = 4; 
    // current state 
    int state = stateSplashScreen;
    
    PFont font1;
    int time; 
    
    // ------------------------------------------------
    
    void setup() {
      // runs once 
      size( 750, 700);
      background(255);
      println ("End of setup().");
    } // func 
    
    void draw() { 
      // runs on and on in a loop
    
      // states: 
      switch(state) {
    
      case stateSplashScreen:
        // show splash screen
        drawForStateSplashScreen();
        break; 
    
      case stateSplashScreenAndLoadingStuff:
        // show splash screen and load 
        drawForStateSplashScreenAndLoadingStuff();
        break; 
    
      case stateGame:
        drawForStateGame();
        break;
    
      case stateHelp:
        // help
        drawForStateHelp();
        break;  
    
      case stateMenu:
        // not in use
        drawForStateHelp();
        break; 
    
      default:
        // error 
        println ("Error 197");
        break;
      } // switch
      //
    } // func 
    
    // -----------------------------------------------------
    // All functions called by draw
    
    void drawForStateHelp() {
      background(111);
      textSize(22);
      textAlign(LEFT);
      int xpos=20;
      text(" Help for ..............", xpos, 90);
      text(" You can ........", xpos, 130);
      text(" ...................", xpos, 160);
      text(" ...........", xpos, 190);
      text(" ........", xpos, 220);
    }
    
    void drawForStateSplashScreen() {
      // 
      splashScreen() ; 
      int time = millis();
      state = stateSplashScreenAndLoadingStuff;
    }
    
    void drawForStateSplashScreenAndLoadingStuff() {
    
      splashScreen() ; 
      init1();
      // get rid of this while loop: 
      while ( millis () < time + 5000) {
        // wait
        // println ("wait");
      } // end of while 
      state = stateGame;
    }
    
    void drawForStateGame() {
      background(111);
      textSize(22);
      //
      rectMode(CENTER);
      stroke(39, 20, 1, 150);
      fill(255);
      rect (30, 30, 100, 100);
      text ("Game", 140, 140);
    }
    
    // ---------------------------------------------
    // Secondary functions 
    
    void splashScreen() {
      // 
      background(255);
      fill(0);
      stroke(0);
      textSize(22);
    
      // the big rect for the splashscreen
      noStroke();
      fill(111);  // gray 
      rect (100, 100, width-200, height-200);
      // the texts 
      fill(255, 0, 0); // red 
      textSize(32);
      text ("Game", width/2-100, height /2);
      fill(0);
      textSize(22);
      text ("Loading...", width/2, height /2+60);
    }
    
    void init1 () {
      // loading all / heavy calculations 
      // make font 
      font1  = createFont("Arial", 32);
      textFont(font1);
    
      // some really heavy nasty calculation 
      float dummy=0.0;
      for (int i = 0; i<36000; i++) 
        dummy = sin(radians(i));
      println (""+"End of init1()."+"");
    }
    
    // =====================================================
    
  • it starts off with a gray screen and then switches to red I know I'm nitpicking here since the gray screen is only like 1/10 of a sec.

    Belatedly: a final thought related to fast screen loading.

    Calling text() for the first time introduces a big lag. Try these two sketches:

    background(255);
    println(millis());
    

    Output:

    367

    and

    text("a",10,10);
    println(millis());
    

    Output:

    2162

    Almost identical sketches, but one is almost two seconds slower (macOS 10.12, Processing 3.3.6).

    If your goal is to draw something to the screen as fast as possible on startup, DO NOT call text for the first time until a later frame.

  • background(255);
    println(millis());  //Prints 171 in Win10 OS 
    
    text("a",10,10);
    println(millis()); //Prints 223 in Win10 OS 
    
    
    
    size(200, 200, P2D);
    background(255);
    println(millis());  //Prints 1845 in Win10 OS 
    
    size(200,200,P2D);
    text("a",10,10);
    println(millis()); //Prints 2416 in Win10 OS 
    

    Kf

Sign In or Register to comment.