
This is the full commented code for the structured main menu:
-- The language still misses very basic functionality like primitive integers
-- and strings. Hence, the code relies on native C symbols, which are
-- prefixed with an underscore (e.g., `_255` and `_("Story")`).
-- `Pico` is a simple graphical library based on SDL.
-- Includes auxiliary files
^"prelude.ceu"
^"int.ceu"
^"float.ceu"
^"pico.ceu"
-- Sets the initial window properties
output Pico.Set.Title _("Pingus")
output Pico.Set.Size [_641,_481]
output Pico.Set.Zoom [_100,_100]
output Pico.Set.Grid _0
output Pico.Set.Color.Clear [_0,_0,_0,_255]
output Pico.Clear
output Pico.Set.Auto _0
-- Menu enumeration
type Menu = <Story=(),Editor=(),Levelsets=(),Options=(),Exit=()>
-- Task to show a single button:
-- - receives point and label to show
-- - terminates on a mouse click
task menu_button: [pos:Point,lbl:_(char*)] -> () -> () {
var size: Size -- get dimensions to detect click
output Pico.Get.Size.Image [/size, _("data/images/menuitem.png")]
-- task to show itself on every Draw event
spawn {
every evt?Draw {
-- draw image with label on top
output Pico.Draw.Image [arg.pos, _("data/images/menuitem.png")]
output Pico.Set.Font [_("data/fonts/film-cryptic/Filmcryptic.ttf"),_45]
output Pico.Draw.Text [arg.pos, arg.lbl]
}
}
-- awaits a mouse click inside its region to terminate
await evt?Mouse?Button?Down until isPointVsRect [pos,[arg.pos,size]]
where {
var pos = evt!Mouse!Button!Down.pos
}
}
-- Task to show the main menu:
-- - spawns a `menu_button` task for each button in the menu
-- - terminates when any button is clicked
-- - returns the `Menu` enumeration associated with the click
task main_menu: () -> () -> Menu {
-- spawns multiple tasks in parallel to wait for the buttons
par {
-- spawns and awaits each button
await spawn menu_button [[_(-125),_( 35)], _("Story")]
-- returns the associated enumeration
return Menu.Story
} with {
await spawn menu_button [[_( 125),_( 35)], _("Editor")]
return Menu.Editor
} with {
await spawn menu_button [[_(-125),_( -35)], _("Levelsets")]
return Menu.Levelsets
} with {
await spawn menu_button [[_( 125),_( -35)], _("Options")]
return Menu.Options
} with {
await spawn menu_button [[_( 0),_(-105)], _("Exit")]
return Menu.Exit
}
}
-- Main application:
-- - a loop that alternates between the menu and the chosen button
spawn {
loop {
-- spawns the main menu and awaits its termination
var opt = await spawn main_menu ()
-- maps the chosen button to a label to show next
var lbl: _(char*) = ifs {
opt ? Story { _("Story") }
opt ? Editor { _("Editor") }
opt ? Levelsets { _("Levelsets") }
opt ? Options { _("Options") }
opt ? Exit { _("Exit") }
}
-- shows and awaits the chosen button in the center of the screen
await spawn menu_button [[_0,_0], lbl]
}
}
-- Enters the engine main loop.
-- Now the application is entirely reactive.
-- In this code, only the individual buttons (`menu_button` task) react to
-- events (evt?Draw and evt?Mouse).
call pico_loop ()
Comment on
@_fsantanna.