Episode 37: Verlet Integration Part 2
author |
Steve Losh <steve@stevelosh.com> |
date |
Sat, 09 Jul 2016 17:41:38 +0000 |
parents |
e2a3c62c574d
|
children |
0157f4a952c6
|
branches/tags |
(none) |
files |
package.lisp src/2d/demo.lisp src/2d/vectors.lisp src/3d/demo.lisp |
Changes
--- a/package.lisp Fri Jul 08 15:49:50 2016 +0000
+++ b/package.lisp Sat Jul 09 17:41:38 2016 +0000
@@ -120,6 +120,9 @@
#:with-vec
#:with-vecs
#:vec-to-list
+ #:vec-set-angle
+ #:vec-set-direction
+ #:vec-set-magnitude
))
(defpackage #:coding-math.2d.hitboxes
@@ -232,7 +235,8 @@
#:coding-math.2d.hitboxes
#:coding-math.2d.particles)
(:shadowing-import-from #:iterate
- #:in))
+ #:in)
+ (:shadow #:point))
(defpackage #:coding-math.2d.ballistics
(:use
@@ -291,5 +295,6 @@
#:coding-math.3d.coordinates
)
(:import-from :sb-cga
- :vec))
+ :vec)
+ (:shadow #:point))
--- a/src/2d/demo.lisp Fri Jul 08 15:49:50 2016 +0000
+++ b/src/2d/demo.lisp Sat Jul 09 17:41:38 2016 +0000
@@ -76,33 +76,57 @@
(defstruct (point
- (:constructor make-point (x y old-x old-y)))
- x y old-x old-y)
+ (:constructor make-point (pos old-pos)))
+ pos old-pos)
+
+(defstruct (stick
+ (:constructor make-stick (a b length)))
+ a b length)
+
+
+(defun make-random-point ()
+ (let ((v (make-random-vec *width* *height*)))
+ (make-point v v)))
(defun update-point (point)
- (with-slots (x y old-x old-y) point
+ (with-slots (pos old-pos) point
(let* ((friction 0.999)
- (bounce 0.9)
- (gravity 0.2)
- (vx (* friction (- x old-x)))
- (vy (* friction (- y old-y))))
- (setf old-x x
- old-y y)
- (incf x vx)
- (incf y vy)
- (decf y gravity)
+ (gravity (make-vec 0 -0.2))
+ (vel (vec-mul (vec-sub pos old-pos) friction)))
+ (setf old-pos pos
+ pos (vec-add gravity (vec-add pos vel))))))
+
+(defun constrain-point (point)
+ (with-slots (pos old-pos) point
+ (let* ((bounce 0.9)
+ (vel (vec-sub pos old-pos)))
(macrolet ((wrap ((cur old vel) comp bound)
`(when (,comp ,cur ,bound)
(setf ,cur ,bound
,old (+ ,cur (* bounce ,vel))))))
- (wrap (x old-x vx) > *width*)
- (wrap (x old-x vx) < 0)
- (wrap (y old-y vy) > *height*)
- (wrap (y old-y vy) < 0)))))
+ (wrap ((vec-x pos) (vec-x old-pos) (vec-x vel)) > *width*)
+ (wrap ((vec-x pos) (vec-x old-pos) (vec-x vel)) < 0)
+ (wrap ((vec-y pos) (vec-y old-pos) (vec-y vel)) > *height*)
+ (wrap ((vec-y pos) (vec-y old-pos) (vec-y vel)) < 0)))))
+
+(defun update-stick (stick)
+ (with-slots (a b length) stick
+ (let* ((pos-a (point-pos a))
+ (pos-b (point-pos b))
+ (between (vec-sub pos-a pos-b))
+ (distance (vec-magnitude between))
+ (change (/ (- length distance) 2))
+ (correction (vec-set-magnitude between change)))
+ (setf (point-pos a) (vec-add pos-a correction))
+ (setf (point-pos b) (vec-sub pos-b correction)))))
(defun render-point (point)
- (with-slots (x y) point
- (draw-circle (make-vec x y) 5)))
+ (draw-circle (point-pos point) 5))
+
+(defun render-stick (stick)
+ (draw-line (point-pos (stick-a stick))
+ (point-pos (stick-b stick))))
+
(defsketch cm
((width *width*) (height *height*) (y-axis :up) (title "Coding Math 2D")
@@ -114,7 +138,12 @@
(previous-time 0)
(total-time 0)
;; Data
- (points (list (make-point 100 100 95 95)))
+ (points (iterate (repeat 4) (collect (make-random-point))))
+ (sticks (append
+ (iterate (for (a . b) :pairs-of-list points)
+ (collect (make-stick a b (random-range 50 200))))
+ (list (make-stick (nth 0 points) (nth 2 points) 100))
+ ))
;; Pens
(particle-pen (make-pen :fill (gray 0.9) :stroke (gray 0.4)))
(black-pen (make-pen :stroke (rgb 0 0 0) :fill (rgb 0.4 0.4 0.4) :weight 1 :curve-steps 50))
@@ -130,7 +159,12 @@
(with-setup
(in-context
(mapc #'update-point points)
- (mapc #'render-point points)
+ (iterate (repeat 3)
+ (mapc #'update-stick sticks)
+ (mapc #'constrain-point points))
+ (with-pen red-pen
+ (mapc #'render-stick sticks)
+ (mapc #'render-point points))
))
;;
--- a/src/2d/vectors.lisp Fri Jul 08 15:49:50 2016 +0000
+++ b/src/2d/vectors.lisp Sat Jul 09 17:41:38 2016 +0000
@@ -54,6 +54,20 @@
(vec-angle vec))
+(defun vec-set-magnitude (vec magnitude)
+ (let ((v (copy-vec vec)))
+ (setf (vec-magnitude v) magnitude)
+ v))
+
+(defun vec-set-angle (vec angle)
+ (let ((v (copy-vec vec)))
+ (setf (vec-angle v) angle)
+ v))
+
+(defun vec-set-direction (vec angle)
+ (vec-set-angle vec angle))
+
+
(defun (setf vec-angle) (angle vec)
(let ((magnitude (vec-magnitude vec)))
(setf (vec-x vec) (* magnitude (cos angle)))
--- a/src/3d/demo.lisp Fri Jul 08 15:49:50 2016 +0000
+++ b/src/3d/demo.lisp Sat Jul 09 17:41:38 2016 +0000
@@ -15,6 +15,7 @@
(defvar *command* nil)
(defvar *option* nil)
+
;;;; Utils
(defmacro with-centered-coords (&body body)
`(in-context