add keys and open close door at end of level

This commit is contained in:
Peter Tillemans 2024-05-23 21:46:50 +02:00
parent 182d9d5693
commit c3d97c2b91
13 changed files with 159 additions and 61 deletions

View file

@ -36,7 +36,7 @@ let the _others_ fall in so you can pass over their head.
So now, go out, collect the keys and maintain a healthy diet!
* Game Plan [9/16]
* Game Plan [11/18]
- [X] start project organization
- [X] select some assets to start with
@ -51,11 +51,13 @@ So now, go out, collect the keys and maintain a healthy diet!
- [X] ensure the assets can be found by the render packages
- [X] upload to itch.io
- [ ] automate upload to itch.io
- [ ] create other's AI
- [ ] add keys and portal
- [X] create other's AI
- [X] add keys and portal
- [ ] add foods and bloat indicator
- [ ] scale hero waist related to bloat level
- [ ] create more levels
- [ ] dig potholes
- [ ] make others steal keys
- [ ] some level celebration/animation
* Installation and Development

View file

@ -2,10 +2,10 @@
-- all content after a '-' is ignored
--
----|----|----|----|----|----|----|----|
WWWWGWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
WWWWWGWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
W H W
W O H O W
W H H W
W H K K K H W
W O BBBBBBBBBBBBBBBBBBBBBBBBBBHB O W -
W H W
W H W
@ -21,7 +21,7 @@ W H W
W H W
W H W
W H W
W H H W -
W H K H W -
W P BHBBBBBBB W
W H W
W H W
@ -29,6 +29,6 @@ W H W
W H W -
W H W
W H W
W H W
W K H W
WBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBW
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW -

View file

@ -3,9 +3,12 @@
#:use-module (game model level)
#:use-module (game model hero)
#:use-module (game model other)
#:use-module (game model key)
#:use-module (game render level)
#:use-module (game render hero)
#:use-module (game render other)
#:use-module (game render key)
#:use-module (game util assets)
#:use-module (chickadee)
#:use-module (chickadee math rect)
#:use-module (chickadee math vector)
@ -22,28 +25,32 @@
(define repl #f)
(define hero #f)
(define others #f)
(define keys #f)
(define inputs '())
(define (load)
(assets-load)
(render-level-load)
(render-hero-load)
(render-other-load)
(set! level (level-parse-file "assets/levels/level-1.map"))
(render-level-set! level)
(set! hero (hero-load level))
(set! others (other-load-others level))
(set! keys (keys-load level))
(set! repl (spawn-coop-repl-server)))
(define (update dt)
(poll-coop-repl-server repl)
(set! hero (hero-update hero level inputs dt))
(set! hero (hero-update hero level inputs keys dt))
(set! others (map (lambda (other) (other-update other level hero others dt)) others))
(set! keys (keys-update keys hero))
)
(define (draw _alpha)
(render-level-draw level)
(render-hero hero)
(for-each render-other others)
(render-keys keys (level-find-goal level))
(render-hero hero)
)
(define (set-add set item)
@ -51,7 +58,6 @@
set
(cons item set)))
(define (key-press key _modifiers _repeat?)
(set! inputs
(cond ((eq? key 'left) (set-add inputs 'left))

View file

@ -51,10 +51,23 @@
"return the current position of the hero"
(runner-position (hero-runner hero)))
(define (collides? a b)
"return true if the hero collides with the given position"
(< (vec2-magnitude (vec2- a b)) level-cell-size))
(define (hero-update hero level inputs dt)
(hero-with-runner hero (runner-update (hero-runner hero) level inputs dt)))
(define (blocked-by-door? level keys position)
"return true if the hero is blocked by a door"
(let ((door-position (level-find-goal level)))
(pk 'blocked-by-door? keys (null? keys) position
(and (collides? position door-position)
(not (null? keys))))))
(define (hero-update hero level inputs keys dt)
(let ((new-runner (runner-update (hero-runner hero) level inputs dt)))
(if (blocked-by-door? level keys (runner-position new-runner))
hero
(hero-with-runner hero new-runner)
)))
;; Tests
@ -69,5 +82,13 @@
(test-equal 1.5 (hero-bloat (hero-with-bloat hero 1.5)))
(test-equal default-bloat (hero-bloat hero)))
(let* ((level (level-parse "WWGWW\nW.H.W\nW.P.W\nWWWWW\n"))
(hero (hero-load level))
(goal-position (level-find-goal level)))
(test-assert (blocked-by-door? level '(dummy-key) goal-position))
(test-assert (not (blocked-by-door? level '() goal-position)))
(test-assert (blocked-by-door? level '(dummy-key) (vec2- goal-position (vec2 0 -15))))
(test-assert (not (blocked-by-door? level '(dummy-key) (vec2- goal-position (vec2 0 -16))))))
(test-end "hero-model")

36
game/model/key.scm Normal file
View file

@ -0,0 +1,36 @@
(define-module (game model key)
#:use-module (chickadee math vector)
#:use-module (game model level)
#:use-module (game model hero)
#:use-module (srfi srfi-9)
#:use-module (srfi srfi-9 gnu)
#:export (key?
key-near-position?
keys-load
key-position
make-key
keys-update
)
)
(define-immutable-record-type <key>
(make-key position)
key?
(position key-position)
)
(define (key-collides? key position)
(< (pk "key distance" (vec2-magnitude (vec2- (key-position key) position))) 4))
(define (keys-load level)
(map make-key (level-find-keys level)))
(define (keys-update keys hero)
(filter (lambda (key)
(not (key-collides? key (hero-position hero))))
keys))
(define (keys-open-door? keys)
(null? keys))

View file

@ -18,12 +18,15 @@
level-tile-at
level-cell-size
level-find-hero
level-find-goal
level-find-others
level-find-keys
level-tile-blocked?
level-same-cell?
))
(define-record-type <level>
(%make-level width height tiles goal hero entities)
(%make-level width height tiles)
level?
(width level-width)
(height level-height)
@ -40,6 +43,7 @@
((#\P) 'hero)
((#\O) 'other)
((#\G) 'goal)
((#\K) 'key)
(else 'empty)))
(define (content->lines content)
@ -65,12 +69,11 @@
(width (string-length (car lines)))
(height (length lines))
(tiles (list->vector
(parse-lines lines)))
(entities '()))
(%make-level width height tiles #f #f entities)))
(parse-lines lines))))
(%make-level width height tiles)))
(define (level-parse-file filename)
(level-parse (call-with-input-file (asset-file-name filename) get-string-all)))
(level-parse (call-with-input-file (assets-file-name filename) get-string-all)))
(define (level-tile-at-row-col level row col )
@ -119,6 +122,14 @@
(define (level-find-others level)
(level-find-tile level 'other))
(define (level-find-keys level)
(level-find-tile level 'key))
(define (level-same-cell? a b)
(and (= (coord->cell (vec2-x a)) (coord->cell (vec2-x b)))
(= (coord->cell (vec2-y a)) (coord->cell (vec2-y b)))))
;; Tests
(test-begin "level")

View file

@ -24,10 +24,13 @@
;; They are represented by a runner and try to reach the player to give
;; unwelcome advice unwittingly killing the player with cringe.
(define-immutable-record-type <other>
(%make-other runner)
(%make-other runner has-key?)
other?
(runner other-runner other-with-runner)
)
(has-key? other-has-key? other-with-key))
(define (make-other runner)
(%make-other runner #f))
(define default-state 'fall)
(define default-bloat 1.0)
@ -35,7 +38,7 @@
(define (other-load-others level)
"Create a other at the position in the level map"
(map
(compose %make-other runner-load)
(compose make-other runner-load)
(level-find-others level)))
(define (other-x other)
@ -44,8 +47,7 @@
(define (other-y other)
"return the y coordinate as an integer"
(runner-y (other-runner other))
)
(runner-y (other-runner other)))
(define (other-state other)
"return the current state of the other"

View file

@ -13,9 +13,7 @@
runner-position runner-with-position
runner-x runner-with-x
runner-y runner-with-y
runner-update
))
runner-update))
(define-immutable-record-type <runner>
(%make-runner position state)
@ -43,7 +41,6 @@
(define (runner-with-y runner y)
(runner-with-position runner (vec2 (runner-x runner) y)))
;; return next state of runner
;; @returns 'go-left 'go-right 'climb 'fall 'stationary
(define (next-state runner level inputs)
@ -68,12 +65,10 @@
((down) (vec2 0 (- distance)))
(else (vec2 0 0))))
(define (round-position pos)
(vec2 (inexact->exact (floor (vec2-x pos)))
(inexact->exact (floor (vec2-y pos)))))
(define (safe-move level pos move)
(let ((new-pos (vec2+ pos move)))
(if (level-tile-blocked? level new-pos)
@ -105,8 +100,6 @@
(runner-with-state state)
(runner-with-position position))))
;; Tests
(test-begin "runner-model")

View file

@ -6,16 +6,7 @@
#:use-module (chickadee graphics sprite)
#:use-module (chickadee graphics texture)
#:export (render-hero
render-hero-load)
)
(define hero-texture #f)
(define hero-atlas #f)
(define (render-hero-load)
(set! hero-texture (load-image (asset-file-name "assets/images/lr_penguin2.png")))
(set! hero-atlas (split-texture hero-texture 32 32)))
render-hero-load))
;; start index of the walk animation
(define hero-walking-offset 56)

31
game/render/key.scm Normal file
View file

@ -0,0 +1,31 @@
(define-module (game render key)
#:use-module (game util assets)
#:use-module (game model key)
#:use-module (chickadee math vector)
#:use-module (chickadee graphics sprite)
#:use-module (chickadee graphics texture)
#:export (render-keys))
(define key-index 1726)
(define closed-goal-index 3404)
(define open-goal-index 3350)
(define (render-key key)
(draw-sprite
(texture-atlas-ref tile-atlas key-index)
(vec2+ (key-position key) (vec2 -8 0))))
(define (render-goal keys goal-position)
(let ((goal-index (if (null? keys) open-goal-index closed-goal-index)))
(draw-sprite
(texture-atlas-ref tile-atlas goal-index)
goal-position)))
(define (render-keys keys goal-position)
(for-each (lambda (key)
(render-key key))
keys)
(render-goal keys goal-position))

View file

@ -12,17 +12,10 @@
))
(define tile-texture #f)
(define tile-atlas #f)
(define tile-index 0)
(define tile-map #f)
(define sprite-batch #f)
;; load the tile texture and split it into a tile atlas
(define (render-level-load)
(set! tile-texture (load-image (asset-file-name "assets/images/simples_pimples.png")
#:transparent-color black))
(set! tile-atlas (split-texture tile-texture 16 16))
(set! sprite-batch (make-sprite-batch tile-texture #:capacity 1200))
)
@ -35,9 +28,10 @@
((brick) 3750)
((wall) 3709)
((ladder) 3350)
((goal) 3404)
((goal) 3800) ;; render empty tile for goal location
((hero) 3800) ;; render empty tile for hero start location
((other) 3800) ;; render empty tile for enemy start location
((key) 3800)
;; render visual reminder of unknown tile
(else 3326)))

View file

@ -10,11 +10,6 @@
(define other-atlas #f)
(define (render-other-load)
(set! other-atlas (split-texture (load-image (asset-file-name "assets/images/simples_pimples.png")) 16 16)))
;; start index of the walk animation
(define other-walking-offset 3926)
(define other-falling-offset 3930)
@ -24,16 +19,16 @@
(let* ((x (other-x other))
(animation-frame (remainder x 3))
(other-index (+ other-walking-offset animation-frame)))
(texture-atlas-ref other-atlas other-index)))
(texture-atlas-ref tile-atlas other-index)))
(define (other-sprite-stationary _other)
(texture-atlas-ref other-atlas other-walking-offset))
(texture-atlas-ref tile-atlas other-walking-offset))
(define (other-sprite-falling other)
(texture-atlas-ref other-atlas other-climbing-offset))
(texture-atlas-ref tile-atlas other-climbing-offset))
(define (other-sprite-climbing other)
(texture-atlas-ref other-atlas other-climbing-offset))
(texture-atlas-ref tile-atlas other-climbing-offset))
(define (render-other other)
(case (other-state other)

View file

@ -1,11 +1,27 @@
(define-module (game util assets)
#:export (asset-file-name)
#:use-module (chickadee graphics texture)
#:use-module (chickadee graphics color)
#:export (assets-load assets-file-name tile-texture tile-atlas hero-texture hero-atlas)
)
(define tile-texture #f)
(define tile-atlas #f)
(define hero-texture #f)
(define hero-atlas #f)
(define prefix (or (getenv "ASSET_DIR") "." ))
(define (asset-file-name name)
(define (assets-file-name name)
(string-append prefix "/" name)
)
(define (assets-load)
(set! tile-texture (load-image (assets-file-name "assets/images/simples_pimples.png")
#:transparent-color black))
(set! tile-atlas (split-texture tile-texture 16 16))
(set! hero-texture (load-image (assets-file-name "assets/images/lr_penguin2.png")))
(set! hero-atlas (split-texture hero-texture 32 32)))