Start Screen: how to select with keys or mouse

Blitz3D Forums/Blitz3D Programming/Start Screen: how to select with keys or mouse

RubyEnemy(Posted 2016) [#1]
how do you have use the arrow keys or the mouse to select the start, controls, and scores options when starting a game?


_PJ_(Posted 2016) [#2]
One of the most annoying and boring parts of the game development process in my opinion is coding the front-end and user interface - unfortunately, there's no simple native Blitz3D solution.

Essentially, you need to read and resolve all of the user input and its on-screen appearance.





Matty(Posted 2016) [#3]
You have to code all that functionality yourself.

That means using commands like keydown, keyhit, mousedown, mousehit along with either images or sprites for button images, and the mousex, mousey commands to check if the cursor is within the boundaries of the button images.

There's a fair bit to do to get that to do it - but if you design it well you can reuse it elsewhere easily throughout the rest of your program.


RubyEnemy(Posted 2016) [#4]
thanks _PJ_ you're a big help


RubyEnemy(Posted 2016) [#5]
how would i apply my custom welcome screen to the the code you gave me?

Const ESC_KEY=1
Const Q_KEY=16

;launches the welcome functions
welcome()

;creating welcome function
Function welcome()
Graphics 640,480
screen=LoadImage("textures/truewelcome.png")
DrawImage screen,0,-75
While Not KeyDown(1)
If KeyDown(16) Then Return
Wend
End Function


Dan(Posted 2016) [#6]
Hi, first, you will need to decide if you want to use only the mouse, or arrow keys or maybe both on your start screen.

If you want to use keys only, then imagine having a variable called menue

This menue variable is starting with the default number 1. This would represent the start button.
number 2 would be controls, and 3 would be score.

now you will need to increase and decrease this menue variable with the arrow keys.

The limits would be minimum 1, maximum 3.

Pressing enter/return would take you to the variable's destination.

here is an example following the above's description:


in this example i have used simple text functions to display the menue.
you can easily replace it to display boxes and even images.


RubyEnemy(Posted 2016) [#7]
how would you make the text appear bigger?


Matty(Posted 2016) [#8]
You would use the font commands, loadfont and setfont.

Or alternatively you would use bitmap fonts, put them on a texture and use 2d-in-3d and scale them on the fly.


_PJ_(Posted 2016) [#9]
Sorry for the late reply. Hadn't noticed there was more to this.

Here's an updated version of the same code I posted above, but now including the Welcome Screen and also a custom loaded font so you can alter the size.


Graphics3D 800,600,32

Const WELCOME_SCREEN_PATH$="textures/truewelcome.png"

Const FONT_NAME$="Arial"
Const FONT_SIZE=18


Const STATE_WELCOME=0
Const STATE_MENU_MAIN=1
Const STATE_MENU_OPTIONS=2
Const STATE_GAME_INITIALISE=3
Const STATE_GAME_RUNNING=4
Const STATE_GAME_OVER=5

Global MACHINE_STATE
Global MENU_HIGHLIGHTED=0

Const MENU_MAIN_SELECTIONS=2
Const MENU_OPTIONS_SELECTIONS=3

Const BUTTON_WIDTH=128
Const BUTTON_HEIGHT=48

Global MENU_BUTTONS[MENU_MAIN_SELECTIONS+MENU_OPTIONS_SELECTIONS]

Const BUTTON_MAIN_START=0
Const BUTTON_MAIN_OPTIONS=1

Const BUTTON_OPTIONS_BACK=2
Const BUTTON_OPTIONS_GRAPHICS=3
Const BUTTON_OPTIONS_SOUND=4

Const KEY_SCANCODE_UP=200
Const KEY_SCANCODE_DOWN=208
Const KEY_SCANCODE_SPACE=57
Const KEY_SCANCODE_Q=16

Global KEY_SELECTION_UP=KEY_SCANCODE_UP
Global KEY_SELECTION_DOWN=KEY_SCANCODE_DOWN
Global KEY_SELECTION_GO=KEY_SCANCODE_SPACE

Global IMG_WELCOME_SPLASH

Runtime


Function Initialise()
	;Load Assets here etc.
	
	IMG_WELCOME_SPLASH=LoadImage(WELCOME_SCREEN_PATH$)
	
	Local Font=LoadFont(FONT_NAME,FONT_SIZE)
	SetFont Font
	
	MENU_BUTTONS[BUTTON_MAIN_START]=CreateImage(BUTTON_WIDTH,BUTTON_HEIGHT)
	SetBuffer ImageBuffer(MENU_BUTTONS[BUTTON_MAIN_START])
	Text BUTTON_WIDTH Shr True ,BUTTON_HEIGHT Shr True,"START GAME",True,True
	
	MENU_BUTTONS[BUTTON_MAIN_OPTIONS]=CreateImage(BUTTON_WIDTH,BUTTON_HEIGHT)
	SetBuffer ImageBuffer(MENU_BUTTONS[BUTTON_MAIN_OPTIONS])
	Text BUTTON_WIDTH Shr True,BUTTON_HEIGHT Shr True,"OPTIONS",True,True
	
	
	
	
	
	MENU_BUTTONS[BUTTON_OPTIONS_BACK]=CreateImage(BUTTON_WIDTH,BUTTON_HEIGHT)
	SetBuffer ImageBuffer(MENU_BUTTONS[BUTTON_OPTIONS_BACK])
	Text BUTTON_WIDTH Shr True ,BUTTON_HEIGHT Shr True,"BACK",True,True
	
	MENU_BUTTONS[BUTTON_OPTIONS_GRAPHICS]=CreateImage(BUTTON_WIDTH,BUTTON_HEIGHT)
	SetBuffer ImageBuffer(MENU_BUTTONS[BUTTON_OPTIONS_GRAPHICS])
	Text BUTTON_WIDTH Shr True ,BUTTON_HEIGHT Shr True,"GRAPHICS",True,True
	
	MENU_BUTTONS[BUTTON_OPTIONS_SOUND]=CreateImage(BUTTON_WIDTH,BUTTON_HEIGHT)
	SetBuffer ImageBuffer(MENU_BUTTONS[BUTTON_OPTIONS_SOUND])
	Text BUTTON_WIDTH Shr True ,BUTTON_HEIGHT Shr True,"SOUND",True,True
	
	FreeFont Font
End Function

Function Runtime()
	Initialise
	SetBuffer BackBuffer()
	Main_Loop
	EndGraphics
	End 
End Function

Function Main_Loop()
	
	While (Not(KeyDown(1)))
		StartLoop 
		UpdateLoop
		EndLoop
	Wend
	
End Function

Function StartLoop()
	Cls
End Function

Function UpdateLoop()
	
	Select (MACHINE_STATE)
		Case STATE_WELCOME:
			WelcomeScreen
		Case STATE_MENU_MAIN,STATE_MENU_OPTIONS:
			Menu
		Case STATE_GAME_INITIALISE:
			RuntimeError("Game Has Begun...")
		Case  STATE_GAME_RUNNING:
		Case STATE_GAME_OVER:
	End Select
	
End Function

Function EndLoop()
	Render
End Function

Function Render()
	Flip
End Function

Function Menu()
	
	Local SelectIonStart
	Local SelectionEnd
	
	Select (MACHINE_STATE)
		Case STATE_MENU_MAIN:
			SelectIonStart=BUTTON_MAIN_START
			SelectionEnd=BUTTON_MAIN_OPTIONS
			
		Case STATE_MENU_OPTIONS:
			SelectIonStart=BUTTON_OPTIONS_BACK
			SelectionEnd=BUTTON_OPTIONS_SOUND
			
	End Select
	
	DrawMenuButtons(SelectIonStart,SelectionEnd)
	UpdateMouseSelection(SelectIonStart,SelectionEnd)
	UpdateKeyboardSelection(SelectIonStart,SelectionEnd)
	ShowSelectionRectangle(SelectIonStart,SelectionEnd)
End Function

Function MenuSelectEvent()
	;Responds to Menu Selection and changes Machine State
	Select (MENU_HIGHLIGHTED)
		Case BUTTON_MAIN_START:
			MACHINE_STATE=STATE_GAME_INITIALISE
			
		Case BUTTON_MAIN_OPTIONS:
			MACHINE_STATE=STATE_MENU_OPTIONS
			MENU_HIGHLIGHTED=BUTTON_OPTIONS_BACK
			
		Case BUTTON_OPTIONS_BACK:
			MACHINE_STATE=STATE_MENU_MAIN
			MENU_HIGHLIGHTED=BUTTON_MAIN_START
			
		Case BUTTON_OPTIONS_GRAPHICS:
			;... etc. Not completed here
			
		Case BUTTON_OPTIONS_SOUND:
			;... etc. Not completed here
	End Select
End Function

Function UpdateMouseSelection(SelectionStart,SelectionEnd)
	;Updates Selection based on MouseOver - Can be replaced with ImagesCollide() if using an Image for the pointer
	Local Iter
	
	Local X
	Local Y
	
	Local Count=SelectionEnd-SelectionStart
	
	For Iter=0 To Count
		X=GetXPosition(Iter,Count)		
		Y=GetYPosition(Iter,Count)
		
		If (GetMouseOver(X,Y,BUTTON_WIDTH,BUTTON_HEIGHT))
			DebugLog(Iter)
			MENU_HIGHLIGHTED=Iter+SelectionStart
			
			If (MouseHit(1))
				;Keep this here, so Mouseclick only calls event whilst mouseover
				MenuSelectEvent
			End If	
			
		End If
		
	Next
End Function	

Function UpdateKeyboardSelection(SelectIonStart,SelectionEnd)
	;Updates Selection based on Key Input
	
	Local SelectionChange=KeyHit(KEY_SELECTION_DOWN)-KeyHit(KEY_SELECTION_UP)
	
	If (SelectionChange)
		MENU_HIGHLIGHTED=MENU_HIGHLIGHTED+SelectionChange
		If (MENU_HIGHLIGHTED>SelectionEnd)
			MENU_HIGHLIGHTED=SelectIonStart
		End If
		If (MENU_HIGHLIGHTED<SelectIonStart)
			MENU_HIGHLIGHTED=SelectionEnd
		End If
	End If
	
	If (KeyHit(KEY_SELECTION_GO))
		MenuSelectEvent
	End If
	
End Function	

Function GetMouseOver(x,y,w,h)
	Local mx=MouseX()
	Local my=MouseY()
	Return  (  ((mx>x) And (mx<(x+w)))    And    ((my>y) And (my<(y+h)))  )
End Function

Function ShowSelectionRectangle(SelectionStart,SelectionEnd)
	Rect GetXPosition(SelectionStart,SelectionEnd),GetYPosition(MENU_HIGHLIGHTED-SelectionStart,SelectionEnd),BUTTON_WIDTH,BUTTON_HEIGHT,False
End Function

Function DrawMenuButtons(ButtonStart,ButtonEnd)
		;Draws the buttons from the library
	Local Count=ButtonEnd-ButtonStart
	
	Local Iter
	Local X
	Local Y
	For Iter= 0 To Count
		X=GetXPosition(Iter,Count)
		Y=GetYPosition(Iter,Count)
		DrawImage MENU_BUTTONS[Iter+ButtonStart],X,Y
	Next
End Function		

Function GetXPosition(Item,Count)
	;So the same function can be used for selection rectangle, mouse events and the actual button drawing
	Return (GraphicsWidth() Shr True) - (BUTTON_WIDTH Shr True)
End Function

Function GetYPosition(Item,Count)		
	;So the same function can be used for selection rectangle, mouse events and the actual button drawing
	Return  (BUTTON_HEIGHT*1.5)*(Item+1)
End Function

Function WelcomeScreen()
	DrawImage IMG_WELCOME_SPLASH,(GraphicsWidth() Shr True)-ImageWidth(IMG_WELCOME_SPLASH),(GraphicsHeight() Shr True)-ImageHeight(IMG_WELCOME_SPLASH)
	If ((KeyHit(KEY_SELECTION_GO)) Or MouseHit(1))
		MACHINE_STATE=STATE_MENU_MAIN
	End If
End Function



RubyEnemy(Posted 2016) [#10]
I've decided to use this as my menu screen because it was simpler and now in just need to figure out ;how or where i would create a code to when i press start it would start the game instead of saying that i hit the start button?

IF you want the code for our game then ask?





menue=1
menuedelay=MilliSecs()
a$=""

SetBuffer BackBuffer()
Graphics3D 640,480,16,2

;Main menue loop starts here
Repeat

Gosub menukeys
Gosub drawscreen

If KeyDown(28) Or KeyDown(57) ;Enter or Space
Select menue
Case 1
Gosub START
Case 2
Gosub CONTROLS
Case 3
Gosub SCORE
Case 4
Gosub OPTIONS
End Select
EndIf
Flip
Until KeyDown(1)
;Escape key exits the main menue loop

End

.start
;game start
A$="Starting"
Return

.controls
;Setting up controls
A$="Controls"
Return

.options
;geyying options
A$="Options"
Return


.score
;Displaying score
A$="Score"
Return

.drawscreen
Cls
Graphics3D 640,480
screen=LoadImage("textures/truewelcome.png")
DrawImage screen,0,0
Const font_nameA$="ariel"
Const font_size=20


Color $ff,$ff,$ff
Text 0,0,"Last item choosen was: "+A$

;If variable number Then Color red, Else Color white

If menue=1 Then Color $ff,0,0 Else Color $ff,$ff,$ff
Text 10,100,"Start"


If menue=2 Then Color $ff,0,0 Else Color $ff,$ff,$ff
Text 10,140,"Controls"


If menue=3 Then Color $ff,0,0 Else Color $ff,$ff,$ff
Text 10,180,"Score"


If menue=4 Then Color $ff,0,0 Else Color $ff,$ff,$ff
Text 10,220,"Options"


Return


.menukeys
If MilliSecs()-menuedelay > 75 ;Delaying the keypress or else it would be too fast, switching between 1 and 3
menuedelay=MilliSecs()

If KeyDown(200) Then menue=menue-1 ;KeyUp
If KeyDown(208) Then menue=menue+1 ;KeyDown
If menue<=1 Then menue=1
If menue=>4 Then menue=4
EndIf

Return


Dan(Posted 2016) [#11]
Hi, please put the code which you want to write here on forums, in code boxes.

Before pasting the text, use


Codebox shoud be written in lower case letters:

[Codebox]
paste your text here
[/Codebox]




Here is the above Code with some Improvements.



You want to make sure, that Graphic command is Called only 1 time in your program.

Setbuffer command is used, normaly, after Graphic.

Loading Images shall be done after Graphic command is set. They will Remain in the memory, so you dont need to load them in a loop.

Loading images and then executing the Graphic command will clear every loaded images. This will Crash your program, as soon as you try to draw the image.



how or where i would create a code to when i press start it would start the game



This is the code which do something after you hit enter:



After hitting the Return button,the Gosub statement leads you to the labels. To start the game, you would then make a game loop inbetween .start and the Return :
.start         ;.start is an label, here does the "Gosub start" jumps into.
;game start

A$="Starting"  ;this is the text, which is displayed in my example.It is here,where your game starts.

Return         ;After the Game ends, Return jumps back to the line where Gosub start was called



RubyEnemy(Posted 2016) [#12]
how would i have an image showing for the controls of my game when i hit enter on the controls option and i can go back to the menu screen again?


RubyEnemy(Posted 2016) [#13]
so any helpful tips?


Dan(Posted 2016) [#14]
you want to display a picture, which is explaining which keys are used ?

then youll have to load a picture into a variable, right after screen=LoadImage("textures/truewelcome.png")

img_controls=LoadImage("images/controls.png")




at the end of the listing use (copy&paste) following function:

Function CheckReturn()
 if keydown(28) or Keydown(57)      ;check if user has pressed the enter or return keys
   while keydown(28) or Keydown(57) ;Wait until user has released the keys
      delay 1
   Wend
   Return 1
 EndIf
 Return 0 
End Function