wh-engine/wh-engine/main.lisp

175 lines
8.3 KiB
Common Lisp

;;;; wh-engine/main.lisp
(in-package wh-engine)
(defun initialize-actors-in (scene &rest actors)
"Properly attach actors and their descendents to scene, and initialize them."
(loop for actor in actors
do ;; attach actor to scene
(o! actor (apply-to-tree (lambda (a)
(setf (o! a :slot scene) nil)
(o! scene (add-actor a)))))
;; (resume) -> automatically resumes children
(o! actor (resume))
;; (activate) -> automatically activates eligible children
(when (o! actor tree-active-p)
(o! actor (activate)))
))
(defvar *delta-time* 0.0
"Time in seconds since the last game tick.")
(defun register-test-scene ()
(let ((test-scene (new! scene :id -1 :name "Test scene")))
(add-scene test-scene)
(initialize-actors-in test-scene
(new! actor
:name "Actor"
:component (new! whe/render:drawable-test))
(new! actor
:name "Actor 2"
:location (vec2 0.5 0.5)
:rotation (coerce (/ pi 4) 'single-float)
:z-layer -1
:component (new! whe/render:drawable-test :colour (vec4 0 1 0 1))
:child (new! actor
:name "Child Actor"
:location (vec2 0 0.5)
:z-layer -2
:component (new! whe/render:drawable-test :colour (vec4 0 1 1 1))
:child (new! actor
:name "Grandchild Actor"
:location (vec2 0 1)
:scale (vec2 0.25 0.25)
:z-layer 1
:component (new! whe/render:drawable-test :colour (vec4 1 1 0 1)))))
(new! actor
:name "Camera"
:component (new! whe/render:view)))
test-scene))
(defmacro run ()
"Run the main game loop."
`(sdl2:with-init (:everything)
(format t "wh-engine: using SDL ~D.~D.~D~%"
sdl2-ffi:+sdl-major-version+
sdl2-ffi:+sdl-minor-version+
sdl2-ffi:+sdl-patchlevel+)
(finish-output)
(sdl2:with-window (win :flags '(:shown :opengl)
:w (* whe/render:*view-width* whe/render:*pixel-scale*) :h (* whe/render:*view-height* whe/render:*pixel-scale*)
:title (format nil "wh-engine ~1{~D.~D.~D~} (Affero GPL; NON-FREE USAGE PROHIBITED)"
+version+))
(sdl2:with-gl-context (gl-context win)
(sdl2:gl-make-current win gl-context)
(let ((prev-tick (sdl2:get-ticks))
(this-tick (sdl2:get-ticks))
(prev-profiling-tick (sdl2:get-performance-counter))
(profiling-scale (/ (sdl2:get-performance-frequency) 1000.0)))
,@(loop for system in *world-systems*
append `((,(second system))))
(sdl2:with-event-loop (:method :poll)
(:quit () t)
(:idle
()
(setf prev-profiling-tick (sdl2:get-performance-counter))
;; calculate delta-time
(setf this-tick (sdl2:get-ticks))
(setf *delta-time* (* (- this-tick prev-tick) 0.001))
(setf prev-tick this-tick)
;; (format t "~%Δt = ~S (~S FPS)~%" *delta-time* (/ 1.0 *delta-time*))
;; update
(loop for scene in *world*
do (o! scene (update)))
;; (format t "game=~S " (/ (- (sdl2:get-performance-counter) prev-profiling-tick) profiling-scale))
,@(loop for system in *world-systems*
append `((,(third system))
;; (format t ,(format nil "~S~A" (first system) "=~S ")
;; (/ (- (sdl2:get-performance-counter) prev-profiling-tick) profiling-scale))
))
(sdl2:gl-swap-window win))
(:keydown
(:keysym keysym)
,@(loop for system in *world-systems*
for handler = (assoc :keydown (fourth system))
when handler
collect `(,(cdr handler) keysym)))
(:keyup
(:keysym keysym)
,@(loop for system in *world-systems*
for handler = (assoc :keyup (fourth system))
when handler
collect `(,(cdr handler) keysym)))
(:mousemotion
(:x mouse-x :y mouse-y :xrel delta-x :yrel delta-y :state state)
,@(loop for system in *world-systems*
for handler = (assoc :mousemotion (fourth system))
when handler
collect `(,(cdr handler)
(vec2 (truncate mouse-x whe/render:*pixel-scale*)
(- wh-engine/render:*view-height* (truncate mouse-y whe/render:*pixel-scale*)))
(vec2 (truncate delta-x whe/render:*pixel-scale*)
(- (truncate delta-y whe/render:*pixel-scale*)))
state)))
(:mousebuttondown
(:x mouse-x :y mouse-y :button button)
,@(loop for system in *world-systems*
for handler = (assoc :mousebuttondown (fourth system))
when handler
collect `(,(cdr handler)
(vec2 (truncate mouse-x whe/render:*pixel-scale*)
(- wh-engine/render:*view-height* (truncate mouse-y whe/render:*pixel-scale*)))
button)))
(:mousebuttonup
(:x mouse-x :y mouse-y :button button)
,@(loop for system in *world-systems*
for handler = (assoc :mousebuttonup (fourth system))
when handler
collect `(,(cdr handler)
(vec2 (truncate mouse-x whe/render:*pixel-scale*)
(- wh-engine/render:*view-height* (truncate mouse-y whe/render:*pixel-scale*)))
button)))
(:joyaxismotion
(:which joy-id :axis axis :value value)
,@(loop for system in *world-systems*
for handler = (assoc :joyaxismotion (fourth system))
when handler
collect `(,(cdr handler) joy-id axis value)))
(:joyballmotion
(:which joy-id :ball ball :xrel delta-x :yrel delta-y)
,@(loop for system in *world-systems*
for handler = (assoc :joyballmotion (fourth system))
when handler
collect `(,(cdr handler) joy-id ball (vec2 delta-x delta-y))))
(:joyhatmotion
(:which joy-id :hat hat :value value)
,@(loop for system in *world-systems*
for handler = (assoc :joyhatmotion (fourth system))
when handler
collect `(,(cdr handler) joy-id hat value)))
(:joybuttondown
(:which joy-id :button button)
,@(loop for system in *world-systems*
for handler = (assoc :joybuttondown (fourth system))
when handler
collect `(,(cdr handler) joy-id button)))
(:joybuttonup
(:which joy-id :button button)
,@(loop for system in *world-systems*
for handler = (assoc :joybuttonup (fourth system))
when handler
collect `(,(cdr handler) joy-id button))))
)))))