Episode 28: More on Easing
author |
Steve Losh <steve@stevelosh.com> |
date |
Sun, 26 Jun 2016 16:55:04 +0000 |
parents |
9ad941538426
|
children |
7f6f46164312
|
branches/tags |
(none) |
files |
package.lisp src/2d/demo.lisp src/2d/particles.lisp |
Changes
--- a/package.lisp Sun May 29 11:47:47 2016 +0000
+++ b/package.lisp Sun Jun 26 16:55:04 2016 +0000
@@ -142,6 +142,7 @@
#:particle-gravitate-to!
#:particle-gravitate-add!
#:particle-gravitate-remove!
+ #:particle-ease-to!
#:particle-spring-to!
#:particle-spring-add!
#:particle-spring-remove!))
--- a/src/2d/demo.lisp Sun May 29 11:47:47 2016 +0000
+++ b/src/2d/demo.lisp Sun Jun 26 16:55:04 2016 +0000
@@ -46,14 +46,40 @@
(or (outsidep (- 0 r) (+ *width* r) (vec-x p))
(outsidep (- 0 r) (+ *height* r) (vec-y p))))
+(defparameter *wheel-rim-pen* (make-pen :weight 10 :stroke (rgb 0.5 0 0)))
+(defparameter *wheel-point-pen* (make-pen :fill (rgb 0.8 0 0)))
+
+(defun draw-wheel (angle)
+ (in-context
+ (translate *center-x* *center-y*)
+ (rotate angle)
+ (with-pen *wheel-rim-pen*
+ (circle 0 0 100))
+ (with-pen *wheel-point-pen*
+ (ngon 3 0 80 30 30 (degrees (/ tau 4)))
+ (rect -5 0 10 80)
+ (rotate (degrees (/ tau 8)))
+ (rect -5 -90 10 80)
+ (rotate (degrees (- (/ tau 4))))
+ (rect -5 -90 10 80))))
+
+
+(defun ease (rate current goal)
+ (+ current (* rate (- goal current))))
+
+(defmacro easef (rate place goal)
+ `(zap% ,place #'ease ,rate % ,goal))
(defsketch cm
((width *width*) (height *height*) (y-axis :up) (title "Coding Math 2D")
(mouse (make-vec 0 0))
;; Data
(p (make-particle 0.0 (random height) :radius 10))
+ (points (loop :repeat 50
+ :collect (make-particle 0.0 0.0 :radius 5)))
(target (make-vec width (random height)))
- (ease 0.1)
+ (easing nil)
+ (wheel-angle 0.0)
;; Pens
(particle-pen (make-pen :fill (gray 0.9) :stroke (gray 0.4)))
(line-pen (make-pen :curve-steps 100
@@ -63,12 +89,26 @@
;;
(in-context
(draw-axes *width* *height*)
- (let* ((distance (vec-sub target (particle-pos p)))
- (velocity (vec-mul distance ease)))
- (setf (particle-vel p) velocity)
- (particle-update! p)
- (with-pen particle-pen
- (draw-particle p)))
+ (easef 0.05 wheel-angle
+ (degrees (map-range 0 *width*
+ (/ tau 2) (- (/ tau 2))
+ (vec-x mouse))))
+ (draw-wheel wheel-angle)
+ (when easing
+ ; (text "easing" 0 100)
+ ; (text (format nil "points: ~D" (length points)) 0 100)
+ (setf easing (particle-ease-to! p target 0.2))
+ (particle-update! p))
+ (with-pen particle-pen
+ (draw-particle p)
+ (do ((previous p current)
+ (current (car points) (car remaining))
+ (remaining (cdr points) (cdr remaining)))
+ ((null current))
+ (particle-ease-to! current (particle-pos previous) 0.2 t)
+ (particle-update! current)
+ (draw-particle current)
+ ))
)
;;
@@ -78,10 +118,11 @@
;;;; Mouse
(defun mousemove (instance x y)
- (with-slots (target mouse) instance
+ (with-slots (target mouse easing) instance
(setf mouse (make-vec x (- *height* y)))
;;
- (setf target mouse)
+ (setf target mouse
+ easing t)
;;
)
)
@@ -155,3 +196,4 @@
;;;; Run
; (defparameter *demo* (make-instance 'cm))
+
--- a/src/2d/particles.lisp Sun May 29 11:47:47 2016 +0000
+++ b/src/2d/particles.lisp Sun Jun 26 16:55:04 2016 +0000
@@ -156,3 +156,20 @@
(defmethod (setf drag-location-vec) (new-value (p particle))
(setf (particle-pos p) new-value))
+
+
+(defun particle-ease-to! (particle target &optional (ease 0.1) (always nil))
+ "Ease this particle toward the target vector.
+
+ Returns whether or not the easing still needs to continue.
+
+ "
+ (with-slots (pos vel) particle
+ (let* ((new-vel (vec-mul (vec-sub target pos) ease))
+ (done (and (not always)
+ (< (abs (vec-x new-vel)) 0.0001)
+ (< (abs (vec-y new-vel)) 0.0001))))
+ (if done
+ (setf pos target)
+ (setf vel new-vel))
+ (not done))))