-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgame-object.lisp
executable file
·170 lines (150 loc) · 6.9 KB
/
game-object.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
;;; Copyright 2009-2011 Christoph Senjak
(in-package :uxul-world)
;; Define a class for the Standard Game-Object which has a draw-Method
;; which will be called at every frame, and a Collision-Box, and has a
;; unique (x, y)-Coordinate with translations for both the Drawable
;; Object and the collision-box
;; We changed the api, and added stuff from Collision-Rectangle (which
;; explains some documentation about it)
(defclass game-object (xy-coordinates)
((width :initarg :width
:initform 0
:accessor width
:type fixnum
:documentation "The width of that rectangle")
(height :initarg :height
:initform 0
:accessor height
:type fixnum
:documentation "The height of that rectangle")
(listen-to :initarg :listen-to
:initform NIL
:accessor listen-to
:documentation "List of rectangles and game-objects to
check for collisions at movement")
(colliding :initarg :colliding
:initform T
:accessor colliding
; :type boolean
:documentation "Throw Collisions with this
Collision-Rectangle to other Collision-Rectangles? (this
makes it a bit easier to \"turn off\" Objects, i.e. you
dont always have to remove them from the
listen-to-lists")
(visible :initarg :visible
:initform T
:accessor visible
; :type boolean
:documentation "Should this Object be drawn?")
(redraw :initarg :redraw
:initform T
:accessor redraw
:documentation "If set to nil, this object will be painted
once onto the Background of the Level and then never be
painted again (except when needed), i.e. the engine first
paints it onto its background-surface, and then it keeps
using its background-surface for all further images. This
makes drawing faster. It should be set to NIL whenever
possible, however, if the Object will change its place or
look different in the future, or should be painted over
some other object that can move or change its look, then it
must be set to T, because it must be redrawn. NOTICE: It is
not specified, what happens, if this Value changes during
runtime. It should not be set manually after it is used by
the engine.
**********************FIXME: DOESNT WORK ATM**********************
")
(active :initarg :active
:initform NIL
:accessor active
; :type boolean
:documentation "Will the Invoke-Function be called?")
(object-id :initarg :object-id
:initform NIL
:accessor object-id
:documentation "To identify an object, a room may give it an id."))
(:documentation "Define a Class for all Game-Objects. This class
has an invoke-, a draw- and an on-collide Function, which do
nothing per default." ))
(defmethod draw ((obj game-object))
"To be called when drawing the object - does nothing per default, except throwing a warning."
(format t "waring: draw-method not overridden. Object: ")
(write obj)
(sdl:push-quit-event))
(defmethod invoke ((obj game-object))
"To be called when invoking the object - does nothing per default, except throwing a warning."
(format t "warning: invoke-method not overridden. Object: ")
(write obj)
(sdl:push-quit-event))
(defmethod on-collision ((moving-object game-object) (standing-object game-object) (collision collision))
"To be called if a Collision occurs. May have more than one overriding declaration, to use the dispatcher."
(declare (ignore standing-object moving-object collision))
(format t "warning: on-collision-method not overridden."))
(defmethod half-width ((obj game-object))
(/ (width obj) 2))
(defmethod (setf half-width) (x (obj game-object))
(setf (width obj) (* x 2)))
(defmethod half-height ((obj game-object))
(/ (height obj) 2))
(defmethod (setf half-height) (x (obj game-object))
(setf (height obj) (* x 2)))
(defmethod mid-x ((obj game-object))
(+ (x obj) (half-width obj)))
(defmethod mid-y ((obj game-object))
(+ (y obj) (half-height obj)))
(defmethod (setf mid-x) (x (obj game-object))
(setf (x obj) (- x (half-width obj))))
(defmethod (setf mid-y) (y (obj game-object))
(setf (y obj) (- y (half-height obj))))
(defmethod move-about ((moving-rectangle game-object) (translation xy-struct))
(if (= (x translation) 0)
(when (not (= (y translation) 0))
(move-collision-rectangle-about-y moving-rectangle (y translation)))
(if (= (y translation) 0)
(move-collision-rectangle-about-x moving-rectangle (x translation))
(move-collision-rectangle-about-xy moving-rectangle (x translation) (y translation)))))
(defmethod move-to ((moving-rectangle game-object) (translation xy-struct))
"This is highly inefficient and should be replaced"
(move-about moving-rectangle
(make-xy (- (x translation) (x moving-rectangle)) (- (y translation) (y moving-rectangle)))))
(defmethod draw-bounds ((obj game-object))
"This function draws a rectangle with the Object's Bounds. May be useful for some debug-spam"
;; (sdl:draw-rectangle-* (+ (x obj) *current-translation-x*)
;; (+ (y obj) *current-translation-y*)
;; (width obj) (height obj)
;; :color sdl:*BLACK*)
)
(defun collide-blocks (moving-rectangle standing-rectangle collision)
"as MANY collision-methods need to move the moving-object around the
standing-object, we will write a function for doing that. IMPORTANT:
moving-rectangle MUST have a dont-ignore-property"
(declare (ignore standing-rectangle))
(directly-with-all-accessors collision collision
(setf (x moving-rectangle) (x pos))
(setf (y moving-rectangle) (y pos))
(cond
((or (eq direction :left) (eq direction :right))
(move-about moving-rectangle (make-xy 0 (truncate (* (- 1 collision-time) (y desired-movement))))))
((or (eq direction :up) (eq direction :down))
(move-about moving-rectangle (make-xy (truncate (* (- 1 collision-time) (x desired-movement))) 0)))
(T ;; diagonal - argh! lets try to move up/down. if this fails,
;; lets try to move left/right. we're setting our
;; dont-ignore-flag to nil for that
(let ((current-y (y moving-rectangle))
(current-x (x moving-rectangle)))
(setf (dont-ignore moving-rectangle) nil)
(move-about moving-rectangle (make-xy (truncate (* (- 1 collision-time) (x desired-movement))) 0))
(if (not (= current-x (x moving-rectangle)))
(progn
(setf (x moving-rectangle) current-x)
(setf (dont-ignore moving-rectangle) T)
;; now really move it!
(move-about moving-rectangle (make-xy (truncate (* (- 1 collision-time) (x desired-movement))) 0)))
;else - it cannot move in x-direction...
(progn
(move-about moving-rectangle (make-xy 0 (truncate (* (- 1 collision-time) (y desired-movement)))))
(when (not (= current-y (y moving-rectangle)))
(setf (y moving-rectangle) current-y)
(setf (dont-ignore moving-rectangle) T)
;; now really move it!
(move-about moving-rectangle (make-xy 0 (truncate (* (- 1 collision-time) (y desired-movement)))))))))))))