root/trunk/projects/bos/m2/tiled-index.lisp

Revision 3671, 6.7 kB (checked in by ksprotte, 4 months ago)

again whitespace cleanup + removed tabs

Line 
1 (in-package :bos.m2)
2
3 ;;;; XXX Dokumentation aus der alten Implementation
4
5 ;;;; TILE
6 ;;;;
7 ;;;; Kacheln sind per x-y-Koordinate ansprechbare Bloecke von Quadratmetern.
8 ;;;; An Kacheln koennen verschiedene Nutzerdaten haengen, diese sind von
9 ;;;; Unterklassen festzulegen.
10 ;;;;
11 ;;;; Kacheln sind transiente Objekte, die lazy, als nur bei Bedarf, angelegt
12 ;;;; werden.  So wird vermieden, fuer das gesamte Vergabegebiet Kachelobjekte
13 ;;;; im Voraus anlegen zu muessen.
14 ;;;;
15 ;;;; Kacheln werden ueber die Quadratmeterkoordinate ihrer Nord-West-Ecke
16 ;;;; addressiert.
17
18 (defclass tile ()
19   ((nw-x :initarg :nw-x :reader tile-nw-x)
20    (nw-y :initarg :nw-y :reader tile-nw-y)
21    (width :initarg :width :reader tile-width)
22    (objects :initarg :objects :reader tile-objects)))
23
24 (defmethod print-object ((tile tile) stream)
25   (print-unreadable-object (tile stream :type t :identity nil)
26     (format stream "at (~D,~D) width ~D"
27             (tile-nw-x tile)
28             (tile-nw-y tile)
29             (tile-width tile))))
30
31 (defmethod initialize-instance :after ((tile tile) &key width &allow-other-keys)
32   (setf (slot-value tile 'objects)
33         (make-array (list width width)
34                     :initial-element nil)))
35
36 (defmethod validate-coords ((tile tile) x y)
37   (unless (and (< -1 (- x (tile-nw-x tile)) (tile-width tile))
38                (< -1 (- y (tile-nw-y tile)) (tile-width tile)))
39     (error "coordinates ~D/~D are out of range for ~A" x y tile)))
40
41 (defmethod tile-height ((tile tile))
42   (tile-width tile))                    ; assume quadratic tiles
43
44 (defmethod tile-absolute-x ((tile tile) relative-x)
45   (+ (tile-nw-x tile) relative-x))
46
47 (defmethod tile-absolute-y ((tile tile) relative-y)
48   (+ (tile-nw-y tile) relative-y))
49
50 (defmethod object-at ((tile tile) x y)
51   (validate-coords tile x y)
52   (aref (tile-objects tile) (- x (tile-nw-x tile)) (- y (tile-nw-y tile))))
53
54 (defmethod (setf object-at) (object (tile tile) x y)
55   (validate-coords tile x y)
56   (setf (aref (tile-objects tile) (- x (tile-nw-x tile)) (- y (tile-nw-y tile))) object))
57
58 (defclass tiled-index ()
59   (x-slot-name
60    y-slot-name
61    (tiles :reader tiled-index-tiles)
62    (width :initarg :width)
63    (height :initarg :height)
64    (tile-size :initarg :tile-size)
65    (tile-class :initarg :tile-class))
66   (:default-initargs :tile-class 'tile))
67
68 (defmethod initialize-instance :after ((tiled-index tiled-index) &key width height tile-size slots &allow-other-keys)
69   (with-slots (x-slot-name y-slot-name) tiled-index
70     (setf x-slot-name (first slots))
71     (setf y-slot-name (second slots)))
72   (unless (and (zerop (mod width tile-size))
73                (zerop (mod height tile-size)))
74     (error "invalid tile-index dimensions (width ~D height ~D) for tile size ~D~%index dimensions must be dividable by tile size"
75            width height tile-size))
76   (index-clear tiled-index))
77
78 (defmethod print-object ((tiled-index tiled-index) stream)
79   (print-unreadable-object (tiled-index stream :type t :identity nil)
80     (ignore-errors
81       (with-slots (width height tile-size tile-class) tiled-index
82         (format stream "width ~D height ~D tile-size ~D tile-class ~D"
83                 width height tile-size tile-class)))))
84
85 (defmethod validate-coords ((tiled-index tiled-index) x y)
86   (unless (and (< -1 x (slot-value tiled-index 'width))
87                (< -1 y (slot-value tiled-index 'height)))
88     (error "coordinates ~D/~D are out of range for ~A" x y tiled-index)))
89
90 (defmethod get-tile ((tiled-index tiled-index) x y)
91   (validate-coords tiled-index x y)
92   (with-slots (tiles tile-size) tiled-index
93     (aref tiles
94           (floor x tile-size)
95           (floor y tile-size))))
96
97 (defmethod ensure-tile ((tiled-index tiled-index) x y)
98   (validate-coords tiled-index x y)
99   (with-slots (tiles tile-size tile-class) tiled-index
100     (or (get-tile tiled-index x y)
101         (setf (aref tiles
102                     (floor x tile-size)
103                     (floor y tile-size))
104               (make-instance tile-class
105                              :nw-x (* tile-size (floor x tile-size))
106                              :nw-y (* tile-size (floor y tile-size))
107                              :width tile-size)))))
108
109 (defmethod object-at ((tiled-index tiled-index) x y)
110   (let ((tile (get-tile tiled-index x y)))
111     (when tile
112       (object-at tile x y))))
113
114 (defmethod (setf object-at) (object (tiled-index tiled-index) x y)
115   (setf (object-at (ensure-tile tiled-index x y) x y) object))
116
117 ;; bknr index protocol methods
118
119 (defmethod index-add ((index tiled-index) object)
120   (with-slots (x-slot-name y-slot-name) index
121     (unless (and (slot-boundp object x-slot-name)
122                  (slot-boundp object y-slot-name))
123       (return-from index-add nil))
124     (setf (object-at index
125                      (slot-value object x-slot-name)
126                      (slot-value object y-slot-name))
127           object)))
128
129 (defmethod index-get ((index tiled-index) coords)
130   (apply #'object-at index coords))
131
132 (defmethod index-remove ((index tiled-index) object)
133   (with-slots (x-slot-name y-slot-name) index
134     (unless (and (slot-boundp object x-slot-name)
135                  (slot-boundp object y-slot-name))
136       (return-from index-remove nil))
137     (unless (eq object
138                 (object-at index
139                            (slot-value object x-slot-name)
140                            (slot-value object y-slot-name)))
141       (error "while removing object ~A from ~A - unexpected object ~A in index, can't remove object"
142              object
143              index
144              (object-at index
145                         (slot-value object x-slot-name)
146                         (slot-value object y-slot-name))))
147     (setf (object-at index
148                      (slot-value object x-slot-name)
149                      (slot-value object y-slot-name))
150           nil)))
151
152 (defmethod index-keys ((index tiled-index))
153   (error "An TILED-INDEX has no keys."))
154
155 (defmethod index-values ((index tiled-index))
156   (error "An TILED-INDEX cannot enumerate its values."))
157
158 (defmethod index-mapvalues ((index tiled-index) fun)
159   (error "An TILED-INDEX cannot enumerate its values."))
160
161 (defmethod index-clear ((index tiled-index))
162   (with-slots (width height tile-size) index
163     (setf (slot-value index 'tiles) (make-array (list (floor width tile-size)
164                                                       (floor height tile-size))
165                                                 :initial-element nil))))
166
167 (defmethod index-reinitialize ((new-index tiled-index) (old-index tiled-index))
168   (unless (every #'(lambda (slot-name) (equal (slot-value old-index slot-name)
169                                               (slot-value new-index slot-name)))
170                  '(width height tile-size x-slot-name y-slot-name))
171     (error "can't change index parameters for index ~A" old-index))
172   (setf (slot-value new-index 'tiles) (slot-value old-index 'tiles)))
Note: See TracBrowser for help on using the browser.