(use-modules (chickadee) (chickadee math vector) (chickadee math rect) (chickadee render font) (chickadee render sprite) (chickadee render texture) (chickadee render tiled) (oop goops)) (define-class () (pos #:init-keyword #:pos #:getter get-pos) (size #:init-keyword #:size #:getter get-size) (vel #:init-value #v(0.0 0.0) #:getter get-vel #:setter set-vel!) (walk-direction #:init-value 0 #:setter set-walk-direction! #:getter get-walk-direction) (face-direction #:init-keyword #:face-dir #:setter set-face-direction! #:getter get-face-direction) (animation-step #:init-value 0 #:getter get-animation-step #:setter set-animation-step!) (sprite #:init-keyword #:sprite #:getter get-sprite)) (define (face-row dir) (if (> 0 dir) 4 12)) (define (draw-animal animal) (draw-sprite (texture-atlas-ref (get-sprite animal) (+ (face-row (get-face-direction animal)) (truncate (/ (get-animation-step animal) 4)))) (get-screen-pos animal))) (define (update-animal animal tstep) (let ((wd (get-walk-direction animal))) (unless (eq? wd 0) (set-face-direction! animal wd) (vec2-add! (get-pos animal) #v((* tstep wd 0.2) 0)) (set-animation-step! animal (floor-remainder (+ (get-animation-step animal) wd) 16)))) (vec2-add! (get-pos animal) (get-vel animal)) (if (> (vec2-y (get-pos animal)) 200.0) (set-vel! animal (vec2+ (get-vel animal) #v(0.0 -1.0))) (set-vel! animal #v(0.0 0.0)))) ;; -------------- Initial game state -------------- (define llama #f) (define tile-map #f) (define view-pos #v(0.0 0.0)) (define (load) (set! llama (make #:pos #v(200.0 200.0) #:size #v(128.0 128.0) #:face-dir 1 #:sprite (split-texture (load-image "llama_walk.png") 128 128))) (set! tile-map (load-tile-map "llama.tmx"))) ;; ------------------------------------------------ (define (draw alpha) (draw-tile-map tile-map #:position (vec2* view-pos -1.0)) (draw-animal llama)) (define (get-screen-pos animal) (vec2- (get-pos animal) view-pos)) (define (rect-xy rect) #v((rect-x rect) (rect-y rect))) (define (get-screen-rect animal) (let ((screen-pos (get-screen-pos animal))) (make-rect (vec2-x screen-pos) (vec2-y screen-pos) (vec2-x (get-size animal)) (vec2-y (get-size animal))))) (define (overshoot small-rect big-rect) (let ((moved-small-rect (rect-clamp small-rect big-rect))) (vec2- (rect-xy small-rect) (rect-xy moved-small-rect)))) (define (update tstep) (update-animal llama tstep) ;; Ensure llama is near centre of screen (let ((fovea (make-rect 150.0 150.0 350.0 350.0)) (llama-rect (get-screen-rect llama))) (unless (rect-within? llama-rect fovea) (vec2-add! view-pos (overshoot llama-rect fovea))))) (define (key-press key scancode modifier repeat?) (case key ((q) (abort-game)) ((right) (set-walk-direction! llama 1)) ((left) (set-walk-direction! llama -1)) ((space) (unless repeat? (set-vel! llama #v(0.0 15.0)))))) (define (key-release key scancode modifier) (case key ((right) (set-walk-direction! llama 0)) ((left) (set-walk-direction! llama 0)))) (run-game #:window-title "Hey Llama!" #:load load #:draw draw #:key-press key-press #:update-hz 60 #:key-release key-release #:update update)