-
Notifications
You must be signed in to change notification settings - Fork 19
Menu Buttons
In this part I want to implement a simple main menu screen.
I use a simple menu, that consist of just two buttons: "Play" and "Quit".
Each button is a rectangle, represented by it's own image (in fact, a different quads of the same image).
A button has a selected
flag, which is activated if a mouse pointer hovers over it.
If a button is selected
, it's image changes.
Being a rectangle, a button needs position, width, and height.
To display a texture, it needs an image and a quad. A different quad is used if
the selected
flag is active. If no image or quad is provided, a text is displayed instead.
According to this description, a button constructor has the following form.
function buttons.new_button( o )
return( { position = o.position or vector( 300, 300 ),
width = o.width or 100,
height = o.height or 50,
text = o.text or "hello",
image = o.image or nil,
quad = o.quad or nil,
quad_when_selected = o.quad_when_selected or nil,
selected = false } )
end
- Update and draw
function buttons.update_button( single_button, dt )
local mouse_pos = vector( love.mouse.getPosition() )
if( buttons.inside( single_button, mouse_pos ) ) then
single_button.selected = true
else
single_button.selected = false
end
end
function buttons.draw_button( single_button )
if single_button.selected then
if single_button.image and single_button.quad_when_selected then
love.graphics.draw( single_button.image,
single_button.quad_when_selected,
single_button.position.x,
single_button.position.y )
else
love.graphics.rectangle( 'line',
single_button.position.x,
single_button.position.y,
single_button.width,
single_button.height )
local r, g, b, a = love.graphics.getColor()
love.graphics.setColor( 255, 0, 0, 100 )
love.graphics.print( single_button.text,
single_button.position.x,
single_button.position.y )
love.graphics.setColor( r, g, b, a )
end
else
if single_button.image and single_button.quad then
love.graphics.draw( single_button.image,
single_button.quad,
single_button.position.x,
single_button.position.y )
else
love.graphics.rectangle( 'line',
single_button.position.x,
single_button.position.y,
single_button.width,
single_button.height )
love.graphics.print( single_button.text,
single_button.position.x,
single_button.position.y )
end
end
end
function buttons.inside( single_button, pos )
return
single_button.position.x < pos.x and
pos.x < ( single_button.position.x + single_button.width ) and
single_button.position.y < pos.y and
pos.y < ( single_button.position.y + single_button.height )
end
- In the "menu" state create start and quit buttons:
local menu_buttons_image = love.graphics.newImage( "img/800x600/buttons.png" )
local button_tile_width = 128
local button_tile_height = 64
local play_button_tile_x_pos = 0
local play_button_tile_y_pos = 0
local quit_button_tile_x_pos = 0
local quit_button_tile_y_pos = 64
local selected_x_shift = 128
local tileset_width = 256
local tileset_height = 128
local play_button_quad = love.graphics.newQuad(
play_button_tile_x_pos,
play_button_tile_y_pos,
button_tile_width,
button_tile_height,
tileset_width,
tileset_height )
local play_button_selected_quad = love.graphics.newQuad(
play_button_tile_x_pos + selected_x_shift,
play_button_tile_y_pos,
button_tile_width,
button_tile_height,
tileset_width,
tileset_height )
local quit_button_quad = love.graphics.newQuad(
quit_button_tile_x_pos,
quit_button_tile_y_pos,
button_tile_width,
button_tile_height,
tileset_width,
tileset_height )
local quit_button_selected_quad = love.graphics.newQuad(
quit_button_tile_x_pos + selected_x_shift,
quit_button_tile_y_pos,
button_tile_width,
button_tile_height,
tileset_width,
tileset_height )
function menu.load( prev_state, ... )
start_button = buttons.new_button{
text = "New game",
position = vector( (800 - button_tile_width) / 2, 200),
width = button_tile_width,
height = button_tile_height,
image = menu_buttons_image,
quad = play_button_quad,
quad_when_selected = play_button_selected_quad
}
quit_button = buttons.new_button{
text = "Quit",
position = vector( (800 - button_tile_width) / 2, 310),
width = button_tile_width,
height = button_tile_height,
image = menu_buttons_image,
quad = quit_button_quad,
quad_when_selected = quit_button_selected_quad
}
music:play()
end
- Draw and update the buttons
function menu.update( dt )
buttons.update_button( start_button, dt )
buttons.update_button( quit_button, dt )
end
function menu.draw()
buttons.draw_button( start_button )
buttons.draw_button( quit_button )
end
- On mousepress quit or activate gamestate
function menu.mousereleased( x, y, button, istouch )
if button == 'l' or button == 1 then
if buttons.mousereleased( start_button, x, y, button ) then
gamestates.set_state( "game", { current_level = 1 } )
elseif buttons.mousereleased( quit_button, x, y, button ) then
love.event.quit()
end
elseif button == 'r' or button == 2 then
love.event.quit()
end
end
function buttons.mousereleased( single_button, x, y, button )
return single_button.selected
end
Feedback is crucial to improve the tutorial!
Let me know if you have any questions, critique, suggestions or just any other ideas.
Chapter 1: Prototype
- The Ball, The Brick, The Platform
- Game Objects as Lua Tables
- Bricks and Walls
- Detecting Collisions
- Resolving Collisions
- Levels
Appendix A: Storing Levels as Strings
Appendix B: Optimized Collision Detection (draft)
Chapter 2: General Code Structure
- Splitting Code into Several Files
- Loading Levels from Files
- Straightforward Gamestates
- Advanced Gamestates
- Basic Tiles
- Different Brick Types
- Basic Sound
- Game Over
Appendix C: Stricter Modules (draft)
Appendix D-1: Intro to Classes (draft)
Appendix D-2: Chapter 2 Using Classes.
Chapter 3 (deprecated): Details
- Improved Ball Rebounds
- Ball Launch From Platform (Two Objects Moving Together)
- Mouse Controls
- Spawning Bonuses
- Bonus Effects
- Glue Bonus
- Add New Ball Bonus
- Life and Next Level Bonuses
- Random Bonuses
- Menu Buttons
- Wall Tiles
- Side Panel
- Score
- Fonts
- More Sounds
- Final Screen
- Packaging
Appendix D: GUI Layouts
Appendix E: Love-release and Love.js
Beyond Programming: