(module wormhole mzscheme
(require (prefix image- "../image.ss")
"../util.ss"
(prefix keyboard- "../keyboard.ss"))
(require (lib "list.ss"))
(define (real->int i)
(inexact->exact (round i)))
(define-values (foo bar)
(define x 1)
(define foo 2)
(define bar 3)
(values foo bar))
(define-values (star-z star-x star-y
star-alive? make-star recalc-star
update-star)
(let ()
(define si 1024)
(define-struct star (x y z cx cy screen-x screen-y))
(define (make-star-user x y z cx cy)
(let ((s (make-star x y z cx cy 0 0)))
(recalc-star s)
s))
(define (star-alive? star)
(and (> (star-z star) 0)
(> (star-screen-x star) 0)
(> (star-screen-y star) 0)
(< (star-screen-x star) 640)
(< (star-screen-y star) 480)))
(define (recalc-star s)
(set-star-screen-x! s
(+ (quotient (* si (star-x s)) (star-z s)) (star-cx s)))
(set-star-screen-y! s
(+ (quotient (* si (star-y s)) (star-z s)) (star-cy s))))
(define (update-star s)
(set-star-z! s (- (star-z s) 9)))
(values star-z star-screen-x star-screen-y
star-alive? make-star-user recalc-star
update-star)))
(define-values (make-starline starline-alive? update-starline draw-starline)
(let ()
(define-struct starline (start end))
(define MAX-Z 500)
(define M-PI 3.14159265358979323846)
(define (Cosine x) (cos (/ (* x M-PI) 180)))
(define (Sine x) (sin (- (/ (* x M-PI) 180))))
(define (starline-alive? star)
(and (star-alive? (starline-start star))
(star-alive? (starline-end star))))
(define (make-starline-real scale mx my)
(let* ((ang (random 360))
(x (real->int (* (Cosine ang) scale)))
(y (real->int (* (Sine ang) scale))))
(make-starline (make-star x y (- MAX-Z (random 9) 4) mx my)
(make-star x y MAX-Z mx my))))
(define (update-starline s)
(update-star (starline-start s))
(update-star (starline-end s)))
(define (draw-starline buffer s colors max-colors)
(let* ((start (starline-start s))
(end (starline-end s))
(ncolor (quotient (* (star-z start) (sub1 max-colors)) MAX-Z)))
(recalc-star start)
(recalc-star end)
(image-putpixel buffer (star-x start) (star-y start) (list-ref colors ncolor))
(image-putpixel buffer (star-x start) (star-y start) (image-color 255 255 255))
(image-line buffer
(star-x start) (star-y start)
(star-x end) (star-y end)
(list-ref colors ncolor))))
(values make-starline-real starline-alive? update-starline draw-starline)))
(define-values (make-wormhole update-wormhole draw-wormhole)
(let ()
(define-struct rgb (r g b))
(define STARS-TO-ADD 20)
(define (set-rgb! rgb r g b)
(set-rgb-r! rgb r)
(set-rgb-g! rgb g)
(set-rgb-b! rgb b))
(define-struct wormhole
(zsize msize x y ang stars colors s1-rgb s2-rgb e1-rgb e2-rgb))
(define WORM-MOVE 9)
(define (move-color! rgb1 rgb2)
(define (change-color! setter! getter)
(when (< (getter rgb1) (getter rgb2))
(setter! rgb1 (add1 (getter rgb1))))
(when (> (getter rgb1) (getter rgb2))
(setter! rgb1 (sub1 (getter rgb1)))))
(for-each
(lambda (x) (change-color! (car x) (cadr x)))
(list (list set-rgb-r! rgb-r)
(list set-rgb-g! rgb-g)
(list set-rgb-b! rgb-b)))
(when (and (= (rgb-r rgb1) (rgb-r rgb2))
(= (rgb-g rgb1) (rgb-g rgb2))
(= (rgb-b rgb1) (rgb-b rgb2)))
(set-rgb! rgb2 (random 255) (random 255) (random 255))))
(define (move-colors! worm)
(move-color! (wormhole-s1-rgb worm) (wormhole-s2-rgb worm))
(move-color! (wormhole-e1-rgb worm) (wormhole-e2-rgb worm))
(set-wormhole-colors!
worm
(blend-palette
(let ((s1 (wormhole-s1-rgb worm)))
(makeColor (rgb-r s1)
(rgb-g s1)
(rgb-b s1)))
(let ((e1 (wormhole-e1-rgb worm)))
(makeColor (rgb-r e1)
(rgb-g e1)
(rgb-b e1)))
50)))
(define (make-wormhole-user)
(let ((worm (make-wormhole 20 20 320 240 0 null null #f #f #f #f)))
(set-wormhole-e1-rgb! worm (make-rgb (random 255)
(random 255)
(random 255)))
(set-wormhole-e2-rgb! worm (make-rgb (random 255)
(random 255)
(random 255)))
(set-wormhole-s1-rgb! worm (make-rgb (random 255)
(random 255)
(random 255)))
(set-wormhole-s2-rgb! worm (make-rgb (random 255)
(random 255)
(random 255)))
(move-colors! worm)
worm))
(define (add-stars! worm num)
(set-wormhole-stars! worm
(let ((zsize (wormhole-zsize worm))
(wx (real->int (wormhole-x worm)))
(wy (real->int (wormhole-y worm))))
(let loop ((stars (wormhole-stars worm))
(q num))
(if (positive? q)
(loop (cons (make-starline zsize wx wy) stars)
(sub1 q))
stars)))))
(define (update-wormhole worm)
(if (or (< (wormhole-x worm) 20)
(< (wormhole-y worm) 20)
(> (wormhole-x worm) 620)
(> (wormhole-y worm) 460))
(set-wormhole-ang!
worm
(real->int (calculate-normal-angle
(wormhole-x worm)
(wormhole-y worm)
320 240)))
(begin
(set-wormhole-ang!
worm
(let ((new-ang (+ (wormhole-ang worm)
(- (random 15)
(random 7)))))
(modulo (+ new-ang 360) 360)))
(when (= (random 60) (random 60))
(set-wormhole-ang! worm (random 360)))))
(set-wormhole-x! worm (+ (wormhole-x worm)
(* WORM-MOVE
(Cosine (wormhole-ang worm)))))
(set-wormhole-y! worm (+ (wormhole-y worm)
(* WORM-MOVE
(Sine (wormhole-ang worm)))))
(when (= (random 20) (random 20))
(set-wormhole-msize! worm (+ (random 40) 5)))
(when (< (wormhole-zsize worm) (wormhole-msize worm))
(set-wormhole-zsize! worm (add1 (wormhole-zsize worm))))
(when (> (wormhole-zsize worm) (wormhole-msize worm))
(set-wormhole-zsize! worm (sub1 (wormhole-zsize worm))))
(add-stars! worm STARS-TO-ADD)
(for-each (lambda (s) (update-starline s)) (wormhole-stars worm))
(set-wormhole-stars! worm (filter starline-alive? (wormhole-stars worm)))
(keyboard-keypressed? 'ESC))
(define foo1 0)
(define foo2 0)
(define (draw-wormhole buffer worm)
(move-colors! worm)
(set! foo1 (current-milliseconds))
(let ((num-colors (length (wormhole-colors worm))))
(for-each (lambda (s)
(draw-starline buffer s (wormhole-colors worm) num-colors))
(wormhole-stars worm)))
(set! foo2 (current-milliseconds))
(printf "Draw: ~a \r" (- foo2 foo1)))
(values make-wormhole-user update-wormhole draw-wormhole)))
(provide run)
(define (run)
(easy-init 640 480 16)
(let* ((wormhole (make-wormhole)))
(game-loop (lambda () (update-wormhole wormhole))
(lambda (buffer) (draw-wormhole buffer wormhole))
(frames-per-second 30)))
(easy-exit))
)