GUI for a simple puzzle game

edited March 2015 in Library Questions

Hi there,

This is my first post on this forum since I am fairly new to processing, although I have some programming background.

I am trying to implement a very simple puzzle game that consists of a small number of 'scenes' namely, a simple menu from where the user can either choose to go to a "help" screen or to a "play" screen. Is there any adequate library out their that provides both:

  • simple GUI controls (buttons, textfields, toggles, etc.)

  • and the ability to switch between multiples 'scenes' (menu, help screen, actual game etc.)?

It does not have to be anything fancy as long as it serves its propose. Any suggestion?

Thanks a lot!

Answers

  • librarys:

    look into the library page please, G4P or controlP5 are good

    stages

    for the stages, there is no lib.

    But it's pretty easy.

    In the forum mostly it's referred to as "state"

    // program state
    final int stateStartScreen = 0;  // consts 
    final int stateNormal = 1;      
    //
    int state = stateStartScreen ;   // current 
    //
    
    
    void setup()
    {
      size( 800, 800, P3D );
      background(0);
    } // setup
    
    void draw()
    {
      // this calls functions for each state
      switch (state) {
    
      case stateStartScreen:
        drawForStateStartScreen(); 
        break;
    
      case stateNormal:
        drawForStateNormal();
        break;
    
      default:
        // error
        println ("undefined state, error 39");
        break;
        //
      } // switch
    } // func
    
    // ----------------------------------------------------
    
    void drawForStateStartScreen() {
      // start screen 
      background(0);
      fill(255);
      String text1 = 
        "This is a small sketch to demonstrate the start screen. \n\n"
        + "\n\n\n"
        +"Press any key.";
      // println(text1);
      text (text1, 30, 50, width-50, 1900);
    }
    
    void drawForStateNormal() {
      // MAIN 
      background(0);
      fill(255);
      text ("main program ", 30, 50);
      pushMatrix();
      fill(255, 2, 2);
      translate(width/2-100, height/2+100);
      box (20, 20, 20);
      popMatrix();
    } // func
    
    // -------------------------------------------------------
    
    void keyPressed() {
      // this could call functions too for each state
      switch (state) {
        //
      case stateStartScreen:
        // move on 
        state=stateNormal;
        break;
    
      case stateNormal:
        if (key == CODED) {
          // cursor is for camera
          if (keyCode == UP) {
          }
          else if (keyCode == DOWN) {
          }
          else if (keyCode == RIGHT) {
          }
          else if (keyCode == LEFT) {
          }
          else {
            // nothing
          }
        }
        else { 
          // not key == CODED
          //
        }
    
        break;
    
      default:
        println ("undefined state, error 89");
        break;
      } // switch
    } // func 
    
    // -------------------------------------------------
    
    void mousePressed() {
      //
      // this could call functions too for each state
      //
      switch (state) {
        //
      case stateStartScreen:
        state = stateNormal;
        break;
    
      case stateNormal:
        println ("Mouse is different now.");
        break;
    
      default:
        println ("undefined state, error 107");
        break;
      } // switch
    } // func 
    
    //
    

    ;-)

  • edited March 2015

    I may add that consts are written UPPER_CASE as a convention ;-)

  • Thanks Chrisir for your great suggestion I will surely look into both libraries and see which one is the best for my purpose!

    I didn't know the right word to describe the concept of having multiple "states" :). I refereed to it as "scene" since this is what it is called in Unity3D, if I'm not wrong. It will surely be useful to know that it is mostly refereed to as "state" in Processing!

    The provided code is also very helpful. Thanks again!

  • there is no right or wrong here, state is just more common but that's maybe coincedence

    ;-)

  • Hi chrisir I am back :)

    I am not sure if you have any experience using the G4P GUI library. It is a great library, however I am experiencing a problem which I have been trying to solve quite a long time although it seems simple!

    To implement various states I am making use of the idea you have me above (it's briliant!). However I cannot figure out how to make use of the GImageButton button (and most probably also the features) in just one states, independent of the others.

    In the provided examples that come with the library, the initalisation of the button is done in the setup() as below:

    GImageButton next;
    String[] nextBtnImages ;
    
    void setup()
    { 
          size(800, 600, P3D);
          nextBtnImages = new String[] { "nextOff.jpg", "nextOver.jpg", "nextOff.jpg" };
          next = new GImageButton(this, width - 70, height - 70, nextBtnImages);
    }
    

    This works fine. However the button will show in all different states, which I don't want. Therefore I was trying to initialize the button from the 'draw' method of the specific state:

    //Application levels
    final int L0_INTRO = 0; 
    final int L1_HELP = 1;    
    int currentAppLevel = L0_INTRO;  
    GImageButton next;
    String[] nextBtnImages ;
    
    void setup()
    { 
      size(800, 600, P3D);
    }
    void draw(){
       //this calls functions for each level
      switch (currentAppLevel) {
        case L0_INTRO : drawLevel0(); 
                        break; 
        case L1_HELP : drawLevel1();
                        break;
        default: println ("undefined state, error 39");
                        break;
      }
    }
    
    void drawLevel0() {
      background(255);
      nextBtnImages = new String[] { "nextOff.jpg", "nextOver.jpg", "nextOff.jpg" };
      next = new GImageButton(this, width - 70, height - 70, nextBtnImages);
    }
    
    void drawLevel1() {
        background(255);
        fill(255);
        text ("Level 1 ", 30, 50);
    } 
    
    
    void handleButtonEvents(GImageButton button, GEvent event) {
      print("X");
      if (button == next)
          currentAppLevel = L1_HELP; 
    
    }
    

    However, although the button is shown and when clicked, the handleButtonEvents() is called ("X" is printed), the 'if' statement of the handleButtonEvents() method is not being executed. Therefore, no event is taking place when the button is clicked.

    Am I missing something or is a limitation of the library (the button can only be initialised in the setup() ) ?

    I would appreciate your advice :)

    Thanks

  • edited March 2015

    maybe you have to check the reference of G4P

    I think there is something like boolean button.setVisible()

    so when you go from one state to the other, tell the old button setVisible(false); and the new ones setVisible(true);

    define all in setup but with setVisible(true); only for the buttons of the 1st state

    [edited]

    ;-)

  • I am not sure if I fully understand you but it seems that you want different displays depending on some 'state' variable and you want buttons to switch between displays and these buttons will depend on the current display.

    Lets assume you have two buttons btnINTRO and btnHELP then this code can be used to switch displays

    void handleButtonEvents(GImageButton button, GEvent event) {
      if (button == btnINTRO) {
        currentAppLevel = L0_INTRO;
        btnINTRO.setVisible(false);
        btnHELP.setVisible(true);
      }
      if (button == btnHELP) {
        currentAppLevel = L1_HELP;
        btnINTRO.setVisible(true);
        btnHELP.setVisible(false);
      }
    }
    
  • edited March 2015

    Thanks a lot, @quark, that was very helpful.

    I may add that not every button will change the state - in fact during the game most buttons won't.

    Therefore in handleButtonEvents() we probably just check the buttons (those that are not visible can't be triggered anyway) and execute there function. - We could also use switch(state) in handleButtonEvents() I guess.

    When the player in the game loses e.g. we say in drawForStateNormal()

    state = stateStartScreen; 
    btnINTRO.setVisible(true);
    btnHELP.setVisible(false);
    

    ;-)

  • Thanks Chrisir and quark, you have been very helpful and understood my query perfectly. Much appreciated :)

  • edited March 2015

    Hi there!

    I am back with another small question. My application is becoming slightly more complex then first predicted! :) I am making use of quite a large number of G4P radio buttons. Is there a more efficient way to set their visibility to false depending on the current state. I am currently using the following approach:

    GOption redCol, greenCol, blueCol, cyanCol, magentaCol, yellowCol, whiteCol, blackCol; 
    GOption circleShape, triShape, quadShape; 
    
    public void setControlVisibility(){
      if(currentAppLevel == 0)
      {
        //visible
        circleShape.setVisible(true);
        triShape.setVisible(true):
        quadShape.setVisible(true);
        //hide
        redCol.setVisible(false);
        greenCol.setVisible(false);
        blueCol.setVisible(false);
        cyanCol.setVisible(false);
        magentaCol.setVisible(false);
        yellowCol.setVisible(false);
        whiteCol.setVisible(false);
        blackCol.setVisible(false);
      }
      else if(currentAppLevel == 1) 
      {
        //hide
        circleShape.setVisible(false);
        triShape.setVisible(false):
        quadShape.setVisible(false);
        //visible
        redCol.setVisible(true);
        greenCol.setVisible(true);
        blueCol.setVisible(true);
        cyanCol.setVisible(true);
        magentaCol.setVisible(true);
        yellowCol.setVisible(true);
        whiteCol.setVisible(true);
        blackCol.setVisible(true);
      }
    
    .
    .
    .
    .
    
    }
    

    In reality I have more levels and radio buttons then the once demonstrated above. I don't think this is the best practice to do such thing. To you thing that there is a better alternative?

    Bdw I am aware that I can make use of 'for' loops to reduce the code (which I will eventually use if there is no better alternative).

    Thanks :)

  • You can group controls and then make the group visible / invisible with a single statement. See the example tgat comes with G4P

  • That is what I tried to go. I grouped a set of radio buttons using GToggleGroup but it seems like the setVisible() method cannot be used on this object. In fact it gives the error:

    The function setVisible(boolean) does not exist.

    Is this what you are referring to when you said "you can group controls"?

  • edited March 2015

    Hi, am I right that it is not possible to set the visibility of a **GToggleGroup ** or am I missing something? This is the best way I found to control the visibility of the toggle button. However I am not convinced about this approach.

    public void setControlVisibility(){
      if(AppLevel == 0)
      {
         for(int i = 0; i < setOneRadioBtn.length; i++)
            setOneRadioBtn[i].setVisible(true);
         for(int i = 0; i < setTwoRadioBtn.length; i++)
            setTwoRadioBtn[i].setVisible(false); 
         for(int i = 0; i < setThreeRadioBtn.length; i++)
            setThreeRadioBtn[i].setVisible(false);   
         for(int i = 0; i < setFourRadioBtn.length; i++)
            setFourRadioBtn[i].setVisible(false); 
      }
      else if(AppLevel == 1) 
      {
         for(int i = 0; i < setOneRadioBtn.length; i++)
            setOneRadioBtn[i].setVisible(false);
         for(int i = 0; i < setTwoRadioBtn.length; i++)
            setTwoRadioBtn[i].setVisible(true);   
         for(int i = 0; i < setThreeRadioBtn.length; i++)
            setThreeRadioBtn[i].setVisible(false);  
         for(int i = 0; i < setFourRadioBtn.length; i++)
            setFourRadioBtn[i].setVisible(false); 
      }
    .
    .
    .
    }
    
  • The GToggleGroup class is simply to group GOptions so that only one in a group can be true at a time. The class you want is the GGroup and is demonstrated in the G4P_GroupControls example and is demonstrated below

    import g4p_controls.*;
    
    String[] labels = { 
      "one", "two", "three", "four", "five"
    };
    GGroup group1;
    GOption[] options;
    GToggleGroup opgGroup;
    GButton btnVisibility;
    
    boolean visible = true;
    int delay = 20;
    
    void setup() {
      size(300, 300);
      group1 = new GGroup(this);
      opgGroup = new GToggleGroup();
      options = new GOption[labels.length];
      for (int i = 0; i < options.length; i++) {
        options[i] = new GOption(this, 20, 20 + 30 * i, 100, 20, labels[i]);
        opgGroup.addControl(options[i]);
        group1.addControl(options[i]);
      }
      options[0].setSelected(true);
      btnVisibility = new GButton(this, 200, 20, 80, 20, "Visibility");
    }
    
    void draw() {
      background(240, 240, 255);
    }
    
    void handleButtonEvents(GButton button, GEvent event) {
      if (button == btnVisibility) {
        visible = !visible;
        group1.setVisible(delay, visible);
      }
    }
    
  • BTW you can also use GGroup to fade in/out the controls :)

Sign In or Register to comment.