Here's the function from my game used for handling any 2d overlay's, from the main menu, to game lobby's, to ingame hud.
It's called every single loop, but only displays what it should according to your current 'menu' and 'selection'
I'm going to optimise it a bit further down the track, but the basic operation is there and it's been bug free for me so far
Code might look a little daunting at first, just copy and paste it into a new project and run it (requires no media) and click on things, you'll find how it works
Note: requires Advanced2D
Note2: supports WASD/Arrows/Mouse click for menu selections and modifying values
Note3: supports key/mouseclick locking, keyboard type rate (with delay)
Note4: if you wish to hide the menu simply set MenuSelection(0)="" anywhere within your gamecode, to display a menu again you set MenuSelection(0) to whichever menu you want to pull up. Because it's running every single loop, any menu can be displayed at any point in time. It also will 'not' stop your game from running in the background and will simply overlay onto the top of it. Ah the beauty of functions
// Setup Variables required for Menu/Mousecheck/Keycheck system to work
Dim MenuSelection(10) As String // 0 = active menu, i.e. main/host/join/gamelobby, 1 = item currently selected, 9=last page, For returning after i.e. Playername->gamelobby, 10=max entries in menu
MenuSelection(0)="main" : MenuSelection(1)="1"
dim KeyLocked(255) as boolean // if keyboard key was pressed previously, must be released to be pressed again, call KeyCheck(#)
dim KeyTimer(255) as integer : KeyTimer(0)=500 : KeyTimer(1)=16 // used for repeated key strokes, 0=Initial delay in ms, 1=repeat delay in ms
dim KeyRepeating(255) as boolean// Checks if key is still in initial delay stage, 0=delayed, 1=repeating
dim MouseLocked(64) as boolean // if mouse button was clicked, must be released to be pressed again, call MouseCheck(#)
Dim Verdana(48) As Integer // Font For use with Advanced2D, i.e. Verdana(32)=verdana 32pt font
for i=2 to array count(verdana(0)) step 2
Verdana(i)=a2CreateFont("verdana",i,a2Size_Char(),a2Style_Bold())
Next i
dim NumberTest(0) as integer
Global Name as string
Name="test"
sync on : sync rate 60
// set basic sprites for menu backgrounds, you can make/load your own if you prefer
set window title "Loading..."
box 0,0,500,100,rgb(50,50,50),rgb(170,170,170),rgb(50,50,50),rgb(170,170,170)
for i=1 to 100
get image i,0,0,500,100
sprite i,-1000,-1000,i
set sprite alpha i,100
next i
cls
set window title "Menu System Test"
do
Menu(MenuSelection(0))
sync
loop
function Menu(MenuType$)
if MenuType$<>"ingame" then hide all sprites
for i=1 to 100
if zone exist(i) then clear zone i
Next i
if KeyCheck(200) or KeyCheck(17) then if MenuSelection(0)<>"gamelobby" then if val(MenuSelection(1))>1 then i=val(MenuSelection(1)) : dec i,1 : MenuSelection(1)=str$(i)
if KeyCheck(208) or KeyCheck(31) then if MenuSelection(0)<>"gamelobby" then if val(MenuSelection(1))<val(MenuSelection(10)) then i=val(MenuSelection(1)) : inc i,1 : MenuSelection(1)=str$(i)
if KeyCheck(2) and val(MenuSelection(10))=>1 then MenuSelection(1)="1"
if KeyCheck(3) and val(MenuSelection(10))=>2 then MenuSelection(1)="2"
if KeyCheck(4) and val(MenuSelection(10))=>3 then MenuSelection(1)="3"
if KeyCheck(5) and val(MenuSelection(10))=>4 then MenuSelection(1)="4"
if KeyCheck(6) and val(MenuSelection(10))=>5 then MenuSelection(1)="5"
if KeyCheck(7) and val(MenuSelection(10))=>6 then MenuSelection(1)="6"
if KeyCheck(8) and val(MenuSelection(10))=>7 then MenuSelection(1)="7"
if KeyCheck(9) and val(MenuSelection(10))=>8 then MenuSelection(1)="8"
if MenuSelection(0)="main"
MenuSelection(10)="3"
// ------ set up visual area ------
// Menu Bar
size sprite 1,300,50 : sprite 1,screen width()/2-sprite width(1)/2,20,1 : show sprite 1
a2boxtext Verdana(40),Sprite x(1),sprite y(1),SpriteX2(1),SpriteY2(1),"Main Menu",1,1,0,rgb(255,0,50,255)
// Menu Selections
size sprite 2,250,35 : sprite 2,50,100,1 : show sprite 2
size sprite 3,250,35 : sprite 3,50,180,1 : show sprite 3
size sprite 4,250,35 : sprite 4,50,260,1 : show sprite 4
a2boxtext Verdana(26),Sprite x(2),sprite y(2),SpriteX2(2),SpriteY2(2),"Single Player",1,1,0,SelectionColor(1)
a2boxtext Verdana(26),Sprite x(3),sprite y(3),SpriteX2(3),SpriteY2(3),"Name: "+Name,1,1,0,SelectionColor(2)
a2boxtext Verdana(26),Sprite x(4),sprite y(4),SpriteX2(4),SpriteY2(4),"Quit Game",1,1,0,SelectionColor(3)
// ------ set up visual area ------
set zone 1,sprite x(2),sprite y(2),spriteX2(2),spriteY2(2) // set clickable zone's, used when checking for mouse clicks
set zone 2,sprite x(3),sprite y(3),spriteX2(3),spriteY2(3) // set clickable zone's, used when checking for mouse clicks
set zone 3,sprite x(4),sprite y(4),spriteX2(4),spriteY2(4) // set clickable zone's, used when checking for mouse clicks
if MouseCheck(1) and zone(mousex(),mousey())=0 then MouseLocked(1)=1
if KeyCheck(28) or MouseCheck(1) and zone(mouseX(),mousey())>0
if MouseCheck(1) then MouseLocked(1)=1 : if zone(mouseX(),mouseY())<>0 then MenuSelection(1)=str$(zone(mouseX(),mouseY()))
if MenuSelection(1)="3" then wait 100 : end
if MenuSelection(1)="1" then MenuSelection(0)="single" : MenuSelection(1)="1"
if MenuSelection(1)="2" then MenuSelection(9)=MenuSelection(0) : MenuSelection(0)="name" : MenuSelection(1)="1"
Endif
Endif
if MenuSelection(0)="single"
MenuSelection(10)="2"
// Menu Bar
size sprite 1,300,50 : sprite 1,screen width()/2-sprite width(1)/2,20,1 : show sprite 1
a2boxtext Verdana(40),sprite x(1),sprite y(1),SpriteX2(1),SpriteY2(1),"Singleplayer",1,1,0,rgb(255,0,0,255)
// Menu Selections
size sprite 2,400,35 : sprite 2,50,100,1 : show sprite 2
size sprite 3,400,35 : sprite 3,50,180,1 : show sprite 3
a2boxtext Verdana(26),Sprite x(2),sprite y(2),SpriteX2(2),SpriteY2(2),"Back to Main Menu",1,1,0,SelectionColor(1)
a2boxtext Verdana(26),Sprite x(3),sprite y(3),SpriteX2(3),SpriteY2(3),"Left/Right Key test ="+str$(NumberTest(0)),1,1,0,SelectionColor(2)
set zone 1,sprite x(2),sprite y(2),spriteX2(2),spriteY2(2) // set clickable zone's, used when checking for mouse clicks
set zone 2,sprite x(3),sprite y(3),spriteX2(3),spriteY2(3) // set clickable zone's, used when checking for mouse clicks
if MouseCheck(1) and zone(mousex(),mousey())=0 then MouseLocked(1)=1
if KeyCheck(28) or MouseCheck(1) and zone(mouseX(),mousey())>0
if MouseCheck(1) then MouseLocked(1)=1 : if zone(mouseX(),mouseY())<>0 then MenuSelection(1)=str$(zone(mouseX(),mouseY()))
if MenuSelection(1)="1" then MenuSelection(0)="main" : MenuSelection(1)="1"
Endif
if KeyCheck(203) or KeyCheck(30) // Left Key
if MenuSelection(1)="2" and NumberTest(0)>0 then dec NumberTest(0),1
Endif
if KeyCheck(205) or KeyCheck(32) // Right Key
if MenuSelection(1)="2" and NumberTest(0)<128 then inc NumberTest(0),1
endif
Endif
if MenuSelection(0)="name"
MenuSelection(10)="1"
// Menu Bar
size sprite 1,300,50 : sprite 1,screen width()/2-sprite width(1)/2,20,1 : show sprite 1
a2boxtext Verdana(40),Sprite x(1),sprite y(1),SpriteX2(1),SpriteY2(1),"Enter a name",1,1,0,rgb(0,0,255)
// Menu Selections
size sprite 2,400,35 : sprite 2,50,100,1 : show sprite 2
a2boxtext Verdana(26),Sprite x(2),sprite y(2),SpriteX2(2),SpriteY2(2),">>"+Name+"<<",1,1,0,rgb(255,0,0)
Name=Name+entry$(1) : Clear Entry Buffer
If KeyCheck(14) Then Name=left$(Name,len(Name)-1)
if len(Name)>16 then Name=left$(Name,16)
if KeyCheck(28)
MenuSelection(0)=MenuSelection(9) : MenuSelection(1)="1"
Endif
Endif
EndFunction
function SelectionColor(Var)
i1=rgb(255,255,20,20) // Selected Color
i2=rgb(255,183,62,255)// Not Selected Color
if val(MenuSelection(1))=Var then i=i1 else i=i2
Endfunction i
function KeyCheck(i)
i2=0
if i=0
for i3=1 to 255
if keystate(i3)=0 then KeyLocked(i3)=0 : KeyRepeating(i3)=0 : KeyTimer(i3)=hitimer(1000)
Next i3
Endif
if KeyLocked(i)=0 and keystate(i)=1 then KeyLocked(i)=1 : i2=1 : KeyTimer(i)=hitimer(1000)
if keystate(i)=0 then KeyLocked(i)=0 : KeyRepeating(i)=0
if keystate(i) then if i>1 and i<28 or i>29 and i<42 or i>42 and i<54 or i=57 or i>70 and i<84 or i=181 or i=199 or i=200 or i=201 or i=203 or i=205 or i>206 and i<212 // check for valid repeatable keys
if KeyRepeating(i)=0 and hitimer(1000)-KeyTimer(i)=>KeyTimer(0) then KeyRepeating(i)=1 : KeyLocked(i)=0
if KeyRepeating(i)=1 and hitimer(1000)-KeyTimer(i)=>KeyTimer(1) then KeyLocked(i)=0 : KeyTimer(i)=hitimer(1000)
Endif
Endfunction i2
function MouseCheck(i)
i2=0
i3=mouseclick()&&i
if MouseLocked(i)=0 and i3>0 then i2=1
if MouseLocked(i)=1 and i3=0 then MouseLocked(i)=0
endfunction i2
function SpriteX2(Var)
i=sprite x(Var)+Sprite Width(Var)
Endfunction i
function SpriteY2(Var)
i=sprite y(Var)+Sprite Height(Var)
Endfunction i