flora-search-aurora/display.lisp
Jaidyn Ann 94335468b3 Begin overworld-rendering loop
It draws to the screen, now! Err, well, it has
been able to do that, since my first day on
this project. But until now, there wasn't a
menu leading you there! c:<
2023-06-09 07:07:28 -05:00

95 lines
3.2 KiB
Common Lisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;;; Copyright © 2023, Jaidyn Ann <jadedctrl@posteo.at>
;;;;
;;;; This program is free software: you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License as
;;;; published by the Free Software Foundation, either version 3 of
;;;; the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;;; FLORA-SEARCH-AURORA.DISPLAY
;;;; All display-related curses go here.
(defpackage :flora-search-aurora.display
(:use :cl)
(:export #:make-screen-matrix #:print-screen-matrix #:matrix-delta
#:clear-screen))
(in-package :flora-search-aurora.display)
(defmacro do-for-cell (matrix &body body)
"Given a 2d-array (matrix), execute the body for every cell.
The body has access to 4 variables:
* i/j — The current row/column.
* dimensions — Dimensions of the given matrix.
* cell — The value of the current cell."
`(let* ((dimensions (array-dimensions ,matrix))
(max-i (car dimensions))
(max-j (cadr dimensions))
(i 0) (j 0))
(loop
(let ((cell (ignore-errors (aref ,matrix i j))))
(cond
((< i max-i)
(cond
((< j max-j)
,@body
(incf j))
((eq j max-j)
(setf j 0)
(incf i))))
((eq i max-i)
(return)))))))
(defun matrix-delta (a b)
"Given two 2D matrices, return a matrix containing only the cells
that change between a→b (favouring those in b) — all others are nil."
(let ((delta (make-array (array-dimensions a))))
(do-for-cell a
(when (not (eq cell
(aref b i j)))
(setf (aref delta i j)
(aref b i j))))
delta))
(defun print-screen-matrix (matrix)
"Given a matrix of characters, print each element to standard output."
(do-for-cell matrix
(when (characterp cell)
(move-cursor (+ i 1) (+ j 1))
(write-char cell)))
(destructuring-bind (i j) (array-dimensions matrix)
(move-cursor i j)))
(defun make-screen-matrix ()
"Create a “screen matrix” — that is, a 2D array representing the
72x20 grid of characters we can print to the terminal."
(make-array '(20 72) :initial-element #\space))
;;; ———————————————————————————————————
;;; Misc. utils
;;; ———————————————————————————————————
(defun move-cursor (row column &key (stream *standard-output*))
"Moves cursor to desired position.
Borrowed from https://github.com/gorozhin/chlorophyll/
Copyright © 2022 Mikhail Gorozhin — MIT license"
(format stream "~C[~A;~AH" #\Esc row column))
(defun clear-screen (&key (stream *standard-output*))
"Completely clear the terminal screen."
(move-cursor 0 0 :stream stream)
(format stream "~C[J" #\Esc))