switching button controls from one function to another

Status
Not open for further replies.

Duhjoker

Well-known member
ok guys I'm having a problem that ive been trying to fix for days. I wrote a menu function for a game I'm working on, that when called brings up a short menu graphic with button controls to move a cursor up and down the menu. But when I open up the menu the new controls don't move the cursor but moves the player instead. Because both menu and player functions use the same up and down buttins. Ive tried else if statements, ive tried moving the set of controls in the function, ive looked up a lot keywords like break and switch but cannot find the answer I need.

Can someone please help me solve this. I'm learning but I have no idea how to fix it.

here is the menu function. I need help with calling the menu as well. it works by giving menu the define of "int menu_1 = 1, then pressing the A button changes the integer by adding up. But this makes the menu calling erratic making me have to push the button several times to get the menu to come back up after the first time. I could remove the addition parts so it comes open just by pressing A but then it kills it when a is released and I cant figure that out either.

Code:
void Menu(){
if (ButtonA.fallingEdge()){
            menu_1 = menu_1 + 1;}


else if(menu_1 == 3){
 tft.writeRectNBPP(16,0,114,32,4,itemmenutop,palette);
  tft.writeRectNBPP(16,32,114,16,4,itemmenu2,palette);
   tft.writeRectNBPP(16,48,114,160,4,itemmenu3,palette);
   tft.writeRectNBPP(16,208,114,16,4,itemmenu4,palette);
}

else if(menu_1 >= 5){
          menu_1 = 1;}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (ButtonUp.fallingEdge()){
     tft.writeRectNBPP(cursor_x,cursor_y,16,16,4,cursordot2,palette);
     cursor_y -= 16;
//     if(checkcolision())
     {
      cursor_y += 16;} 
     }
     if(cursor_y <= 32){
        cursor_y = 32;}
          
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////Down///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 if (ButtonDown.fallingEdge()){
   tft.writeRectNBPP(cursor_x, cursor_y,16,16,4,cursordot2,palette);
   cursor_y += 16;
//    if(checkcolision())
    {
    cursor_y -= 16;}
    }
    if(cursor_y >= 224){
       cursor_y = 224;}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

now here is the function that controls the player movement...
Code:
void drawplayer() {
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////camera controls////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Clamp cameraX
if(cameraX < cameraXMin)
{
  cameraX = cameraXMin;
}
else if(cameraX > cameraXMax)
{
   cameraX = cameraXMax;
}

// Clamp cameraY
if(cameraY < cameraYMin)
{
  cameraY = cameraYMin;
}
else if(cameraY > cameraYMax)
{
   cameraY = cameraYMax;  
}

// Check if player is beyond X boundary
if(player_x < playerXMin)
{
  cameraX += cameraXSpeed;
  if(cameraX > cameraXMin && cameraX < cameraXMax)
  {
    player_x = playerXMin;
  }
}
else if(player_x > playerXMax)
{
  cameraX -= cameraXSpeed;
  if(cameraX > cameraXMin && cameraX < cameraXMax)
  {
    player_x = playerXMax;
  }
}

// Check if player is beyond Y boundary
if(player_y < playerYMin)
{
  cameraY += cameraYSpeed;
  if(cameraY > cameraYMin && cameraY < cameraYMax)
  {
    player_y = playerYMin;
  }
}
else if(player_y > playerYMax)
{
  cameraY -= cameraYSpeed;
  if(cameraY > cameraYMin && cameraY < cameraYMax)
  {
    player_y = playerYMax;
  }
}
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////Palette////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 palette[0] = 0;
       palette[1] = BLACK;
             palette[2] = BLUE;
                   palette[3] = BROWN;
                         palette[4] = DARKGREEN;
                              palette[5] = GREY;
                                    palette[6] = PINK;
                                          palette[7] = RED;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////                                                
                                           palette[8] = BEIGE;
                                     palette[9] = GREEN;
                               palette[a]= DARKGREY;
                         palette[b] = LIGHTGREY;
                   palette[c] = YELLOW; 
             palette[d] = PURPLE; 
       palette[e] = WHITE;
 palette[f] = ORANGE;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////Tilemap/////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/////// top center rock formation
        
        if(room == 1){
  tft.drawTilemap(cameraX, cameraY, imperialbasin, spritesheet, palette);}
   else if(room == 2){
  tft.drawTilemap(cameraX, cameraY, dungeon1, spritesheet, palette);}
   else if(room == 3){
  tft.drawTilemap(cameraX, cameraY, arakeen, spritesheet, palette);}
   else if(room == 4){
  tft.drawTilemap(cameraX, cameraY, arakeen1l1, spritesheet, palette);}
   else if(room == 5){
  tft.drawTilemap(cameraX, cameraY, arakeen1l2, spritesheet, palette);}
   else if(room == 6){
  tft.drawTilemap(cameraX, cameraY, arakeen2l1, spritesheet, palette);}
   else if(room == 7){
  tft.drawTilemap(cameraX, cameraY, arakeen2l2, spritesheet, palette);}
   else if(room == 8){
  tft.drawTilemap(cameraX, cameraY, arakeen2l3, spritesheet, palette);}
   else if(room == 9){
  tft.drawTilemap(cameraX, cameraY, arakeen3, spritesheet, palette);}
   else if(room == 10){
  tft.drawTilemap(cameraX, cameraY, arakeen4l1, spritesheet, palette);}
   else if(room == 11){
  tft.drawTilemap(cameraX, cameraY, arakeen4l2, spritesheet, palette);}
   else if(room == 12){
  tft.drawTilemap(cameraX, cameraY, arakeen4l3, spritesheet, palette);}
   else if(room == 13){
  tft.drawTilemap(cameraX, cameraY, arakeen5l1, spritesheet, palette);}
   else if(room == 14){
  tft.drawTilemap(cameraX, cameraY, arakeen5b1, spritesheet, palette);}
   else if(room == 15){
  tft.drawTilemap(cameraX, cameraY, arakeen5b2, spritesheet, palette);}
   else if(room == 16){
  tft.drawTilemap(cameraX, cameraY, arakeen5l2, spritesheet, palette);}
   else if(room == 17){
  tft.drawTilemap(cameraX, cameraY, arakeen5l3, spritesheet, palette);}
   else if(room == 18){
  tft.drawTilemap(cameraX, cameraY, arakeen6l1, spritesheet, palette);}
   else if(room == 19){
  tft.drawTilemap(cameraX, cameraY, arakeen6l2, spritesheet, palette);}
   else if(room == 20){
  tft.drawTilemap(cameraX, cameraY, arakeen7, spritesheet, palette);}
   else if(room == 21){
  tft.drawTilemap(cameraX, cameraY, arakeen8, spritesheet, palette);}
   else if(room == 22){
  tft.drawTilemap(cameraX, cameraY, arakeen9, spritesheet, palette);}
   else if(room == 23){
  tft.drawTilemap(cameraX, cameraY, arakeen10, spritesheet, palette);}
   else if(room == 24){
  tft.drawTilemap(cameraX, cameraY, dungeon2, spritesheet, palette);}
   else if(room == 25){
  tft.drawTilemap(cameraX, cameraY, village2, spritesheet, palette);}
   else if(room == 26){
  tft.drawTilemap(cameraX, cameraY, village2r1, spritesheet, palette);}
   else if(room == 27){
  tft.drawTilemap(cameraX, cameraY, village2r2, spritesheet, palette);}
   else if(room == 28){
  tft.drawTilemap(cameraX, cameraY, village2r3, spritesheet, palette);}
   else if(room == 29){
  tft.drawTilemap(cameraX, cameraY, village2r4, spritesheet, palette);}
   else if(room == 30){
  tft.drawTilemap(cameraX, cameraY, village2r5, spritesheet, palette);}
   else if(room == 31){
  tft.drawTilemap(cameraX, cameraY, village2r6, spritesheet, palette);}
   else if(room == 32){
  tft.drawTilemap(cameraX, cameraY, village2r7, spritesheet, palette);}
   else if(room == 33){
  tft.drawTilemap(cameraX, cameraY, village2r8l1, spritesheet, palette);}
   else if(room == 34){
  tft.drawTilemap(cameraX, cameraY, village2r8l2, spritesheet, palette);}
   else if(room == 35){
  tft.drawTilemap(cameraX, cameraY, dungeon3, spritesheet, palette);}
   else if(room == 36){
  tft.drawTilemap(cameraX, cameraY, village3, spritesheet, palette);}
   else if(room == 37){
  tft.drawTilemap(cameraX, cameraY, village3r1, spritesheet, palette);}
   else if(room == 38){
  tft.drawTilemap(cameraX, cameraY, village3r2, spritesheet, palette);}
   else if(room == 39){
  tft.drawTilemap(cameraX, cameraY, village3r3, spritesheet, palette);}
   else if(room == 40){
  tft.drawTilemap(cameraX, cameraY, village3r4, spritesheet, palette);}
   else if(room == 41){
  tft.drawTilemap(cameraX, cameraY, village3r5, spritesheet, palette);}
   else if(room == 42){
  tft.drawTilemap(cameraX, cameraY, village3r6l1, spritesheet, palette);}
   else if(room == 43){
  tft.drawTilemap(cameraX, cameraY, village3r6l2, spritesheet, palette);}
   else if(room == 44){
  tft.drawTilemap(cameraX, cameraY, dungeon4, spritesheet, palette);}
   else if(room == 45){
  tft.drawTilemap(cameraX, cameraY, desertp1, spritesheet, palette);}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////Buttons Repeat//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////  
       if (ButtonUp.update());
               if (ButtonDown.update());
                       if (ButtonLeft.update());
                             if (ButtonRight.update());
                                       if (ButtonA.update());
                                              if (ButtonB.update());
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
                                              ButtonUp.rebounce(10);
                                     ButtonDown.rebounce(10);
                              ButtonLeft.rebounce(10);
                      ButtonRight.rebounce(10);
 //              ButtonA.rebounce(10);
          ButtonA.rebounce(10);
///////////////////////////////////////////////////////////////////////////////
////////////////////////////Up/////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
if (ButtonUp.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearwa,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearwb,palette);
    player_direction = 1;
    player_y -= 4;
    if(checkcolision())
    {
        player_y += 4;} 
    }
     if(player_y <= 16){
        player_y = 16;}  

//////////////////////////////////////////////////////////////////////////////
///////////////////////////////Down///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (ButtonDown.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontwa,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontwb,palette);
    player_direction = 2;
    player_y += 4;
    if(checkcolision())
    {
       player_y -=4;}
    }
    if(player_y >= 224){
       player_y = 224;}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////Left////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (ButtonLeft.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleftw,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleft,palette);
    player_direction = 3;
    player_x -= 4;
    if(checkcolision())
   {
      player_x += 4;}  
   }
   if(player_x >= 304){
      player_x = 304;}    
/////////////////////////////////////////////////////////////////////////////
////////////////////////////Right////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
if (ButtonRight.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulrightw,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulright,palette);
    player_direction = 4;
    player_x += 4;
  if(checkcolision())
  {
    player_x -= 4;}
  }
            if(player_x <= 16){
              player_x = 16;}
///////////////////////////////////////////////////////////////////////////////     
//////////////////////////////PLAYER DIRECTION/////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
if (player_direction == 1){
  tft.writeRectNBPP(player_x, player_y,16,16,4,paulrear,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 2){
   tft.writeRectNBPP(player_x, player_y,16,16,4,paulfront,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 3){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleft,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 4){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulright,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////        
/////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////for use with movey blocks////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 5){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearwa,palette);
}     
else if (player_direction == 6){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontwa,palette);
}     
else if (player_direction == 7){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulleftw,palette);
}          
else if (player_direction == 8){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulrightw,palette); 
}          
};

so as you can see I need to make up several button control systems that I can separate so only the called function uses a certain set of buttons
 
Saw this posted on your other thread - and snippets here don't let me show for sure.

But: Where "ButtonA.fallingEdge()" is done for Player Control - that needs to be disabled or redirected when the MENU is to be displayed.

I don't know where that code resides - somehow that needs to be taken care of:
> If menu active all xxx.fallingEdge() test and response comes from MENU code { This code must terminate MENU mode when done. }
> else MENU not active then button input moves the player as it is. { this code activates MENU mode }
 
ok here is the repository for the game as it is now...

https://github.com/Duhjoker/Pokedune

I actually posted both functions that deal with the button controls. ButtonA.fallingEdge() opens the menu and has nothing to do with any player stuff. Its the up and down and left and right buttons I'm worried about. I understand the problem as you described but don't know how to do so. like i said ive looked up and tried a lot of stuff but I cant seem to shut the first set off for the second set of controls.

both functions get called from the void loop. I tried adding if else statements for the function drawplayer() and menu()
 
Last edited:
Quick search on github shows these places taking buttons - the places taking the button input - assuming they all read using the same fallingEdge() detection will point to the area to be changed.

It other player move buttons are not fallingEdge() detected - those are the things to isolate and 'ignore' when in menu mode.

GameMenu.PNG
 
ok what about using a state else if?


Code:
if(state == drawplayer){
drawplayer();
}

else if(state == menu){
Menu();

Maybe instead of using drawplayer() and menu() straight up like listed but move the whole function over to the ino file
 
Last edited:
I found an arduboy game demo for an rpg that I'm looking and from which the state stuff comes from. Heres the void loop...
Code:
#define STATE_TITLE 0
#define STATE_ENTERNAME 1
#define STATE_GAMEPLAY 2
#define STATE_SHOP 3
#define STATE_BATTLE 4
#define STATE_TRANSITION 5
#define STATE_GAMEOVER 6
#define NONE 255

bool menuIsVisible = false;
bool menuIsSpecific = false;

#include "Arglib.h"
#include "Title.h"
#include "Item.h"
#include "Player.h"
#include "Map.h"
#include "Trigger.h"
#include "Text.h"
#include "Menu.h"
#include "Shop.h"
#include "Battle.h"

Arduboy arduboy;

byte state = STATE_TITLE;
byte nextState = STATE_ENTERNAME;

byte randomCounter = 0;

byte buttons = 0;

void setup()
{
  arduboy.start();
  arduboy.setFrameRate(60);
  
  resetPlayer();
}

void loop() 
{
  if(!arduboy.nextFrame()) return;
   arduboy.clearDisplay();

  if(state == STATE_TITLE)
  {
    arduboy.drawBitmap(10, 8, title, 109, 16, WHITE);

    if(checkLoad())
    {
      drawText(labelContinue, 40, 32, WHITE, ALIGN_LEFT);

      if(getButtonDown(UP_BUTTON) || getButtonDown(DOWN_BUTTON))
      {
        titleChoice = (titleChoice)?0:1;
      }
    }
    
    drawText(labelNewGame, 40, (checkLoad())?44:32, WHITE, ALIGN_LEFT);
    arduboy.drawBitmap(34, 32 + (titleChoice * 12), font[43], 5, 5, WHITE);

    if(arduboy.pressed(B_BUTTON))
    {
      if(checkLoad() && titleChoice == 0)
      {
        load();
        nextState = STATE_GAMEPLAY;
      }
      else nextState = STATE_ENTERNAME;
      
      state = STATE_TRANSITION;
      titleChoice = 0;
    }
  }
  else if(state == STATE_ENTERNAME) doEnterName();
  else if(state == STATE_GAMEPLAY)
  {    
    if(battleStartEffectCounter > 0)
    {
      if(--battleStartEffectCounter % 4 == 0) battleStartEffectToggle = !battleStartEffectToggle;   
      if(battleStartEffectToggle) arduboy.fillRect(0, 0, 128, 64, WHITE);

      if(battleStartEffectCounter == 0)
      {
        state = STATE_TRANSITION;
        nextState = STATE_BATTLE;
      }
    }
    else
    {
      if(!textboxIsVisible && !menuIsVisible)
      {
        updatePlayer();
        updateScene();
      }
    }

    if(!menuIsSpecific)
    {
      drawScene();
      drawPlayer();
    }
  }
  else if(state == STATE_SHOP)
  {
    drawText((shopState == SHOPSTATE_BUY)?labelShopBuy:labelShopSell, 4, 2, WHITE, ALIGN_LEFT);

    generateGoldText();
    drawText(dynamicText, 120, 2, WHITE, ALIGN_RIGHT);
    
    arduboy.fillRect(0, 10, 128, 36, WHITE);
    doItemList();

    if(!textboxIsVisible && getButtonDown(A_BUTTON)) state = STATE_GAMEPLAY;
  }
  else if(state == STATE_BATTLE)
  {
    drawBattle();
    updateBattle();
  }
  else if(state == STATE_GAMEOVER)
  {
    drawText(labelGameOver, 37, 26, WHITE, ALIGN_LEFT);

    if(arduboy.pressed(B_BUTTON))
    {
      nextState = STATE_TITLE;
      state = STATE_TRANSITION;
    }
  }
  else if(state == STATE_TRANSITION)
  {
    arduboy.display();
    delay(800);
    state = nextState;
  }
  
  if(menuIsVisible) doMenu();
  if(textboxIsVisible) doTextbox();

  if(state != STATE_TRANSITION) arduboy.display();
}

what I don't understand is how to transistion between states. And I don't understand how this works with the menu is specific and menu is visible

https://github.com/TEAMarg/ID-46-Arduventure
 
ok I tried some thing simple and it compiles and runs. Plus it kills the cursor everytime the up and down buttons are pressed outside the menu call which was one of the problems I was having. So it seems as if it has separated the functions but Hitting the A button refuses to bring up the menu. I think this has something to do with state transitions. Maybe Menu should be first so it stays visible then overlay the rest of the game over the menu?
Code:
#include <GrafxT3.h>
#include <SPIN.h>
#include <SPI.h>
#include <Bounce.h>
//#include "Battle.h"
#include "Player.h"
#include "World.h"
#include "Monsters.h"

#define STATE_Player 0
#define STATE_Menu 1
#define STATE_Transition 3

byte state = STATE_Player;
byte nextState = STATE_Menu;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#define TFT_DC  9
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 39
#define TFT_MOSI 11
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
uint8_t use_fb = 1;
uint8_t use_clip_rect = 0;
uint8_t use_set_origin = 0;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
GrafxT3 tft = GrafxT3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////Set-up//////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void setup() {
  while (!Serial && (millis() < 4000)) ;
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(BLACK);
  //tft.setFrameRate(60);
  tft.persistence = false;
   pinMode(buttonUp, INPUT_PULLUP);
   pinMode(buttonDown, INPUT_PULLUP);
   pinMode(buttonLeft, INPUT_PULLUP);
   pinMode(buttonRight, INPUT_PULLUP);
   pinMode(buttonS, INPUT_PULLUP);
   pinMode(buttonX, INPUT_PULLUP);
   pinMode(buttonY, INPUT_PULLUP);
   pinMode(buttonA, INPUT_PULLUP);
   pinMode(buttonB, INPUT_PULLUP);
   pinMode(buttonT, INPUT_PULLUP); 
   SPI.setMISO(39);
     tft.useFrameBuffer(use_fb);
 
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////Loop////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void loop(void) {

if(state == STATE_Player){
drawplayer();}
if(state == STATE_Menu){
Menu();}

///drawbattle(player_x, player_y);
  tft.updateScreen();
 
}
 
Ok I think I Know how to change states Kind of. But I still cant get the menu to popup.

Code:
 void loop(void) {

if(state == STATE_Player){
drawplayer();
   state = STATE_Player;
        nextState = STATE_Transition;
}
else if(state == STATE_Menu){
Menu();
state = STATE_Menu;
}

else if(state == STATE_Transition){
    state = nextState;
  }
 
///drawbattle(player_x, player_y);
  tft.updateScreen();
 
   }

can you see what I'm doing wrong?
 
I still cant figure out why I cant activate the menu when using states. I saw that the function page was not included in the ino so I fixed that as well but I still cant get the menu to come up.

Also is there an example for using one digital button to toggle a function. I saw one that uses three pins (input pin output pin and ground) but I don't know if it would work that way?

https://github.com/Duhjoker/Pokedune
 
usually if i use something for multifunction i set up all the different controls in the same function separated by a uint_8 switch statement, where when you write the uint8_t value, the button uses the actions in the proper switch statement.
for readability purposes you could add enums, or even instead of switch statements you can use else if conditions on the uint8_t

ex, 1 == control menu, 2 == control game, if your in the menu of the game you set the var to 1, and everything under that function will be controlled accordingly, when you exit the menu to the game, have your code set the variable to 2, this restores player controls function(obviously if you know when your menu is open or not (known state) itll be easy to set the control variable...)
 
ok let me ask for a clarification......

Create a function, we will call it controls so void controls(). And in this function I add an else if loop. So I can give it if variable A = player use this set of controls and list the controls then do an else if variable B = menu use this set of controls? Or since I have state set up already I can name the if statements if state = State_player else if state = state_menu
 
Ok I have restructured the program a lil to add the else if thing to the controls. Then I ended up having to put the function in my ino file instead of its own header.
Code:
#include <GrafxT3.h>
#include <SPIN.h>
#include <SPI.h>
#include <Bounce.h>
#include "Variables.h"
#include "Player.h"
#include "World.h"
#include "Monsters.h"
#include "Menu.h"


#define STATE_Player 1
#define STATE_Menu 0
////#define STATE_Transition 3

byte state = STATE_Menu;
byte nextState = STATE_Player;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#define TFT_DC  9
#define TFT_CS 10
#define TFT_RST 7
#define TFT_SCK 13
#define TFT_MISO 39
#define TFT_MOSI 11
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
uint8_t use_fb = 1;
uint8_t use_clip_rect = 0;
uint8_t use_set_origin = 0;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
GrafxT3 tft = GrafxT3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO, &SPIN);
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////Set-up//////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

void setup() {
  while (!Serial && (millis() < 4000)) ;
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(BLACK);
  //tft.setFrameRate(60);
  tft.persistence = false;
   pinMode(buttonUp, INPUT_PULLUP);
   pinMode(buttonDown, INPUT_PULLUP);
   pinMode(buttonLeft, INPUT_PULLUP);
   pinMode(buttonRight, INPUT_PULLUP);
   pinMode(buttonS, INPUT_PULLUP);
   pinMode(buttonX, INPUT_PULLUP);
   pinMode(buttonY, INPUT_PULLUP);
   pinMode(buttonA, INPUT_PULLUP);
   pinMode(buttonB, INPUT_PULLUP);
   pinMode(buttonT, INPUT_PULLUP); 
   SPI.setMISO(39);
     tft.useFrameBuffer(use_fb);
 
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////Loop////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void loop(void) {

if(state == STATE_Menu){
Menu();
   state = STATE_Menu;
        nextState = STATE_Player;
}
else if(state == STATE_Player){
 drawplayer();
     state = STATE_Player;
//      nextState = STATE_Menu;   
 }

if(nextState != state) state = nextState;
  

  tft.updateScreen();
 
 }

 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////controls//////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void controls(){
  //////////////////////////////////////////////////////////////////////////////
///////////////////////////////Palette////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 palette[0] = 0;
       palette[1] = BLACK;
             palette[2] = BLUE;
                   palette[3] = BROWN;
                         palette[4] = DARKGREEN;
                              palette[5] = GREY;
                                    palette[6] = PINK;
                                          palette[7] = RED;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////                                                
                                           palette[8] = BEIGE;
                                     palette[9] = GREEN;
                               palette[a]= DARKGREY;
                         palette[b] = LIGHTGREY;
                   palette[c] = YELLOW; 
             palette[d] = PURPLE; 
       palette[e] = WHITE;
 palette[f] = ORANGE;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////Buttons Repeat//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////  
       if (ButtonUp.update());
               if (ButtonDown.update());
                       if (ButtonLeft.update());
                             if (ButtonRight.update());
                                       if (ButtonA.update());
                                              if (ButtonB.update());
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
                                              ButtonUp.rebounce(10);
                                     ButtonDown.rebounce(10);
                              ButtonLeft.rebounce(10);
                      ButtonRight.rebounce(10);
               ButtonA.rebounce(10);
          ButtonB.rebounce(10);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
if(state == STATE_Player){

///////////////////////////////////////////////////////////////////////////////
////////////////////////////Up/////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
if (ButtonUp.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearwa,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearwb,palette);
    player_direction = 1;
    player_y -= 4;
    if(checkcolision())
    {
        player_y += 4;} 
    }
     if(player_y <= 16){
        player_y = 16;}  

//////////////////////////////////////////////////////////////////////////////
///////////////////////////////Down///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (ButtonDown.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontwa,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontwb,palette);
    player_direction = 2;
    player_y += 4;
    if(checkcolision())
    {
       player_y -=4;}
    }
    if(player_y >= 224){
       player_y = 224;}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////Left////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
if (ButtonLeft.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleftw,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleft,palette);
    player_direction = 3;
    player_x -= 4;
    if(checkcolision())
   {
      player_x += 4;}  
   }
   if(player_x >= 304){
      player_x = 304;}    
/////////////////////////////////////////////////////////////////////////////
////////////////////////////Right////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
if (ButtonRight.fallingEdge()){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulrightw,palette);
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulright,palette);
    player_direction = 4;
    player_x += 4;
  if(checkcolision())
  {
    player_x -= 4;}
  }
            if(player_x <= 16){
              player_x = 16;}
///////////////////////////////////////////////////////////////////////////////     
//////////////////////////////PLAYER DIRECTION/////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
if (player_direction == 1){
  tft.writeRectNBPP(player_x, player_y,16,16,4,paulrear,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 2){
   tft.writeRectNBPP(player_x, player_y,16,16,4,paulfront,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 3){
    tft.writeRectNBPP(player_x, player_y,16,16,4,paulleft,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 4){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulright,palette);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////        
/////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////for use with movey blocks////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
else if (player_direction == 5){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulrearwa,palette);
}     
else if (player_direction == 6){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulfrontwa,palette);
}     
else if (player_direction == 7){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulleftw,palette);
}          
else if (player_direction == 8){
     tft.writeRectNBPP(player_x, player_y,16,16,4,paulrightw,palette); 
     }          
 }
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// 
else if(state == STATE_Menu){

if (ButtonUp.fallingEdge()){
     tft.writeRectNBPP(cursor_x,cursor_y,16,16,4,cursordot2,palette);
     cursor_y -= 16;
//     if(checkcolision())
     {
      cursor_y += 16;} 
     }
     if(cursor_y <= 32){
        cursor_y = 32;}
          
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////Down///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 if (ButtonDown.fallingEdge()){
   tft.writeRectNBPP(cursor_x, cursor_y,16,16,4,cursordot2,palette);
   cursor_y += 16;
//    if(checkcolision())
    {
    cursor_y -= 16;}
    }
    if(cursor_y >= 224){
       cursor_y = 224;}
   }
 }

now I'm trying to figure out where to add the controls function. do I nest them in the functions that use controls or do I add them to the void loop for each state

Edit ::: adding the controls function to each state in the loop gives me controls but now I cant seem to get the menu to pop up

updated::::https://github.com/Duhjoker/Pokedune
 
Last edited:
Noted before - it is up to the STATE_Player section to set the MENU state, and the MENU state to exit by returning to STATE_Player. Does that get to the answer?

Those button presses as defined must be recognized and acted on - stop player and draw menu - and exit menu and resume player.

Very special cases to swap the state and do any screen updates and depending on menu functions offered it will change, resume, exit or restart the game.
 
ok well I had marked out the next state part in the player state so it didn't have a way to change it.
Code:
void loop(void) {

if(state == STATE_Menu){
Menu();
controls();
   state = STATE_Menu;
        nextState = STATE_Player;
}
else if(state == STATE_Player){
 drawplayer();
 controls();
     state = STATE_Player;
      nextState = STATE_Menu;   ////////////// this was commented out
 }

if(nextState != state) state = nextState;
  

  tft.updateScreen();
 
 }

What is happening now is that the menu comes on and flashes between the player screen and the menu when A is pressed and I still haven't found the proper way to toggle it on and off using the A button. But I was having a problem with the menu staying open any way.

On the controls.... when the console is powered and the program starts the controls slow annoyingly to point that the characters is barely moving. That's at all times. when the menu comes on and starts its flashing the cursor appears but does not move.


if I add and else to this line in the void loop
Code:
 if(nextState != state) state = nextState;

the console goes to black screen and the menu can be called but it wont turn off and no control of the cursor. Lol I don't understand why the controls are still acting screwy. its messing with my logic
 
Last edited:
it flashes because the mcu is so fast when you press the button it can toggle the state thousands of times, you will need to handle that (without delays hopefully) using millis() to ignore for a few seconds after activate and never switch until let go of button.

as a test, you could put a delay(1000); as a test when changing state to see if it switches properly. note: holding it down after one sec will toggle it again, but this is a test right now to check if it enters menu and player properly
 
I found a toggle example on an Arduino page and I was trying something like this....

Code:
void Menu(){
//if (ButtonA.fallingEdge()){

if(digitalRead(buttonA) ==  HIGH){
  Button = 1 - Button;
}  

if (Button == 1 && OldButton == 0){
  
 tft.writeRectNBPP(0,0,136,20,4,menul1,palette);
  tft.writeRectNBPP(0,20,136,40,4,menul2,palette);
   tft.writeRectNBPP(0,60,136,40,4,menul3,palette);
    tft.writeRectNBPP(0,100,136,40,4,menul4,palette);
     tft.writeRectNBPP(0,140,136,40,4,menul5,palette);
      tft.writeRectNBPP(0,180,136,40,4,menul6,palette);
       tft.writeRectNBPP(0,220,136,20,4,menul7,palette);
        tft.writeRectNBPP(136,0,184,26,4,menur1,palette);
         tft.writeRectNBPP(136,26,184,16,4,menur2,palette);
          tft.writeRectNBPP(136,42,184,16,4,menur2,palette);
           tft.writeRectNBPP(136,58,184,16,4,menur2,palette);
          tft.writeRectNBPP(136,74,184,16,4,menur2,palette);
         tft.writeRectNBPP(136,90,184,16,4,menur2,palette);
        tft.writeRectNBPP(136,106,184,16,4,menur2,palette);
       tft.writeRectNBPP(136,122,184,16,4,menur2,palette);
      tft.writeRectNBPP(136,138,184,16,4,menur2,palette);
     tft.writeRectNBPP(136,154,184,16,4,menur2,palette);
    tft.writeRectNBPP(136,170,184,16,4,menur2,palette);
   tft.writeRectNBPP(136,186,184,16,4,menur2,palette);
  tft.writeRectNBPP(136,202,184,16,4,menur2,palette);
 tft.writeRectNBPP(136,218,184,22,4,menur3,palette);
 delay(500);
  }
 if (Button == 0 && OldButton == 1){
  drawplayer();
 delay(500);
 }

 OldButton = Button;
}

But its giving me an error about drawplayer saying it hasn't been declared. I have Player.h included in my menu header. I tried to fix it by changing void drawplayer to a bool drawplayer(void) but it wont include draw player

post 5
https://forum.arduino.cc/index.php?topic=58284.0
 
ugghh. I haven't made any progress but ive been busy making some much needed changes. The main thing was changing my player stuff to a structure. For some reason I though that might help with the controls switch. I also added a collision system to the menu function for when I get the controls to work. I left the do it parts empty but I should be able to save check and load the player structure(game).

Ive tried about 5 different things tonight as well to toggle the menu on and off when hitting the A button then hitting the A button again to turn it off.

https://github.com/Duhjoker/Pokedune

Edit:::

Adding a delay as suggested produces an erratic effect with the menu coming on for a flash ramdomly when A button is pressed.

I also tried giving each set of controls thier own function then adding the appropriate function to the appropriate state after calling the function like its done now.

On the toggle menu part it seems like i could add drawplayer() after a second button press but that doesnt work either.
 
Last edited:
Ok I'm out of knowledgeable options I'm still trying to get the cursor to move but it wont. The weird part is that the cursor does show up when in menu mode and down or up are pressed and disappears when in player mode. This tells me the function is partially working but not as it should. So the question is what is letting the player move but not the cursor. I checked my end points up and down so the cursor doesn't go off the screen and corrected those coordinates thinking it might help. Idk this is beyond my understanding of how things work.

I did add a delay between the menu and player state and while it looked erratic to me because I set it at 2 seconds it performed the delay when hitting the A button. Maybe some one could take a look at the program? maybe I'm missing something or have something I shouldn't. Links hints anything.

https://github.com/Duhjoker/Pokedune
 
All right guys ive read up on program structure, function structure and variable structures, My latest fail was this lil bit of code. it was supposed to check for the state then use the proper function to either move the cursor or move the player.


Code:
void ButtonOutputs() {
  //start with decoding the buttons we just read in the readInputs() function
 if (state == STATE_Menu){
ButtonUp.update(); ButtonUp.rebounce(10);ButtonDown.update(); ButtonDown.rebounce(10) ;ButtonA.update(); ButtonA.rebounce(10);
    if(ButtonUp.fallingEdge()){cursorUp();}
    if(ButtonDown.fallingEdge()){ cursorDown();}
//    if(ButtonA.fallingEdge()) {state = STATE_Player;}
  }
else if (state == STATE_Player){
ButtonUp.update(); ButtonUp.rebounce(10); ButtonDown.update(); ButtonDown.rebounce(10);ButtonLeft.update(); ButtonLeft.rebounce(10);
ButtonRight.update(); ButtonRight.rebounce(10);ButtonA.update(); ButtonA.rebounce(10);
    //we're in the normal player-movement mode...
    if(ButtonUp.fallingEdge()) {playerUp();}
    if(ButtonDown.fallingEdge()) {playerDown();}
    if(ButtonLeft.fallingEdge()) {playerLeft();}
    if(ButtonRight.fallingEdge()) {playerRight();}
//    if(ButtonA.fallingEdge()) {state = STATE_Menu;}
     }
}

I'm wondering if something like this might work....
Code:
else if((state == State_Menu  &&  (ButtonUp.fallingEdge)){ movecursor}

I'm up for any ideas though
 
ok guys what am I missing? Why cant I get the button functions to pause for others?
Code:
void controls(){
ButtonUp.update(); ButtonUp.rebounce(10); ButtonDown.update(); ButtonDown.rebounce(10);ButtonLeft.update();
ButtonLeft.rebounce(10);ButtonRight.update(); ButtonRight.rebounce(10); ButtonA.update(); ButtonA.rebounce(10);
  
if ((ButtonUp.fallingEdge() && state == STATE_Menu)){cursorUp();}
else if ((ButtonDown.fallingEdge() && state == STATE_Menu)){cursorDown();}
/////////////////////////////////////////////////////////////////////////
else if ((ButtonUp.fallingEdge() && state == STATE_Player)){playerUp();}
else if ((ButtonDown.fallingEdge() && state == STATE_Player)){playerDown();}
else if ((ButtonLeft.fallingEdge() && state == STATE_Player)){playerLeft();}
else if ((ButtonRight.fallingEdge() && state == STATE_Player)){playerRight();}
}
 
Once i removed the timer on one of my functions, it started working right. Are there timers pre-installed or do i need a crystal to use them? My updateAll command uses timers as well in millis but ive never gotten to work when dropping functions in it. Theres a definite reason i ask that pertains to the thread.
 
Status
Not open for further replies.
Back
Top