Add a game module
The game module contains for now a internal loop to allow the game to always update at 16ms and a simple scene graph to place object in a 3d world. A camera class is defined to be able to view the world.
This commit is contained in:
parent
75f40f6be8
commit
d4fd7ecc55
3 changed files with 163 additions and 0 deletions
100
src/game/game-object.lisp
Normal file
100
src/game/game-object.lisp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
#|
|
||||
This file is a part of stoe project.
|
||||
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
||||
|#
|
||||
|
||||
(in-package :cl-user)
|
||||
(defpackage stoe.game.game-object
|
||||
(:use :cl)
|
||||
(:nicknames :game-object :go)
|
||||
(:shadow :position)
|
||||
(:export :node
|
||||
:parent
|
||||
:children
|
||||
:attach
|
||||
:detach
|
||||
:walk
|
||||
:position
|
||||
:direction
|
||||
:make-object
|
||||
:update-trans-matrix
|
||||
:make-camera
|
||||
:view
|
||||
:update-view))
|
||||
(in-package :stoe.game.game-object)
|
||||
|
||||
(defclass scene-node ()
|
||||
((parent :initform nil :reader parent)
|
||||
(children :initform nil :reader children))
|
||||
(:documentation "Base class for a node in the scene graph."))
|
||||
|
||||
(defgeneric attach (scene-node parent)
|
||||
(:documentation "Attach a new node to the scene graph to be rendered."))
|
||||
|
||||
(defmethod attach ((scene-node scene-node) (parent scene-node))
|
||||
(with-slots (children) parent
|
||||
(with-slots ((new-parent parent)) scene-node
|
||||
(push scene-node children)
|
||||
(setf new-parent parent))))
|
||||
|
||||
(defgeneric detach (scene-node)
|
||||
(:documentation "Detach a node from the scene graph to prevent it and its
|
||||
children from being rendered."))
|
||||
|
||||
(defmethod detach ((scene-node scene-node))
|
||||
(with-slots (parent) scene-node
|
||||
(with-slots (children) parent
|
||||
(setf children (remove scene-node children))
|
||||
(setf parent nil))))
|
||||
|
||||
(defun walk (fun node)
|
||||
"Walk through the scene graph and apply `fun' at each node."
|
||||
(with-slots (children) node
|
||||
(loop for child in children
|
||||
do (progn
|
||||
(apply fun child)
|
||||
(walk fun child)))))
|
||||
|
||||
(defclass game-object (scene-node)
|
||||
((position :initarg :position :accessor position :type 'f3:float3)
|
||||
(direction :initarg :direction :accessor direction :type 'q:quaternion)
|
||||
(trans-matrix :initform (f44:mat-ident) :accessor trans-matrix :type 'f44:float44)
|
||||
(components :initform nil))
|
||||
(:documentation "Base class for all objects existing in the game world."))
|
||||
|
||||
(defclass camera (game-object)
|
||||
((fovy :initarg :fovy :accessor fovy)
|
||||
(aspect :initarg :aspect :accessor aspect)
|
||||
(near :initarg :near :accessor near)
|
||||
(far :initarg :far :accessor far)
|
||||
(projection :initarg :projection :accessor projection :type 'f44:float44)
|
||||
(view :accessor view :type 'f44:float44))
|
||||
(:documentation "Base class for a camera representing a view of the game world."))
|
||||
|
||||
(defun make-object (&key (pos (v:vec 0 0 0)) (dir (q:from-axis-and-angle (v:vec 0 0 1) 0)) mesh)
|
||||
(let ((obj (make-instance 'game-object :position pos :direction dir)))
|
||||
(when mesh
|
||||
(with-slots (components) obj
|
||||
(push mesh components)))
|
||||
obj))
|
||||
|
||||
(defun update-trans-matrix (node)
|
||||
(setf (trans-matrix node) (m:* (trans-matrix (parent node))
|
||||
(geom:mat-trans (position node))
|
||||
(q:to-float44 (direction node)))))
|
||||
|
||||
(defun make-camera (fovy aspect near far)
|
||||
(let ((camera (make-instance 'camera :position (v:vec 0 0 2)
|
||||
:direction (q:from-axis-and-angle (v:vec 0 0 1) 0)
|
||||
:fovy fovy
|
||||
:aspect aspect
|
||||
:near near
|
||||
:far far
|
||||
:projection (geom:make-persp-matrix fovy aspect near far))))
|
||||
(update-view camera)
|
||||
camera))
|
||||
|
||||
(defun update-view (camera)
|
||||
"Compute the world to view matrix from the position and the direction of `camera'."
|
||||
(with-accessors ((pos go:position) (dir go:direction) (view view)) camera
|
||||
(setf view (m:* (m::transpose (q:to-float44 dir)) (geom:mat-trans (v:- pos))))))
|
||||
59
src/game/game.lisp
Normal file
59
src/game/game.lisp
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
#|
|
||||
This file is a part of stoe project.
|
||||
Copyright (c) 2014 Renaud Casenave-Péré (renaud@casenave-pere.fr)
|
||||
|#
|
||||
|
||||
(in-package :cl-user)
|
||||
(defpackage stoe.game
|
||||
(:use :cl)
|
||||
(:nicknames :game)
|
||||
(:export :get-world-origin
|
||||
:get-current-camera))
|
||||
(in-package :stoe.game)
|
||||
|
||||
(defconstant +loop-step-time+ 16000.0
|
||||
"The length of one game loop frame.")
|
||||
|
||||
(defvar *last-frame-remaining-time* 0.0
|
||||
"The game loop advance +loop-step-time+ at a time but when the delta time doesn't correspond
|
||||
we need to keep the remaining time.")
|
||||
|
||||
(defvar *current-camera* nil
|
||||
"The camera used to render the scene.")
|
||||
|
||||
(defvar *world-origin* nil
|
||||
"The origin node of the scene.")
|
||||
|
||||
(defun initialize (&optional argv)
|
||||
"Initialize the game module."
|
||||
(declare (ignore argv))
|
||||
(format t "Initialize Game module~%")
|
||||
(input:initialize)
|
||||
(setf *world-origin* (go:make-object))
|
||||
(setf *current-camera* (go:make-camera 90 (/ 16 9) 1.0 1000.0))
|
||||
(go:attach *current-camera* *world-origin*))
|
||||
|
||||
(defun finalize ()
|
||||
"Finalize the game module."
|
||||
(setf *current-camera* nil)
|
||||
(setf *world-origin* nil)
|
||||
(input:finalize))
|
||||
|
||||
(defun update (delta-time)
|
||||
"Update the game module.
|
||||
Advance the world by `delta-time', +loop-step-time+ at a time."
|
||||
(setf delta-time (+ delta-time *last-frame-remaining-time*))
|
||||
(loop while (> delta-time +loop-step-time+)
|
||||
do (progn
|
||||
(when *current-camera*
|
||||
(go:update-view *current-camera*))
|
||||
(input:update +loop-step-time+)
|
||||
(decf delta-time +loop-step-time+)))
|
||||
(setf *last-frame-remaining-time* delta-time))
|
||||
|
||||
(modules:register-initialize-fun #'initialize)
|
||||
(modules:register-finalize-fun #'finalize)
|
||||
(modules:register-update-fun #'update)
|
||||
|
||||
(defun get-world-origin () *world-origin*)
|
||||
(defun get-current-camera () *current-camera*)
|
||||
4
stoe.asd
4
stoe.asd
|
|
@ -49,6 +49,10 @@
|
|||
:depends-on ("thread" "containers" "utils"))
|
||||
(:file "file"
|
||||
:depends-on ("jobs"))
|
||||
(:module "game"
|
||||
:components
|
||||
((:file "game-object")
|
||||
(:file "game")))
|
||||
(:module "render"
|
||||
:components
|
||||
((:file "gl-utils")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue