Implement menu input-loop; changing selection

This commit is contained in:
Jaidyn Ann 2023-06-07 19:02:11 -05:00
parent e59c192888
commit f06849b710
2 changed files with 71 additions and 16 deletions

View File

@ -17,7 +17,8 @@
;; A simple TUI-game made for the text-flavoured LibreJam of 2023-06! ;; A simple TUI-game made for the text-flavoured LibreJam of 2023-06!
;; See: https://jamgaroo.xyz/jams/2 ;; See: https://jamgaroo.xyz/jams/2
(ql:quickload '(alexandria cl-charms cl-tiled str)) (ql:quickload '(alexandria assoc-utils cl-charms cl-tiled str))
(load "input.lisp") (load "input.lisp")
(load "display.lisp") (load "display.lisp")
(load "ui.lisp") (load "ui.lisp")

78
ui.lisp
View File

@ -18,7 +18,7 @@
;;;; Let's get to it, we're on a deadline! ;;;; Let's get to it, we're on a deadline!
(defpackage :flora-search-aurora.ui (defpackage :flora-search-aurora.ui
(:use :cl :flora-search-aurora.display) (:use :cl :flora-search-aurora.display :flora-search-aurora.input :assoc-utils)
(:export #:ui-loop #:render-menu-strip :selection :selected)) (:export #:ui-loop #:render-menu-strip :selection :selected))
(in-package :flora-search-aurora.ui) (in-package :flora-search-aurora.ui)
@ -33,7 +33,7 @@ with menus."
(let* ((matrix (make-screen-matrix)) (let* ((matrix (make-screen-matrix))
(new-menu (ui-update matrix menu-alist))) (new-menu (ui-update matrix menu-alist)))
(ui-draw matrix last-matrix) (ui-draw matrix last-matrix)
(sleep .2) (sleep .02)
(ui-loop matrix new-menu))) (ui-loop matrix new-menu)))
@ -46,9 +46,10 @@ with menus."
(defun ui-update (matrix menu-alist) (defun ui-update (matrix menu-alist)
"The update loop for menus. It processes all input, state, etc, and "The update loop for menus. It processes all input, state, etc, and
returns the new state of the menu." returns the new state of the menu."
(let ((new-menu (progress-menu-items menu-alist))) (progress-menu-items menu-alist)
(render-menu-strip matrix new-menu 0 0) (process-menu-input menu-alist)
new-menu)) (render-menu-strip matrix menu-alist 0 0)
menu-alist)
@ -68,7 +69,7 @@ returns the new state of the menu."
(defun render-menu-item (defun render-menu-item
(matrix text x y &key (width (+ (length text) 2)) (height 3) (selection 100)) (matrix text x y &key (width (+ (length text) 2)) (height 3) (selection 0) (selected nil))
"Render a menu-item that is, text surrounded by a box with an optional "Render a menu-item that is, text surrounded by a box with an optional
'selected' form. If selected is a non-zero number below 100, then that percent 'selected' form. If selected is a non-zero number below 100, then that percent
of the box will be displayed as selected/highlighted. This percent is from of the box will be displayed as selected/highlighted. This percent is from
@ -95,8 +96,7 @@ left-to-right, unless negative — in which case, right-to-left."
(setf (aref matrix (+ y (- height 1)) (+ x bar-start i)) #\=)))) (setf (aref matrix (+ y (- height 1)) (+ x bar-start i)) #\=))))
;; Render the horizontal “earmuffs” for helping the selected item stand out. ;; Render the horizontal “earmuffs” for helping the selected item stand out.
(when (and selection (when selected
(not (eq selection 0)))
(dotimes (i (- height 2)) (dotimes (i (- height 2))
(setf (aref matrix (+ y i 1) x) #\|) (setf (aref matrix (+ y i 1) x) #\|)
(setf (aref matrix (+ y i 1) (+ x width -1)) #\|)) (setf (aref matrix (+ y i 1) (+ x width -1)) #\|))
@ -119,7 +119,8 @@ The item list should be an alist of the following format:
(render-menu-item matrix label x y (render-menu-item matrix label x y
:width width :width width
:height height :height height
:selection selection) :selection selection
:selected (cdr (assoc 'selected (cdr item))))
(setf x (+ x width 1)))) (setf x (+ x width 1))))
items)) items))
matrix) matrix)
@ -153,16 +154,69 @@ item's “selected-percentage”, so that they converge at the right percent.
That is, 0 for non-selected items and 100 for selected items." That is, 0 for non-selected items and 100 for selected items."
(mapcar (mapcar
(lambda (item) (lambda (item)
(let ((selection (assoc 'selection (cdr item))) (let* ((selection (assoc 'selection (cdr item)))
(selectedp (assoc 'selected (cdr item)))) (selection-num (or (cdr selection) 0))
(selectedp (cdr (assoc 'selected (cdr item)))))
(if selection (if selection
(setf (cdr selection) (setf (cdr selection)
(gravitate-toward (if selectedp 100 0) (gravitate-toward
(cond ((and selectedp (< selection-num 0) 0)
-100)
(selectedp 100)
('t 0))
(cdr selection) 10))))) (cdr selection) 10)))))
menu-alist) menu-alist)
menu-alist) menu-alist)
(defun process-menu-input (menu-alist)
"Get and process any keyboard input, modifying the menu alist as necessary."
(when (listen)
(let ((input (normalize-char-plist (read-char-plist)))
(current (selected-menu-item-position menu-alist)))
(case (getf input :char)
(#\→ (select-right-menu-item menu-alist))
(#\← (select-left-menu-item menu-alist))))))
(defun select-menu-item (menu-alist position)
"Given a menu associative list, select the menu-item at the given position."
(let ((old-position (selected-menu-item-position menu-alist)))
;; The “polarity” (direction of selection) depends on the relative
;; direction of the previous selection.
(setf (aget (cdr (nth position menu-alist)) 'selection)
(if (< old-position position) 10 -10))
(setf (aget (cdr (nth position menu-alist)) 'selected) 't)
;; Likewise for the previously-selected item.
(setf (aget (cdr (nth old-position menu-alist)) 'selection)
(if (< old-position position) -90 90))
(setf (aget (cdr (nth old-position menu-alist)) 'selected) nil))
menu-alist)
(defun select-right-menu-item (menu-alist)
"Select the item to the right of the currenty-selected item."
(let ((new-selection (+ (selected-menu-item-position menu-alist) 1)))
(if (< new-selection (length menu-alist))
(select-menu-item menu-alist new-selection))))
(defun select-left-menu-item (menu-alist)
"Select the item to the left of the currenty-selected item."
(let ((new-selection (- (selected-menu-item-position menu-alist) 1)))
(if (>= new-selection 0)
(select-menu-item menu-alist new-selection))))
(defun selected-menu-item-position (menu-alist)
"Returns the index of the menu alist's selected item."
(position
't menu-alist
:test (lambda (ignore list-item)
(cdr (assoc 'selected
(cdr list-item))))))
;;; ——————————————————————————————————— ;;; ———————————————————————————————————
;;; Misc. utils ;;; Misc. utils