OSDN Git Service

correcting input and rulp main loop
authorGiulio De Stasio <giuliodestasio98@gmail.com>
Wed, 31 May 2023 19:37:05 +0000 (21:37 +0200)
committerGiulio De Stasio <giuliodestasio98@gmail.com>
Wed, 31 May 2023 19:37:05 +0000 (21:37 +0200)
18 files changed:
core.lisp
data.lisp
graphics/grid.lisp
graphics/inputs.lisp
graphics/menu.lisp
graphics/package.lisp
graphics/render.lisp
graphics/text-rendering.lisp
graphics/view.lisp
layers/entities.lisp
layers/interactions.lisp
layers/models.lisp
layers/package.lisp
layers/planes.lisp
layers/screens.lisp
package.lisp
parameters.lisp
script.lisp

index f8ef07e..8764771 100644 (file)
--- a/core.lisp
+++ b/core.lisp
@@ -14,7 +14,7 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :core)
+(in-package :rulp.core)
 
 (defparameter *screen-width* 1000)
 (defparameter *screen-height* 750)
   (let ((mapfile (clingon:getopt cmd :rulp/map))
         (initfile (clingon:getopt cmd :rulp/initfile))
         (softwarep (clingon:getopt cmd :rulp/softwarep))
-        (name (format nil "Ru*** roLeplay Playground v~A" parameters:+rulp-version+)))
+        (name (format nil "Ru*** roLeplay Playground v~A" rulp.parameters:+rulp-version+)))
     (test-correctness-required mapfile "json")
     (test-correctness-optional initfile "lisp")
     (format t "rulp-~A on ~A-~A~%"
-            parameters:+rulp-version+
-            parameters:+rulp-system+
-            parameters:+rulp-type+)
+            rulp.parameters:+rulp-version+
+            rulp.parameters:+rulp-system+
+            rulp.parameters:+rulp-type+)
     (if initfile (load initfile) (load "init.lisp" :if-does-not-exist nil))
-    (setf graphics:+plane+ (create-plane-from-json mapfile))
-    (graphics:playground name)))
+    (multiple-value-bind (json path) (decode-from-json mapfile)
+      (setf rulp.graphics:*map-info* json)
+      (setf rulp.graphics:*map-path* path))
+    (rulp.graphics:playground name)))
 
 (defun rulp/command ()
   (clingon:make-command
    :version "0.0.1"
    :description "Roleplay playground"
    :authors '("Giulio 'Zull' De Stasio <giuliodestasio98@gmail.com>")
-   :usage "[-i INITFILE] -m MAP | COMMAND"
+   :usage "[-i INITFILE] -m map [COMMAND]"
    :license "GPLv3"
    :handler #'rulp/handler
    :options (rulp/options)
-   :examples '(("rulp -m map.json") ("rulp editor -m map.json"))
+   :examples '(("rulp -m map.json") ("rulp -m map.json editor"))
    :sub-commands (rulp/sub-commands)))
 
 (defun rulp/options ()
   (test-correctness-required mapfile "json")
   (test-correctness-optional initfile "lisp")
   (format t "rulp-~A on ~A-~A~%"
-          parameters:+rulp-version+
-          parameters:+rulp-system+
-          parameters:+rulp-type+)
+          rulp.parameters:+rulp-version+
+          rulp.parameters:+rulp-system+
+          rulp.parameters:+rulp-type+)
   (if initfile (load initfile) (load "init.lisp" :if-does-not-exist nil))
-  (setf graphics:+plane+ (create-plane-from-json mapfile))
-  (graphics:playground (format nil "RULP over repl"))
+  (multiple-value-bind (json path) (decode-from-json mapfile)
+    (setf rulp.graphics:*map-info* json)
+    (setf rulp.graphics:*map-path* path))
+  ;; (setf graphics:*plane* (create-plane-from-json mapfile))
+  (sb-thread:make-thread (lambda () (rulp.graphics:playground (format nil "RULP over repl"))))
   )
 
-(defun start () (repl-pipe "lab/test.json"))
+(defun start () (repl-pipe "lab/test2.json"))
index 2c3dd0a..c625c46 100644 (file)
--- a/data.lisp
+++ b/data.lisp
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :core)
+(in-package :rulp.core)
 
 (defun decode-from-json (json-file)
   "take a json file path and decode it"
   (with-open-file (json-stream json-file)
-    (json:decode-json json-stream)))
+    (values (json:decode-json json-stream)
+            (make-pathname :directory (pathname-directory json-file)))))
 
 ;; this definition is hard coded, when planes will change this
 ;; function needs to be edited alike. Look for a better and
   "take a parsed alist and create a plane on those specs"
   (let* ((json-position (make-pathname :directory (pathname-directory json-file)))
          (alist (decode-from-json json-file))
-         (img-path (if (assoc ':image-path alist)
-                       (merge-pathnames json-position (cdr (assoc ':image-path alist)))
-                       (error "Image-path missing from \"~A\", exits~%" json-file)))
          (img-path (merge-pathnames json-position (cdr (assoc ':image-path alist))))
-         (ret (make-instance 'layers:plane :image img-path)))
-    (when (assoc ':size alist) (setf (layers:size ret) (cdr (assoc ':size alist))))
-    (when (assoc ':grid-dimension alist) (setf (layers:grid-dimension ret) (cdr (assoc ':grid-dimension alist))))
+         (ret (make-instance 'rulp.layers:screen :image img-path)))
+    ;; (when (assoc ':size alist) (setf (layers:size ret) (cdr (assoc ':size alist))))
+    ;; (when (assoc ':grid-dimension alist) (setf (graphics:-dimension ret) (cdr (assoc ':grid-dimension alist))))
     ret))
 
+
 ;; posso usare le hash piuttosto che interpretarlo sul momento. Infatti creerò un metodo che
 ;; analizza json e lo traduce in una tabella hash e una funzione che prende la hash e crea
 ;; l'oggetto tramite i metodi standard.
index 986acef..f92b278 100644 (file)
@@ -14,7 +14,7 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :graphics)
+(in-package :rulp.graphics)
 
 (defparameter +grid-span+ 50)
 (defparameter +is-grid-letters+ t)
       (setf +is-grid-letters+ nil)
       (setf +is-grid-letters+ t)))
 
-(defmacro grid-render (renderer plane &optional (x 0) (y 0) (w 100) (h 100))
+;; FIXME: the function doesn't consider *viewpoint-zoom*
+(defmacro grid-render (renderer &optional (x 0) (y 0) (w 100) (h 100))
   "renderize a grid in where required"
   `(let ((neg-x (* ,x -1))
          (neg-y (* ,y -1))
-         (plane-x (x ,plane))
-         (plane-y (y ,plane))
-         (x-iterations (/ (- ,w ,x) (grid-dimension ,plane)))
-         (y-iterations (/ (- ,h ,y) (grid-dimension ,plane)))
-         (grid-spacing (grid-dimension ,plane)))
+         (plane-x (x *plane*))
+         (plane-y (y *plane*))
+         (x-iterations (/ (- ,w ,x) *plane-grid*))
+         (y-iterations (/ (- ,h ,y) *plane-grid*)))
     (progn
       ;; (sdl2:set-render-draw-color ,renderer ,red ,green ,blue 255)
-      (loop :for i :from (ceiling (/ neg-x grid-spacing)) :to x-iterations
+      (loop :for i :from (ceiling (/ neg-x *plane-grid*)) :to x-iterations
             :do
                (sdl2:render-draw-line ,renderer
-                                      (+ (* i grid-spacing) plane-x)
+                                      (+ (* i *plane-grid*) plane-x)
                                       (+ plane-y neg-y)
-                                      (+ (* i grid-spacing) plane-x)
+                                      (+ (* i *plane-grid*) plane-x)
                                       (+ ,h plane-y neg-y))
             )
-      (loop :for j :from (ceiling (/ neg-y grid-spacing)) :to y-iterations
+      (loop :for j :from (ceiling (/ neg-y *plane-grid*)) :to y-iterations
             :do
                (sdl2:render-draw-line ,renderer
                                       (+ plane-x neg-x)
-                                      (+ (* j grid-spacing) plane-y)
+                                      (+ (* j *plane-grid*) plane-y)
                                       (+ plane-x ,w neg-x)
-                                      (+ (* j grid-spacing) plane-y))
+                                      (+ (* j *plane-grid*) plane-y))
             ))
     (sdl2:set-render-draw-color ,renderer 0 0 0 255)
      ))
 
-(defmacro indexes-render (renderer plane &optional (x 0) (y 0) (w 0) (h 0))
+(defmacro indexes-render (renderer &optional (x 0) (y 0) (w 0) (h 0))
   `(let ((neg-x (* ,x -1))
          (neg-y (* ,y -1))
-         (x-offset (x ,plane))
-         (y-offset (y ,plane))
-         (x-iterations (/ (- ,w ,x) (grid-dimension ,plane)))
-         (y-iterations (/ (- ,h ,y) (grid-dimension ,plane)))
-         (grid-spacing (grid-dimension ,plane)))
-     (loop :for k :from (floor (/ neg-x grid-spacing)) :to x-iterations
-           :do (loop :for l :from (floor (/ neg-y grid-spacing)) :to y-iterations
+         (x-offset (x *plane*))
+         (y-offset (y *plane*))
+         (x-iterations (/ (- ,w ,x) *plane-grid*))
+         (y-iterations (/ (- ,h ,y) *plane-grid*)))
+     (loop :for k :from (floor (/ neg-x *plane-grid*)) :to x-iterations
+           :do (loop :for l :from (floor (/ neg-y *plane-grid*)) :to y-iterations
                      :do (tr-write (coordinate-to-grid-index (cons l (+ k 1)))
-                                   (+ x-offset (* k grid-spacing))
-                                   (+ y-offset (* l grid-spacing))
-                                   (floor (/ grid-spacing 3))
-                                   (floor (/ grid-spacing 3))
+                                   (+ x-offset (* k *plane-grid*))
+                                   (+ y-offset (* l *plane-grid*))
+                                   (floor (/ *plane-grid* 3))
+                                   (floor (/ *plane-grid* 3))
                                    ,renderer)))
      ;; (sdl2:set-render-draw-color ,renderer 0 255 0 100) ; remember to uncomment both
      ;; (sdl2:render-fill-rect ,renderer (sdl2:make-rect ,x ,y ,w ,h)) ; test for x y w and h
index 7946fd5..7fcbead 100644 (file)
@@ -14,7 +14,7 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :graphics)
+(in-package :rulp.graphics)
 
 ;; this functions are changed every frame with the mouse position. This
 ;; is then used everywhere. This assure syncronization between two functions.
@@ -29,14 +29,8 @@ using *mouse-position*. The usefullness of this value is to create velocity")
 (defparameter *is-mouse-hold* nil
   "this variable is modified when a button is hold down. This doesn't specifies
 which button is being hold.")
-(defparameter +mode+ '+normal-mode+)
+;; (defparameter +mode+ '+normal-mode+)
 
-(defun mouse-actions (keybinds)
-  "given an association list of keybinds it returns the associated element
-when the button is pressed"
-  (loop :for button :in keybinds
-        :collect (when (sdl2:mouse-state-p (eval (car button))) ; BUG: watch out for this eval
-                   (cdr button))))
 
 ;; NOTE: this is a frame dependent version, correction is easy when i'll have
 ;; time deltas.
@@ -45,11 +39,13 @@ when the button is pressed"
   (cons (- (car actual-point) (car previous-point))
         (- (cdr actual-point) (cdr previous-point))))
 
-(defun panning (value delta)
+(defun panning (position previous-position viewpoint)
   "destructive function. It update the value with the given delta. Both value
-and delta are coordinate cons (like '(x . y))"
-  (setf (car value) (+ (car value) (car delta))
-        (cdr value) (+ (cdr value) (cdr delta))))
+and delta are coordinate cons (like '(x . y)), output is garbage"
+  (let ((delta (cons (- (car position) (car previous-position))
+                     (- (cdr position) (cdr previous-position)))))
+    (setf (car viewpoint) (+ (car viewpoint) (car delta))
+          (cdr viewpoint) (+ (cdr viewpoint) (cdr delta)))))
 
 ;; (defgeneric select-entry (x y p)
 ;;   (:documentation "operate with menues, create them, destroy them and apply them"))
@@ -72,32 +68,91 @@ and delta are coordinate cons (like '(x . y))"
 
 ;; FIXME: this method can be designed non destructively. by just returning the position
 ;; in the list of the selected entity
-(defgeneric select-pointer (coordinate p))
-
-(defmethod select-pointer (coordinate (p plane))
-  "with left button it select and deselect entities the map-gplane contain"
-  (let ((mouse-point (sdl2:make-rect (car coordinate) (cdr coordinate) 10 10))
-        (entities (entities-list p)))
+(defun select-pointer (coordinates previous viewpoint)
+  "given coordinates and a list of entities return the position in the list of the selected
+entity or nil if noone is selected"
+  (declare (ignore previous viewpoint))           ; mouse-previous is not used in this function
+  (let ((mouse-point (sdl2:make-rect (floor (/  (- (car coordinates) (car *viewpoint-offset*)) *viewpoint-zoom*))
+                                     (floor (/  (- (cdr coordinates) (cdr *viewpoint-offset*)) *viewpoint-zoom*)) 10 10)))
     (setf *pointer* nil)
-    (loop :for obj :in entities
-          :for obj-nth :from 0 :to (length entities)
+    (loop :for obj :in *entities-list*
+          :for obj-nth :from 0 :to (length *entities-list*)
           :do
-             (when (sdl2:has-intersect mouse-point
-                                       (screen-destination obj p))
-               (setf *pointer* obj-nth)))
+             (multiple-value-bind (c s) (grid-layout (x obj) (y obj) :size (size obj))
+               (when (sdl2:has-intersect mouse-point
+                                         (arrange-rect (car c) (cdr c) s s))
+                 (setf *pointer* obj-nth))))
     ))
 
-(defgeneric move-entity (coordinate p))
-
-(defmethod move-entity (coordinate (p plane))
+(defun move-entity (coordinates previous viewpoint)
   "with right button it move the entity around the plane"
+  (declare (ignore previous viewpoint))
   (when (numberp *pointer*)
-    (let* ((x-offset (x p))
-           (y-offset (y p))
-           (i-x (floor (/ (- (car coordinate) x-offset) (grid-dimension p))))
-           (i-y (floor (/ (- (cdr coordinate) y-offset) (grid-dimension p))))
-           (object (nth *pointer* (entities-list p))))
-      (setf (coordinate object) (cons i-x i-y))
+    (let* ((x-offset (floor (/  (+ (x *plane*) (car *viewpoint-offset*)) *viewpoint-zoom*)))
+           (y-offset (floor (/  (+ (y *plane*) (cdr *viewpoint-offset*)) *viewpoint-zoom*)))
+           (i-x (floor (/ (- (car coordinates) x-offset) *plane-grid*)))
+           (i-y (floor (/ (- (cdr coordinates) y-offset) *plane-grid*)))
+           (object (nth *pointer* *entities-list*)))
+      ;; (setf (coordinate object) (cons i-x i-y))
+      (setf (coordinate (nth *pointer* *entities-list*)) (cons i-x i-y))
       ;; (setf (x object) i-x)
       ;; (setf (y object) i-y)
       )))
+
+(defun summon-entry (coordinates contents &key (title ""))
+  (make-instance 'entry :title title
+                        :coordinate coordinates
+                        :contents contents
+                        ))
+
+
+(defun mouse-actions (keybinds)
+  "given an association list of keybinds it returns the associated element
+when the button is pressed"
+  (loop :for button :in keybinds
+        :collect (when (sdl2:mouse-state-p (eval (car button))) ; NOTE: watch out for this eval
+                   (cdr button))))
+
+
+(defconstant +mouse-button-left+ 1 "this binds the left button")
+(defconstant +mouse-button-right+ 3 "this binds the right button")
+(defconstant +mouse-button-middle+ 2 "this binds the scroll button")
+
+;; FIXME: replace with apply system and fixed arguments *mouse-position*, *mouse-previous-position* *viewpoint-offset*
+;; (defparameter *mouse-keybinds* (list
+;;                                 '(+mouse-button-left+ nil (select-pointer *mouse-position* *entities-list*))
+;;                                 '(+mouse-button-middle+ (panning *viewpoint-offset* (velocity *mouse-position* *mouse-previous-position*)) nil)
+;;                                 '(+mouse-button-right+ nil (move-entity *mouse-position*))
+;;                                 ;; '(+mouse-button-right+ nil (push (summon-entry *mouse-position* '(1)) *active-entries*))
+;;                                 )
+;;   "This is the mouse-keybinds association list. The first value is the button, the second
+;; is the action executed on hold and the third is the action executed on release (if any)")
+
+;;             mouse-keybinds    (+button pressed+       drag-event click-event     )
+(defparameter *mouse-keybinds* (list
+                                '(+mouse-button-left+    nil       select-pointer   )
+                                '(+mouse-button-middle+  panning   nil              )
+                                '(+mouse-button-right+   nil       move-entity      )
+                                ;; '(+mouse-button-right+ nil (push (summon-entry *mouse-position* '(1)) *active-entries*))
+                                )
+  "This is the mouse-keybinds association list. The first value is the button, the second
+is the action executed on hold and the third is the action executed on release (if any)")
+
+(defun mouse-event (coordinates &key (dragp nil))
+  "this function is called when the mouse is pressed, it takes the mouse
+coordinates and execute the necessary actions. This function depends on
+rulp.entries:*entries-list*"
+  (flet ((action (x) (if dragp
+                         (cadr x)
+                         (caddr x))))
+    (if rulp.entries:*entries-list*
+        (unless (rulp.entries:click-event
+                 (first rulp.entries:*entries-list*)
+                 *mouse-position*)
+          (pop rulp.entries:*entries-list*))
+        (loop :for button :in *mouse-keybinds*
+              :do (when (and (action button) (sdl2:mouse-state-p (eval (car button))))
+                    (apply (action button) (list coordinates
+                                                 *mouse-previous-position*
+                                                 *viewpoint-offset*)))
+              ))))
index efe4fdf..3519ae8 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :graphics)
+(defpackage :rulp.entries
+  (:use :cl)
+  (:export *entries-list* push pop entry x y width height rectangle click-event
+           render-entry make-plist))
 
-(defgeneric entry-width (y))
-(defgeneric entry-height (y))
-(defgeneric entry-rectangle (y))
+(in-package :rulp.entries)
+
+(defparameter *entries-list* nil
+  "List of entries, menues who are generated into the window with options")
+
+(defgeneric x (entry))
+(defgeneric y (entry))
+(defgeneric width (entry))
+(defgeneric height (entry))
+(defgeneric rectangle (entry))
 
 (defclass entry ()
-    ((coordinate :accessor coordinate
-                 :initarg :coordinate
-                 :initform '(0 . 0)
-                 :documentation "the starting position of the entry generation"
-                 :type list)
+    ((coordinates :accessor coordinates
+                  :initarg :coordinates
+                  :initform '(0 . 0)
+                  :documentation "the starting position of the entry generation"
+                  :type list)
      (title :accessor title
             :initarg :title
-            :initform ""
+            :initform "custom"
             :documentation "title for the entry")
-     (text-size :accessor text-size
-                :initarg :text-size
-                :initform 30
-                :type number
-                :documentation "the font size in the entry")
+     (margin :accessor margin
+             :initarg :margin
+             :initform 5
+             :type number
+             :documentation "the margin between the content and the borders of the rectangle")
+     (padding :accessor padding
+              :initarg :padding
+              :initform 0
+              :type number
+              :documentation "the padding between the coordinates and the borders")
+     (action :accessor action
+             :initarg :action
+             :initform nil
+             :documentation "action when pressed")
      (contents :accessor contents
-               :initarg :contents
-               :initform nil
-               :type list
-               :documentation "alist containing entry name and related action")))
+                :initarg :contents
+                :initform nil
+                :type list
+                :documentation "a list of other entries")
+     (text-size :accessor size
+                :initarg :size
+                :initform 20
+                :type number)
+     (content-orientation :accessor orientation
+                          :initarg :orientation
+                          :initform :v
+                          :documentation "when :v the contents and title
+are displaced vertically, when :h the contents are horizontally displayed")))
+
+(defmethod x ((entry entry))
+  (car (coordinates entry)))
+
+(defmethod y ((entry entry))
+  (cdr (coordinates entry)))
+
+;; (defmethod width ((entry entry))
+;;   200)
+
+;; (defmethod height ((entry entry))
+;;   200)
+
+(defun width-vertical (plist)
+  (let* ((i 0))
+    (labels ((operation (element)
+               (setf i (max i (length (getf element :title)))) ; FIXME: add padding
+               (loop :for x :in (getf element :contents)
+                     :do (operation x))
+               ))
+      (operation plist))
+    i
+    ))
+
+(defun width-horizontal (plist)
+  (let* ((i 0))
+    (labels ((operation (element)
+               (incf i (length (getf element :title)))
+               (loop :for x :in (getf element :contents)
+                     :do (operation x))
+               ))
+      (operation plist))
+    i
+    ))
+
+(defun height-vertical (plist)
+  (let* ((i 0))
+    (labels ((operation (element)
+               (1+ i)
+               (loop :for x :in (getf element :contents)
+                     :do (operation x))
+               ))
+      (operation plist))
+    i
+    ))
 
-(defmethod entry-width ((y entry))
-  "give the length of the longest menu entry, useful for creating a box containing them all"
-  (reduce #'max (loop :for content :in (contents y)
-                      :collect (length (car content)))))
+(defun height-horizontal (plist) 1)
 
-(defmethod entry-height ((y entry))
-  "give the number of entries, useful for creating a box containing them all"
-  (length (contents y)))
+;; (defmethod width ((entry entry))
+;;   "give the length of the longest menu entry, useful for creating a box containing them all"
+;;   (reduce #'max (loop :for content :in (contents entry))))
 
-(defmethod entry-rectangle ((y entry))
+;; (defmethod height ((entry entry))
+;;   "give the number of entries, useful for creating a box containing them all"
+;;   (length (contents entry)))
+
+(defmethod rectangle ((entry entry))
   (flet ((on-size (a) (* a (text-size y))))
-    (sdl2:make-rect (car (coordinate y))
-                    (cdr (coordinate y))
+    (sdl2:make-rect (x entry)
+                    (y entry)
                     (on-size (entry-width y))
-                    (on-size (entry-height y)))))
+                    )))
+
+;; NOTE: this method makes the entry class totally useless. It is possible
+;; to replace entries with these plists and use them directly with the macro
+(defmethod make-plist ((entry entry))
+  (list ':entry 'entry
+        ':title (title entry)
+        ':coordinates (coordinates entry)
+        ':padding (padding entry)
+        ':margin (margin entry)
+        ':text-size (size entry)
+        ':action (action entry)
+        ':contents (contents entry)
+        ':orientation (orientation entry))
+  )
+;; NOTE: The idea of replacing the whole class idea with the plist system makes
+;; room for special functions that can create rectangles out of the correct size,
+;; can adjust the text and aid the macro in the rendering process.
+
+(defun n-letter-content (pair)
+  "given a list of two elements, one a string and the other a generic symbol, it returns the
+length of the string. This is used in display-entry, where it is used to find
+the maximum size of a list of options to make the correct dimension for the entry"
+  (length (car pair)))
+
+(defun keep-inside (position size limit)
+  (if (> position (- limit size))
+      (- position size)
+      position
+    ))
+
+(defmacro render-entry (renderer plist)
+  `(let* ((entry-margin (if (numberp (getf ,plist :margin)) (getf ,plist :margin) 0))
+          (entry-padding (if (numberp (getf ,plist :padding)) (getf ,plist :padding) 0))
+          (entry-size (getf ,plist :text-size)) ; NOTE: make error checking instead of redefinition
+          (entry-x (+ entry-margin (car (getf ,plist :coordinates))))
+          (entry-y (+ entry-margin (cdr (getf ,plist :coordinates))))
+          (entry-w (if (eq (getf ,plist :orientation) 'v)
+                       (width-vertical ,plist)
+                       (width-horizontal ,plist)))
+          (entry-h (if (eq (getf ,plist :orientation) 'v)
+                       (height-vertical ,plist)
+                       (height-horizontal ,plist))))
+     (setf entry-x (keep-inside entry-x entry-w rulp.graphics:*window-width*))
+     (setf entry-y (keep-inside entry-y entry-h rulp.graphics:*window-height*)) ; BUG: doesn't seems to work
+     ;; (when (> entry-x (- rulp.graphics:*window-width* entry-w))
+     ;;   (setf entry-x (- entry-x entry-w)))
+     ;; (when (> entry-y (- rulp.graphics:*window-height* entry-h))
+     ;;   (setf entry-y (- entry-y entry-h)))
+     (sdl2:set-render-draw-color ,renderer 255 255 255 255)
+     (sdl2:render-fill-rect ,renderer (rulp.graphics:arrange-rect
+                                       entry-x
+                                       entry-y
+                                       (+ (* 2 entry-padding) (* entry-w entry-size))
+                                       (+ (* 2 entry-padding) (* entry-h entry-size)))) ; FIXME: fixed size font
+     ;; NOTE: temporary solution, to be extended with the content-rendering
+     ;; function into a rendering engine for nested schemas
+     (sdl2:set-render-draw-color ,renderer 0 0 0 255)
+     (rulp.graphics:tr-write (getf ,plist :title)
+                             (+ entry-x entry-padding)
+                             (+ entry-y entry-padding)
+                             entry-size
+                             entry-size
+                             ,renderer)
+     ;; FIXME: continue with contents
+     ))
+
+(defmacro display-entry (renderer entry)
+  "macro for creating the actual menu given the renderer and the entry"
+  `(let* ((entry-x (+ (car (coordinate ,entry)) (padding ,entry)))
+          (entry-y (+ (cdr (coordinate ,entry)) (padding ,entry)))
+          (maximum-letters (apply #'max (cons (length (title ,entry)) (mapcar #'n-letter-content (contents ,entry)))))
+          (number-of-elements (1+ (length (contents ,entry))))
+          (entry-h (+ (* number-of-elements (text-size ,entry)) (* 2 (margin ,entry))))
+          (entry-w (+ (* maximum-letters (text-size ,entry)) (* (margin ,entry))))
+          )
+     (when (> entry-x (- *window-width* entry-w))
+       (setf entry-x (- entry-x entry-w)))
+     (when (> entry-y (- *window-height* entry-h))
+       (setf entry-y (- entry-y entry-h)))
+     (sdl2:set-render-draw-color ,renderer 255 255 255 255)
+     (sdl2:render-fill-rect ,renderer (arrange-rect entry-x entry-y entry-w entry-h))
+     (tr-write (title ,entry)
+               (+ entry-x (margin ,entry))
+               (+ entry-y (margin ,entry))
+               (text-size ,entry)
+               (text-size ,entry)
+               ,renderer
+               )
+     ;; FIXME: to complete with the actual menu
+     )
+  )
+
+(defun select-entry (renderer entry)
+  "given the renderer and an entry, returns the option pressed or return nil if
+nothing was pressed"
+  nil)
+
+(defgeneric click-event (entry coordinates)
+  (:documentation "this function is activated when the
+mouse/cursor is pressed with a entry active. From here the method can execute
+command and destroy itself by returning nil. The destruction has to be handled
+by whatever call the entry event"))
+
+;; NOTE: test if the mouse-state-p is enought, to get to this method is a long
+;; run and it could be that mouse-state-p has changed from when was triggered
+(defmethod click-event ((entry entry) coordinates)
+  "event for mouse/cursor action. This function applies events on an element of a
+list"
+  'destroy
+  )
index 7be7b95..61ee8e7 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(defpackage :graphics
-  (:use :cl :layers)
+(defpackage :rulp.graphics
+  (:use :cl :rulp.layers)
   (:export
-   playground +plane+
+   playground +plane+ *plane* *plane-grid* *map-info* *map-path* *entities-list*
+   arrange-rect *window-width* *window-height* tr-write
            ))
+;; NOTE: remove +plane+, there is no other occurrence of the parameter on the code
 
-(in-package :graphics)
+(in-package :rulp.graphics)
 
-(defparameter +plane+ nil
-  "the rendered plane, this variable contain the plane which is gonna be presented
-into the main window")
+;; these variables contain information for the plane and grid systems. The default
+;; grid is a square grid but by changing the grid-layout function it is possible
+;; to modify it
+(defparameter *plane* nil
+  "the plane containing the graphics to be desplayed on the background. This is a
+basic layout:screen")
+
+(defparameter *plane-grid* 10
+  "the grid for the plane. By default the grid is square and this value contain the
+pixels between lines")
+
+(defparameter *entities-list* nil
+  "the list of the entities to be displayed on the plane. these entities are global and
+by default not connected to the *plane* choice. To change planes and entities use the proper
+functions")
 
 (defparameter *renderer* nil
   "a variable containing the tool to render textures to screen, this is associated
@@ -34,20 +48,17 @@ side variable and cannot be moved in a sdl enviroinment.")
 (defparameter *pointer* nil
   "this is a numeric value whose refer to the selected entity in the plane, it is
 used combined with input to apply the actions and with view to display a 1x1 over
-grid square of the entity"
-  )
+grid square of the entity")
 
 ;; tr stands for text-rendering
 (defparameter *tr-string* "abcdefghijklmnopqrstuvwxyz 0123456789-"
   "This string is used to generate a texture with the alphabet, the software
 in the text.lisp file will 'write' on the screen selecting squares and using
-this string again to parse a string variable into coordinate in the texture"
-  )
+this string again to parse a string variable into coordinate in the texture")
 
 (defparameter *alphabet* "abcdefghijklmnopqrstuvwxyz-"
   "this is used to generate the grid, when the coordinates run out of letters
-they restart from the beginning"
-  )
+they restart from the beginning")
 
 (defparameter *tr-texture* nil
   "this contains the texture of the characters from *tr-string*. This
@@ -58,25 +69,31 @@ with render-copy")
 (defconstant +mouse-button-right+ 3 "this binds the right button")
 (defconstant +mouse-button-middle+ 2 "this binds the scroll button")
 
+;; FIXME: replace with apply system and fixed arguments *mouse-position*, *mouse-previous-position* *viewpoint-offset*
 (defparameter *mouse-keybinds* (list
-                                '(+mouse-button-left+ nil (select-pointer *mouse-position* +plane+))
-                                '(+mouse-button-middle+ (panning (coordinate +plane+) (velocity *mouse-position* *mouse-previous-position*)))
-                                '(+mouse-button-right+ nil (move-entity *mouse-position* +plane+))
+                                '(+mouse-button-left+ nil (select-pointer *mouse-position* *entities-list*))
+                                '(+mouse-button-middle+ (panning *viewpoint-offset* (velocity *mouse-position* *mouse-previous-position*)) nil)
+                                '(+mouse-button-right+ nil (move-entity *mouse-position*))
+                                ;; '(+mouse-button-right+ nil (push (summon-entry *mouse-position* '(1)) *active-entries*))
                                 )
   "This is the mouse-keybinds association list. The first value is the button, the second
-is the action executed on hold and the third is the action executed on release (if any)"
-  )
+is the action executed on hold and the third is the action executed on release (if any)")
 
 
 (defparameter *is-grid* t
   "Parameter for displaying the grid, when nil it does not display a grid, when t
-it display a grid as defined by the +plane+")
+it display a grid as defined by the *plane-grid*")
 (defparameter *is-indexes* t
   "Parameter for displaying the indexes, when nil it does not display them, when t
 it uses the grid to create a chessboard like indexes")
 
-(defparameter *entries-list* nil
-  "List of entries, menues who are generated into the window with options")
-
 (defparameter *window-width* 1001)
 (defparameter *window-height* 750)
+
+;; NOTE: probably they need to be moved below in layers, for now they can stay here
+(defparameter *map-info* nil
+  "when the json informations are read, the content is dumped into this parameter and then
+used on uninitialized data to bootstrap the data")
+
+(defparameter *map-path* nil
+  "this is the path where the json file lived")
index 503a99b..ffea82f 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :graphics)
+(in-package :rulp.graphics)
 
 (defgeneric texture (s))
 (defgeneric surface (s))
 
+(defparameter courtesy-rectangle (sdl2:make-rect 0 0 10 10)
+  "creating and destroying rectangles waste resources and leaving them in ram is even worse. Do not use this
+rectangle directly, but use the arrange-rect")
+
+(defun arrange-rect (x y w h)
+  (progn
+    (setf (sdl2:rect-x courtesy-rectangle) x)
+    (setf (sdl2:rect-y courtesy-rectangle) y)
+    (setf (sdl2:rect-width courtesy-rectangle) w)
+    (setf (sdl2:rect-height courtesy-rectangle) h)
+    courtesy-rectangle)
+  )
+
 (defmethod texture ((s screen))
   "returns the screen texture, useful for accelerated enviroinments"
   (unless (slot-value s 'texture)
-    (setf (slot-value s 'texture) (sdl2:create-texture-from-surface *renderer* (surface s))))
+    (setf (slot-value s 'texture) (sdl2:create-texture-from-surface *renderer* (surface s)))
+    (sdl2:free-surface (slot-value s 'surface))
+    (setf (slot-value s 'surface) nil))
   (slot-value s 'texture))
 
 (defmethod surface ((s screen))
                                         (screen-destination entity plane))
                 entity))))
 
-;; NOTE: this doesn't directly uses +plane+ so it can be easily generalized
-(defmacro render-plane-and-contents (renderer plane)
-  "given a PLANE it renders globally the plane images and entities. With
-globally it means that this plane is rendered full on whatever texture is used.
-to render locally use sdl2:set-render-target before calling this macro."
-  `(when ,plane
-     (sdl2:render-copy ,renderer (texture ,plane)
-                       :source-rect (screen-source ,plane)
-                       :dest-rect (screen-destination ,plane t))
-     (loop :for entity :in (entities-list ,plane)
-           :do (when (displayp entity)
-                 (sdl2:render-copy ,renderer (texture entity)
-                                   :source-rect (screen-source entity)
-                                   :dest-rect (screen-destination entity ,plane))
-                 ))))
-
-;; NOTE: test if it is necessary to create render-plane-without-contents
+(defmacro render-plane-and-entities (renderer)
+  "using *plane* and *entities-list* the macro display on the current rendering texture
+the plane 'as is' and the entities with the grid-layout function"
+  `(when *plane*
+     ;; NOTE: add error for non-screen planes
+     (sdl2:render-copy ,renderer (texture *plane*)
+                       :source-rect nil
+                       :dest-rect (screen-destination *plane* t))
+     (loop :for entity :in *entities-list*
+           :do
+              (when (displayp entity)
+                (multiple-value-bind (coordinates size) (grid-layout (car (coordinate entity))
+                                                                     (cdr (coordinate entity))
+                                                                     :size (size entity))
+                  (sdl2:render-copy ,renderer (texture entity)
+                                    :source-rect nil ; NOTE: not general
+                                    :dest-rect (arrange-rect (car coordinates) (cdr coordinates) size size)))) ; FIXME: create a grid-layout function
+           )
+     )
+  )
index 6d03125..146dfa2 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :graphics)
+(in-package :rulp.graphics)
+
+(defparameter *tr-s-rectangle* (sdl2:make-rect 0 0 60 130)) ; FIXME: hardcoded,
+                                                            ; defparameter over
+                                                            ; font for
+                                                            ; generalization
+(defparameter *tr-d-rectangle* (sdl2:make-rect 0 0 10 10))
 
 (defun coordinate-to-grid-index (value)
   "translate a coordinate into the chess coordinate as a string"
   `(let ((value-indexes (tr-parse-string ,value)))
      (loop :for character :in value-indexes
            :for character-position :from 0 :to (length value-indexes)
-           :do (let ((source-rectangle (sdl2:make-rect (* character 60) 0 60 130))
-                     (destination-rectangle (sdl2:make-rect (+ ,x (* character-position ,width)) ,y ,width ,height)))
-                 (sdl2:render-copy ,renderer *tr-texture*
-                                   :source-rect source-rectangle
-                                   :dest-rect destination-rectangle)
-                 (sdl2:free-rect source-rectangle)
-                 (sdl2:free-rect destination-rectangle)))))
+           :do (setf (sdl2:rect-x *tr-s-rectangle*) (* character 60)
+                     (sdl2:rect-x *tr-d-rectangle*) (+ ,x (* character-position ,width))
+                     (sdl2:rect-y *tr-d-rectangle*) ,y
+                     (sdl2:rect-width *tr-d-rectangle*) ,width
+                     (sdl2:rect-height *tr-d-rectangle*) ,height)
+               (sdl2:render-copy ,renderer *tr-texture*
+                                 :source-rect *tr-s-rectangle*
+                                 :dest-rect *tr-d-rectangle*))))
index 49650be..e5d4b2e 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :graphics)
+(in-package :rulp.graphics)
 #| -------------------------------------------
  | This file manipulate the window and the
  | sdl initialization.
  | -------------------------------------------
  |#
 
+(defun create-plane (map-info map-path &key (number 0))
+  "convert the map informations into a functioning plane, without number it convert the
+first element"
+  (let ((plane-info (nth number (cdr (assoc :planes map-info)))))
+    (values
+     (make-instance 'rulp.layers:screen
+                    :image (merge-pathnames map-path (cdr (assoc :image-path plane-info))))
+     (cdr (assoc :grid-dimension plane-info))
+     )
+    ;; FIXME: generalize... somehow
+    )
+  )
+
+;; FIXME: search alternative
+(defun create-entities (map-info map-path)
+  (let ((entities-info (cdr (assoc :entities map-info))))
+    (loop :for entity-info :in entities-info
+          :collect
+          (make-instance 'entity
+                         :image (merge-pathnames map-path (cdr (assoc :image-path entity-info)))
+                         :name (assoc :name entity-info)
+                         )
+          )
+    )
+  )
+
+(defun grid-layout (x y &key (size 1))
+  "converts natural coordinates and size into pixel positions. This function can be replaced to change
+the actual grid layout"
+  (values (cons (* x *plane-grid*)
+                (* y *plane-grid*))
+          (* size *plane-grid*)))
+
+(defun actors-layout (x y)
+  (cons (floor (/ x *plane-grid*))
+        (floor (/ y *plane-grid*)))
+  )
+
 (defmacro with-playground ((window renderer &key (title "RuLP")) &body body)
   `(sdl2:with-window (,window :title title :w *window-width* :h *window-height* :flags '(:resizable))
      ;; NOTE: here is where you should set the window icon, if there's the method to do that
        )))
 
 ;; FIXME: temporary place
+;; set boundaries so the plane doesn't go away with the panning. fix boundaries to -window width, -window height, plane width, plane height
 (defparameter *viewpoint-offset* '(0 . 0))
 (defparameter *viewpoint-zoom* 1)
 (defparameter *mouse-previous* '(0 . 0))
 
+(defparameter *framerule* 20
+  "every 20 frames the parameter *changep* is set to t, so it updates informations
+even when away from keyboard")
+
+(defparameter *active-entries* nil
+  "contain the active menu in form of a entry class")
+
+(defparameter *changep* t
+  "set to t when a change on the plane is made, if nil the viewpoint is not updated")
+
 ;; renderer exists only inside this function, so you cannot create a texture outside
 ;; (at least for now), more on this later os
 (defun playground (title &optional (fps 60) (debug-info nil))
@@ -50,12 +99,15 @@ DEBUG-INFO can be used to display the content on screen for test and debug purpo
                                 (font-texture (sdl2:create-texture-from-surface *renderer* font-surface)))
                            (sdl2:free-surface font-surface)
                            font-texture))
-      ;; NOTE: all those variables are binded to +plane+. This should be updated whenever +plane+ is
-      ;; no longer the default plane
-      (let ((mouse-button-previous nil)
+      (multiple-value-bind (p g) (create-plane *map-info* *map-path*)
+        (setf *plane* p)
+        (setf *plane-grid* g))
+      (setf *entities-list* (create-entities *map-info* *map-path*))
+      (let (;; (mouse-button-previous nil)
             (window-texture (sdl2:get-render-target *renderer*))
             (viewpoint-texture (sdl2:create-texture *renderer* (sdl2:get-window-pixel-format window)
-                                                    2 (width +plane+) (height +plane+))))
+                                                    2 (width *plane*) (height *plane*))) ;camping into the ramhog
+            (viewpoint-rectangle (sdl2:make-rect 0 0 10 10)))
         (sdl2:with-event-loop (:method :poll)
           (:quit () t)
           (:keydown ()
@@ -69,19 +121,19 @@ DEBUG-INFO can be used to display the content on screen for test and debug purpo
                     )
           (:mousebuttondown ()
                             (setf *is-mouse-hold* t)
+                            ;; this routine seems identical to the one in idle, instead
+                            ;; of calling the second element of the keybind list it calls
+                            ;; the third element. If there is something there it would
+                            ;; execute a special function for when the mouse is released.
+                            (mouse-event *mouse-position*)
                             )
           (:mousebuttonup ()
-                          ;; this routine seems identical to the one in idle, instead
-                          ;; of calling the second element of the keybind list it calls
-                          ;; the third element. If there is something there it would
-                          ;; execute a special function for when the mouse is released.
-                          (setf *is-mouse-hold* nil)
-                          (loop :for action :in mouse-button-previous
-                                :do (when (cdr action) (eval (cadr action))))
-                          (setf mouse-button-previous nil)
                           ;; what about functions that require a single press? just create
                           ;; a keybind (+key+ nil (...)) and it will execute just on
                           ;; release and not on hold
+                          ;; (setf mouse-button-previous nil)
+                          (setf *changep* t)
+                          (setf *is-mouse-hold* nil)
                           )
           (:windowevent ()
                         ;; bug prevention method. SDL2 can look the :mousebuttonup event
@@ -93,68 +145,83 @@ DEBUG-INFO can be used to display the content on screen for test and debug purpo
           (:multigesture ()
                          ;; same as for windowevent
                          (setf *is-mouse-hold* nil))
+          ;; NOTE: When the user prefear to use only the keyboard or joystick
+          ;; the *cursor-position* is set default, this is set when a key or
+          ;; koystick button is pressed, then menues and actions are chosed with
+          ;; the cursor position. When a mouse motion is detected the
+          ;; mouse-position is set default. the cursor follows the grid on each
+          ;; step and it is an alternative to the mouse movement to do
+          ;; everything.
           (:idle ()
                  (setf *mouse-previous-position* *mouse-position*)
                  (multiple-value-bind (x y) (sdl2:mouse-state)
                    (setf *mouse-position* (cons x y)))
                  ;; mouse-holding-event
+                 ;; (unless *active-entries*
+                 ;;   (when *is-mouse-hold*
+                 ;;     (loop :for action :in (mouse-actions *mouse-keybinds*)
+                 ;;           :do (when action (eval (car action))) ; FIXME: replace eval with a more safer DSL eval
+                 ;;           )
+                 ;;     ;; (setf mouse-button-previous (mouse-actions *mouse-keybinds*))
+                 ;;     ))
                  (when *is-mouse-hold*
-                   (loop :for action :in (mouse-actions *mouse-keybinds*)
-                         :do (when action (eval (car action))) ; FIXME: replace eval with a more safer DSL eval
-                         )
-                   (setf mouse-button-previous (mouse-actions *mouse-keybinds*))
-                   )
+                   (mouse-event *mouse-position* :dragp t))
 
                  ;; trick to avoid functions to change the global draw-color
                  (sdl2:set-render-draw-color *renderer* 0 0 0 255)
-                 ;; clear view
-                 (sdl2:render-clear *renderer*)
 
                  ;; local viewpoint
                  ;; NOTE: generalize
-                 (sdl2:set-render-target *renderer* viewpoint-texture)
-                 (sdl2:render-clear *renderer*)
-                 (render-plane-and-contents *renderer* +plane+)
-                 (when *is-grid*
-                   (grid-render *renderer* +plane+ (car *viewpoint-offset*) (cdr *viewpoint-offset*)
-                       (floor (* (width +plane+) *viewpoint-zoom*))
-                       (floor (* (height +plane+) *viewpoint-zoom*))))
-                 (when *is-indexes*
-                   (indexes-render *renderer* +plane+ (car *viewpoint-offset*) (cdr *viewpoint-offset*)
-                       (floor (* (width +plane+) *viewpoint-zoom*))
-                       (floor (* (height +plane+) *viewpoint-zoom*))))
-                 (sdl2:set-render-draw-color *renderer* 0 255 0 155)
-                 (sdl2:set-render-draw-color *renderer* 0 0 0 255)
+                 (when *changep*
+                   (sdl2:destroy-texture viewpoint-texture)
+                   (setf viewpoint-texture (sdl2:create-texture *renderer*
+                                                                (sdl2:get-window-pixel-format window)
+                                                                2
+                                                                (width *plane*)
+                                                                (height *plane*)))
+                   (sdl2:set-render-target *renderer* viewpoint-texture)
+                   (sdl2:render-clear *renderer*)
+                   (render-plane-and-entities *renderer*)
+                   (when *is-grid*
+                     (grid-render *renderer* 0 0 (width *plane*) (height *plane*))
+                     )
+                   (when *is-indexes*
+                     (indexes-render *renderer* 0 0 (width *plane*) (height *plane*)))
+                   (sdl2:set-render-draw-color *renderer* 0 0 0 255)
+                   (setf *changep* nil)
+                   ;; pointer section
+                   (when *pointer* ;; NOTE: to test this out
+                     (sdl2:set-render-draw-color *renderer* 128 250 33 255)
+                     (multiple-value-bind (coordinates size) (grid-layout (car (coordinate (nth *pointer* *entities-list*)))
+                                                                          (cdr (coordinate (nth *pointer* *entities-list*)))
+                                                                          :size (size (nth *pointer* *entities-list*)))
+                       (let ((select-rectangle (sdl2:make-rect (car coordinates) (cdr coordinates) size size)))
+                         (sdl2:render-draw-rect *renderer* select-rectangle)
+                         (sdl2:free-rect select-rectangle)))
+                     (sdl2:set-render-draw-color *renderer* 0 0 0 255)
+                     ))
+
+
+
+                 ;; display viewpoint on window
                  (sdl2:set-render-target *renderer* window-texture)
-                 (let ((viewpoint-rectangle (sdl2:make-rect (car *viewpoint-offset*)
-                                                            (cdr *viewpoint-offset*)
-                                                            (floor (* (width +plane+) *viewpoint-zoom*)) ; NOTE: hardcoded +plane+ usage
-                                                            (floor (* (height +plane+) *viewpoint-zoom*)))))
-                   (sdl2:render-copy *renderer* viewpoint-texture
-                                     :source-rect nil
-                                     :dest-rect viewpoint-rectangle)
-                   (sdl2:free-rect viewpoint-rectangle))
-
-                 ;; pointer section
-                 (when *pointer*
-                   (sdl2:set-render-draw-color *renderer* 128 250 33 255)
-                   (let ((select-rectangle (screen-destination (nth *pointer* (entities-list +plane+)) +plane+)))
-                     (sdl2:render-draw-rect *renderer* select-rectangle)
-                     (sdl2:free-rect select-rectangle))
-                   )
-                 ;; entries generation
-                 ;; (loop :for entry :in (reverse *entries-list*)
-                 ;;       :do (sdl2:set-render-draw-color *renderer* 255 255 255 255)
-                 ;;           (sdl2:render-fill-rect *renderer* (entry-rectangle entry))
-                 ;;           (sdl2:set-render-draw-color *renderer* 0 0 0 255)
-                 ;;           (loop :for content :in (contents entry)
-                 ;;                 :for content-position :from 0 :to (length (contents entry))
-                 ;;                 :do (tr-write (car content)
-                 ;;                               (car (coordinate entry))
-                 ;;                               (+ (* content-position (text-size entry)) (cdr (coordinate entry)))
-                 ;;                               (text-size entry) (text-size entry) *renderer*
-                 ;;                               ))
-                 ;;       )
+                 (sdl2:render-clear *renderer*)
+                 (setf (sdl2:rect-x viewpoint-rectangle) (car *viewpoint-offset*))
+                 (setf (sdl2:rect-y viewpoint-rectangle) (cdr *viewpoint-offset*))
+                 (setf (sdl2:rect-width viewpoint-rectangle) (floor (* (width *plane*) *viewpoint-zoom*)))
+                 (setf (sdl2:rect-height viewpoint-rectangle) (floor (* (height *plane*) *viewpoint-zoom*)))
+                 (sdl2:render-copy *renderer* viewpoint-texture
+                                   :source-rect nil
+                                   :dest-rect viewpoint-rectangle)
+
+                 ;; entries visualization
+                 (loop :for entry :in rulp.entries:*entries-list*
+                       :do (rulp.entries:render-entry
+                            *renderer*
+                            (rulp.entries:make-plist entry)))
+                 ;; (loop :for entry :in *active-entries*
+                 ;;       :do (display-entry *renderer* entry))
+
                  ;; debug infos
                  (when debug-info
                    (tr-write (format nil "~A" debug-info) 0 0 10 15 *renderer*))
@@ -163,5 +230,11 @@ DEBUG-INFO can be used to display the content on screen for test and debug purpo
                  ;;  FIXME: i hate this, find a better way to dinamically change the window dimension
                  (multiple-value-bind (new-width new-height) (sdl2:get-window-size window)
                    (setf *window-width* new-width)
-                   (setf *window-height* new-height)))))))
+                   (setf *window-height* new-height))
+                 (1- *framerule*)
+                 (when (< *framerule* 1)
+                   (setf *changep* t)
+                   (setf *framerule* 20))))
+        (setf *changep* t)              ; useful in the repl where parameters are not reset
+        )))
   )
index 2119a5b..dae061d 100644 (file)
@@ -29,7 +29,7 @@
 ;; polarity direction and it is not possible to check if someone is watching in what
 ;; direction.
 ;;
-(in-package :layers)
+(in-package :rulp.layers)
 
 (defun abs- (a b)
   "This is a rapid function used for the norm, it can be disappear or be modified in future commits"
       (setf i (cons 0 value)))
     (setf (cdr i) value)))
 
-(defmethod norm ((e t)) ; (e) and ((e t)) are identical, this is clearer
+(defmethod (setf width) (value (s entity))
+  nil
+  )
+
+(defmethod (setf height) (value (s entity))
+  nil)
+
+(defmethod norm ((e t))         ; (e) and ((e t)) are identical, this is clearer
   "classical norm, it works with everything but classes"
   (let ((xe (car e))
         (ye (cdr e)))
index 3f5892b..65c0af9 100644 (file)
@@ -1,4 +1,4 @@
-(in-package :layers)
+(in-package :rulp.layers)
 
 (defgeneric interact (e p)
   (:documentation "check what actions entities can do and return an alist with a lambda
index 210d73e..19ca652 100644 (file)
@@ -14,7 +14,7 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :layers)
+(in-package :rulp.layers)
 
 (defgeneric create-entity (m))
 
index 89841ba..31f00a9 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(defpackage :layers
+(defpackage :rulp.layers
   (:use :cl)
   (:export screen x y width height rotation path texture surface image-path
-           screen-source screen-destination coordinate size
+           screen-source screen-destination screen-purge coordinate size
            model interactions interact
            movep usep pokep ;; temporaries
            plane collision-list entities-list span grid-dimension bounce
            entity ball grid-span displayp))
 
-(in-package :layers)
+(in-package :rulp.layers)
 
 ;; (defparameter entropy 0
 ;;   "parameter used for the random number generator, this variable is
index b646a0a..268c44a 100644 (file)
@@ -14,7 +14,7 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :layers)
+(in-package :rulp.layers)
 
 (defgeneric bounce (v p)
   (:documentation "Given a point v and a plane p this generic check if
@@ -63,18 +63,18 @@ when it is, nil otherwise"))
   (member v (collision-list p)))
 
 ;; doesn't care about the function used
-(defmethod screen-destination ((s screen) (p plane))
-  (let ((x (x s))
-        (y (y s))
-        (w (width s))
-        (h (height s))
-        (x-offset (x p))
-        (y-offset (y p))
-        (span (grid-dimension p)))
-   (sdl2:make-rect (+ (* x span) x-offset)
-                   (+ (* y span) y-offset)
-                   (* w span)
-                   (* h span))))
+;; (defmethod screen-destination ((s screen) (p plane))
+;;   (let ((x (x s))
+;;         (y (y s))
+;;         (w (width s))
+;;         (h (height s))
+;;         (x-offset (x p))
+;;         (y-offset (y p))
+;;         (span (grid-dimension p)))
+;;    (sdl2:make-rect (+ (* x span) x-offset)
+;;                    (+ (* y span) y-offset)
+;;                    (* w span)
+;;                    (* h span))))
 
 ;; (defmethod width ((s plane))
 ;;   (if (original-dimension s)
index c2ccb27..a251f93 100644 (file)
@@ -14,7 +14,7 @@
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
-(in-package :layers)
+(in-package :rulp.layers)
 ;; This is the most generic class in the program with model, this class define
 ;; objects to be displayed on screen, whenever they are entities, planes text
 ;; or icons.
@@ -58,7 +58,7 @@ where the screen should be displayed"))
            :accessor surface)
    (path :accessor image-path
          :initarg :image
-         :initform (merge-pathnames parameters:*rulp-share* "test.png"))
+         :initform (merge-pathnames rulp.parameters:*rulp-share* "test.png"))
    (s-rect :initform nil
            :documentation "this value contains the source rectangle to be used, don't
 interact directly with this but use screen-source instead")
@@ -99,12 +99,17 @@ interact directly with this but use screen-destination instead")
 (defmethod (setf height) (value (s screen))
   (setf (cdr (slot-value s 'size)) value))
 
+;; FIXME: entities use size as a simple integer, change to make it work better
 (defmethod initialize-instance :after ((s screen) &rest args)
-  (setf (surface s) (sdl2-image:load-image (slot-value s 'path))))
+  (declare (ignore args))
+  (setf (surface s) (sdl2-image:load-image (slot-value s 'path)))
+  (setf (width s) (sdl2:surface-width (surface s))
+        (height s) (sdl2:surface-height (surface s)))
+  (setf (slot-value s 's-rect) (sdl2:make-rect 0 0 (width s) (height s))))
 
 (defmethod screen-source ((s screen))
   "return the source rectangle, the portion of texture to display (standard all)"
-  nil)
+  (slot-value s 's-rect))
 
 ;; FIXME: save and use the make-rect. destroy and create a new one when
 ;; info don't match
@@ -131,7 +136,8 @@ top left of the window"
   (sdl2:make-rect (x s) (y s) (width s) (height s))
   )
 
-(defmethod screen-purge ((s screen))
+(defun screen-purge (screen)
   "purge screens video data. This data is automatically generated during rendering"
   (sdl2:destroy-texture (texture s))
-  (sdl2:free-surface (surface s)))
+  (when (surface s)
+    (sdl2:free-surface (surface s))))
index fe47d86..c9f3a1f 100644 (file)
@@ -1,3 +1,3 @@
-(defpackage :core
+(defpackage :rulp.core
   (:use :cl :json)
   (:export main))
index 2400c14..01dcb09 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(defpackage parameters
+(defpackage :rulp.parameters
   (:use :cl)
   (:export +rulp-version+ +rulp-type+ +rulp-system+ *rulp-share* *rulp-local*))
 
-(in-package :parameters)
+(in-package :rulp.parameters)
 
 
 ;; by standard parameters surrounded by asterisks (*) are seen as
index 68d9821..ca62ccd 100644 (file)
 ;;;; You should have received a copy of the GNU General Public License
 ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-(defpackage :script
-  (:use :cl :graphics :layers))
+(defpackage :rulp.script
+  (:use :cl :rulp.graphics :rulp.layers))
 
-(in-package :script)
+(in-package :rulp.script)
 
 (defun active-plane ()
-  graphics:+plane+)
+  *plane*)
 
 (defun (setf active-plane) (value)
-  (setf graphics:+plane+ value))
+  (setf *plane* value))
 
 (defun entities ()
-  (entities-list graphics:+plane+))
+  *entities-list*)
 
 (defun (setf entities) (value)
   (if (listp value)
-      (setf (entities-list graphics:+plane+) value)
-      (error "(setf entities) error: given symbol is not a list")))
+      (setf *entities-list* value)
+      (warn "(setf entities) error: symbol ~A is not of type list, operation stopped" value)))
 
 (defun add-entity (entity)
   "add an entity into the active plane"
-  (push entity graphics:+plane+))
+  (push entity *entities-list*))
 
 (defun remove-entity (number)
   "remove the nth entity from the active plane"
-  (screen-purge (nth number (entities-list graphics:+plane+)))
-  (setf (nth number (entities-list graphics:+plane+)) nil)
-  (remove nil (entities-list graphics:+plane+)))
-
-(defparameter *plane-list* nil)
-
-(defun new-plane (image)
-  "create a new plane and add it to the plane list"
-  (let ((gen-plane (make-instance 'plane :image image)))
-        (push gen-plane *plane-list*)
-        gen-plane))
-
-(defun remove-plane (number)
-  "remove the nth plane from the plane list"
-  (screen-purge (nth number *plane-list*))
-  (setf (nth number *plane-list*) nil)
-  (setf *plane-list* (remove nil *plane-list*)))
-
-(defun list-planes ()
-  "list the content in the plane list"
-  *plane-list*)
+  (screen-purge (nth number *entities-list*))
+  (setf (nth number *entities-list*) nil)
+  (remove nil *entities-list*))